Skip to content

Commit

Permalink
feat(lib/grandpa): verify GRANDPA justification before applying the b…
Browse files Browse the repository at this point in the history
…lock (#4144)

Co-authored-by: JimboJ <[email protected]>
  • Loading branch information
timwu20 and jimjbrettj committed Sep 10, 2024
1 parent 646a445 commit 1836e44
Show file tree
Hide file tree
Showing 32 changed files with 2,355 additions and 583 deletions.
2 changes: 1 addition & 1 deletion dot/mock_node_builder_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dot/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ type nodeBuilderIface interface {
) (*core.Service, error)
createGRANDPAService(config *cfg.Config, st *state.Service, ks KeyStore,
net *network.Service, telemetryMailer Telemetry) (*grandpa.Service, error)
newSyncService(config *cfg.Config, st *state.Service, finalityGadget BlockJustificationVerifier,
newSyncService(config *cfg.Config, st *state.Service, finalityGadget dotsync.FinalityGadget,
verifier *babe.VerificationManager, cs *core.Service, net *network.Service,
telemetryMailer Telemetry) (*dotsync.Service, error)
createBABEService(config *cfg.Config, st *state.Service, ks KeyStore, cs *core.Service,
Expand Down
2 changes: 1 addition & 1 deletion dot/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ func (nodeBuilder) createBlockVerifier(st *state.Service) *babe.VerificationMana
return babe.NewVerificationManager(st.Block, st.Slot, st.Epoch)
}

func (nodeBuilder) newSyncService(config *cfg.Config, st *state.Service, fg BlockJustificationVerifier,
func (nodeBuilder) newSyncService(config *cfg.Config, st *state.Service, fg sync.FinalityGadget,
verifier *babe.VerificationManager, cs *core.Service, net *network.Service, telemetryMailer Telemetry) (
*sync.Service, error) {
slotDuration, err := st.Epoch.GetSlotDuration()
Expand Down
3 changes: 2 additions & 1 deletion dot/services_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/ChainSafe/gossamer/dot/network"
rpc "github.com/ChainSafe/gossamer/dot/rpc"
"github.com/ChainSafe/gossamer/dot/state"
"github.com/ChainSafe/gossamer/dot/sync"
"github.com/ChainSafe/gossamer/dot/telemetry"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/internal/log"
Expand Down Expand Up @@ -373,7 +374,7 @@ func Test_nodeBuilder_newSyncService(t *testing.T) {
require.NoError(t, err)

type args struct {
fg BlockJustificationVerifier
fg sync.FinalityGadget
verifier *babe.VerificationManager
cs *core.Service
net *network.Service
Expand Down
43 changes: 25 additions & 18 deletions dot/sync/chain_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -843,18 +843,40 @@ func (cs *chainSync) processBlockData(blockData types.BlockData, origin blockOri
announceImportedBlock := cs.getSyncMode() == tip

if blockData.Header != nil {
var (
hasJustification = blockData.Justification != nil && len(*blockData.Justification) > 0
round uint64
setID uint64
)

if hasJustification {
var err error
round, setID, err = cs.finalityGadget.VerifyBlockJustification(
blockData.Header.Hash(), blockData.Header.Number, *blockData.Justification)
if err != nil {
return fmt.Errorf("verifying justification: %w", err)
}
}

if blockData.Body != nil {
err := cs.processBlockDataWithHeaderAndBody(blockData, origin, announceImportedBlock)
if err != nil {
return fmt.Errorf("processing block data with header and body: %w", err)
}
}

if blockData.Justification != nil && len(*blockData.Justification) > 0 {
err := cs.handleJustification(blockData.Header, *blockData.Justification)
if hasJustification {
header := blockData.Header
err := cs.blockState.SetFinalisedHash(header.Hash(), round, setID)
if err != nil {
return fmt.Errorf("handling justification: %w", err)
return fmt.Errorf("setting finalised hash: %w", err)
}
err = cs.blockState.SetJustification(header.Hash(), *blockData.Justification)
if err != nil {
return fmt.Errorf("setting justification for block number %d: %w", header.Number, err)
}

return nil
}
}

Expand Down Expand Up @@ -902,21 +924,6 @@ func (cs *chainSync) handleBody(body *types.Body) {
blockSizeGauge.Set(float64(acc))
}

func (cs *chainSync) handleJustification(header *types.Header, justification []byte) (err error) {
headerHash := header.Hash()
err = cs.finalityGadget.VerifyBlockJustification(headerHash, justification)
if err != nil {
return fmt.Errorf("verifying block number %d justification: %w", header.Number, err)
}

err = cs.blockState.SetJustification(headerHash, justification)
if err != nil {
return fmt.Errorf("setting justification for block number %d: %w", header.Number, err)
}

return nil
}

// handleHeader handles blocks (header+body) included in BlockResponses
func (cs *chainSync) handleBlock(block *types.Block, announceImportedBlock bool) error {
parent, err := cs.blockState.GetHeader(block.Header.ParentHash)
Expand Down
1 change: 1 addition & 0 deletions dot/sync/chain_sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1851,6 +1851,7 @@ func TestChainSync_BootstrapSync_SuccessfulSync_WithInvalidJusticationBlock(t *t
mockFinalityGadget.EXPECT().
VerifyBlockJustification(
invalidJustificationBlock.Header.Hash(),
invalidJustificationBlock.Header.Number,
*invalidJustification).
Return(uint64(0), uint64(0), errVerifyBlockJustification)

Expand Down
4 changes: 3 additions & 1 deletion dot/sync/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type BlockState interface {
GetReceipt(common.Hash) ([]byte, error)
GetMessageQueue(common.Hash) ([]byte, error)
GetJustification(common.Hash) ([]byte, error)
SetFinalisedHash(hash common.Hash, round uint64, setID uint64) error
SetJustification(hash common.Hash, data []byte) error
GetHashByNumber(blockNumber uint) (common.Hash, error)
GetBlockByHash(common.Hash) (*types.Block, error)
Expand Down Expand Up @@ -61,7 +62,8 @@ type BabeVerifier interface {

// FinalityGadget implements justification verification functionality
type FinalityGadget interface {
VerifyBlockJustification(common.Hash, []byte) error
VerifyBlockJustification(finalizedHash common.Hash, finalizedNumber uint, encoded []byte) (
round uint64, setID uint64, err error)
}

// BlockImportHandler is the interface for the handler of newly imported blocks
Expand Down
28 changes: 22 additions & 6 deletions dot/sync/mocks_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions dot/sync/syncer_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ func newTestSyncer(t *testing.T) *Service {
cfg.LogLvl = log.Trace
mockFinalityGadget := NewMockFinalityGadget(ctrl)
mockFinalityGadget.EXPECT().VerifyBlockJustification(gomock.AssignableToTypeOf(common.Hash{}),
gomock.AssignableToTypeOf([]byte{})).DoAndReturn(func(hash common.Hash, justification []byte) error {
return nil
}).AnyTimes()
gomock.AssignableToTypeOf(uint(0)), gomock.AssignableToTypeOf([]byte{})).
DoAndReturn(func(hash common.Hash, justification []byte) error {
return nil
}).AnyTimes()

cfg.FinalityGadget = mockFinalityGadget
cfg.Network = NewMockNetwork(ctrl)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ require (
github.com/stretchr/testify v1.9.0
github.com/tetratelabs/wazero v1.1.0
github.com/tidwall/btree v1.7.0
github.com/tyler-smith/go-bip39 v1.1.0
go.uber.org/mock v0.4.0
golang.org/x/crypto v0.26.0
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
Expand Down
10 changes: 10 additions & 0 deletions internal/client/consensus/grandpa/authorities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright 2023 ChainSafe Systems (ON)
// SPDX-License-Identifier: LGPL-3.0-only

package grandpa

// generic representation of hash and number tuple
type HashNumber[H, N any] struct {
Hash H
Number N
}
Loading

0 comments on commit 1836e44

Please sign in to comment.