Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added checks on proofs parameters like epoch, nonce and shard #6698

Open
wants to merge 3 commits into
base: equivalent-proofs-feat-stabilization
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package common

import (
"fmt"

"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"
)

Expand All @@ -24,3 +27,25 @@ func IsFlagEnabledAfterEpochsStartBlock(header data.HeaderHandler, enableEpochsH
func ShouldBlockHavePrevProof(header data.HeaderHandler, enableEpochsHandler EnableEpochsHandler, flag core.EnableEpochFlag) bool {
return IsFlagEnabledAfterEpochsStartBlock(header, enableEpochsHandler, flag) && header.GetNonce() > 1
}

// VerifyProofAgainstHeader verifies the fields on the proof match the ones on the header
func VerifyProofAgainstHeader(proof data.HeaderProofHandler, header data.HeaderHandler) error {
if check.IfNilReflect(proof) {
return ErrInvalidHeaderProof
}

if proof.GetHeaderNonce() != header.GetNonce() {
return fmt.Errorf("%w, nonce mismatch", ErrInvalidHeaderProof)
}
if proof.GetHeaderShardId() != header.GetShardID() {
return fmt.Errorf("%w, shard id mismatch", ErrInvalidHeaderProof)
}
if proof.GetHeaderEpoch() != header.GetEpoch() {
return fmt.Errorf("%w, epoch mismatch", ErrInvalidHeaderProof)
}
if proof.GetHeaderRound() != header.GetRound() {
return fmt.Errorf("%w, round mismatch", ErrInvalidHeaderProof)
}

return nil
}
3 changes: 3 additions & 0 deletions common/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ var ErrNilWasmChangeLocker = errors.New("nil wasm change locker")

// ErrNilStateSyncNotifierSubscriber signals that a nil state sync notifier subscriber has been provided
var ErrNilStateSyncNotifierSubscriber = errors.New("nil state sync notifier subscriber")

// ErrInvalidHeaderProof signals that an invalid equivalent proof has been provided
var ErrInvalidHeaderProof = errors.New("invalid equivalent proof")
33 changes: 21 additions & 12 deletions consensus/spos/bls/v2/subroundBlock.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,19 +389,27 @@ func isProofEmpty(proof data.HeaderProofHandler) bool {
len(proof.GetHeaderHash()) == 0
}

func (sr *subroundBlock) saveProofForPreviousHeaderIfNeeded(header data.HeaderHandler) {
func (sr *subroundBlock) saveProofForPreviousHeaderIfNeeded(header data.HeaderHandler, prevHeader data.HeaderHandler) {
hasProof := sr.EquivalentProofsPool().HasProof(sr.ShardCoordinator().SelfId(), header.GetPrevHash())
if hasProof {
log.Debug("saveProofForPreviousHeaderIfNeeded: no need to set proof since it is already saved")
return
}

proof := header.GetPreviousProof()
err := sr.EquivalentProofsPool().AddProof(proof)
err := common.VerifyProofAgainstHeader(proof, prevHeader)
if err != nil {
log.Debug("saveProofForPreviousHeaderIfNeeded: invalid proof, %w", err)
return
}

err = sr.EquivalentProofsPool().AddProof(proof)
if err != nil {
log.Debug("saveProofForPreviousHeaderIfNeeded: failed to add proof, %w", err)
return
}

return
}

// receivedBlockBody method is called when a block body is received through the block body channel
Expand Down Expand Up @@ -445,30 +453,30 @@ func (sr *subroundBlock) receivedBlockBody(ctx context.Context, cnsDta *consensu
return blockProcessedWithSuccess
}

func (sr *subroundBlock) isHeaderForCurrentConsensus(header data.HeaderHandler) bool {
func (sr *subroundBlock) isHeaderForCurrentConsensus(header data.HeaderHandler) (bool, data.HeaderHandler) {
if check.IfNil(header) {
return false
return false, nil
}
if header.GetShardID() != sr.ShardCoordinator().SelfId() {
return false
return false, nil
}
if header.GetRound() != uint64(sr.RoundHandler().Index()) {
return false
return false, nil
}

prevHeader, prevHash := sr.getPrevHeaderAndHash()
if check.IfNil(prevHeader) {
return false
return false, nil
}
if !bytes.Equal(header.GetPrevHash(), prevHash) {
return false
return false, nil
}
if header.GetNonce() != prevHeader.GetNonce()+1 {
return false
return false, nil
}
prevRandSeed := prevHeader.GetRandSeed()

return bytes.Equal(header.GetPrevRandSeed(), prevRandSeed)
return bytes.Equal(header.GetPrevRandSeed(), prevRandSeed), prevHeader
}

func (sr *subroundBlock) getLeaderForHeader(headerHandler data.HeaderHandler) ([]byte, error) {
Expand All @@ -495,7 +503,8 @@ func (sr *subroundBlock) receivedBlockHeader(headerHandler data.HeaderHandler) {
return
}

if !sr.isHeaderForCurrentConsensus(headerHandler) {
isHeaderForCurrentConsensus, prevHeader := sr.isHeaderForCurrentConsensus(headerHandler)
if !isHeaderForCurrentConsensus {
return
}

Expand Down Expand Up @@ -539,7 +548,7 @@ func (sr *subroundBlock) receivedBlockHeader(headerHandler data.HeaderHandler) {
sr.SetData(sr.Hasher().Compute(string(marshalledHeader)))
sr.SetHeader(headerHandler)

sr.saveProofForPreviousHeaderIfNeeded(headerHandler)
sr.saveProofForPreviousHeaderIfNeeded(headerHandler, prevHeader)

log.Debug("step 1: block header has been received",
"nonce", sr.GetHeader().GetNonce(),
Expand Down
11 changes: 10 additions & 1 deletion process/block/baseProcess.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,16 @@ func (bp *baseProcessor) checkBlockValidity(
return process.ErrEpochDoesNotMatch
}

return nil
return bp.checkPrevProofValidity(currentBlockHeader, headerHandler)
}

func (bp *baseProcessor) checkPrevProofValidity(prevHeader, headerHandler data.HeaderHandler) error {
if !common.ShouldBlockHavePrevProof(headerHandler, bp.enableEpochsHandler, common.EquivalentMessagesFlag) {
return nil
}

prevProof := headerHandler.GetPreviousProof()
return common.VerifyProofAgainstHeader(prevProof, prevHeader)
}

// checkScheduledRootHash checks if the scheduled root hash from the given header is the same with the current user accounts state root hash
Expand Down
22 changes: 22 additions & 0 deletions process/block/interceptedBlocks/interceptedEquivalentProof.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package interceptedBlocks

import (
"encoding/hex"
"fmt"

"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-core-go/data/block"
"github.com/multiversx/mx-chain-core-go/marshal"
"github.com/multiversx/mx-chain-go/common"
"github.com/multiversx/mx-chain-go/consensus"
"github.com/multiversx/mx-chain-go/dataRetriever"
proofscache "github.com/multiversx/mx-chain-go/dataRetriever/dataPool/proofsCache"
Expand All @@ -25,13 +27,15 @@ type ArgInterceptedEquivalentProof struct {
ShardCoordinator sharding.Coordinator
HeaderSigVerifier consensus.HeaderSigVerifier
Proofs dataRetriever.ProofsPool
Headers dataRetriever.HeadersPool
}

type interceptedEquivalentProof struct {
proof *block.HeaderProof
isForCurrentShard bool
headerSigVerifier consensus.HeaderSigVerifier
proofsPool dataRetriever.ProofsPool
headersPool dataRetriever.HeadersPool
}

// NewInterceptedEquivalentProof returns a new instance of interceptedEquivalentProof
Expand All @@ -51,6 +55,7 @@ func NewInterceptedEquivalentProof(args ArgInterceptedEquivalentProof) (*interce
isForCurrentShard: extractIsForCurrentShard(args.ShardCoordinator, equivalentProof),
headerSigVerifier: args.HeaderSigVerifier,
proofsPool: args.Proofs,
headersPool: args.Headers,
}, nil
}

Expand All @@ -70,6 +75,9 @@ func checkArgInterceptedEquivalentProof(args ArgInterceptedEquivalentProof) erro
if check.IfNil(args.Proofs) {
return process.ErrNilProofsPool
}
if check.IfNil(args.Headers) {
return process.ErrNilHeadersDataPool
}

return nil
}
Expand Down Expand Up @@ -115,9 +123,23 @@ func (iep *interceptedEquivalentProof) CheckValidity() error {
return proofscache.ErrAlreadyExistingEquivalentProof
}

err = iep.checkHeaderParamsFromProof()
if err != nil {
return err
}

return iep.headerSigVerifier.VerifyHeaderProof(iep.proof)
}

func (iep *interceptedEquivalentProof) checkHeaderParamsFromProof() error {
header, err := iep.headersPool.GetHeaderByHash(iep.proof.GetHeaderHash())
if err != nil {
return fmt.Errorf("%w while getting header for proof hash %s", err, hex.EncodeToString(iep.proof.GetHeaderHash()))
}

return common.VerifyProofAgainstHeader(iep.proof, header)
}

func (iep *interceptedEquivalentProof) integrity() error {
isProofValid := len(iep.proof.AggregatedSignature) > 0 &&
len(iep.proof.PubKeysBitmap) > 0 &&
Expand Down
Loading
Loading