From b8e5baa97861634a4fbad1a179c57e12c9c93a3e Mon Sep 17 00:00:00 2001 From: wgr523 Date: Wed, 17 Sep 2025 22:50:52 +0800 Subject: [PATCH] all: fix minted token recorded value is zero (#1480) --- .../tests/engine_v2_tests/reward_test.go | 68 +++++++++++++++++++ core/state/statedb_utils.go | 5 ++ eth/hooks/engine_v2_hooks.go | 2 + 3 files changed, 75 insertions(+) diff --git a/consensus/tests/engine_v2_tests/reward_test.go b/consensus/tests/engine_v2_tests/reward_test.go index dbc9733148..961209feb8 100644 --- a/consensus/tests/engine_v2_tests/reward_test.go +++ b/consensus/tests/engine_v2_tests/reward_test.go @@ -305,6 +305,74 @@ func TestHookRewardAfterUpgrade(t *testing.T) { common.TIPUpgradeReward = backup } +func TestFinalizeAfterUpgrade(t *testing.T) { + b, err := json.Marshal(params.TestXDPoSMockChainConfig) + assert.Nil(t, err) + configString := string(b) + + var config params.ChainConfig + err = json.Unmarshal([]byte(configString), &config) + assert.Nil(t, err) + // set switch to 1800, so that it covers 901-1799, 1800-2700 two epochs + config.XDPoS.V2.SwitchBlock.SetUint64(1800) + config.XDPoS.V2.SwitchEpoch = 2 + // set upgrade number to 0 + backup := common.TIPUpgradeReward + common.TIPUpgradeReward = big.NewInt(0) + + blockchain, _, _, signer, signFn := PrepareXDCTestBlockChainWithProtectorObserver(t, int(config.XDPoS.Epoch)*3+10, &config) + + adaptor := blockchain.Engine().(*XDPoS.XDPoS) + hooks.AttachConsensusV2Hooks(adaptor, blockchain, &config) + assert.NotNil(t, adaptor.EngineV2.HookReward) + // forcely insert signing tx into cache, to give rewards. + header915 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch + 15) + header916 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch + 16) + header1785 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch*2 - 15) + header1799 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch*2 - 1) + tx, err := signingTxWithSignerFn(header915, 0, signer, signFn) + assert.Nil(t, err) + adaptor.CacheSigningTxs(header916.Hash(), []*types.Transaction{tx}) + tx2, err := signingTxWithKey(header915, 0, acc1Key) + assert.Nil(t, err) + tx3, err := signingTxWithKey(header1785, 0, acc1Key) + assert.Nil(t, err) + tx4, err := signingTxWithKey(header1785, 0, protector1Key) + assert.Nil(t, err) + tx5, err := signingTxWithKey(header1785, 0, observer1Key) + assert.Nil(t, err) + tx6, err := signingTxWithKey(header915, 0, protector2Key) + assert.Nil(t, err) + tx7, err := signingTxWithKey(header1785, 0, protector2Key) + assert.Nil(t, err) + tx8, err := signingTxWithKey(header1785, 0, observer2Key) + assert.Nil(t, err) + adaptor.CacheSigningTxs(header1799.Hash(), []*types.Transaction{tx2, tx3, tx4, tx5, tx6, tx7, tx8}) + + header2700 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch * 3) + header2699 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch*3 - 1) + statedb, err := blockchain.StateAt(header2700.Root) + assert.Nil(t, err) + parentstatedb, err := blockchain.StateAt(header2699.Root) + assert.Nil(t, err) + + blockAfterFinalize, err := adaptor.Finalize(blockchain, header2700, statedb, parentstatedb, nil, nil, nil) + assert.Nil(t, err) + + _, err = blockchain.WriteBlockWithState(blockAfterFinalize, nil, statedb, nil, nil) + assert.Nil(t, err) + + statedbAfterFinalize, err := blockchain.StateAt(blockAfterFinalize.Header().Root) + assert.Nil(t, err) + + // the recorded reward cannot be zero + minted := state.GetTotalMinted(statedbAfterFinalize) + assert.False(t, minted.IsZero()) + t.Log("total minted", minted) + + common.TIPUpgradeReward = backup +} + func TestRewardHalvingVanishing(t *testing.T) { billion := big.NewInt(1000000000) epochRewardTotal := big.NewInt(16000) diff --git a/core/state/statedb_utils.go b/core/state/statedb_utils.go index bc459235a8..8eb4b817ce 100644 --- a/core/state/statedb_utils.go +++ b/core/state/statedb_utils.go @@ -179,3 +179,8 @@ func PutLastEpochNum(statedb *StateDB, value common.Hash) { hash := GetLocSimpleVariable(slotMintedRecordLastEpochNum) statedb.SetState(common.MintedRecordAddressBinary, hash, value) } + +func IncrementMintedRecordNonce(statedb *StateDB) { + nonce := statedb.GetNonce(common.MintedRecordAddressBinary) + statedb.SetNonce(common.MintedRecordAddressBinary, nonce+1) +} diff --git a/eth/hooks/engine_v2_hooks.go b/eth/hooks/engine_v2_hooks.go index cba681c53b..63d1af53b3 100644 --- a/eth/hooks/engine_v2_hooks.go +++ b/eth/hooks/engine_v2_hooks.go @@ -365,6 +365,8 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf log.Debug("[HookReward] total minted in hook", "value", totalMinted) state.PutTotalMinted(stateBlock, common.BigToHash(totalMinted)) state.PutLastEpochNum(stateBlock, common.Uint64ToHash(epochNum)) + // Increment nonce so that statedb does not treat it as empty account + state.IncrementMintedRecordNonce(stateBlock) } log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) return rewardsMap, nil