From 2cd731a067fc74fd23240edae6366fa87939bb3d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 11 Nov 2024 19:58:12 +0300 Subject: [PATCH] check: extend ProcessBlock callback with error handler For anti-MEV extension it's possible that some commits carry invalid share which is impossible to check at the commit verification level. In this case node should collect some more commits. Signed-off-by: Anna Shaleva --- check.go | 13 ++++++++++--- config.go | 6 +++--- dbft_test.go | 2 +- internal/consensus/consensus.go | 2 +- internal/simulation/main.go | 3 ++- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/check.go b/check.go index 4109f721..7338ee05 100644 --- a/check.go +++ b/check.go @@ -112,8 +112,6 @@ func (d *DBFT[H]) checkCommit() { return } - d.lastBlockIndex = d.BlockIndex - d.lastBlockTime = d.Timer.Now() d.block = d.CreateBlock() hash := d.block.Hash() @@ -124,8 +122,17 @@ func (d *DBFT[H]) checkCommit() { zap.Stringer("merkle", d.block.MerkleRoot()), zap.Stringer("prev", d.block.PrevHash())) + err := d.ProcessBlock(d.block) + if err != nil && d.isAntiMEVExtensionEnabled() { // errors not supported for AntiMEVExtensions mode off. + d.Logger.Info("can't process Block, waiting for more Commits to be collected", + zap.Error(err), + zap.Int("count", count)) + return + } + + d.lastBlockIndex = d.BlockIndex + d.lastBlockTime = d.Timer.Now() d.blockProcessed = true - d.ProcessBlock(d.block) // Do not initialize consensus process immediately. It's the caller's duty to // start the new block acceptance process and call Reset at the diff --git a/config.go b/config.go index 3db107a2..6339d00e 100644 --- a/config.go +++ b/config.go @@ -51,7 +51,7 @@ type Config[H Hash] struct { // ProcessBlock is called every time new preBlock is accepted. ProcessPreBlock func(b PreBlock[H]) error // ProcessBlock is called every time new block is accepted. - ProcessBlock func(b Block[H]) + ProcessBlock func(b Block[H]) error // GetBlock should return block with hash. GetBlock func(h H) Block[H] // WatchOnly tells if a node should only watch. @@ -108,7 +108,7 @@ func defaultConfig[H Hash]() *Config[H] { GetVerified: func() []Transaction[H] { return make([]Transaction[H], 0) }, VerifyBlock: func(Block[H]) bool { return true }, Broadcast: func(ConsensusPayload[H]) {}, - ProcessBlock: func(Block[H]) {}, + ProcessBlock: func(Block[H]) error { return nil }, GetBlock: func(H) Block[H] { return nil }, WatchOnly: func() bool { return false }, CurrentHeight: nil, @@ -276,7 +276,7 @@ func WithBroadcast[H Hash](f func(m ConsensusPayload[H])) func(config *Config[H] } // WithProcessBlock sets ProcessBlock. -func WithProcessBlock[H Hash](f func(b Block[H])) func(config *Config[H]) { +func WithProcessBlock[H Hash](f func(b Block[H]) error) func(config *Config[H]) { return func(cfg *Config[H]) { cfg.ProcessBlock = f } diff --git a/dbft_test.go b/dbft_test.go index da113e80..2fcdea1a 100644 --- a/dbft_test.go +++ b/dbft_test.go @@ -1131,7 +1131,7 @@ func (s *testState) getOptions() []func(*dbft.Config[crypto.Uint256]) { }), dbft.WithBroadcast[crypto.Uint256](func(p Payload) { s.ch = append(s.ch, p) }), dbft.WithGetTx[crypto.Uint256](s.pool.Get), - dbft.WithProcessBlock[crypto.Uint256](func(b dbft.Block[crypto.Uint256]) { s.blocks = append(s.blocks, b) }), + dbft.WithProcessBlock[crypto.Uint256](func(b dbft.Block[crypto.Uint256]) error { s.blocks = append(s.blocks, b); return nil }), dbft.WithWatchOnly[crypto.Uint256](func() bool { return false }), dbft.WithGetBlock[crypto.Uint256](func(crypto.Uint256) dbft.Block[crypto.Uint256] { return nil }), dbft.WithTimer[crypto.Uint256](timer.New()), diff --git a/internal/consensus/consensus.go b/internal/consensus/consensus.go index c4cd7b69..e0ebdd6d 100644 --- a/internal/consensus/consensus.go +++ b/internal/consensus/consensus.go @@ -13,7 +13,7 @@ func New(logger *zap.Logger, key dbft.PrivateKey, pub dbft.PublicKey, getTx func(uint256 crypto.Uint256) dbft.Transaction[crypto.Uint256], getVerified func() []dbft.Transaction[crypto.Uint256], broadcast func(dbft.ConsensusPayload[crypto.Uint256]), - processBlock func(dbft.Block[crypto.Uint256]), + processBlock func(dbft.Block[crypto.Uint256]) error, currentHeight func() uint32, currentBlockHash func() crypto.Uint256, getValidators func(...dbft.Transaction[crypto.Uint256]) []dbft.PublicKey, diff --git a/internal/simulation/main.go b/internal/simulation/main.go index 0a2973ec..0e12bc1a 100644 --- a/internal/simulation/main.go +++ b/internal/simulation/main.go @@ -179,7 +179,7 @@ func (n *simNode) GetValidators(...dbft.Transaction[crypto.Uint256]) []dbft.Publ return n.validators } -func (n *simNode) ProcessBlock(b dbft.Block[crypto.Uint256]) { +func (n *simNode) ProcessBlock(b dbft.Block[crypto.Uint256]) error { n.d.Logger.Debug("received block", zap.Uint32("height", b.Index())) for _, tx := range b.Transactions() { @@ -188,6 +188,7 @@ func (n *simNode) ProcessBlock(b dbft.Block[crypto.Uint256]) { n.height = b.Index() n.lastHash = b.Hash() + return nil } // VerifyPayload verifies that payload was received from a good validator.