From e493ddfd6d7a5f6779972671a76a9c5fcc926a35 Mon Sep 17 00:00:00 2001 From: Jerome Date: Wed, 2 Mar 2022 09:17:57 +1100 Subject: [PATCH] add verifyTC and verifyTimeoutMessage (#63) * add verifyTC and verifyTimeoutMessage * remove v2 func from adaptor --- consensus/XDPoS/XDPoS.go | 12 --- consensus/XDPoS/engines/engine_v2/engine.go | 89 +++++++++++++++++---- consensus/XDPoS/utils/errors.go | 1 + consensus/tests/countdown_test.go | 30 ------- consensus/tests/mine_test.go | 16 ++-- consensus/tests/timeout_test.go | 67 ++++++++++++++++ core/blockchain.go | 2 +- eth/bft/bft_hander_test.go | 8 +- eth/bft/bft_handler.go | 16 ++-- 9 files changed, 165 insertions(+), 76 deletions(-) delete mode 100644 consensus/tests/countdown_test.go diff --git a/consensus/XDPoS/XDPoS.go b/consensus/XDPoS/XDPoS.go index e132b17e5f..e70c3a6cce 100644 --- a/consensus/XDPoS/XDPoS.go +++ b/consensus/XDPoS/XDPoS.go @@ -521,15 +521,3 @@ func (x *XDPoS) initialV2FromLastV1(chain consensus.ChainReader, header *types.H } return nil } - -func (x *XDPoS) VerifyVote(*utils.Vote) error { - return nil -} - -func (x *XDPoS) VerifyTimeout(*utils.Timeout) error { - return nil -} - -func (x *XDPoS) VerifySyncInfo(*utils.SyncInfo) error { - return nil -} diff --git a/consensus/XDPoS/engines/engine_v2/engine.go b/consensus/XDPoS/engines/engine_v2/engine.go index cff912706d..6fa6dd51b8 100644 --- a/consensus/XDPoS/engines/engine_v2/engine.go +++ b/consensus/XDPoS/engines/engine_v2/engine.go @@ -378,7 +378,7 @@ func (x *XDPoS_v2) YourTurn(chain consensus.ChainReader, parent *types.Header, s var masterNodes []common.Address if isEpochSwitch { if x.config.V2.SwitchBlock.Cmp(parent.Number) == 0 { - snap, err := x.getSnapshot(chain, x.config.V2.SwitchBlock.Uint64()) + snap, err := x.getSnapshot(chain, x.config.V2.SwitchBlock.Uint64(), false) if err != nil { log.Error("[YourTurn] Cannot find snapshot at gap num of last V1", "err", err, "number", x.config.V2.SwitchBlock.Uint64()) return false, err @@ -456,7 +456,7 @@ func (x *XDPoS_v2) IsAuthorisedAddress(chain consensus.ChainReader, header *type func (x *XDPoS_v2) GetSnapshot(chain consensus.ChainReader, header *types.Header) (*SnapshotV2, error) { number := header.Number.Uint64() log.Trace("get snapshot", "number", number) - snap, err := x.getSnapshot(chain, number) + snap, err := x.getSnapshot(chain, number, false) if err != nil { return nil, err } @@ -464,9 +464,14 @@ func (x *XDPoS_v2) GetSnapshot(chain consensus.ChainReader, header *types.Header } // snapshot retrieves the authorization snapshot at a given point in time. -func (x *XDPoS_v2) getSnapshot(chain consensus.ChainReader, number uint64) (*SnapshotV2, error) { - // checkpoint snapshot = checkpoint - gap - gapBlockNum := number - number%x.config.Epoch - x.config.Gap +func (x *XDPoS_v2) getSnapshot(chain consensus.ChainReader, number uint64, isGapNumber bool) (*SnapshotV2, error) { + var gapBlockNum uint64 + if isGapNumber { + gapBlockNum = number + } else { + gapBlockNum = number - number%x.config.Epoch - x.config.Gap + } + gapBlockHash := chain.GetHeaderByNumber(gapBlockNum).Hash() log.Debug("get snapshot from gap block", "number", gapBlockNum, "hash", gapBlockHash.Hex()) @@ -663,7 +668,7 @@ func (x *XDPoS_v2) VerifySyncInfoMessage(chain consensus.ChainReader, syncInfo * log.Warn("SyncInfo message verification failed due to QC", err) return err } - err = x.verifyTC(syncInfo.HighestTimeoutCert) + err = x.verifyTC(chain, syncInfo.HighestTimeoutCert) if err != nil { log.Warn("SyncInfo message verification failed due to TC", err) return err @@ -701,7 +706,7 @@ func (x *XDPoS_v2) VerifyVoteMessage(chain consensus.ChainReader, vote *utils.Vo if err != nil { return false, err } - snapshot, err := x.getSnapshot(chain, vote.ProposedBlockInfo.Number.Uint64()) + snapshot, err := x.getSnapshot(chain, vote.ProposedBlockInfo.Number.Uint64(), false) if err != nil { log.Error("[VerifyVoteMessage] fail to get snapshot for a vote message", "BlockNum", vote.ProposedBlockInfo.Number, "Hash", vote.ProposedBlockInfo.Hash, "Error", err.Error()) } @@ -820,12 +825,19 @@ func (x *XDPoS_v2) onVotePoolThresholdReached(chain consensus.ChainReader, poole 3. Broadcast(Not part of consensus) */ func (x *XDPoS_v2) VerifyTimeoutMessage(chain consensus.ChainReader, timeoutMsg *utils.Timeout) (bool, error) { + snap, err := x.getSnapshot(chain, timeoutMsg.GapNumber, true) + if err != nil { + log.Error("[VerifyTimeoutMessage] Fail to get snapshot when verifying timeout message!", "messageGapNumber", timeoutMsg.GapNumber) + } + if snap == nil || len(snap.NextEpochMasterNodes) == 0 { + log.Error("[VerifyTimeoutMessage] Something wrong with the snapshot from gapNumber", "messageGapNumber", timeoutMsg.GapNumber, "snapshot", snap) + return false, fmt.Errorf("Empty master node lists from snapshot") + } - masternodes := x.GetMasternodesAtRound(chain, timeoutMsg.Round, chain.CurrentHeader()) return x.verifyMsgSignature(utils.TimeoutSigHash(&utils.TimeoutForSign{ Round: timeoutMsg.Round, GapNumber: timeoutMsg.GapNumber, - }), timeoutMsg.Signature, masternodes) + }), timeoutMsg.Signature, snap.NextEpochMasterNodes) } /* @@ -1045,7 +1057,7 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert * return x.VerifyBlockInfo(blockChainReader, quorumCert.ProposedBlockInfo) } -func (x *XDPoS_v2) verifyTC(timeoutCert *utils.TimeoutCert) error { +func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *utils.TimeoutCert) error { /* 1. Get epoch master node list by gapNumber 2. Check number of signatures > threshold, as well as it's format. (Same as verifyQC) @@ -1054,6 +1066,53 @@ func (x *XDPoS_v2) verifyTC(timeoutCert *utils.TimeoutCert) error { - Use the above public key to find out the xdc address - Use the above xdc address to check against the master node list from step 1(For the received TC epoch) */ + snap, err := x.getSnapshot(chain, timeoutCert.GapNumber, true) + if err != nil { + log.Error("[verifyTC] Fail to get snapshot when verifying TC!", "TCGapNumber", timeoutCert.GapNumber) + return fmt.Errorf("[verifyTC] Unable to get snapshot") + } + if snap == nil || len(snap.NextEpochMasterNodes) == 0 { + log.Error("[verifyTC] Something wrong with the snapshot from gapNumber", "messageGapNumber", timeoutCert.GapNumber, "snapshot", snap) + return fmt.Errorf("Empty master node lists from snapshot") + } + + if timeoutCert == nil { + log.Warn("[verifyTC] TC is Nil") + return utils.ErrInvalidTC + } else if timeoutCert.Signatures == nil || (len(timeoutCert.Signatures) < x.config.V2.CertThreshold) { + log.Warn("[verifyTC] Invalid TC Signature is nil or empty", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(timeoutCert.Signatures)) + return utils.ErrInvalidTC + } + + var wg sync.WaitGroup + wg.Add(len(timeoutCert.Signatures)) + var haveError error + + signedTimeoutObj := utils.TimeoutSigHash(&utils.TimeoutForSign{ + Round: timeoutCert.Round, + GapNumber: timeoutCert.GapNumber, + }) + + for _, signature := range timeoutCert.Signatures { + go func(sig utils.Signature) { + defer wg.Done() + verified, err := x.verifyMsgSignature(signedTimeoutObj, sig, snap.NextEpochMasterNodes) + if err != nil { + log.Error("[verifyTC] Error while verfying TC message signatures", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(timeoutCert.Signatures), "Error", err) + haveError = fmt.Errorf("Error while verfying TC message signatures") + return + } + if !verified { + log.Warn("[verifyTC] Signature not verified doing TC verification", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(timeoutCert.Signatures)) + haveError = fmt.Errorf("Fail to verify TC due to signature mis-match") + return + } + }(signature) + } + wg.Wait() + if haveError != nil { + return haveError + } return nil } @@ -1213,14 +1272,14 @@ func (x *XDPoS_v2) sendTimeout(chain consensus.ChainReader) error { if isEpochSwitch { // Notice this +1 is because we expect a block whos is the child of currentHeader currentNumber := currentBlockHeader.Number.Uint64() + 1 - gapNumber := currentNumber - currentNumber%x.config.Epoch - x.config.Gap + gapNumber = currentNumber - currentNumber%x.config.Epoch - x.config.Gap log.Debug("[sendTimeout] is epoch switch when sending out timeout message", "currentNumber", currentNumber, "gapNumber", gapNumber) } else { epochSwitchInfo, err := x.getEpochSwitchInfo(chain, currentBlockHeader, currentBlockHeader.Hash()) if err != nil { log.Error("[sendTimeout] Error when trying to get current epoch switch info for a non-epoch block", "currentRound", x.currentRound, "currentBlockNum", currentBlockHeader.Number, "currentBlockHash", currentBlockHeader.Hash(), "epochNum", epochNum) } - gapNumber := epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64() - epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64()%x.config.Epoch - x.config.Gap + gapNumber = epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64() - epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64()%x.config.Epoch - x.config.Gap log.Debug("[sendTimeout] non-epoch-switch block found its epoch block and calculated the gapNumber", "epochSwitchInfo.EpochSwitchBlockInfo.Number", epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64(), "gapNumber", gapNumber) } @@ -1302,10 +1361,6 @@ func (x *XDPoS_v2) broadcastToBftChannel(msg interface{}) { }() } -func (x *XDPoS_v2) GetMasternodesAtRound(chain consensus.ChainReader, round utils.Round, currentHeader *types.Header) []common.Address { - return []common.Address{} -} - func (x *XDPoS_v2) getSyncInfo() *utils.SyncInfo { return &utils.SyncInfo{ HighestQuorumCert: x.highestQuorumCert, @@ -1560,7 +1615,7 @@ func (x *XDPoS_v2) GetCurrentEpochSwitchBlock(chain consensus.ChainReader, block } func (x *XDPoS_v2) calcMasternodes(chain consensus.ChainReader, blockNum *big.Int, parentHash common.Hash) ([]common.Address, []common.Address, error) { - snap, err := x.getSnapshot(chain, blockNum.Uint64()) + snap, err := x.getSnapshot(chain, blockNum.Uint64(), false) if err != nil { log.Error("[calcMasternodes] Adaptor v2 getSnapshot has error", "err", err) return nil, nil, err diff --git a/consensus/XDPoS/utils/errors.go b/consensus/XDPoS/utils/errors.go index a0571ea2f2..f643cd992a 100644 --- a/consensus/XDPoS/utils/errors.go +++ b/consensus/XDPoS/utils/errors.go @@ -82,6 +82,7 @@ var ( ErrInvalidV2Extra = errors.New("Invalid v2 extra in the block") ErrInvalidQC = errors.New("Invalid QC content") + ErrInvalidTC = errors.New("Invalid TC content") ErrEmptyBlockInfoHash = errors.New("BlockInfo hash is empty") ErrInvalidFieldInNonEpochSwitch = errors.New("Invalid field exist in a non-epoch swtich block") ) diff --git a/consensus/tests/countdown_test.go b/consensus/tests/countdown_test.go deleted file mode 100644 index 4e687a1b53..0000000000 --- a/consensus/tests/countdown_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package tests - -import ( - "testing" - - "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS" - "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils" - "github.com/XinFinOrg/XDPoSChain/params" - "github.com/stretchr/testify/assert" -) - -func TestCountdownTimeoutToSendTimeoutMessage(t *testing.T) { - blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 901, params.TestXDPoSMockChainConfig, 0) - engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2 - - engineV2.SetNewRoundFaker(blockchain, utils.Round(1), true) - - timeoutMsg := <-engineV2.BroadcastCh - poolSize := engineV2.GetTimeoutPoolSize(timeoutMsg.(*utils.Timeout)) - assert.Equal(t, poolSize, 1) - assert.NotNil(t, timeoutMsg) - assert.Equal(t, uint64(0), timeoutMsg.(*utils.Timeout).GapNumber) - assert.Equal(t, utils.Round(1), timeoutMsg.(*utils.Timeout).Round) - - valid, err := engineV2.VerifyTimeoutMessage(blockchain, timeoutMsg.(*utils.Timeout)) - // We can only test valid = false for now as the implementation for getCurrentRoundMasterNodes is not complete - assert.False(t, valid) - // This shows we are able to decode the timeout message, which is what this test is all about - assert.Regexp(t, "Empty masternode list detected when verifying message signatures", err.Error()) -} diff --git a/consensus/tests/mine_test.go b/consensus/tests/mine_test.go index 25d505fbcd..368bd002e5 100644 --- a/consensus/tests/mine_test.go +++ b/consensus/tests/mine_test.go @@ -66,17 +66,18 @@ func TestUpdateMasterNodes(t *testing.T) { snap, err := x.GetSnapshot(blockchain, currentBlock.Header()) assert.Nil(t, err) - assert.Equal(t, int(snap.Number), 450) + assert.Equal(t, 450, int(snap.Number)) // Insert block 1350 t.Logf("Inserting block with propose at 1350...") blockCoinbaseA := "0xaaa0000000000000000000000000000000001350" - tx, err := voteTX(37117, 0, acc1Addr.String()) + // NOTE: voterAddr never exist in the Masternode list, but all acc1,2,3 already does + tx, err := voteTX(37117, 0, voterAddr.String()) if err != nil { t.Fatal(err) } //Get from block validator error message - merkleRoot := "46234e9cd7e85a267f7f0435b15256a794a2f6d65cc98cdbd21dcd10a01d9772" + merkleRoot := "ef9198eb14b003774a505033f6cdcea2d357cbf7a7e7b004d8034d4e2a9770ee" header := &types.Header{ Root: common.HexToHash(merkleRoot), Number: big.NewInt(int64(1350)), @@ -90,7 +91,11 @@ func TestUpdateMasterNodes(t *testing.T) { } parentBlock, err := createBlockFromHeader(blockchain, header, []*types.Transaction{tx}) assert.Nil(t, err) - blockchain.InsertBlock(parentBlock) + err = blockchain.InsertBlock(parentBlock) + assert.Nil(t, err) + // 1350 is a gap block, need to update the snapshot + err = blockchain.UpdateM1() + assert.Nil(t, err) t.Logf("Inserting block from 1351 to 1800...") for i := 1351; i <= 1800; i++ { blockCoinbase := fmt.Sprintf("0xaaa000000000000000000000000000000000%4d", i) @@ -117,8 +122,7 @@ func TestUpdateMasterNodes(t *testing.T) { snap, err = x.GetSnapshot(blockchain, parentBlock.Header()) assert.Nil(t, err) - assert.False(t, snap.IsMasterNodes(acc3Addr)) - assert.True(t, snap.IsMasterNodes(acc1Addr)) + assert.True(t, snap.IsMasterNodes(voterAddr)) assert.Equal(t, int(snap.Number), 1350) } diff --git a/consensus/tests/timeout_test.go b/consensus/tests/timeout_test.go index 55a9f8719c..82942ff94f 100644 --- a/consensus/tests/timeout_test.go +++ b/consensus/tests/timeout_test.go @@ -3,12 +3,25 @@ package tests import ( "testing" + "github.com/XinFinOrg/XDPoSChain/accounts" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS" "github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils" "github.com/XinFinOrg/XDPoSChain/params" "github.com/stretchr/testify/assert" ) +func TestCountdownTimeoutToSendTimeoutMessage(t *testing.T) { + blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 2251, params.TestXDPoSMockChainConfig, 0) + engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2 + + timeoutMsg := <-engineV2.BroadcastCh + poolSize := engineV2.GetTimeoutPoolSize(timeoutMsg.(*utils.Timeout)) + assert.Equal(t, poolSize, 1) + assert.NotNil(t, timeoutMsg) + assert.Equal(t, uint64(1350), timeoutMsg.(*utils.Timeout).GapNumber) + assert.Equal(t, utils.Round(1), timeoutMsg.(*utils.Timeout).Round) +} + // Timeout handler func TestTimeoutMessageHandlerSuccessfullyGenerateTCandSyncInfo(t *testing.T) { blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 11, params.TestXDPoSMockChainConfig, 0) @@ -101,3 +114,57 @@ func TestThrowErrorIfTimeoutMsgRoundNotEqualToCurrentRound(t *testing.T) { // Timeout msg round < currentRound assert.Equal(t, "timeout message round number: 2 does not match currentRound: 1", err.Error()) } + +func TestShouldVerifyTimeoutMessageForFirstV2Block(t *testing.T) { + blockchain, _, _, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 901, params.TestXDPoSMockChainConfig, 0) + engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2 + + signedHash, err := signFn(accounts.Account{Address: signer}, utils.TimeoutSigHash(&utils.TimeoutForSign{ + Round: utils.Round(1), + GapNumber: 450, + }).Bytes()) + assert.Nil(t, err) + timeoutMsg := &utils.Timeout{ + Round: utils.Round(1), + GapNumber: 450, + Signature: signedHash, + } + + verified, err := engineV2.VerifyTimeoutMessage(blockchain, timeoutMsg) + assert.Nil(t, err) + assert.True(t, verified) + + signedHash, err = signFn(accounts.Account{Address: signer}, utils.TimeoutSigHash(&utils.TimeoutForSign{ + Round: utils.Round(2), + GapNumber: 450, + }).Bytes()) + assert.Nil(t, err) + timeoutMsg = &utils.Timeout{ + Round: utils.Round(2), + GapNumber: 450, + Signature: signedHash, + } + + verified, err = engineV2.VerifyTimeoutMessage(blockchain, timeoutMsg) + assert.Nil(t, err) + assert.True(t, verified) +} + +func TestShouldVerifyTimeoutMessage(t *testing.T) { + blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 2251, params.TestXDPoSMockChainConfig, 0) + engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2 + + signedHash := SignHashByPK(acc1Key, utils.TimeoutSigHash(&utils.TimeoutForSign{ + Round: utils.Round(5000), + GapNumber: 2250, + }).Bytes()) + timeoutMsg := &utils.Timeout{ + Round: utils.Round(5000), + GapNumber: 2250, + Signature: signedHash, + } + + verified, err := engineV2.VerifyTimeoutMessage(blockchain, timeoutMsg) + assert.Nil(t, err) + assert.True(t, verified) +} diff --git a/core/blockchain.go b/core/blockchain.go index 602f425a35..9ca580c17b 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2516,7 +2516,7 @@ func (bc *BlockChain) UpdateM1() error { header := bc.CurrentHeader() var maxMasternodes int // check if block number is increase ms checkpoint - if bc.chainConfig.IsTIPIncreaseMasternodes(header.Number) { + if bc.chainConfig.IsTIPIncreaseMasternodes(header.Number) || (bc.chainConfig.XDPoS.V2.SwitchBlock != nil && header.Number.Cmp(bc.chainConfig.XDPoS.V2.SwitchBlock) == 1) { // using new masterndoes maxMasternodes = common.MaxMasternodesV2 } else { diff --git a/eth/bft/bft_hander_test.go b/eth/bft/bft_hander_test.go index 5de638a82c..07f0edd8fe 100644 --- a/eth/bft/bft_hander_test.go +++ b/eth/bft/bft_hander_test.go @@ -155,9 +155,9 @@ func TestTimeoutHandler(t *testing.T) { broadcastCounter := uint32(0) targetVotes := 1 - tester.bfter.consensus.verifyTimeout = func(timeout *utils.Timeout) error { + tester.bfter.consensus.verifyTimeout = func(consensus.ChainReader, *utils.Timeout) (bool, error) { atomic.AddUint32(&verifyCounter, 1) - return nil + return true, nil } tester.bfter.consensus.timeoutHandler = func(chain consensus.ChainReader, timeout *utils.Timeout) error { @@ -186,8 +186,8 @@ func TestTimeoutHandler(t *testing.T) { func TestTimeoutHandlerRoundNotEqual(t *testing.T) { tester := newTester() - tester.bfter.consensus.verifyTimeout = func(timeout *utils.Timeout) error { - return nil + tester.bfter.consensus.verifyTimeout = func(consensus.ChainReader, *utils.Timeout) (bool, error) { + return true, nil } tester.bfter.consensus.timeoutHandler = func(chain consensus.ChainReader, timeout *utils.Timeout) error { diff --git a/eth/bft/bft_handler.go b/eth/bft/bft_handler.go index a443460b98..14e01157f2 100644 --- a/eth/bft/bft_handler.go +++ b/eth/bft/bft_handler.go @@ -37,10 +37,10 @@ type ConsensusFns struct { verifyVote func(consensus.ChainReader, *utils.Vote) (bool, error) voteHandler func(consensus.ChainReader, *utils.Vote) error - verifyTimeout func(*utils.Timeout) error + verifyTimeout func(consensus.ChainReader, *utils.Timeout) (bool, error) timeoutHandler func(consensus.ChainReader, *utils.Timeout) error - verifySyncInfo func(*utils.SyncInfo) error + verifySyncInfo func(consensus.ChainReader, *utils.SyncInfo) error syncInfoHandler func(consensus.ChainReader, *utils.SyncInfo) error } @@ -69,9 +69,9 @@ func (b *Bfter) SetConsensusFuns(engine consensus.Engine) { e := engine.(*XDPoS.XDPoS) b.broadcastCh = e.EngineV2.BroadcastCh b.consensus = ConsensusFns{ - verifySyncInfo: e.VerifySyncInfo, + verifySyncInfo: e.EngineV2.VerifySyncInfoMessage, verifyVote: e.EngineV2.VerifyVoteMessage, - verifyTimeout: e.VerifyTimeout, + verifyTimeout: e.EngineV2.VerifyTimeoutMessage, voteHandler: e.EngineV2.VoteHandler, timeoutHandler: e.EngineV2.TimeoutHandler, @@ -116,11 +116,15 @@ func (b *Bfter) Timeout(timeout *utils.Timeout) error { log.Trace("Discarded Timeout, known Timeout", "Signature", timeout.Signature, "hash", timeout.Hash(), "round", timeout.Round) return nil } - err := b.consensus.verifyTimeout(timeout) + verified, err := b.consensus.verifyTimeout(b.blockChainReader, timeout) if err != nil { log.Error("Verify BFT Timeout", "error", err) return err } + if !verified { + log.Warn("Timeout message failed to verify", "timeoutRound", timeout.Round, "timeoutGapNum", timeout.GapNumber) + return fmt.Errorf("Fail to verify the received timeout message") + } b.broadcastCh <- timeout err = b.consensus.timeoutHandler(b.blockChainReader, timeout) @@ -140,7 +144,7 @@ func (b *Bfter) SyncInfo(syncInfo *utils.SyncInfo) error { log.Trace("Discarded SyncInfo, known SyncInfo", "hash", syncInfo.Hash()) return nil } - err := b.consensus.verifySyncInfo(syncInfo) + err := b.consensus.verifySyncInfo(b.blockChainReader, syncInfo) if err != nil { log.Error("Verify BFT SyncInfo", "error", err) return err