From de97793d7466d270439e7906b71bd6322ae474fc Mon Sep 17 00:00:00 2001 From: gop Date: Mon, 9 Oct 2023 12:26:23 -0500 Subject: [PATCH] Added a Difficulty check in Zone for stale broadcast --- consensus/blake3pow/consensus.go | 5 +++++ consensus/consensus.go | 4 ++++ consensus/progpow/consensus.go | 5 +++++ eth/fetcher/block_fetcher.go | 24 +++++++++++++++++++++++- eth/handler.go | 8 +++++++- 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/consensus/blake3pow/consensus.go b/consensus/blake3pow/consensus.go index 0b04db4641..00b5aa2a9b 100644 --- a/consensus/blake3pow/consensus.go +++ b/consensus/blake3pow/consensus.go @@ -385,6 +385,11 @@ func (blake3pow *Blake3pow) IsDomCoincident(chain consensus.ChainHeaderReader, h return order < common.NodeLocation.Context() } +// VerifySeal returns the PowHash and the verifySeal output +func (blake3pow *Blake3pow) VerifySeal(header *types.Header) (common.Hash, error) { + return header.Hash(), blake3pow.verifySeal(header) +} + // verifySeal checks whether a block satisfies the PoW difficulty requirements, // either using the usual blake3pow cache for it, or alternatively using a full DAG // to make remote mining fast. diff --git a/consensus/consensus.go b/consensus/consensus.go index c498c9c3c2..ff5dc64948 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -142,6 +142,10 @@ type Engine interface { // dominant chain, or even that the claimed dominant difficulty is valid. IsDomCoincident(chain ChainHeaderReader, header *types.Header) bool + // VerifySeal computes the PowHash and checks if work meets the difficulty + // requirement specified in header + VerifySeal(header *types.Header) (common.Hash, error) + // APIs returns the RPC APIs this consensus engine provides. APIs(chain ChainHeaderReader) []rpc.API diff --git a/consensus/progpow/consensus.go b/consensus/progpow/consensus.go index 02429e337a..d11efdc621 100644 --- a/consensus/progpow/consensus.go +++ b/consensus/progpow/consensus.go @@ -408,6 +408,11 @@ func (progpow *Progpow) ComputePowLight(header *types.Header) (mixHash, powHash return mixHash, powHash } +// VerifySeal returns the PowHash and the verifySeal output +func (progpow *Progpow) VerifySeal(header *types.Header) (common.Hash, error) { + return progpow.verifySeal(header) +} + // verifySeal checks whether a block satisfies the PoW difficulty requirements, // either using the usual progpow cache for it, or alternatively using a full DAG // to make remote mining fast. diff --git a/eth/fetcher/block_fetcher.go b/eth/fetcher/block_fetcher.go index adddd89496..976f859275 100644 --- a/eth/fetcher/block_fetcher.go +++ b/eth/fetcher/block_fetcher.go @@ -83,6 +83,9 @@ type bodyRequesterFn func([]common.Hash) error // headerVerifierFn is a callback type to verify a block's header for fast propagation. type headerVerifierFn func(header *types.Header) error +// verifySealFn is a callback type to verify seal of a block header and get the PowHash +type verifySealFn func(header *types.Header) (common.Hash, error) + // blockBroadcasterFn is a callback type for broadcasting a block to connected peers. type blockBroadcasterFn func(block *types.Block, propagate bool) @@ -95,6 +98,9 @@ type currentIntrinsicSFn func() *big.Int // currentSFn is a callback type to retrieve the current chain heads Entropy type currentSFn func() *big.Int +// currentDifficultyFn is a callback type to retrieve the current chain heads difficulty +type currentDifficultyFn func() *big.Int + // peerDropFn is a callback type for dropping a peer detected as malicious. type peerDropFn func(id string) @@ -185,10 +191,12 @@ type BlockFetcher struct { getBlock blockRetrievalFn // Retrieves a block from the local chain writeBlock blockWriteFn // Writes the block to the DB verifyHeader headerVerifierFn // Checks if a block's headers have a valid proof of work + verifySeal verifySealFn // Checks if blocks PoWHash meets the difficulty requirement broadcastBlock blockBroadcasterFn // Broadcasts a block to connected peers chainHeight chainHeightFn // Retrieves the current chain's height currentIntrinsicS currentIntrinsicSFn // Retrieves the current headers intrinsic logS currentS currentSFn // Retrieves the current heads logS + currentDifficulty currentDifficultyFn // Retrieves the current difficulty dropPeer peerDropFn // Drops a peer for misbehaving isBlockHashABadHash badHashCheckFn // Checks if the block hash exists in the bad hashes list @@ -201,7 +209,7 @@ type BlockFetcher struct { } // NewBlockFetcher creates a block fetcher to retrieve blocks based on hash announcements. -func NewBlockFetcher(getBlock blockRetrievalFn, writeBlock blockWriteFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, currentIntrinsicS currentIntrinsicSFn, currentS currentSFn, dropPeer peerDropFn, isBlockHashABadHash badHashCheckFn) *BlockFetcher { +func NewBlockFetcher(getBlock blockRetrievalFn, writeBlock blockWriteFn, verifyHeader headerVerifierFn, verifySeal verifySealFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, currentIntrinsicS currentIntrinsicSFn, currentS currentSFn, currentDifficulty currentDifficultyFn, dropPeer peerDropFn, isBlockHashABadHash badHashCheckFn) *BlockFetcher { return &BlockFetcher{ notify: make(chan *blockAnnounce), inject: make(chan *blockOrHeaderInject), @@ -219,9 +227,11 @@ func NewBlockFetcher(getBlock blockRetrievalFn, writeBlock blockWriteFn, verifyH getBlock: getBlock, writeBlock: writeBlock, verifyHeader: verifyHeader, + verifySeal: verifySeal, broadcastBlock: broadcastBlock, chainHeight: chainHeight, currentIntrinsicS: currentIntrinsicS, + currentDifficulty: currentDifficulty, currentS: currentS, dropPeer: dropPeer, isBlockHashABadHash: isBlockHashABadHash, @@ -705,6 +715,18 @@ func (f *BlockFetcher) enqueue(peer string, header *types.Header, block *types.B // the phase states accordingly. func (f *BlockFetcher) ImportBlocks(peer string, block *types.Block, relay bool) { hash := block.Hash() + nodeCtx := common.NodeLocation.Context() + + powhash, err := f.verifySeal(block.Header()) + if err != nil { + return + } + // Check if the Block is atleast half the current difficulty in Zone Context, + // this makes sure that the nodes don't listen to the forks with the PowHash + // with less than 50% of current difficulty + if nodeCtx == common.ZONE_CTX && new(big.Int).SetBytes(powhash.Bytes()).Cmp(new(big.Int).Div(f.currentDifficulty(), big.NewInt(2))) < 0 { + return + } currentIntrinsicS := f.currentIntrinsicS() maxAllowableEntropyDist := new(big.Int).Mul(currentIntrinsicS, big.NewInt(maxAllowableEntropyDist)) diff --git a/eth/handler.go b/eth/handler.go index 75012ed141..7b439b4cf9 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -168,6 +168,9 @@ func newHandler(config *handlerConfig) (*handler, error) { validator := func(header *types.Header) error { return h.core.Engine().VerifyHeader(h.core, header) } + verifySeal := func(header *types.Header) (common.Hash, error) { + return h.core.Engine().VerifySeal(header) + } heighter := func() uint64 { return h.core.CurrentHeader().NumberU64() } @@ -184,6 +187,9 @@ func newHandler(config *handlerConfig) (*handler, error) { // broadcast distance only, ParentEntropy should suffice return h.core.CurrentHeader().ParentEntropy() } + currentDifficulty := func() *big.Int { + return h.core.CurrentHeader().Difficulty() + } // writeBlock writes the block to the DB writeBlock := func(block *types.Block) { if nodeCtx == common.ZONE_CTX && block.NumberU64()-1 == h.core.CurrentHeader().NumberU64() && h.core.ProcessingState() { @@ -193,7 +199,7 @@ func newHandler(config *handlerConfig) (*handler, error) { } h.core.WriteBlock(block) } - h.blockFetcher = fetcher.NewBlockFetcher(h.core.GetBlockOrCandidateByHash, writeBlock, validator, h.BroadcastBlock, heighter, currentThresholdS, currentS, h.removePeer, h.core.IsBlockHashABadHash) + h.blockFetcher = fetcher.NewBlockFetcher(h.core.GetBlockOrCandidateByHash, writeBlock, validator, verifySeal, h.BroadcastBlock, heighter, currentThresholdS, currentS, currentDifficulty, h.removePeer, h.core.IsBlockHashABadHash) // Only initialize the Tx fetcher in zone if nodeCtx == common.ZONE_CTX && h.core.ProcessingState() {