From c0a00802972552aeac462908e3df4901054dab54 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 10 Dec 2024 17:25:30 +0200 Subject: [PATCH 01/12] adapt header checks --- cmd/node/factory/interface.go | 3 +- consensus/interface.go | 2 +- consensus/spos/interface.go | 2 +- consensus/spos/worker.go | 10 ++- .../disabled/disabledHeaderSigVerifier.go | 3 +- process/block/interceptedBlocks/common.go | 2 +- .../interceptedBlockHeader.go | 5 -- .../interceptedMetaBlockHeader.go | 5 -- process/headerCheck/errors.go | 6 ++ process/headerCheck/headerSignatureVerify.go | 85 ++++++++----------- .../headerCheck/headerSignatureVerify_test.go | 8 +- process/interface.go | 1 - .../consensus/headerSigVerifierStub.go | 4 +- 13 files changed, 61 insertions(+), 75 deletions(-) diff --git a/cmd/node/factory/interface.go b/cmd/node/factory/interface.go index 4e123d762d6..4e4aaeb2f5f 100644 --- a/cmd/node/factory/interface.go +++ b/cmd/node/factory/interface.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-go/p2p" ) @@ -15,7 +16,7 @@ type HeaderSigVerifierHandler interface { VerifyRandSeedAndLeaderSignature(header data.HeaderHandler) error VerifySignature(header data.HeaderHandler) error VerifySignatureForHash(header data.HeaderHandler, hash []byte, pubkeysBitmap []byte, signature []byte) error - VerifyPreviousBlockProof(header data.HeaderHandler) error + verifyProofIntegrity(proof data.HeaderProofHandler) error VerifyHeaderProof(headerProof data.HeaderProofHandler) error IsInterfaceNil() bool } diff --git a/consensus/interface.go b/consensus/interface.go index 89e217c3af7..4f336229f42 100644 --- a/consensus/interface.go +++ b/consensus/interface.go @@ -127,7 +127,7 @@ type HeaderSigVerifier interface { VerifyLeaderSignature(header data.HeaderHandler) error VerifySignature(header data.HeaderHandler) error VerifySignatureForHash(header data.HeaderHandler, hash []byte, pubkeysBitmap []byte, signature []byte) error - VerifyPreviousBlockProof(header data.HeaderHandler) error + verifyProofIntegrity(proof data.HeaderProofHandler) error VerifyHeaderProof(headerProof data.HeaderProofHandler) error IsInterfaceNil() bool } diff --git a/consensus/spos/interface.go b/consensus/spos/interface.go index c351cffad54..d85c94f2b7a 100644 --- a/consensus/spos/interface.go +++ b/consensus/spos/interface.go @@ -138,7 +138,7 @@ type HeaderSigVerifier interface { VerifyLeaderSignature(header data.HeaderHandler) error VerifySignature(header data.HeaderHandler) error VerifySignatureForHash(header data.HeaderHandler, hash []byte, pubkeysBitmap []byte, signature []byte) error - VerifyPreviousBlockProof(header data.HeaderHandler) error + VerifyHeaderWithProof(header data.HeaderHandler) error VerifyHeaderProof(headerProof data.HeaderProofHandler) error IsInterfaceNil() bool } diff --git a/consensus/spos/worker.go b/consensus/spos/worker.go index cdec8c35151..295c41bc4a7 100644 --- a/consensus/spos/worker.go +++ b/consensus/spos/worker.go @@ -525,10 +525,12 @@ func (wrk *Worker) doJobOnMessageWithHeader(cnsMsg *consensus.Message) error { err) } - err = wrk.headerSigVerifier.VerifyPreviousBlockProof(header) - if err != nil { - return fmt.Errorf("%w : verify previous block proof for received header from consensus topic failed", - err) + if wrk.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { + err = wrk.headerSigVerifier.VerifyHeaderWithProof(header) + if err != nil { + return fmt.Errorf("%w : verify previous block proof for received header from consensus topic failed", + err) + } } wrk.processReceivedHeaderMetric(cnsMsg) diff --git a/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go b/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go index e23d223c3b9..3967e75be03 100644 --- a/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go +++ b/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go @@ -2,6 +2,7 @@ package disabled import ( "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-go/process" ) @@ -41,7 +42,7 @@ func (h *headerSigVerifier) VerifySignatureForHash(_ data.HeaderHandler, _ []byt } // VerifyPreviousBlockProof returns nil as it is disabled -func (h *headerSigVerifier) VerifyPreviousBlockProof(_ data.HeaderHandler) error { +func (h *headerSigVerifier) verifyProofIntegrity(proof data.HeaderProofHandler) error { return nil } diff --git a/process/block/interceptedBlocks/common.go b/process/block/interceptedBlocks/common.go index cece10ee626..d514968c4e2 100644 --- a/process/block/interceptedBlocks/common.go +++ b/process/block/interceptedBlocks/common.go @@ -6,6 +6,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/sharding" @@ -70,7 +71,6 @@ func checkMiniblockArgument(arg *ArgInterceptedMiniblock) error { } func checkHeaderHandler(hdr data.HeaderHandler, enableEpochsHandler common.EnableEpochsHandler) error { - // TODO[cleanup cns finality]: remove these checks if len(hdr.GetPubKeysBitmap()) == 0 && !enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, hdr.GetEpoch()) { return process.ErrNilPubKeysBitmap } diff --git a/process/block/interceptedBlocks/interceptedBlockHeader.go b/process/block/interceptedBlocks/interceptedBlockHeader.go index 9c009b8bb3f..cde4be46170 100644 --- a/process/block/interceptedBlocks/interceptedBlockHeader.go +++ b/process/block/interceptedBlocks/interceptedBlockHeader.go @@ -78,11 +78,6 @@ func (inHdr *InterceptedHeader) CheckValidity() error { return err } - err = inHdr.sigVerifier.VerifyPreviousBlockProof(inHdr.hdr) - if err != nil { - return err - } - return inHdr.verifySignatures() } diff --git a/process/block/interceptedBlocks/interceptedMetaBlockHeader.go b/process/block/interceptedBlocks/interceptedMetaBlockHeader.go index 52edea546a0..c3f92781e7e 100644 --- a/process/block/interceptedBlocks/interceptedMetaBlockHeader.go +++ b/process/block/interceptedBlocks/interceptedMetaBlockHeader.go @@ -124,11 +124,6 @@ func (imh *InterceptedMetaHeader) CheckValidity() error { return err } - err = imh.sigVerifier.VerifyPreviousBlockProof(imh.hdr) - if err != nil { - return err - } - return imh.integrityVerifier.Verify(imh.hdr) } diff --git a/process/headerCheck/errors.go b/process/headerCheck/errors.go index e0d4123ae2b..b808de98518 100644 --- a/process/headerCheck/errors.go +++ b/process/headerCheck/errors.go @@ -23,3 +23,9 @@ var ErrIndexOutOfBounds = errors.New("index is out of bounds") // ErrIndexNotSelected signals that the given index is not selected var ErrIndexNotSelected = errors.New("index is not selected") + +// ErrProofShardMismatch signals that the proof shard does not match the header shard +var ErrProofShardMismatch = errors.New("proof shard mismatch") + +// ErrProofHeaderHashMismatch signals that the proof header hash does not match the header hash +var ErrProofHeaderHashMismatch = errors.New("proof header hash mismatch") diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index 94471949ba0..d1f87672fec 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -1,6 +1,7 @@ package headerCheck import ( + "bytes" "fmt" "math/bits" @@ -175,8 +176,11 @@ func getPubKeySigners(consensusPubKeys []string, pubKeysBitmap []byte) [][]byte } // VerifySignature will check if signature is correct -// TODO: Adapt header signature verification for the changes related to equivalent proofs func (hsv *HeaderSigVerifier) VerifySignature(header data.HeaderHandler) error { + if hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { + return hsv.VerifyHeaderWithProof(header) + } + headerCopy, err := hsv.copyHeaderWithoutSig(header) if err != nil { return err @@ -189,14 +193,20 @@ func (hsv *HeaderSigVerifier) VerifySignature(header data.HeaderHandler) error { bitmap := header.GetPubKeysBitmap() sig := header.GetSignature() - if hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, headerCopy.GetEpoch()) { - headerCopy, hash, sig, bitmap, err = hsv.getPrevHeaderInfo(headerCopy) - if err != nil { - return err - } + return hsv.VerifySignatureForHash(headerCopy, hash, bitmap, sig) +} + +func verifyPrevProofForHeader(header data.HeaderHandler) error { + prevProof := header.GetPreviousProof() + if header.GetShardID() != prevProof.GetHeaderShardId() { + return ErrProofShardMismatch } - return hsv.VerifySignatureForHash(headerCopy, hash, bitmap, sig) + if !bytes.Equal(header.GetPrevHash(), prevProof.GetHeaderHash()) { + return ErrProofHeaderHashMismatch + } + + return nil } // VerifySignatureForHash will check if signature is correct for the provided hash @@ -214,12 +224,26 @@ func (hsv *HeaderSigVerifier) VerifySignatureForHash(header data.HeaderHandler, return multiSigVerifier.VerifyAggregatedSig(pubKeysSigners, hash, signature) } +func (hsv *HeaderSigVerifier) VerifyHeaderWithProof(header data.HeaderHandler) error { + err := verifyPrevProofForHeader(header) + if err != nil { + return err + } + + prevProof := header.GetPreviousProof() + return hsv.VerifyHeaderProof(prevProof) +} + // VerifyHeaderProof checks if the proof is correct for the header func (hsv *HeaderSigVerifier) VerifyHeaderProof(proofHandler data.HeaderProofHandler) error { if check.IfNilReflect(proofHandler) { return process.ErrNilHeaderProof } + err := hsv.verifyProofIntegrity(proofHandler) + if err != nil { + return err + } if !hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.FixedOrderInConsensusFlag, proofHandler.GetHeaderEpoch()) { return fmt.Errorf("%w for %s", process.ErrFlagNotActive, common.FixedOrderInConsensusFlag) } @@ -239,59 +263,22 @@ func (hsv *HeaderSigVerifier) VerifyHeaderProof(proofHandler data.HeaderProofHan return multiSigVerifier.VerifyAggregatedSig(pubKeysSigners, proofHandler.GetHeaderHash(), proofHandler.GetAggregatedSignature()) } -func (hsv *HeaderSigVerifier) getPrevHeaderInfo(currentHeader data.HeaderHandler) (data.HeaderHandler, []byte, []byte, []byte, error) { - previousProof := currentHeader.GetPreviousProof() - - var sig, bitmap []byte - if previousProof != nil { - sig, bitmap = previousProof.GetAggregatedSignature(), previousProof.GetPubKeysBitmap() - } - - hash := currentHeader.GetPrevHash() - prevHeader, err := hsv.headersPool.GetHeaderByHash(hash) - if err != nil { - return nil, nil, nil, nil, err - } - - headerCopy, err := hsv.copyHeaderWithoutSig(prevHeader) - if err != nil { - return nil, nil, nil, nil, err - } - - hash, err = core.CalculateHash(hsv.marshalizer, hsv.hasher, headerCopy) - if err != nil { - return nil, nil, nil, nil, err - } - - return headerCopy, hash, sig, bitmap, nil -} - // VerifyPreviousBlockProof verifies if the structure of the header matches the expected structure in regards with the consensus flag -func (hsv *HeaderSigVerifier) VerifyPreviousBlockProof(header data.HeaderHandler) error { - previousProof := header.GetPreviousProof() - +func (hsv *HeaderSigVerifier) verifyProofIntegrity(proof data.HeaderProofHandler) error { hasProof := false - hasLeaderSignature := false - - if previousProof != nil { - previousAggregatedSignature, previousBitmap := previousProof.GetAggregatedSignature(), previousProof.GetPubKeysBitmap() - hasProof = len(previousAggregatedSignature) > 0 && len(previousBitmap) > 0 - if len(previousBitmap) > 0 { - hasLeaderSignature = previousBitmap[0]&1 != 0 - } + if proof != nil { + aggregatedSignature, proofBitmap := proof.GetAggregatedSignature(), proof.GetPubKeysBitmap() + hasProof = len(aggregatedSignature) > 0 && len(proofBitmap) > 0 } - isFlagEnabled := hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) + isFlagEnabled := hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, proof.GetHeaderEpoch()) if isFlagEnabled && !hasProof { return fmt.Errorf("%w, received header without proof after flag activation", process.ErrInvalidHeader) } if !isFlagEnabled && hasProof { return fmt.Errorf("%w, received header with proof before flag activation", process.ErrInvalidHeader) } - if isFlagEnabled && !hasLeaderSignature { - return fmt.Errorf("%w, received header without leader signature after flag activation", process.ErrInvalidHeader) - } return nil } diff --git a/process/headerCheck/headerSignatureVerify_test.go b/process/headerCheck/headerSignatureVerify_test.go index dd361ca8f7c..68e14fe0ff1 100644 --- a/process/headerCheck/headerSignatureVerify_test.go +++ b/process/headerCheck/headerSignatureVerify_test.go @@ -668,7 +668,7 @@ func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { return nil }, } - err := hdrSigVerifier.VerifyPreviousBlockProof(hdr) + err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) assert.True(t, errors.Is(err, process.ErrInvalidHeader)) assert.True(t, strings.Contains(err.Error(), "received header without proof after flag activation")) }) @@ -688,7 +688,7 @@ func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { } }, } - err := hdrSigVerifier.VerifyPreviousBlockProof(hdr) + err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) assert.True(t, errors.Is(err, process.ErrInvalidHeader)) assert.True(t, strings.Contains(err.Error(), "received header with proof before flag activation")) }) @@ -712,7 +712,7 @@ func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { } }, } - err := hdrSigVerifier.VerifyPreviousBlockProof(hdr) + err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) assert.True(t, errors.Is(err, process.ErrInvalidHeader)) assert.True(t, strings.Contains(err.Error(), "received header without leader signature after flag activation")) }) @@ -736,7 +736,7 @@ func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { } }, } - err := hdrSigVerifier.VerifyPreviousBlockProof(hdr) + err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) assert.Nil(t, err) }) } diff --git a/process/interface.go b/process/interface.go index 6a410980c35..dcda64a20fc 100644 --- a/process/interface.go +++ b/process/interface.go @@ -850,7 +850,6 @@ type InterceptedHeaderSigVerifier interface { VerifyLeaderSignature(header data.HeaderHandler) error VerifySignature(header data.HeaderHandler) error VerifySignatureForHash(header data.HeaderHandler, hash []byte, pubkeysBitmap []byte, signature []byte) error - VerifyPreviousBlockProof(header data.HeaderHandler) error VerifyHeaderProof(headerProof data.HeaderProofHandler) error IsInterfaceNil() bool } diff --git a/testscommon/consensus/headerSigVerifierStub.go b/testscommon/consensus/headerSigVerifierStub.go index 9517d871a6a..aee6239d6b2 100644 --- a/testscommon/consensus/headerSigVerifierStub.go +++ b/testscommon/consensus/headerSigVerifierStub.go @@ -59,9 +59,9 @@ func (mock *HeaderSigVerifierMock) VerifySignatureForHash(header data.HeaderHand } // VerifyPreviousBlockProof - -func (mock *HeaderSigVerifierMock) VerifyPreviousBlockProof(header data.HeaderHandler) error { +func (mock *HeaderSigVerifierMock) verifyProofIntegrity(proof data.HeaderProofHandler) error { if mock.VerifyPreviousBlockProofCalled != nil { - return mock.VerifyPreviousBlockProofCalled(header) + return mock.VerifyPreviousBlockProofCalled(proof) } return nil From eea9c9bec4cac899d4cf3d8c1970e38cbfca8ee7 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 10 Dec 2024 17:27:36 +0200 Subject: [PATCH 02/12] fix stub --- testscommon/consensus/headerSigVerifierStub.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testscommon/consensus/headerSigVerifierStub.go b/testscommon/consensus/headerSigVerifierStub.go index aee6239d6b2..34d7d57a0a6 100644 --- a/testscommon/consensus/headerSigVerifierStub.go +++ b/testscommon/consensus/headerSigVerifierStub.go @@ -9,7 +9,7 @@ type HeaderSigVerifierMock struct { VerifyRandSeedCalled func(header data.HeaderHandler) error VerifyLeaderSignatureCalled func(header data.HeaderHandler) error VerifySignatureForHashCalled func(header data.HeaderHandler, hash []byte, pubkeysBitmap []byte, signature []byte) error - VerifyPreviousBlockProofCalled func(header data.HeaderHandler) error + VerifyPreviousBlockProofCalled func(proof data.HeaderProofHandler) error VerifyHeaderProofCalled func(proofHandler data.HeaderProofHandler) error } @@ -59,7 +59,7 @@ func (mock *HeaderSigVerifierMock) VerifySignatureForHash(header data.HeaderHand } // VerifyPreviousBlockProof - -func (mock *HeaderSigVerifierMock) verifyProofIntegrity(proof data.HeaderProofHandler) error { +func (mock *HeaderSigVerifierMock) VerifyPreviousBlockProof(proof data.HeaderProofHandler) error { if mock.VerifyPreviousBlockProofCalled != nil { return mock.VerifyPreviousBlockProofCalled(proof) } From 77c0cf70119d19efcfac5fce60bece821531363c Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 10 Dec 2024 18:08:08 +0200 Subject: [PATCH 03/12] fixes tests and mocks --- consensus/interface.go | 1 - .../bootstrap/disabled/disabledHeaderSigVerifier.go | 5 +++++ process/headerCheck/headerSignatureVerify.go | 1 + process/interface.go | 1 + testscommon/consensus/headerSigVerifierStub.go | 10 +++++----- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/consensus/interface.go b/consensus/interface.go index 4f336229f42..23f989c72c5 100644 --- a/consensus/interface.go +++ b/consensus/interface.go @@ -127,7 +127,6 @@ type HeaderSigVerifier interface { VerifyLeaderSignature(header data.HeaderHandler) error VerifySignature(header data.HeaderHandler) error VerifySignatureForHash(header data.HeaderHandler, hash []byte, pubkeysBitmap []byte, signature []byte) error - verifyProofIntegrity(proof data.HeaderProofHandler) error VerifyHeaderProof(headerProof data.HeaderProofHandler) error IsInterfaceNil() bool } diff --git a/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go b/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go index 3967e75be03..051c927b811 100644 --- a/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go +++ b/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go @@ -46,6 +46,11 @@ func (h *headerSigVerifier) verifyProofIntegrity(proof data.HeaderProofHandler) return nil } +// VerifyHeaderWithProof returns nil as it is disabled +func (h *headerSigVerifier) VerifyHeaderWithProof(header data.HeaderHandler) error { + return nil +} + // VerifyHeaderProof returns nil as it is disabled func (h *headerSigVerifier) VerifyHeaderProof(_ data.HeaderProofHandler) error { return nil diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index d1f87672fec..e21559f5642 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -224,6 +224,7 @@ func (hsv *HeaderSigVerifier) VerifySignatureForHash(header data.HeaderHandler, return multiSigVerifier.VerifyAggregatedSig(pubKeysSigners, hash, signature) } +// VerifyHeaderWithProof checks if the proof on the header is correct func (hsv *HeaderSigVerifier) VerifyHeaderWithProof(header data.HeaderHandler) error { err := verifyPrevProofForHeader(header) if err != nil { diff --git a/process/interface.go b/process/interface.go index dcda64a20fc..20e19cbb37e 100644 --- a/process/interface.go +++ b/process/interface.go @@ -851,6 +851,7 @@ type InterceptedHeaderSigVerifier interface { VerifySignature(header data.HeaderHandler) error VerifySignatureForHash(header data.HeaderHandler, hash []byte, pubkeysBitmap []byte, signature []byte) error VerifyHeaderProof(headerProof data.HeaderProofHandler) error + VerifyHeaderWithProof(header data.HeaderHandler) error IsInterfaceNil() bool } diff --git a/testscommon/consensus/headerSigVerifierStub.go b/testscommon/consensus/headerSigVerifierStub.go index 34d7d57a0a6..d6f1004e9fd 100644 --- a/testscommon/consensus/headerSigVerifierStub.go +++ b/testscommon/consensus/headerSigVerifierStub.go @@ -9,7 +9,7 @@ type HeaderSigVerifierMock struct { VerifyRandSeedCalled func(header data.HeaderHandler) error VerifyLeaderSignatureCalled func(header data.HeaderHandler) error VerifySignatureForHashCalled func(header data.HeaderHandler, hash []byte, pubkeysBitmap []byte, signature []byte) error - VerifyPreviousBlockProofCalled func(proof data.HeaderProofHandler) error + VerifyHeaderWithProofCalled func(header data.HeaderHandler) error VerifyHeaderProofCalled func(proofHandler data.HeaderProofHandler) error } @@ -58,10 +58,10 @@ func (mock *HeaderSigVerifierMock) VerifySignatureForHash(header data.HeaderHand return nil } -// VerifyPreviousBlockProof - -func (mock *HeaderSigVerifierMock) VerifyPreviousBlockProof(proof data.HeaderProofHandler) error { - if mock.VerifyPreviousBlockProofCalled != nil { - return mock.VerifyPreviousBlockProofCalled(proof) +// VerifyHeaderWithProof - +func (mock *HeaderSigVerifierMock) VerifyHeaderWithProof(header data.HeaderHandler) error { + if mock.VerifyHeaderWithProofCalled != nil { + return mock.VerifyHeaderWithProofCalled(header) } return nil From a8e7a8efe41fafc68c5e63edcfc493312d9d2d8b Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 11 Dec 2024 10:51:00 +0200 Subject: [PATCH 04/12] fixes proof checks in consensus message --- cmd/node/factory/interface.go | 1 - consensus/spos/errors.go | 6 ++--- consensus/spos/worker.go | 25 ++++++++++++++----- .../disabled/disabledHeaderSigVerifier.go | 7 +----- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/cmd/node/factory/interface.go b/cmd/node/factory/interface.go index 4e4aaeb2f5f..8f90ce3ee89 100644 --- a/cmd/node/factory/interface.go +++ b/cmd/node/factory/interface.go @@ -16,7 +16,6 @@ type HeaderSigVerifierHandler interface { VerifyRandSeedAndLeaderSignature(header data.HeaderHandler) error VerifySignature(header data.HeaderHandler) error VerifySignatureForHash(header data.HeaderHandler, hash []byte, pubkeysBitmap []byte, signature []byte) error - verifyProofIntegrity(proof data.HeaderProofHandler) error VerifyHeaderProof(headerProof data.HeaderProofHandler) error IsInterfaceNil() bool } diff --git a/consensus/spos/errors.go b/consensus/spos/errors.go index abb3c9fb40b..5905e1d8a13 100644 --- a/consensus/spos/errors.go +++ b/consensus/spos/errors.go @@ -253,9 +253,6 @@ var ErrEquivalentMessageAlreadyReceived = errors.New("equivalent message already // ErrNilEnableEpochsHandler signals that a nil enable epochs handler has been provided var ErrNilEnableEpochsHandler = errors.New("nil enable epochs handler") -// ErrMissingProposerSignature signals that proposer signature is missing -var ErrMissingProposerSignature = errors.New("missing proposer signature") - // ErrNilThrottler signals that a nil throttler has been provided var ErrNilThrottler = errors.New("nil throttler") @@ -267,3 +264,6 @@ var ErrNilEquivalentProofPool = errors.New("nil equivalent proof pool") // ErrNilHeaderProof signals that a nil header proof has been provided var ErrNilHeaderProof = errors.New("nil header proof") + +// ErrHeaderProofNotExpected signals that a header proof was not expected +var ErrHeaderProofNotExpected = errors.New("header proof not expected") diff --git a/consensus/spos/worker.go b/consensus/spos/worker.go index 295c41bc4a7..1ddb7795b30 100644 --- a/consensus/spos/worker.go +++ b/consensus/spos/worker.go @@ -525,12 +525,9 @@ func (wrk *Worker) doJobOnMessageWithHeader(cnsMsg *consensus.Message) error { err) } - if wrk.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { - err = wrk.headerSigVerifier.VerifyHeaderWithProof(header) - if err != nil { - return fmt.Errorf("%w : verify previous block proof for received header from consensus topic failed", - err) - } + err = wrk.checkHeaderPreviousProof(header) + if err != nil { + return err } wrk.processReceivedHeaderMetric(cnsMsg) @@ -546,6 +543,22 @@ func (wrk *Worker) doJobOnMessageWithHeader(cnsMsg *consensus.Message) error { return nil } +func (wrk *Worker) checkHeaderPreviousProof(header data.HeaderHandler) error { + if wrk.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { + err := wrk.headerSigVerifier.VerifyHeaderWithProof(header) + if err != nil { + return fmt.Errorf("%w : verify previous block proof for received header from consensus topic failed", + err) + } + } else { + if header.GetPreviousProof() != nil { + return fmt.Errorf("%w : received header from consensus topic has previous proof", ErrHeaderProofNotExpected) + } + } + + return nil +} + func (wrk *Worker) verifyHeaderHash(hash []byte, marshalledHeader []byte) bool { computedHash := wrk.hasher.Compute(string(marshalledHeader)) return bytes.Equal(hash, computedHash) diff --git a/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go b/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go index 051c927b811..e4c4bb14a25 100644 --- a/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go +++ b/epochStart/bootstrap/disabled/disabledHeaderSigVerifier.go @@ -41,13 +41,8 @@ func (h *headerSigVerifier) VerifySignatureForHash(_ data.HeaderHandler, _ []byt return nil } -// VerifyPreviousBlockProof returns nil as it is disabled -func (h *headerSigVerifier) verifyProofIntegrity(proof data.HeaderProofHandler) error { - return nil -} - // VerifyHeaderWithProof returns nil as it is disabled -func (h *headerSigVerifier) VerifyHeaderWithProof(header data.HeaderHandler) error { +func (h *headerSigVerifier) VerifyHeaderWithProof(_ data.HeaderHandler) error { return nil } From 93f1a71f3de841c177a86be1076295ae03843fb4 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 11 Dec 2024 17:54:27 +0200 Subject: [PATCH 05/12] fixes proofs nil checks --- consensus/broadcast/delayedBroadcast.go | 3 +- consensus/spos/errors.go | 3 ++ consensus/spos/worker.go | 14 +++----- .../dataPool/proofsCache/proofsPool.go | 3 +- .../consensus/consensusSigning_test.go | 8 +++-- process/block/baseProcess.go | 2 +- process/headerCheck/headerSignatureVerify.go | 13 +++++--- .../headerCheck/headerSignatureVerify_test.go | 32 ++++++++----------- process/peer/process.go | 2 +- 9 files changed, 41 insertions(+), 39 deletions(-) diff --git a/consensus/broadcast/delayedBroadcast.go b/consensus/broadcast/delayedBroadcast.go index f56e65694c7..a1c94cf33d7 100644 --- a/consensus/broadcast/delayedBroadcast.go +++ b/consensus/broadcast/delayedBroadcast.go @@ -699,9 +699,8 @@ func (dbb *delayedBlockBroadcaster) interceptedHeader(_ string, headerHash []byt // TODO: should be handled from interceptor proof := headerHandler.GetPreviousProof() - var aggSig, bitmap []byte - if proof != nil { + if !check.IfNilReflect(proof) { aggSig, bitmap = proof.GetAggregatedSignature(), proof.GetPubKeysBitmap() } diff --git a/consensus/spos/errors.go b/consensus/spos/errors.go index 5905e1d8a13..62f9c23ad17 100644 --- a/consensus/spos/errors.go +++ b/consensus/spos/errors.go @@ -267,3 +267,6 @@ var ErrNilHeaderProof = errors.New("nil header proof") // ErrHeaderProofNotExpected signals that a header proof was not expected var ErrHeaderProofNotExpected = errors.New("header proof not expected") + +// ErrConsensusMessageNotExpected signals that a consensus message was not expected +var ErrConsensusMessageNotExpected = errors.New("consensus message not expected") diff --git a/consensus/spos/worker.go b/consensus/spos/worker.go index 1ddb7795b30..62f31dfc8ab 100644 --- a/consensus/spos/worker.go +++ b/consensus/spos/worker.go @@ -545,15 +545,11 @@ func (wrk *Worker) doJobOnMessageWithHeader(cnsMsg *consensus.Message) error { func (wrk *Worker) checkHeaderPreviousProof(header data.HeaderHandler) error { if wrk.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { - err := wrk.headerSigVerifier.VerifyHeaderWithProof(header) - if err != nil { - return fmt.Errorf("%w : verify previous block proof for received header from consensus topic failed", - err) - } - } else { - if header.GetPreviousProof() != nil { - return fmt.Errorf("%w : received header from consensus topic has previous proof", ErrHeaderProofNotExpected) - } + return fmt.Errorf("%w : received header on consensus topic after equivalent messages activation", ErrConsensusMessageNotExpected) + } + + if !check.IfNilReflect(header.GetPreviousProof()) { + return fmt.Errorf("%w : received header from consensus topic has previous proof", ErrHeaderProofNotExpected) } return nil diff --git a/dataRetriever/dataPool/proofsCache/proofsPool.go b/dataRetriever/dataPool/proofsCache/proofsPool.go index b0de8e005cd..1662f6c5cdc 100644 --- a/dataRetriever/dataPool/proofsCache/proofsPool.go +++ b/dataRetriever/dataPool/proofsCache/proofsPool.go @@ -4,6 +4,7 @@ import ( "fmt" "sync" + "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" logger "github.com/multiversx/mx-chain-logger-go" ) @@ -26,7 +27,7 @@ func NewProofsPool() *proofsPool { func (pp *proofsPool) AddProof( headerProof data.HeaderProofHandler, ) error { - if headerProof == nil { + if check.IfNilReflect(headerProof) { return ErrNilProof } diff --git a/integrationTests/consensus/consensusSigning_test.go b/integrationTests/consensus/consensusSigning_test.go index ec3fc12292f..c2d6f6ded60 100644 --- a/integrationTests/consensus/consensusSigning_test.go +++ b/integrationTests/consensus/consensusSigning_test.go @@ -8,8 +8,10 @@ import ( "testing" "time" - "github.com/multiversx/mx-chain-go/integrationTests" + logger "github.com/multiversx/mx-chain-logger-go" "github.com/stretchr/testify/assert" + + "github.com/multiversx/mx-chain-go/integrationTests" ) func initNodesWithTestSigner( @@ -69,6 +71,8 @@ func TestConsensusWithInvalidSigners(t *testing.T) { t.Skip("this is not a short test") } + _ = logger.SetLogLevel("*:DEBUG") + numMetaNodes := uint32(4) numNodes := uint32(4) consensusSize := uint32(4) @@ -103,7 +107,7 @@ func TestConsensusWithInvalidSigners(t *testing.T) { go checkBlockProposedEveryRound(numCommBlock, nonceForRoundMap, mutex, chDone, t) extraTime := uint64(2) - endTime := time.Duration(roundTime)*time.Duration(numCommBlock+extraTime)*time.Millisecond + time.Minute + endTime := time.Duration(roundTime)*time.Duration(numCommBlock+extraTime)*time.Millisecond + 10*time.Minute select { case <-chDone: case <-time.After(endTime): diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index 53cfa96e997..4f2a3661ece 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -364,7 +364,7 @@ func displayHeader(headerHandler data.HeaderHandler) []*display.LineData { proof := headerHandler.GetPreviousProof() var prevAggregatedSig, prevBitmap []byte - if proof != nil { + if !check.IfNilReflect(proof) { prevAggregatedSig, prevBitmap = proof.GetAggregatedSignature(), proof.GetPubKeysBitmap() } diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index e21559f5642..e1b0a70c4df 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -198,6 +198,10 @@ func (hsv *HeaderSigVerifier) VerifySignature(header data.HeaderHandler) error { func verifyPrevProofForHeader(header data.HeaderHandler) error { prevProof := header.GetPreviousProof() + if check.IfNilReflect(prevProof) { + return process.ErrNilHeaderProof + } + if header.GetShardID() != prevProof.GetHeaderShardId() { return ErrProofShardMismatch } @@ -237,10 +241,6 @@ func (hsv *HeaderSigVerifier) VerifyHeaderWithProof(header data.HeaderHandler) e // VerifyHeaderProof checks if the proof is correct for the header func (hsv *HeaderSigVerifier) VerifyHeaderProof(proofHandler data.HeaderProofHandler) error { - if check.IfNilReflect(proofHandler) { - return process.ErrNilHeaderProof - } - err := hsv.verifyProofIntegrity(proofHandler) if err != nil { return err @@ -266,8 +266,11 @@ func (hsv *HeaderSigVerifier) VerifyHeaderProof(proofHandler data.HeaderProofHan // VerifyPreviousBlockProof verifies if the structure of the header matches the expected structure in regards with the consensus flag func (hsv *HeaderSigVerifier) verifyProofIntegrity(proof data.HeaderProofHandler) error { - hasProof := false + if check.IfNilReflect(proof) { + return process.ErrNilHeaderProof + } + hasProof := false if proof != nil { aggregatedSignature, proofBitmap := proof.GetAggregatedSignature(), proof.GetPubKeysBitmap() hasProof = len(aggregatedSignature) > 0 && len(proofBitmap) > 0 diff --git a/process/headerCheck/headerSignatureVerify_test.go b/process/headerCheck/headerSignatureVerify_test.go index 68e14fe0ff1..e8b85fbdb3f 100644 --- a/process/headerCheck/headerSignatureVerify_test.go +++ b/process/headerCheck/headerSignatureVerify_test.go @@ -651,7 +651,7 @@ func TestHeaderSigVerifier_VerifySignatureOkWhenFallbackThresholdCouldBeApplied( func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { t.Parallel() - t.Run("flag enabled and no proof should error", func(t *testing.T) { + t.Run("flag enabled and nil proof should error", func(t *testing.T) { t.Parallel() args := createHeaderSigVerifierArgs() @@ -669,38 +669,34 @@ func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { }, } err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) - assert.True(t, errors.Is(err, process.ErrInvalidHeader)) - assert.True(t, strings.Contains(err.Error(), "received header without proof after flag activation")) + assert.True(t, errors.Is(err, process.ErrNilHeaderProof)) }) - t.Run("flag not enabled and proof should error", func(t *testing.T) { + t.Run("flag enabled and empty proof should error", func(t *testing.T) { t.Parallel() args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.EquivalentMessagesFlag + }, + } hdrSigVerifier, _ := NewHeaderSigVerifier(args) hdr := &testscommon.HeaderHandlerStub{ GetPreviousProofCalled: func() data.HeaderProofHandler { - return &block.HeaderProof{ - AggregatedSignature: []byte("sig"), - PubKeysBitmap: []byte("bitmap"), - } + return &dataBlock.HeaderProof{} }, } err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) assert.True(t, errors.Is(err, process.ErrInvalidHeader)) - assert.True(t, strings.Contains(err.Error(), "received header with proof before flag activation")) + assert.True(t, strings.Contains(err.Error(), "received header without proof after flag activation")) }) - t.Run("flag enabled and no leader signature should error", func(t *testing.T) { + t.Run("flag not enabled and proof should error", func(t *testing.T) { t.Parallel() args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ - IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.EquivalentMessagesFlag - }, - } + args.EnableEpochsHandler = enableEpochsHandlerMock.NewEnableEpochsHandlerStub() hdrSigVerifier, _ := NewHeaderSigVerifier(args) @@ -708,13 +704,13 @@ func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { GetPreviousProofCalled: func() data.HeaderProofHandler { return &block.HeaderProof{ AggregatedSignature: []byte("sig"), - PubKeysBitmap: []byte{0, 1, 1, 1}, + PubKeysBitmap: []byte("bitmap"), } }, } err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) assert.True(t, errors.Is(err, process.ErrInvalidHeader)) - assert.True(t, strings.Contains(err.Error(), "received header without leader signature after flag activation")) + assert.True(t, strings.Contains(err.Error(), "received header with proof before flag activation")) }) t.Run("should work, flag enabled with proof", func(t *testing.T) { t.Parallel() diff --git a/process/peer/process.go b/process/peer/process.go index ccbd46dda83..97ea34fc21a 100644 --- a/process/peer/process.go +++ b/process/peer/process.go @@ -407,7 +407,7 @@ func (vs *validatorStatistics) UpdatePeerState(header data.MetaHeaderHandler, ca bitmap := previousHeader.GetPubKeysBitmap() if vs.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, previousHeader.GetEpoch()) { proof := previousHeader.GetPreviousProof() - if proof != nil { + if !check.IfNilReflect(proof) { bitmap = proof.GetPubKeysBitmap() } } From 1e09723f28de0e010f7dfcf450f0a4e065a02d79 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Thu, 12 Dec 2024 19:07:08 +0200 Subject: [PATCH 06/12] fixes proof verification - use correct consensus group --- consensus/interface.go | 1 + fallback/headerValidator.go | 27 +++-- process/block/interceptedBlocks/common.go | 35 +++++- process/errors.go | 3 + process/headerCheck/headerSignatureVerify.go | 105 ++++++++++-------- .../headerCheck/headerSignatureVerify_test.go | 91 --------------- process/interface.go | 1 + testscommon/fallbackHeaderValidatorStub.go | 11 +- 8 files changed, 125 insertions(+), 149 deletions(-) diff --git a/consensus/interface.go b/consensus/interface.go index 23f989c72c5..8dfc1018172 100644 --- a/consensus/interface.go +++ b/consensus/interface.go @@ -133,6 +133,7 @@ type HeaderSigVerifier interface { // FallbackHeaderValidator defines the behaviour of a component able to signal when a fallback header validation could be applied type FallbackHeaderValidator interface { + ShouldApplyFallbackValidationForHeaderWith(shardID uint32, startOfEpochBlock bool, round uint64, prevHeaderHash []byte) bool ShouldApplyFallbackValidation(headerHandler data.HeaderHandler) bool IsInterfaceNil() bool } diff --git a/fallback/headerValidator.go b/fallback/headerValidator.go index 8e2d0eda037..4b9110582b0 100644 --- a/fallback/headerValidator.go +++ b/fallback/headerValidator.go @@ -5,10 +5,11 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/process" - "github.com/multiversx/mx-chain-logger-go" ) var log = logger.GetOrCreate("fallback") @@ -45,28 +46,34 @@ func NewFallbackHeaderValidator( return hv, nil } -// ShouldApplyFallbackValidation returns if for the given header could be applied fallback validation or not -func (fhv *fallbackHeaderValidator) ShouldApplyFallbackValidation(headerHandler data.HeaderHandler) bool { - if check.IfNil(headerHandler) { - return false - } - if headerHandler.GetShardID() != core.MetachainShardId { +// ShouldApplyFallbackValidationForHeaderWith returns if for the given header data fallback validation could be applied or not +func (fhv *fallbackHeaderValidator) ShouldApplyFallbackValidationForHeaderWith(shardID uint32, startOfEpochBlock bool, round uint64, prevHeaderHash []byte) bool { + if shardID != core.MetachainShardId { return false } - if !headerHandler.IsStartOfEpochBlock() { + if !startOfEpochBlock { return false } - previousHeader, err := process.GetMetaHeader(headerHandler.GetPrevHash(), fhv.headersPool, fhv.marshalizer, fhv.storageService) + previousHeader, err := process.GetMetaHeader(prevHeaderHash, fhv.headersPool, fhv.marshalizer, fhv.storageService) if err != nil { log.Debug("ShouldApplyFallbackValidation", "GetMetaHeader", err.Error()) return false } - isRoundTooOld := int64(headerHandler.GetRound())-int64(previousHeader.GetRound()) >= common.MaxRoundsWithoutCommittedStartInEpochBlock + isRoundTooOld := int64(round)-int64(previousHeader.GetRound()) >= common.MaxRoundsWithoutCommittedStartInEpochBlock return isRoundTooOld } +// ShouldApplyFallbackValidation returns if for the given header could be applied fallback validation or not +func (fhv *fallbackHeaderValidator) ShouldApplyFallbackValidation(headerHandler data.HeaderHandler) bool { + if check.IfNil(headerHandler) { + return false + } + + return fhv.ShouldApplyFallbackValidationForHeaderWith(headerHandler.GetShardID(), headerHandler.IsStartOfEpochBlock(), headerHandler.GetRound(), headerHandler.GetPrevHash()) +} + // IsInterfaceNil returns true if there is no value under the interface func (fhv *fallbackHeaderValidator) IsInterfaceNil() bool { return fhv == nil diff --git a/process/block/interceptedBlocks/common.go b/process/block/interceptedBlocks/common.go index d514968c4e2..90a604dba23 100644 --- a/process/block/interceptedBlocks/common.go +++ b/process/block/interceptedBlocks/common.go @@ -71,13 +71,15 @@ func checkMiniblockArgument(arg *ArgInterceptedMiniblock) error { } func checkHeaderHandler(hdr data.HeaderHandler, enableEpochsHandler common.EnableEpochsHandler) error { - if len(hdr.GetPubKeysBitmap()) == 0 && !enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, hdr.GetEpoch()) { + equivalentMessagesEnabled := enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, hdr.GetEpoch()) + + if len(hdr.GetPubKeysBitmap()) == 0 && !equivalentMessagesEnabled { return process.ErrNilPubKeysBitmap } if len(hdr.GetPrevHash()) == 0 { return process.ErrNilPreviousBlockHash } - if len(hdr.GetSignature()) == 0 && !enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, hdr.GetEpoch()) { + if len(hdr.GetSignature()) == 0 && !equivalentMessagesEnabled { return process.ErrNilSignature } if len(hdr.GetRootHash()) == 0 { @@ -90,16 +92,42 @@ func checkHeaderHandler(hdr data.HeaderHandler, enableEpochsHandler common.Enabl return process.ErrNilPrevRandSeed } + err := checkProofIntegrity(hdr, enableEpochsHandler) + if err != nil { + return err + } + return hdr.CheckFieldsForNil() } +func checkProofIntegrity(hdr data.HeaderHandler, enableEpochsHandler common.EnableEpochsHandler) error { + equivalentMessagesEnabled := enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, hdr.GetEpoch()) + + prevHeaderProof := hdr.GetPreviousProof() + nilPreviousProof := check.IfNilReflect(prevHeaderProof) + missingProof := nilPreviousProof && equivalentMessagesEnabled + unexpectedProof := !nilPreviousProof && !equivalentMessagesEnabled + hasProof := !nilPreviousProof && equivalentMessagesEnabled + + if missingProof { + return process.ErrMissingHeaderProof + } + if unexpectedProof { + return process.ErrUnexpectedHeaderProof + } + if hasProof && isIncompleteProof(prevHeaderProof) { + return process.ErrInvalidHeaderProof + } + + return nil +} + func checkMetaShardInfo( shardInfo []data.ShardDataHandler, coordinator sharding.Coordinator, headerSigVerifier process.InterceptedHeaderSigVerifier, ) error { wgProofsVerification := sync.WaitGroup{} - wgProofsVerification.Add(len(shardInfo)) errChan := make(chan error, len(shardInfo)) for _, sd := range shardInfo { if sd.GetShardID() >= coordinator.NumberOfShards() && sd.GetShardID() != core.MetachainShardId { @@ -111,6 +139,7 @@ func checkMetaShardInfo( return err } + wgProofsVerification.Add(1) checkProofAsync(sd.GetPreviousProof(), headerSigVerifier, &wgProofsVerification, errChan) } diff --git a/process/errors.go b/process/errors.go index da775c21ec1..ba66ec2ab93 100644 --- a/process/errors.go +++ b/process/errors.go @@ -1271,3 +1271,6 @@ var ErrMissingHeaderProof = errors.New("missing header proof") // ErrInvalidHeaderProof signals that an invalid equivalent proof has been provided var ErrInvalidHeaderProof = errors.New("invalid equivalent proof") + +// ErrUnexpectedHeaderProof signals that a header proof has been provided unexpectedly +var ErrUnexpectedHeaderProof = errors.New("unexpected header proof") diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index e1b0a70c4df..09ed8a3506c 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -2,7 +2,6 @@ package headerCheck import ( "bytes" - "fmt" "math/bits" "github.com/multiversx/mx-chain-core-go/core" @@ -126,35 +125,48 @@ func isIndexInBitmap(index uint16, bitmap []byte) error { return nil } -func (hsv *HeaderSigVerifier) getConsensusSigners(header data.HeaderHandler, pubKeysBitmap []byte) ([][]byte, error) { - randSeed := header.GetPrevRandSeed() +func (hsv *HeaderSigVerifier) getConsensusSigners( + randSeed []byte, + shardID uint32, + epoch uint32, + startOfEpochBlock bool, + round uint64, + prevHash []byte, + pubKeysBitmap []byte, +) ([][]byte, error) { if len(pubKeysBitmap) == 0 { return nil, process.ErrNilPubKeysBitmap } - if !hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { + if !hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, epoch) { if pubKeysBitmap[0]&1 == 0 { return nil, process.ErrBlockProposerSignatureMissing } } // TODO: remove if start of epochForConsensus block needs to be validated by the new epochForConsensus nodes - epochForConsensus := header.GetEpoch() - if header.IsStartOfEpochBlock() && epochForConsensus > 0 { + epochForConsensus := epoch + if startOfEpochBlock && epochForConsensus > 0 { epochForConsensus = epochForConsensus - 1 } _, consensusPubKeys, err := hsv.nodesCoordinator.GetConsensusValidatorsPublicKeys( randSeed, - header.GetRound(), - header.GetShardID(), + round, + shardID, epochForConsensus, ) if err != nil { return nil, err } - err = hsv.verifyConsensusSize(consensusPubKeys, header, pubKeysBitmap) + err = hsv.verifyConsensusSize( + consensusPubKeys, + pubKeysBitmap, + shardID, + startOfEpochBlock, + round, + prevHash) if err != nil { return nil, err } @@ -220,7 +232,16 @@ func (hsv *HeaderSigVerifier) VerifySignatureForHash(header data.HeaderHandler, return err } - pubKeysSigners, err := hsv.getConsensusSigners(header, pubkeysBitmap) + randSeed := header.GetPrevRandSeed() + pubKeysSigners, err := hsv.getConsensusSigners( + randSeed, + header.GetShardID(), + header.GetEpoch(), + header.IsStartOfEpochBlock(), + header.GetRound(), + header.GetPrevHash(), + pubkeysBitmap, + ) if err != nil { return err } @@ -241,15 +262,12 @@ func (hsv *HeaderSigVerifier) VerifyHeaderWithProof(header data.HeaderHandler) e // VerifyHeaderProof checks if the proof is correct for the header func (hsv *HeaderSigVerifier) VerifyHeaderProof(proofHandler data.HeaderProofHandler) error { - err := hsv.verifyProofIntegrity(proofHandler) - if err != nil { - return err - } - if !hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.FixedOrderInConsensusFlag, proofHandler.GetHeaderEpoch()) { - return fmt.Errorf("%w for %s", process.ErrFlagNotActive, common.FixedOrderInConsensusFlag) + if check.IfNilReflect(proofHandler) { + return process.ErrNilHeaderProof } - consensusPubKeys, err := hsv.nodesCoordinator.GetAllEligibleValidatorsPublicKeysForShard(proofHandler.GetHeaderEpoch(), proofHandler.GetHeaderShardId()) + // for the start of epoch block the consensus is taken from the previous epoch + header, err := hsv.headersPool.GetHeaderByHash(proofHandler.GetHeaderHash()) if err != nil { return err } @@ -259,35 +277,29 @@ func (hsv *HeaderSigVerifier) VerifyHeaderProof(proofHandler data.HeaderProofHan return err } - pubKeysSigners := getPubKeySigners(consensusPubKeys, proofHandler.GetPubKeysBitmap()) - - return multiSigVerifier.VerifyAggregatedSig(pubKeysSigners, proofHandler.GetHeaderHash(), proofHandler.GetAggregatedSignature()) -} - -// VerifyPreviousBlockProof verifies if the structure of the header matches the expected structure in regards with the consensus flag -func (hsv *HeaderSigVerifier) verifyProofIntegrity(proof data.HeaderProofHandler) error { - if check.IfNilReflect(proof) { - return process.ErrNilHeaderProof - } - - hasProof := false - if proof != nil { - aggregatedSignature, proofBitmap := proof.GetAggregatedSignature(), proof.GetPubKeysBitmap() - hasProof = len(aggregatedSignature) > 0 && len(proofBitmap) > 0 - } - - isFlagEnabled := hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, proof.GetHeaderEpoch()) - if isFlagEnabled && !hasProof { - return fmt.Errorf("%w, received header without proof after flag activation", process.ErrInvalidHeader) - } - if !isFlagEnabled && hasProof { - return fmt.Errorf("%w, received header with proof before flag activation", process.ErrInvalidHeader) - } + // round, prevHash and prevRandSeed could be removed when we remove fallback validation and we don't need backwards compatibility + // (e.g new binary from epoch x forward) + consensusPubKeys, err := hsv.getConsensusSigners( + header.GetPrevRandSeed(), + proofHandler.GetHeaderShardId(), + proofHandler.GetHeaderEpoch(), + header.IsStartOfEpochBlock(), + header.GetRound(), + header.GetPrevHash(), + proofHandler.GetPubKeysBitmap(), + ) - return nil + return multiSigVerifier.VerifyAggregatedSig(consensusPubKeys, proofHandler.GetHeaderHash(), proofHandler.GetAggregatedSignature()) } -func (hsv *HeaderSigVerifier) verifyConsensusSize(consensusPubKeys []string, header data.HeaderHandler, bitmap []byte) error { +func (hsv *HeaderSigVerifier) verifyConsensusSize( + consensusPubKeys []string, + bitmap []byte, + shardID uint32, + startOfEpochBlock bool, + round uint64, + prevHash []byte, +) error { consensusSize := len(consensusPubKeys) expectedBitmapSize := consensusSize / 8 @@ -307,7 +319,12 @@ func (hsv *HeaderSigVerifier) verifyConsensusSize(consensusPubKeys []string, hea } minNumRequiredSignatures := core.GetPBFTThreshold(consensusSize) - if hsv.fallbackHeaderValidator.ShouldApplyFallbackValidation(header) { + if hsv.fallbackHeaderValidator.ShouldApplyFallbackValidationForHeaderWith( + shardID, + startOfEpochBlock, + round, + prevHash, + ) { minNumRequiredSignatures = core.GetPBFTFallbackThreshold(consensusSize) log.Warn("HeaderSigVerifier.verifyConsensusSize: fallback validation has been applied", "minimum number of signatures required", minNumRequiredSignatures, diff --git a/process/headerCheck/headerSignatureVerify_test.go b/process/headerCheck/headerSignatureVerify_test.go index e8b85fbdb3f..c70eebbe94c 100644 --- a/process/headerCheck/headerSignatureVerify_test.go +++ b/process/headerCheck/headerSignatureVerify_test.go @@ -8,10 +8,8 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data" - "github.com/multiversx/mx-chain-core-go/data/block" dataBlock "github.com/multiversx/mx-chain-core-go/data/block" crypto "github.com/multiversx/mx-chain-crypto-go" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/multiversx/mx-chain-go/common" @@ -648,95 +646,6 @@ func TestHeaderSigVerifier_VerifySignatureOkWhenFallbackThresholdCouldBeApplied( require.True(t, wasCalled) } -func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { - t.Parallel() - - t.Run("flag enabled and nil proof should error", func(t *testing.T) { - t.Parallel() - - args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ - IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.EquivalentMessagesFlag - }, - } - - hdrSigVerifier, _ := NewHeaderSigVerifier(args) - - hdr := &testscommon.HeaderHandlerStub{ - GetPreviousProofCalled: func() data.HeaderProofHandler { - return nil - }, - } - err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) - assert.True(t, errors.Is(err, process.ErrNilHeaderProof)) - }) - t.Run("flag enabled and empty proof should error", func(t *testing.T) { - t.Parallel() - - args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ - IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.EquivalentMessagesFlag - }, - } - - hdrSigVerifier, _ := NewHeaderSigVerifier(args) - - hdr := &testscommon.HeaderHandlerStub{ - GetPreviousProofCalled: func() data.HeaderProofHandler { - return &dataBlock.HeaderProof{} - }, - } - err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) - assert.True(t, errors.Is(err, process.ErrInvalidHeader)) - assert.True(t, strings.Contains(err.Error(), "received header without proof after flag activation")) - }) - t.Run("flag not enabled and proof should error", func(t *testing.T) { - t.Parallel() - - args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = enableEpochsHandlerMock.NewEnableEpochsHandlerStub() - - hdrSigVerifier, _ := NewHeaderSigVerifier(args) - - hdr := &testscommon.HeaderHandlerStub{ - GetPreviousProofCalled: func() data.HeaderProofHandler { - return &block.HeaderProof{ - AggregatedSignature: []byte("sig"), - PubKeysBitmap: []byte("bitmap"), - } - }, - } - err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) - assert.True(t, errors.Is(err, process.ErrInvalidHeader)) - assert.True(t, strings.Contains(err.Error(), "received header with proof before flag activation")) - }) - t.Run("should work, flag enabled with proof", func(t *testing.T) { - t.Parallel() - - args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ - IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.EquivalentMessagesFlag - }, - } - - hdrSigVerifier, _ := NewHeaderSigVerifier(args) - - hdr := &testscommon.HeaderHandlerStub{ - GetPreviousProofCalled: func() data.HeaderProofHandler { - return &block.HeaderProof{ - AggregatedSignature: []byte("sig"), - PubKeysBitmap: []byte{1, 1, 1, 1}, - } - }, - } - err := hdrSigVerifier.verifyProofIntegrity(hdr.GetPreviousProof()) - assert.Nil(t, err) - }) -} - func TestHeaderSigVerifier_VerifyHeaderProof(t *testing.T) { t.Parallel() diff --git a/process/interface.go b/process/interface.go index 20e19cbb37e..d7cbe87825b 100644 --- a/process/interface.go +++ b/process/interface.go @@ -1204,6 +1204,7 @@ type PayableHandler interface { // FallbackHeaderValidator defines the behaviour of a component able to signal when a fallback header validation could be applied type FallbackHeaderValidator interface { + ShouldApplyFallbackValidationForHeaderWith(shardID uint32, startOfEpochBlock bool, round uint64, prevHeaderHash []byte) bool ShouldApplyFallbackValidation(headerHandler data.HeaderHandler) bool IsInterfaceNil() bool } diff --git a/testscommon/fallbackHeaderValidatorStub.go b/testscommon/fallbackHeaderValidatorStub.go index b769aa94976..2ba582c7118 100644 --- a/testscommon/fallbackHeaderValidatorStub.go +++ b/testscommon/fallbackHeaderValidatorStub.go @@ -6,7 +6,16 @@ import ( // FallBackHeaderValidatorStub - type FallBackHeaderValidatorStub struct { - ShouldApplyFallbackValidationCalled func(headerHandler data.HeaderHandler) bool + ShouldApplyFallbackValidationCalled func(headerHandler data.HeaderHandler) bool + ShouldApplyFallbackValidationForHeaderWithCalled func(shardID uint32, startOfEpochBlock bool, round uint64, prevHeaderHash []byte) bool +} + +// ShouldApplyFallbackValidationForHeaderWith - +func (fhvs *FallBackHeaderValidatorStub) ShouldApplyFallbackValidationForHeaderWith(shardID uint32, startOfEpochBlock bool, round uint64, prevHeaderHash []byte) bool { + if fhvs.ShouldApplyFallbackValidationForHeaderWithCalled != nil { + return fhvs.ShouldApplyFallbackValidationForHeaderWithCalled(shardID, startOfEpochBlock, round, prevHeaderHash) + } + return false } // ShouldApplyFallbackValidation - From 18bc9c09f654564df8e2e4c40f77a426bf3f544b Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Thu, 12 Dec 2024 19:13:35 +0200 Subject: [PATCH 07/12] fix linter --- process/headerCheck/headerSignatureVerify.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index 09ed8a3506c..e8f21de41ff 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -288,6 +288,9 @@ func (hsv *HeaderSigVerifier) VerifyHeaderProof(proofHandler data.HeaderProofHan header.GetPrevHash(), proofHandler.GetPubKeysBitmap(), ) + if err != nil { + return err + } return multiSigVerifier.VerifyAggregatedSig(consensusPubKeys, proofHandler.GetHeaderHash(), proofHandler.GetAggregatedSignature()) } From 8528bf2769b66499c4c730c0682f45cd767007de Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Fri, 13 Dec 2024 16:57:30 +0200 Subject: [PATCH 08/12] fixes unit tests --- .../interceptedBlockHeader_test.go | 10 ++-- process/headerCheck/common.go | 3 + process/headerCheck/headerSignatureVerify.go | 8 +++ .../headerCheck/headerSignatureVerify_test.go | 57 +++++++++++++++---- 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/process/block/interceptedBlocks/interceptedBlockHeader_test.go b/process/block/interceptedBlocks/interceptedBlockHeader_test.go index 462e040af50..bb58691cd38 100644 --- a/process/block/interceptedBlocks/interceptedBlockHeader_test.go +++ b/process/block/interceptedBlocks/interceptedBlockHeader_test.go @@ -90,7 +90,7 @@ func createMockShardHeader() *dataBlock.Header { } } -//------- TestNewInterceptedHeader +// ------- TestNewInterceptedHeader func TestNewInterceptedHeader_NilArgumentShouldErr(t *testing.T) { t.Parallel() @@ -174,7 +174,7 @@ func TestNewInterceptedHeader_MetachainForThisShardShouldWork(t *testing.T) { assert.True(t, inHdr.IsForCurrentShard()) } -//------- Verify +// ------- Verify func TestInterceptedHeader_CheckValidityNilPubKeyBitmapShouldErr(t *testing.T) { t.Parallel() @@ -236,6 +236,7 @@ func TestInterceptedHeader_CheckValidityLeaderSignatureOkShouldWork(t *testing.T func TestInterceptedHeader_CheckValidityLeaderSignatureOkWithFlagActiveShouldWork(t *testing.T) { t.Parallel() + headerHash := []byte("header hash") arg := createDefaultShardArgumentWithV2Support() arg.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { @@ -264,6 +265,7 @@ func TestInterceptedHeader_CheckValidityLeaderSignatureOkWithFlagActiveShouldWor PreviousHeaderProof: &block.HeaderProof{ PubKeysBitmap: providedPrevBitmap, AggregatedSignature: providedPrevSig, + HeaderHash: headerHash, }, } buff, _ := marshaller.Marshal(hdr) @@ -357,7 +359,7 @@ func TestInterceptedHeader_CheckAgainstFinalHeaderErrorsShouldErr(t *testing.T) assert.Equal(t, expectedErr, err) } -//------- getters +// ------- getters func TestInterceptedHeader_Getters(t *testing.T) { t.Parallel() @@ -370,7 +372,7 @@ func TestInterceptedHeader_Getters(t *testing.T) { assert.Equal(t, hash, inHdr.Hash()) } -//------- IsInterfaceNil +// ------- IsInterfaceNil func TestInterceptedHeader_IsInterfaceNil(t *testing.T) { t.Parallel() diff --git a/process/headerCheck/common.go b/process/headerCheck/common.go index edd365fa63b..353c112e501 100644 --- a/process/headerCheck/common.go +++ b/process/headerCheck/common.go @@ -18,6 +18,9 @@ func ComputeConsensusGroup(header data.HeaderHandler, nodesCoordinator nodesCoor } prevRandSeed := header.GetPrevRandSeed() + if prevRandSeed == nil { + return nil, nil, process.ErrNilPrevRandSeed + } // TODO: change here with an activation flag if start of epoch block needs to be validated by the new epoch nodes epoch := header.GetEpoch() diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index e8f21de41ff..a88bac03270 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -411,7 +411,15 @@ func (hsv *HeaderSigVerifier) IsInterfaceNil() bool { func (hsv *HeaderSigVerifier) verifyRandSeed(leaderPubKey crypto.PublicKey, header data.HeaderHandler) error { prevRandSeed := header.GetPrevRandSeed() + if prevRandSeed == nil { + return process.ErrNilPrevRandSeed + } + randSeed := header.GetRandSeed() + if randSeed == nil { + return process.ErrNilRandSeed + } + return hsv.singleSigVerifier.Verify(leaderPubKey, prevRandSeed, randSeed) } diff --git a/process/headerCheck/headerSignatureVerify_test.go b/process/headerCheck/headerSignatureVerify_test.go index c70eebbe94c..43947e337b1 100644 --- a/process/headerCheck/headerSignatureVerify_test.go +++ b/process/headerCheck/headerSignatureVerify_test.go @@ -28,13 +28,23 @@ const defaultChancesSelection = 1 var expectedErr = errors.New("expected error") func createHeaderSigVerifierArgs() *ArgsHeaderSigVerifier { + v1, _ := nodesCoordinator.NewValidator([]byte("pubKey1"), 1, defaultChancesSelection) + v2, _ := nodesCoordinator.NewValidator([]byte("pubKey1"), 1, defaultChancesSelection) return &ArgsHeaderSigVerifier{ - Marshalizer: &mock.MarshalizerMock{}, - Hasher: &hashingMocks.HasherMock{}, - NodesCoordinator: &shardingMocks.NodesCoordinatorMock{}, - MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(cryptoMocks.NewMultiSigner()), - SingleSigVerifier: &mock.SignerMock{}, - KeyGen: &mock.SingleSignKeyGenMock{}, + Marshalizer: &mock.MarshalizerMock{}, + Hasher: &hashingMocks.HasherMock{}, + NodesCoordinator: &shardingMocks.NodesCoordinatorMock{ + ComputeValidatorsGroupCalled: func(randomness []byte, round uint64, shardId uint32, epoch uint32) (leader nodesCoordinator.Validator, validators []nodesCoordinator.Validator, err error) { + return v1, []nodesCoordinator.Validator{v1, v2}, nil + }, + }, + MultiSigContainer: cryptoMocks.NewMultiSignerContainerMock(cryptoMocks.NewMultiSigner()), + SingleSigVerifier: &mock.SignerMock{}, + KeyGen: &mock.SingleSignKeyGenMock{ + PublicKeyFromByteArrayCalled: func(b []byte) (key crypto.PublicKey, err error) { + return &mock.SingleSignPublicKey{}, nil + }, + }, FallbackHeaderValidator: &testscommon.FallBackHeaderValidatorStub{}, EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), HeadersPool: &mock.HeadersCacherStub{}, @@ -223,10 +233,13 @@ func TestHeaderSigVerifier_VerifyRandSeedAndLeaderSignatureNilRandomnessShouldEr args := createHeaderSigVerifierArgs() hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + RandSeed: nil, + PrevRandSeed: []byte("prev rand seed"), + } err := hdrSigVerifier.VerifyRandSeedAndLeaderSignature(header) - require.Equal(t, nodesCoordinator.ErrNilRandomness, err) + require.Equal(t, process.ErrNilRandSeed, err) } func TestHeaderSigVerifier_VerifyRandSeedAndLeaderSignatureVerifyShouldErrWhenValidationFails(t *testing.T) { @@ -638,7 +651,7 @@ func TestHeaderSigVerifier_VerifySignatureOkWhenFallbackThresholdCouldBeApplied( hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.MetaBlock{ - PubKeysBitmap: []byte("C"), + PubKeysBitmap: []byte{15}, } err := hdrSigVerifier.VerifySignature(header) @@ -646,6 +659,17 @@ func TestHeaderSigVerifier_VerifySignatureOkWhenFallbackThresholdCouldBeApplied( require.True(t, wasCalled) } +func getFilledHeader() data.HeaderHandler { + return &dataBlock.Header{ + Nonce: 0, + PrevHash: []byte("prev hash"), + PrevRandSeed: []byte("prev rand seed"), + RandSeed: []byte("rand seed"), + PubKeysBitmap: []byte{0xFF}, + LeaderSignature: []byte("leader signature"), + } +} + func TestHeaderSigVerifier_VerifyHeaderProof(t *testing.T) { t.Parallel() @@ -717,12 +741,17 @@ func TestHeaderSigVerifier_VerifyHeaderProof(t *testing.T) { }) t.Run("should work", func(t *testing.T) { t.Parallel() - + headerHash := []byte("header hash") wasVerifyAggregatedSigCalled := false args := createHeaderSigVerifierArgs() + args.HeadersPool = &mock.HeadersCacherStub{ + GetHeaderByHashCalled: func(hash []byte) (data.HeaderHandler, error) { + return getFilledHeader(), nil + }, + } args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.FixedOrderInConsensusFlag + return flag == common.FixedOrderInConsensusFlag || flag == common.EquivalentMessagesFlag }, } args.MultiSigContainer = &cryptoMocks.MultiSignerContainerStub{ @@ -738,7 +767,11 @@ func TestHeaderSigVerifier_VerifyHeaderProof(t *testing.T) { hdrSigVerifier, err := NewHeaderSigVerifier(args) require.NoError(t, err) - err = hdrSigVerifier.VerifyHeaderProof(&dataBlock.HeaderProof{}) + err = hdrSigVerifier.VerifyHeaderProof(&dataBlock.HeaderProof{ + PubKeysBitmap: []byte{0x3}, + AggregatedSignature: make([]byte, 10), + HeaderHash: headerHash, + }) require.NoError(t, err) require.True(t, wasVerifyAggregatedSigCalled) }) From 6228e447a3adcb5b9bd4e628600966d76ed95c7a Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Fri, 13 Dec 2024 18:00:45 +0200 Subject: [PATCH 09/12] fixes unit tests for new checks --- process/block/baseProcess_test.go | 7 ++- process/headerCheck/headerSignatureVerify.go | 3 + .../headerCheck/headerSignatureVerify_test.go | 59 +++++++++++++++---- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/process/block/baseProcess_test.go b/process/block/baseProcess_test.go index a65369611fa..017f7b3e1d0 100644 --- a/process/block/baseProcess_test.go +++ b/process/block/baseProcess_test.go @@ -3140,7 +3140,10 @@ func TestBaseProcessor_CheckSentSignaturesAtCommitTime(t *testing.T) { arguments.NodesCoordinator = nodesCoordinatorInstance bp, _ := blproc.NewShardProcessor(arguments) - err := bp.CheckSentSignaturesAtCommitTime(&block.Header{}) + err := bp.CheckSentSignaturesAtCommitTime(&block.Header{ + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), + }) assert.Equal(t, expectedErr, err) }) t.Run("should work with bitmap", func(t *testing.T) { @@ -3164,6 +3167,8 @@ func TestBaseProcessor_CheckSentSignaturesAtCommitTime(t *testing.T) { bp, _ := blproc.NewShardProcessor(arguments) err := bp.CheckSentSignaturesAtCommitTime(&block.Header{ + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), PubKeysBitmap: []byte{0b00000101}, }) assert.Nil(t, err) diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index a88bac03270..8c3d4161a5b 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -233,6 +233,9 @@ func (hsv *HeaderSigVerifier) VerifySignatureForHash(header data.HeaderHandler, } randSeed := header.GetPrevRandSeed() + if randSeed == nil { + return process.ErrNilPrevRandSeed + } pubKeysSigners, err := hsv.getConsensusSigners( randSeed, header.GetShardID(), diff --git a/process/headerCheck/headerSignatureVerify_test.go b/process/headerCheck/headerSignatureVerify_test.go index 43947e337b1..2392c98649b 100644 --- a/process/headerCheck/headerSignatureVerify_test.go +++ b/process/headerCheck/headerSignatureVerify_test.go @@ -47,7 +47,11 @@ func createHeaderSigVerifierArgs() *ArgsHeaderSigVerifier { }, FallbackHeaderValidator: &testscommon.FallBackHeaderValidatorStub{}, EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), - HeadersPool: &mock.HeadersCacherStub{}, + HeadersPool: &mock.HeadersCacherStub{ + GetHeaderByHashCalled: func(hash []byte) (data.HeaderHandler, error) { + return &dataBlock.Header{}, nil + }, + }, } } @@ -153,10 +157,13 @@ func TestHeaderSigVerifier_VerifySignatureNilPrevRandSeedShouldErr(t *testing.T) args := createHeaderSigVerifierArgs() hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + PrevRandSeed: nil, + RandSeed: []byte("rand seed"), + } err := hdrSigVerifier.VerifyRandSeed(header) - require.Equal(t, nodesCoordinator.ErrNilRandomness, err) + require.Equal(t, process.ErrNilPrevRandSeed, err) } func TestHeaderSigVerifier_VerifyRandSeedOk(t *testing.T) { @@ -186,7 +193,10 @@ func TestHeaderSigVerifier_VerifyRandSeedOk(t *testing.T) { } args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + PrevRandSeed: []byte("prev rand seed"), + RandSeed: []byte("rand seed"), + } err := hdrSigVerifier.VerifyRandSeed(header) require.Nil(t, err) @@ -221,7 +231,10 @@ func TestHeaderSigVerifier_VerifyRandSeedShouldErrWhenVerificationFails(t *testi } args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), + } err := hdrSigVerifier.VerifyRandSeed(header) require.Equal(t, localError, err) @@ -270,7 +283,10 @@ func TestHeaderSigVerifier_VerifyRandSeedAndLeaderSignatureVerifyShouldErrWhenVa } args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), + } err := hdrSigVerifier.VerifyRandSeedAndLeaderSignature(header) require.Equal(t, localErr, err) @@ -310,6 +326,8 @@ func TestHeaderSigVerifier_VerifyRandSeedAndLeaderSignatureVerifyLeaderSigShould args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), LeaderSignature: leaderSig, } @@ -345,22 +363,28 @@ func TestHeaderSigVerifier_VerifyRandSeedAndLeaderSignatureOk(t *testing.T) { } args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), + } err := hdrSigVerifier.VerifyRandSeedAndLeaderSignature(header) require.Nil(t, err) require.Equal(t, 2, count) } -func TestHeaderSigVerifier_VerifyLeaderSignatureNilRandomnessShouldErr(t *testing.T) { +func TestHeaderSigVerifier_VerifyLeaderSignatureNilPrevRandomnessShouldErr(t *testing.T) { t.Parallel() args := createHeaderSigVerifierArgs() hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + RandSeed: []byte("rand seed "), + PrevRandSeed: nil, + } err := hdrSigVerifier.VerifyLeaderSignature(header) - require.Equal(t, nodesCoordinator.ErrNilRandomness, err) + require.Equal(t, process.ErrNilPrevRandSeed, err) } func TestHeaderSigVerifier_VerifyLeaderSignatureVerifyShouldErrWhenValidationFails(t *testing.T) { @@ -391,7 +415,10 @@ func TestHeaderSigVerifier_VerifyLeaderSignatureVerifyShouldErrWhenValidationFai } args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), + } err := hdrSigVerifier.VerifyLeaderSignature(header) require.Equal(t, localErr, err) @@ -431,6 +458,8 @@ func TestHeaderSigVerifier_VerifyLeaderSignatureVerifyLeaderSigShouldErr(t *test args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), LeaderSignature: leaderSig, } @@ -466,7 +495,10 @@ func TestHeaderSigVerifier_VerifyLeaderSignatureOk(t *testing.T) { } args.NodesCoordinator = nc hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), + } err := hdrSigVerifier.VerifyLeaderSignature(header) require.Nil(t, err) @@ -503,6 +535,8 @@ func TestHeaderSigVerifier_VerifySignatureNilRandomnessShouldErr(t *testing.T) { args := createHeaderSigVerifierArgs() hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ + RandSeed: nil, + PrevRandSeed: []byte("prevRandSeed"), PubKeysBitmap: []byte("1"), } @@ -661,7 +695,6 @@ func TestHeaderSigVerifier_VerifySignatureOkWhenFallbackThresholdCouldBeApplied( func getFilledHeader() data.HeaderHandler { return &dataBlock.Header{ - Nonce: 0, PrevHash: []byte("prev hash"), PrevRandSeed: []byte("prev rand seed"), RandSeed: []byte("rand seed"), From ca5f851a6bafedf86099cc5b990dfa64b1a36f79 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 16 Dec 2024 15:08:37 +0200 Subject: [PATCH 10/12] add flag check for proof verification --- process/headerCheck/headerSignatureVerify.go | 5 ++ .../headerCheck/headerSignatureVerify_test.go | 52 +++++++++---------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index 8c3d4161a5b..50bc3ff42ac 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -2,6 +2,7 @@ package headerCheck import ( "bytes" + "fmt" "math/bits" "github.com/multiversx/mx-chain-core-go/core" @@ -269,6 +270,10 @@ func (hsv *HeaderSigVerifier) VerifyHeaderProof(proofHandler data.HeaderProofHan return process.ErrNilHeaderProof } + if !hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, proofHandler.GetHeaderEpoch()) { + return fmt.Errorf("%w for flag %s", process.ErrFlagNotActive, common.EquivalentMessagesFlag) + } + // for the start of epoch block the consensus is taken from the previous epoch header, err := hsv.headersPool.GetHeaderByHash(proofHandler.GetHeaderHash()) if err != nil { diff --git a/process/headerCheck/headerSignatureVerify_test.go b/process/headerCheck/headerSignatureVerify_test.go index 2392c98649b..adb372ba15c 100644 --- a/process/headerCheck/headerSignatureVerify_test.go +++ b/process/headerCheck/headerSignatureVerify_test.go @@ -49,7 +49,9 @@ func createHeaderSigVerifierArgs() *ArgsHeaderSigVerifier { EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), HeadersPool: &mock.HeadersCacherStub{ GetHeaderByHashCalled: func(hash []byte) (data.HeaderHandler, error) { - return &dataBlock.Header{}, nil + return &dataBlock.Header{ + PrevRandSeed: []byte("prevRandSeed"), + }, nil }, }, } @@ -510,7 +512,11 @@ func TestHeaderSigVerifier_VerifySignatureNilBitmapShouldErr(t *testing.T) { args := createHeaderSigVerifierArgs() hdrSigVerifier, _ := NewHeaderSigVerifier(args) - header := &dataBlock.Header{} + header := &dataBlock.Header{ + PubKeysBitmap: nil, + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), + } err := hdrSigVerifier.VerifySignature(header) require.Equal(t, process.ErrNilPubKeysBitmap, err) @@ -523,6 +529,8 @@ func TestHeaderSigVerifier_VerifySignatureBlockProposerSigMissingShouldErr(t *te hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ PubKeysBitmap: []byte("0"), + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), } err := hdrSigVerifier.VerifySignature(header) @@ -535,13 +543,12 @@ func TestHeaderSigVerifier_VerifySignatureNilRandomnessShouldErr(t *testing.T) { args := createHeaderSigVerifierArgs() hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ - RandSeed: nil, - PrevRandSeed: []byte("prevRandSeed"), + PrevRandSeed: nil, PubKeysBitmap: []byte("1"), } err := hdrSigVerifier.VerifySignature(header) - require.Equal(t, nodesCoordinator.ErrNilRandomness, err) + require.Equal(t, process.ErrNilPrevRandSeed, err) } func TestHeaderSigVerifier_VerifySignatureWrongSizeBitmapShouldErr(t *testing.T) { @@ -560,6 +567,8 @@ func TestHeaderSigVerifier_VerifySignatureWrongSizeBitmapShouldErr(t *testing.T) hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ PubKeysBitmap: []byte("11"), + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), } err := hdrSigVerifier.VerifySignature(header) @@ -582,6 +591,8 @@ func TestHeaderSigVerifier_VerifySignatureNotEnoughSigsShouldErr(t *testing.T) { hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ PubKeysBitmap: []byte("A"), + RandSeed: []byte("randSeed"), + PrevRandSeed: []byte("prevRandSeed"), } err := hdrSigVerifier.VerifySignature(header) @@ -611,6 +622,7 @@ func TestHeaderSigVerifier_VerifySignatureOk(t *testing.T) { hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.Header{ PubKeysBitmap: []byte("1"), + PrevRandSeed: []byte("prevRandSeed"), } err := hdrSigVerifier.VerifySignature(header) @@ -649,6 +661,7 @@ func TestHeaderSigVerifier_VerifySignatureNotEnoughSigsShouldErrWhenFallbackThre hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.MetaBlock{ PubKeysBitmap: []byte("C"), + PrevRandSeed: []byte("prevRandSeed"), } err := hdrSigVerifier.VerifySignature(header) @@ -686,6 +699,7 @@ func TestHeaderSigVerifier_VerifySignatureOkWhenFallbackThresholdCouldBeApplied( hdrSigVerifier, _ := NewHeaderSigVerifier(args) header := &dataBlock.MetaBlock{ PubKeysBitmap: []byte{15}, + PrevRandSeed: []byte("prevRandSeed"), } err := hdrSigVerifier.VerifySignature(header) @@ -723,29 +737,11 @@ func TestHeaderSigVerifier_VerifyHeaderProof(t *testing.T) { hdrSigVerifier, err := NewHeaderSigVerifier(createHeaderSigVerifierArgs()) require.NoError(t, err) - err = hdrSigVerifier.VerifyHeaderProof(&dataBlock.HeaderProof{}) + err = hdrSigVerifier.VerifyHeaderProof(&dataBlock.HeaderProof{ + PubKeysBitmap: []byte{3}, + }) require.True(t, errors.Is(err, process.ErrFlagNotActive)) - require.True(t, strings.Contains(err.Error(), string(common.FixedOrderInConsensusFlag))) - }) - t.Run("GetAllEligibleValidatorsPublicKeysForShard error should error", func(t *testing.T) { - t.Parallel() - - args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ - IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.FixedOrderInConsensusFlag - }, - } - args.NodesCoordinator = &shardingMocks.NodesCoordinatorStub{ - GetAllEligibleValidatorsPublicKeysForShardCalled: func(epoch uint32, shardID uint32) ([]string, error) { - return nil, expectedErr - }, - } - hdrSigVerifier, err := NewHeaderSigVerifier(args) - require.NoError(t, err) - - err = hdrSigVerifier.VerifyHeaderProof(&dataBlock.HeaderProof{}) - require.Equal(t, expectedErr, err) + require.True(t, strings.Contains(err.Error(), string(common.EquivalentMessagesFlag))) }) t.Run("GetMultiSigner error should error", func(t *testing.T) { t.Parallel() @@ -754,7 +750,7 @@ func TestHeaderSigVerifier_VerifyHeaderProof(t *testing.T) { args := createHeaderSigVerifierArgs() args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.FixedOrderInConsensusFlag + return flag == common.EquivalentMessagesFlag }, } args.MultiSigContainer = &cryptoMocks.MultiSignerContainerStub{ From 972412543ecacbce9e1fcd4b9e1c502c0df85149 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 16 Dec 2024 16:52:29 +0200 Subject: [PATCH 11/12] add consensus header interceptor check for v1 --- consensus/spos/bls/v1/subroundBlock.go | 21 +++++++++++++++++++-- consensus/spos/bls/v2/subroundBlock.go | 4 ++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/consensus/spos/bls/v1/subroundBlock.go b/consensus/spos/bls/v1/subroundBlock.go index eac4a7c9204..31485aec724 100644 --- a/consensus/spos/bls/v1/subroundBlock.go +++ b/consensus/spos/bls/v1/subroundBlock.go @@ -415,9 +415,14 @@ func (sr *subroundBlock) receivedBlockBodyAndHeader(ctx context.Context, cnsDta return false } + header := sr.BlockProcessor().DecodeBlockHeader(cnsDta.Header) + if headerHasProof(header) { + return false + } + sr.SetData(cnsDta.BlockHeaderHash) sr.SetBody(sr.BlockProcessor().DecodeBlockBody(cnsDta.Body)) - sr.SetHeader(sr.BlockProcessor().DecodeBlockHeader(cnsDta.Header)) + sr.SetHeader(header) isInvalidData := check.IfNil(sr.GetBody()) || sr.isInvalidHeaderOrData() if isInvalidData { @@ -514,8 +519,13 @@ func (sr *subroundBlock) receivedBlockHeader(ctx context.Context, cnsDta *consen return false } + header := sr.BlockProcessor().DecodeBlockHeader(cnsDta.Header) + if headerHasProof(header) { + return false + } + sr.SetData(cnsDta.BlockHeaderHash) - sr.SetHeader(sr.BlockProcessor().DecodeBlockHeader(cnsDta.Header)) + sr.SetHeader(header) if sr.isInvalidHeaderOrData() { return false @@ -535,6 +545,13 @@ func (sr *subroundBlock) receivedBlockHeader(ctx context.Context, cnsDta *consen return blockProcessedWithSuccess } +func headerHasProof(headerHandler data.HeaderHandler) bool { + if check.IfNil(headerHandler) { + return true + } + return headerHandler.GetPreviousProof() != nil +} + func (sr *subroundBlock) processReceivedBlock(ctx context.Context, cnsDta *consensus.Message) bool { if check.IfNil(sr.GetBody()) { return false diff --git a/consensus/spos/bls/v2/subroundBlock.go b/consensus/spos/bls/v2/subroundBlock.go index 890cf0c5c3c..2454ad3643e 100644 --- a/consensus/spos/bls/v2/subroundBlock.go +++ b/consensus/spos/bls/v2/subroundBlock.go @@ -9,6 +9,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/consensus" "github.com/multiversx/mx-chain-go/consensus/spos" @@ -110,7 +111,6 @@ func (sr *subroundBlock) doBlockJob(ctx context.Context) bool { return false } - // todo: check again the block proof verification & leader signature verification // block proof verification should be done over the header that contains the leader signature leaderSignature, err := sr.signBlockHeader(header) if err != nil { @@ -177,7 +177,7 @@ func printLogMessage(ctx context.Context, baseMessage string, err error) { log.Debug(baseMessage, "error", err.Error()) } -func (sr *subroundBlock) sendBlock(header data.HeaderHandler, body data.BodyHandler, leader string) bool { +func (sr *subroundBlock) sendBlock(header data.HeaderHandler, body data.BodyHandler, _ string) bool { marshalledBody, err := sr.Marshalizer().Marshal(body) if err != nil { log.Debug("sendBlock.Marshal: body", "error", err.Error()) From 893302e3f5da61e8fbb71fc7434d951c811973b6 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 16 Dec 2024 18:04:45 +0200 Subject: [PATCH 12/12] fixes after review --- consensus/spos/bls/v1/subroundBlock.go | 4 ++-- integrationTests/consensus/consensusSigning_test.go | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/consensus/spos/bls/v1/subroundBlock.go b/consensus/spos/bls/v1/subroundBlock.go index 31485aec724..504cb82a180 100644 --- a/consensus/spos/bls/v1/subroundBlock.go +++ b/consensus/spos/bls/v1/subroundBlock.go @@ -547,9 +547,9 @@ func (sr *subroundBlock) receivedBlockHeader(ctx context.Context, cnsDta *consen func headerHasProof(headerHandler data.HeaderHandler) bool { if check.IfNil(headerHandler) { - return true + return false } - return headerHandler.GetPreviousProof() != nil + return !check.IfNilReflect(headerHandler.GetPreviousProof()) } func (sr *subroundBlock) processReceivedBlock(ctx context.Context, cnsDta *consensus.Message) bool { diff --git a/integrationTests/consensus/consensusSigning_test.go b/integrationTests/consensus/consensusSigning_test.go index c2d6f6ded60..dfa6966f1f0 100644 --- a/integrationTests/consensus/consensusSigning_test.go +++ b/integrationTests/consensus/consensusSigning_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - logger "github.com/multiversx/mx-chain-logger-go" "github.com/stretchr/testify/assert" "github.com/multiversx/mx-chain-go/integrationTests" @@ -71,8 +70,6 @@ func TestConsensusWithInvalidSigners(t *testing.T) { t.Skip("this is not a short test") } - _ = logger.SetLogLevel("*:DEBUG") - numMetaNodes := uint32(4) numNodes := uint32(4) consensusSize := uint32(4) @@ -107,7 +104,7 @@ func TestConsensusWithInvalidSigners(t *testing.T) { go checkBlockProposedEveryRound(numCommBlock, nonceForRoundMap, mutex, chDone, t) extraTime := uint64(2) - endTime := time.Duration(roundTime)*time.Duration(numCommBlock+extraTime)*time.Millisecond + 10*time.Minute + endTime := time.Duration(roundTime)*time.Duration(numCommBlock+extraTime)*time.Millisecond + time.Minute select { case <-chDone: case <-time.After(endTime):