Skip to content

Commit

Permalink
feat(sync): Validate bad blocks (#3220)
Browse files Browse the repository at this point in the history
  • Loading branch information
dimartiro authored and jimjbrettj committed Apr 25, 2023
1 parent 2f100f6 commit fe5b054
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 0 deletions.
6 changes: 6 additions & 0 deletions dot/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,11 @@ func (nodeBuilder) newSyncService(cfg *Config, st *state.Service, fg BlockJustif
return nil, err
}

genesisData, err := st.Base.LoadGenesisData()
if err != nil {
return nil, err
}

syncCfg := &sync.Config{
LogLvl: cfg.Log.SyncLvl,
Network: net,
Expand All @@ -454,6 +459,7 @@ func (nodeBuilder) newSyncService(cfg *Config, st *state.Service, fg BlockJustif
MaxPeers: cfg.Network.MaxPeers,
SlotDuration: slotDuration,
Telemetry: telemetryMailer,
BadBlocks: genesisData.BadBlocks,
}

return sync.NewService(syncCfg)
Expand Down
1 change: 1 addition & 0 deletions dot/sync/chain_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type chainProcessorConfig struct {
finalityGadget FinalityGadget
blockImportHandler BlockImportHandler
telemetry Telemetry
badBlocks []string
}

func newChainProcessor(cfg chainProcessorConfig) *chainProcessor {
Expand Down
10 changes: 10 additions & 0 deletions dot/sync/chain_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/libp2p/go-libp2p/core/peer"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"golang.org/x/exp/slices"

"github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/peerset"
Expand Down Expand Up @@ -165,6 +166,7 @@ type chainSync struct {
logSyncTickerC <-chan time.Time // channel as field for unit testing
logSyncStarted bool
logSyncDone chan struct{}
badBlocks []string
}

type chainSyncConfig struct {
Expand All @@ -174,6 +176,7 @@ type chainSyncConfig struct {
pendingBlocks DisjointBlockSet
minPeers, maxPeers int
slotDuration time.Duration
badBlocks []string
}

func newChainSync(cfg chainSyncConfig) *chainSync {
Expand Down Expand Up @@ -204,6 +207,7 @@ func newChainSync(cfg chainSyncConfig) *chainSync {
logSyncTicker: logSyncTicker,
logSyncTickerC: logSyncTicker.C,
logSyncDone: make(chan struct{}),
badBlocks: cfg.badBlocks,
}
}

Expand Down Expand Up @@ -829,6 +833,7 @@ func (cs *chainSync) determineSyncPeers(req *network.BlockRequestMessage, peersT
// It checks the following:
// - the response is not empty
// - the response contains all the expected fields
// - the block is not contained in the bad block list
// - each block has the correct parent, ie. the response constitutes a valid chain
func (cs *chainSync) validateResponse(req *network.BlockRequestMessage,
resp *network.BlockResponseMessage, p peer.ID) error {
Expand Down Expand Up @@ -929,6 +934,11 @@ func (cs *chainSync) validateBlockData(req *network.BlockRequestMessage, bd *typ

requestedData := req.RequestedData

if slices.Contains(cs.badBlocks, bd.Hash.String()) {
logger.Errorf("Rejecting known bad block Number: %d Hash: %s", bd.Number(), bd.Hash)
return errBadBlock
}

if (requestedData&network.RequestedDataHeader) == 1 && bd.Header == nil {
cs.network.ReportPeer(peerset.ReputationChange{
Value: peerset.IncompleteHeaderValue,
Expand Down
30 changes: 30 additions & 0 deletions dot/sync/chain_sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,8 @@ func TestWorkerToRequests(t *testing.T) {

func TestChainSync_validateResponse(t *testing.T) {
t.Parallel()
badBlockHash := common.NewHash([]byte("badblockhash"))

tests := map[string]struct {
blockStateBuilder func(ctrl *gomock.Controller) BlockState
networkBuilder func(ctrl *gomock.Controller) Network
Expand Down Expand Up @@ -813,6 +815,31 @@ func TestChainSync_validateResponse(t *testing.T) {
},
expectedError: errUnknownParent,
},
"handle_error_bad_block": {
blockStateBuilder: func(ctrl *gomock.Controller) BlockState {
mockBlockState := NewMockBlockState(ctrl)
mockBlockState.EXPECT().GetFinalisedNotifierChannel().Return(make(chan *types.FinalisationInfo))
return mockBlockState
},
networkBuilder: func(ctrl *gomock.Controller) Network {
return NewMockNetwork(ctrl)
},
req: &network.BlockRequestMessage{
RequestedData: network.RequestedDataHeader,
},
resp: &network.BlockResponseMessage{
BlockData: []*types.BlockData{
{
Hash: badBlockHash,
Header: &types.Header{
Number: 2,
},
Body: &types.Body{},
},
},
},
expectedError: errBadBlock,
},
"no_error": {
blockStateBuilder: func(ctrl *gomock.Controller) BlockState {
mockBlockState := NewMockBlockState(ctrl)
Expand Down Expand Up @@ -858,6 +885,9 @@ func TestChainSync_validateResponse(t *testing.T) {
pendingBlocks: newDisjointBlockSet(pendingBlocksLimit),
readyBlocks: newBlockQueue(maxResponseSize),
net: tt.networkBuilder(ctrl),
badBlocks: []string{
badBlockHash.String(),
},
}
cs := newChainSync(cfg)

Expand Down
1 change: 1 addition & 0 deletions dot/sync/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ var (
errFailedToGetParent = errors.New("failed to get parent header")
errStartAndEndMismatch = errors.New("request start and end hash are not on the same chain")
errFailedToGetDescendant = errors.New("failed to find descendant block")
errBadBlock = errors.New("known bad block")
)
2 changes: 2 additions & 0 deletions dot/sync/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Config struct {
MinPeers, MaxPeers int
SlotDuration time.Duration
Telemetry Telemetry
BadBlocks []string
}

// NewService returns a new *sync.Service
Expand Down Expand Up @@ -67,6 +68,7 @@ func NewService(cfg *Config) (*Service, error) {
finalityGadget: cfg.FinalityGadget,
blockImportHandler: cfg.BlockImportHandler,
telemetry: cfg.Telemetry,
badBlocks: cfg.BadBlocks,
}
chainProcessor := newChainProcessor(cpCfg)

Expand Down

0 comments on commit fe5b054

Please sign in to comment.