From 9d40fb40fca7407237b9c2cbb32d5138599faeea Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Mon, 3 Nov 2025 18:45:48 +0800 Subject: [PATCH] engine_v2: verify gap number in UpdateMasternodes, close XFN-11 (#1622) --- consensus/XDPoS/engines/engine_v1/engine.go | 5 +-- consensus/XDPoS/engines/engine_v2/engine.go | 5 ++- consensus/tests/engine_v2_tests/api_test.go | 2 +- consensus/tests/engine_v2_tests/helper.go | 38 ++++++++++----------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/consensus/XDPoS/engines/engine_v1/engine.go b/consensus/XDPoS/engines/engine_v1/engine.go index bdc2c92012..2c1d73d3e0 100644 --- a/consensus/XDPoS/engines/engine_v1/engine.go +++ b/consensus/XDPoS/engines/engine_v1/engine.go @@ -790,6 +790,9 @@ func (x *XDPoS_v1) Prepare(chain consensus.ChainReader, header *types.Header) er // Update masternodes into snapshot. In V1, truncating ms[:MaxMasternodes] is done in this function. func (x *XDPoS_v1) UpdateMasternodes(chain consensus.ChainReader, header *types.Header, ms []utils.Masternode) error { + number := header.Number.Uint64() + log.Trace("take snapshot", "number", number, "hash", header.Hash()) + var maxMasternodes int // check if block number is increase ms checkpoint if x.chainConfig.IsTIPIncreaseMasternodes(header.Number) || (x.config.V2.SwitchBlock != nil && header.Number.Cmp(x.config.V2.SwitchBlock) == 1) { @@ -802,8 +805,6 @@ func (x *XDPoS_v1) UpdateMasternodes(chain consensus.ChainReader, header *types. if len(ms) > maxMasternodes { ms = ms[:maxMasternodes] } - number := header.Number.Uint64() - log.Trace("take snapshot", "number", number, "hash", header.Hash()) // get snapshot snap, err := x.snapshot(chain, number, header.Hash(), nil, header) if err != nil { diff --git a/consensus/XDPoS/engines/engine_v2/engine.go b/consensus/XDPoS/engines/engine_v2/engine.go index 0469d3aec8..56d4d16412 100644 --- a/consensus/XDPoS/engines/engine_v2/engine.go +++ b/consensus/XDPoS/engines/engine_v2/engine.go @@ -509,7 +509,10 @@ func (x *XDPoS_v2) GetSnapshot(chain consensus.ChainReader, header *types.Header func (x *XDPoS_v2) UpdateMasternodes(chain consensus.ChainReader, header *types.Header, ms []utils.Masternode) error { number := header.Number.Uint64() - log.Trace("[UpdateMasternodes]") + log.Trace("[UpdateMasternodes]", "number", number, "hash", header.Hash()) + if number%x.config.Epoch != x.config.Epoch-x.config.Gap { + return fmt.Errorf("[UpdateMasternodes] not gap block, number: %d, epoch: %d,gap: %d", number, x.config.Epoch, x.config.Gap) + } masterNodes := []common.Address{} for _, m := range ms { diff --git a/consensus/tests/engine_v2_tests/api_test.go b/consensus/tests/engine_v2_tests/api_test.go index d02790d894..4c65a52a29 100644 --- a/consensus/tests/engine_v2_tests/api_test.go +++ b/consensus/tests/engine_v2_tests/api_test.go @@ -86,7 +86,7 @@ func TestGetMissedRoundsInEpochByBlockNum(t *testing.T) { } // Update Signer as there is no previous signer assigned - err = UpdateSigner(blockchain) + blockchain.UpdateM1() if err != nil { t.Fatal(err) } diff --git a/consensus/tests/engine_v2_tests/helper.go b/consensus/tests/engine_v2_tests/helper.go index e07a02a0b2..d351421a04 100644 --- a/consensus/tests/engine_v2_tests/helper.go +++ b/consensus/tests/engine_v2_tests/helper.go @@ -295,11 +295,6 @@ func signingTxWithSignerFn(header *types.Header, nonce uint64, signer common.Add return signedTx, nil } -func UpdateSigner(bc *core.BlockChain) error { - err := bc.UpdateM1() - return err -} - func GetSnapshotSigner(bc *core.BlockChain, header *types.Header) (signersList, error) { engine := bc.Engine().(*XDPoS.XDPoS) snap, err := engine.GetSnapshot(bc, header) @@ -425,12 +420,13 @@ func PrepareXDCTestBlockChainForV2Engine(t *testing.T, numOfBlocks int, chainCon } currentBlock = block - } - // Update Signer as there is no previous signer assigned - err = UpdateSigner(blockchain) - if err != nil { - t.Fatal(err) + if uint64(i)%chainConfig.XDPoS.Epoch == chainConfig.XDPoS.Epoch-chainConfig.XDPoS.Gap { + err := blockchain.UpdateM1() + if err != nil { + t.Fatal(err) + } + } } return blockchain, backend, currentBlock, signer, signFn, currentForkBlock @@ -476,12 +472,13 @@ func PrepareXDCTestBlockChainWithPenaltyForV2Engine(t *testing.T, numOfBlocks in t.Fatal(err) } currentBlock = block - } - // Update Signer as there is no previous signer assigned - err = UpdateSigner(blockchain) - if err != nil { - t.Fatal(err) + if uint64(i)%chainConfig.XDPoS.Epoch == chainConfig.XDPoS.Epoch-chainConfig.XDPoS.Gap { + err := blockchain.UpdateM1() + if err != nil { + t.Fatal(err) + } + } } return blockchain, backend, currentBlock, signer, signFn @@ -539,12 +536,13 @@ func PrepareXDCTestBlockChainWith128Candidates(t *testing.T, numOfBlocks int, ch } currentBlock = block - } - // Update Signer as there is no previous signer assigned - err = UpdateSigner(blockchain) - if err != nil { - t.Fatal(err) + if uint64(i)%chainConfig.XDPoS.Epoch == chainConfig.XDPoS.Epoch-chainConfig.XDPoS.Gap { + err := blockchain.UpdateM1() + if err != nil { + t.Fatal(err) + } + } } return blockchain, backend, currentBlock, signer, signFn