diff --git a/dot/services.go b/dot/services.go index 60a26ca4ed..d0cee3b2a2 100644 --- a/dot/services.go +++ b/dot/services.go @@ -442,6 +442,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, @@ -455,6 +460,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) diff --git a/dot/sync/chain_sync.go b/dot/sync/chain_sync.go index 8e80b8a54e..24a6d339fb 100644 --- a/dot/sync/chain_sync.go +++ b/dot/sync/chain_sync.go @@ -16,6 +16,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" @@ -174,6 +175,7 @@ type chainSync struct { finalityGadget FinalityGadget blockImportHandler BlockImportHandler telemetry Telemetry + badBlocks []string } type chainSyncConfig struct { @@ -189,6 +191,7 @@ type chainSyncConfig struct { finalityGadget FinalityGadget blockImportHandler BlockImportHandler telemetry Telemetry + badBlocks []string } func newChainSync(cfg chainSyncConfig) *chainSync { @@ -226,6 +229,7 @@ func newChainSync(cfg chainSyncConfig) *chainSync { logSyncTickerC: logSyncTicker.C, logSyncDone: make(chan struct{}), workerPool: newSyncWorkerPool(cfg.net), + badBlocks: cfg.badBlocks, } } @@ -632,6 +636,10 @@ loop: err := cs.validateResponse(request, response, who) switch { + case errors.Is(err, errBadBlock): + logger.Criticalf("Rejecting known bad block: $s", err) + cs.workerPool.shutdownWorker(taskResult.who, true) + cs.workerPool.submitRequest(taskResult.request, workersResults) case errors.Is(err, errResponseIsNotChain): logger.Criticalf("response invalid: %s", err) cs.workerPool.shutdownWorker(taskResult.who, true) @@ -1014,6 +1022,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, diff --git a/dot/sync/errors.go b/dot/sync/errors.go index 51334ab66f..1a90802d68 100644 --- a/dot/sync/errors.go +++ b/dot/sync/errors.go @@ -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") ) diff --git a/dot/sync/sync_worker.go b/dot/sync/sync_worker.go index 271df3b015..8c9cddad64 100644 --- a/dot/sync/sync_worker.go +++ b/dot/sync/sync_worker.go @@ -57,7 +57,6 @@ func (s *syncWorker) update(bestHash common.Hash, bestNumber uint) { } var errBadPeerWorker = errors.New("bad peer worker") -var errBadBlock = errors.New("bad block") func (s *syncWorker) Start(tasks <-chan *syncTask, wg *sync.WaitGroup) { wg.Add(1) diff --git a/dot/sync/syncer.go b/dot/sync/syncer.go index 12a339099d..efa9e58962 100644 --- a/dot/sync/syncer.go +++ b/dot/sync/syncer.go @@ -35,6 +35,7 @@ type Config struct { MinPeers, MaxPeers int SlotDuration time.Duration Telemetry Telemetry + BadBlocks []string } // NewService returns a new *sync.Service @@ -58,6 +59,7 @@ func NewService(cfg *Config) (*Service, error) { finalityGadget: cfg.FinalityGadget, blockImportHandler: cfg.BlockImportHandler, telemetry: cfg.Telemetry, + badBlocks: cfg.BadBlocks, } chainSync := newChainSync(csCfg)