From cdb8de988b408cfafe558841a194a789f1c0303b Mon Sep 17 00:00:00 2001 From: wanwiset25 Date: Sun, 16 Nov 2025 22:25:16 +0400 Subject: [PATCH 1/2] use epochInfo.Masternodes instead of snap.NextEpochCandidates --- consensus/XDPoS/engines/engine_v2/syncInfo.go | 14 +++++------ consensus/XDPoS/engines/engine_v2/timeout.go | 25 +++++++++++-------- consensus/XDPoS/engines/engine_v2/vote.go | 9 ++++--- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/consensus/XDPoS/engines/engine_v2/syncInfo.go b/consensus/XDPoS/engines/engine_v2/syncInfo.go index 7c6b34d0016b..38838e3704c4 100644 --- a/consensus/XDPoS/engines/engine_v2/syncInfo.go +++ b/consensus/XDPoS/engines/engine_v2/syncInfo.go @@ -31,9 +31,9 @@ func (x *XDPoS_v2) VerifySyncInfoMessage(chain consensus.ChainReader, syncInfo * return false, nil } - snapshot, err := x.getSnapshot(chain, qc.GapNumber, true) + epochInfo, err := x.getEpochSwitchInfo(chain, nil, qc.ProposedBlockInfo.Hash) if err != nil { - log.Error("[VerifySyncInfoMessage] fail to get snapshot for a syncInfo message", "blockNum", qc.ProposedBlockInfo.Number, "blockHash", qc.ProposedBlockInfo.Hash, "error", err) + log.Error("[VerifySyncInfoMessage] fail to get epochInfo for qc syncInfo message", "blockNum", qc.ProposedBlockInfo.Number, "blockHash", qc.ProposedBlockInfo.Hash, "error", err) return false, err } @@ -42,16 +42,16 @@ func (x *XDPoS_v2) VerifySyncInfoMessage(chain consensus.ChainReader, syncInfo * GapNumber: qc.GapNumber, }) - if err := x.verifySignatures(voteSigHash, qc.Signatures, snapshot.NextEpochCandidates); err != nil { + if err := x.verifySignatures(voteSigHash, qc.Signatures, epochInfo.Masternodes); err != nil { log.Warn("[VerifySyncInfoMessage] SyncInfo message verification failed due to QC", "blockNum", qc.ProposedBlockInfo.Number, "gapNum", qc.GapNumber, "round", qc.ProposedBlockInfo.Round, "error", err) return false, err } if tc != nil { // tc is optional, when the node is starting up there is no TC at the memory - snapshot, err = x.getSnapshot(chain, tc.GapNumber, true) + epochInfo, err := x.getTCEpochInfo(chain, tc.Round) if err != nil { - log.Error("[VerifySyncInfoMessage] Fail to get snapshot when verifying TC!", "tcGapNumber", tc.GapNumber) - return false, fmt.Errorf("[VerifySyncInfoMessage] Unable to get snapshot, %s", err) + log.Error("[VerifySyncInfoMessage] Fail to get epochInfo for tc syncInfo message", "tcRound", tc.Round, "error", err) + return false, err } signedTimeoutObj := types.TimeoutSigHash(&types.TimeoutForSign{ @@ -59,7 +59,7 @@ func (x *XDPoS_v2) VerifySyncInfoMessage(chain consensus.ChainReader, syncInfo * GapNumber: tc.GapNumber, }) - if err := x.verifySignatures(signedTimeoutObj, tc.Signatures, snapshot.NextEpochCandidates); err != nil { + if err := x.verifySignatures(signedTimeoutObj, tc.Signatures, epochInfo.Masternodes); err != nil { log.Warn("[VerifySyncInfoMessage] SyncInfo message verification failed due to TC", "gapNum", tc.GapNumber, "round", tc.Round, "error", err) return false, err } diff --git a/consensus/XDPoS/engines/engine_v2/timeout.go b/consensus/XDPoS/engines/engine_v2/timeout.go index 15f030cdd90d..4d69ed137138 100644 --- a/consensus/XDPoS/engines/engine_v2/timeout.go +++ b/consensus/XDPoS/engines/engine_v2/timeout.go @@ -22,12 +22,15 @@ func (x *XDPoS_v2) VerifyTimeoutMessage(chain consensus.ChainReader, timeoutMsg log.Debug("[VerifyTimeoutMessage] Disqualified timeout message as the proposed round does not match currentRound", "timeoutHash", timeoutMsg.Hash(), "timeoutRound", timeoutMsg.Round, "currentRound", x.currentRound) return false, nil } - snap, err := x.getSnapshot(chain, timeoutMsg.GapNumber, true) - if err != nil || snap == nil { - log.Error("[VerifyTimeoutMessage] Fail to get snapshot when verifying timeout message!", "messageGapNumber", timeoutMsg.GapNumber, "err", err) + + epochInfo, err := x.getTCEpochInfo(chain, timeoutMsg.Round) + if err != nil { + log.Error("[VerifyTimeoutMessage] Fail to get epochInfo for timeout message", "tcGapNumber", timeoutMsg.GapNumber, "tcRound", timeoutMsg.Round, "error", err) return false, err } - if len(snap.NextEpochCandidates) == 0 { + + if len(epochInfo.Masternodes) == 0 { + // TODO: why this check is needed here? how about other places for epochInfo.Masternodes? log.Error("[VerifyTimeoutMessage] cannot find NextEpochCandidates from snapshot", "messageGapNumber", timeoutMsg.GapNumber) return false, errors.New("empty master node lists from snapshot") } @@ -35,7 +38,7 @@ func (x *XDPoS_v2) VerifyTimeoutMessage(chain consensus.ChainReader, timeoutMsg verified, signer, err := x.verifyMsgSignature(types.TimeoutSigHash(&types.TimeoutForSign{ Round: timeoutMsg.Round, GapNumber: timeoutMsg.GapNumber, - }), timeoutMsg.Signature, snap.NextEpochCandidates) + }), timeoutMsg.Signature, epochInfo.Masternodes) if err != nil { log.Warn("[VerifyTimeoutMessage] cannot verify timeout signature", "err", err) @@ -116,7 +119,7 @@ func (x *XDPoS_v2) onTimeoutPoolThresholdReached(blockChainReader consensus.Chai return nil } -func (x *XDPoS_v2) getTCEpochInfo(chain consensus.ChainReader, timeoutCert *types.TimeoutCert) (*types.EpochSwitchInfo, error) { +func (x *XDPoS_v2) getTCEpochInfo(chain consensus.ChainReader, timeoutRound types.Round) (*types.EpochSwitchInfo, error) { epochSwitchInfo, err := x.getEpochSwitchInfo(chain, (chain.CurrentHeader()), (chain.CurrentHeader()).Hash()) if err != nil { log.Error("[getTCEpochInfo] Error when getting epoch switch info", "error", err) @@ -131,18 +134,18 @@ func (x *XDPoS_v2) getTCEpochInfo(chain consensus.ChainReader, timeoutCert *type Round: epochRound, Number: epochSwitchInfo.EpochSwitchBlockInfo.Number, } - log.Info("[getTCEpochInfo] Init epochInfo", "number", epochBlockInfo.Number, "round", epochRound, "tcRound", timeoutCert.Round, "tcEpoch", tempTCEpoch) - for epochBlockInfo.Round > timeoutCert.Round { + log.Info("[getTCEpochInfo] Init epochInfo", "number", epochBlockInfo.Number, "round", epochRound, "tcRound", timeoutRound, "tcEpoch", tempTCEpoch) + for epochBlockInfo.Round > timeoutRound { tempTCEpoch-- epochBlockInfo, err = x.GetBlockByEpochNumber(chain, tempTCEpoch) if err != nil { log.Error("[getTCEpochInfo] Error when getting epoch block info by tc round", "error", err) return nil, fmt.Errorf("fail on getTCEpochInfo due to failure in getting epoch block info tc round, %s", err) } - log.Debug("[getTCEpochInfo] Loop to get right epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutCert.Round, "tcEpoch", tempTCEpoch) + log.Debug("[getTCEpochInfo] Loop to get right epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutRound, "tcEpoch", tempTCEpoch) } tcEpoch := tempTCEpoch - log.Info("[getTCEpochInfo] Final TC epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutCert.Round, "tcEpoch", tcEpoch) + log.Info("[getTCEpochInfo] Final TC epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutRound, "tcEpoch", tcEpoch) epochInfo, err := x.getEpochSwitchInfo(chain, nil, epochBlockInfo.Hash) if err != nil { @@ -175,7 +178,7 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time } } - epochInfo, err := x.getTCEpochInfo(chain, timeoutCert) + epochInfo, err := x.getTCEpochInfo(chain, timeoutCert.Round) if err != nil { return err } diff --git a/consensus/XDPoS/engines/engine_v2/vote.go b/consensus/XDPoS/engines/engine_v2/vote.go index c7a8cdec82c9..c2e960086bf9 100644 --- a/consensus/XDPoS/engines/engine_v2/vote.go +++ b/consensus/XDPoS/engines/engine_v2/vote.go @@ -22,17 +22,18 @@ func (x *XDPoS_v2) VerifyVoteMessage(chain consensus.ChainReader, vote *types.Vo return false, nil } - snapshot, err := x.getSnapshot(chain, vote.GapNumber, true) + epochInfo, err := x.getEpochSwitchInfo(chain, chain.CurrentHeader(), chain.CurrentHeader().Hash()) if err != nil { - log.Error("[VerifyVoteMessage] fail to get snapshot for a vote message", "blockNum", vote.ProposedBlockInfo.Number, "blockHash", vote.ProposedBlockInfo.Hash, "voteHash", vote.Hash(), "error", err.Error()) + log.Error("[VerifyVoteMessage] Fail to get epochInfo when verifying vote message!", "blockNum", vote.ProposedBlockInfo.Number, "blockHash", vote.ProposedBlockInfo.Hash, "voteHash", vote.Hash(), "voteGapNumber", vote.GapNumber, "err", err) return false, err } + verified, signer, err := x.verifyMsgSignature(types.VoteSigHash(&types.VoteForSign{ ProposedBlockInfo: vote.ProposedBlockInfo, GapNumber: vote.GapNumber, - }), vote.Signature, snapshot.NextEpochCandidates) + }), vote.Signature, epochInfo.Masternodes) if err != nil { - for i, mn := range snapshot.NextEpochCandidates { + for i, mn := range epochInfo.Masternodes { log.Warn("[VerifyVoteMessage] Master node list item", "index", i, "Master node", mn.Hex()) } log.Warn("[VerifyVoteMessage] Error while verifying vote message", "votedBlockNum", vote.ProposedBlockInfo.Number.Uint64(), "votedBlockHash", vote.ProposedBlockInfo.Hash.Hex(), "voteHash", vote.Hash(), "error", err.Error()) From f5e4dd1df380985824b83d80d0d6e891c2d2f227 Mon Sep 17 00:00:00 2001 From: wanwiset25 Date: Tue, 18 Nov 2025 01:52:25 +0400 Subject: [PATCH 2/2] remove missing snapshot test (now irrelevant) --- consensus/tests/engine_v2_tests/vote_test.go | 26 -------------------- 1 file changed, 26 deletions(-) diff --git a/consensus/tests/engine_v2_tests/vote_test.go b/consensus/tests/engine_v2_tests/vote_test.go index 7febbd8cc7b5..777efc11d7c0 100644 --- a/consensus/tests/engine_v2_tests/vote_test.go +++ b/consensus/tests/engine_v2_tests/vote_test.go @@ -537,32 +537,6 @@ func TestVerifyVoteMsg(t *testing.T) { assert.Nil(t, err) } -func TestVoteMsgMissingSnapshot(t *testing.T) { - blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 915, params.TestXDPoSMockChainConfig, nil) - engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2 - - blockInfo := &types.BlockInfo{ - Hash: currentBlock.Hash(), - Round: types.Round(14), - Number: big.NewInt(915), - } - voteForSign := &types.VoteForSign{ - ProposedBlockInfo: blockInfo, - GapNumber: 450, - } - - signHash, _ := signFn(accounts.Account{Address: signer}, types.VoteSigHash(voteForSign).Bytes()) - voteMsg := &types.Vote{ - ProposedBlockInfo: blockInfo, - Signature: signHash, - GapNumber: 1350, // missing 1350 snapshot - } - engineV2.SetNewRoundFaker(blockchain, types.Round(14), false) - verified, err := engineV2.VerifyVoteMessage(blockchain, voteMsg) - assert.False(t, verified) - assert.NotNil(t, err) -} - func TestVoteMessageHandlerWrongGapNumber(t *testing.T) { blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil) engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2