mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 02:40:45 +00:00
record total minted into smart contract (#1026)
* feat: record total minted into smart contract * feat: GetCurrentTotalMinted API
This commit is contained in:
parent
ae70b5dc14
commit
e13265a7d7
6 changed files with 84 additions and 0 deletions
|
|
@ -68,6 +68,7 @@ var (
|
||||||
XDCXLendingFinalizedTradeAddressBinary = HexToAddress("0x0000000000000000000000000000000000000094")
|
XDCXLendingFinalizedTradeAddressBinary = HexToAddress("0x0000000000000000000000000000000000000094")
|
||||||
XDCNativeAddressBinary = HexToAddress("0x0000000000000000000000000000000000000001")
|
XDCNativeAddressBinary = HexToAddress("0x0000000000000000000000000000000000000001")
|
||||||
LendingLockAddressBinary = HexToAddress("0x0000000000000000000000000000000000000011")
|
LendingLockAddressBinary = HexToAddress("0x0000000000000000000000000000000000000011")
|
||||||
|
MintedRecordAddressBinary = HexToAddress("0x000000000000000000000000000000000000009a")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ func TestHookRewardAfterUpgrade(t *testing.T) {
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
// set switch to 1800, so that it covers 901-1799, 1800-2700 two epochs
|
// set switch to 1800, so that it covers 901-1799, 1800-2700 two epochs
|
||||||
config.XDPoS.V2.SwitchBlock.SetUint64(1800)
|
config.XDPoS.V2.SwitchBlock.SetUint64(1800)
|
||||||
|
config.XDPoS.V2.SwitchEpoch = 2
|
||||||
// set upgrade number to 0
|
// set upgrade number to 0
|
||||||
backup := common.TIPUpgradeReward
|
backup := common.TIPUpgradeReward
|
||||||
common.TIPUpgradeReward = big.NewInt(0)
|
common.TIPUpgradeReward = big.NewInt(0)
|
||||||
|
|
@ -296,6 +297,11 @@ func TestHookRewardAfterUpgrade(t *testing.T) {
|
||||||
b, _ := big.NewInt(0).SetString("30012500000000000000", 10) // this value tests the float64 reward
|
b, _ := big.NewInt(0).SetString("30012500000000000000", 10) // this value tests the float64 reward
|
||||||
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]), "real reward is", r[config.XDPoS.FoudationWalletAddr])
|
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]), "real reward is", r[config.XDPoS.FoudationWalletAddr])
|
||||||
}
|
}
|
||||||
|
totalMinted := state.GetTotalMinted(statedb).Big()
|
||||||
|
totalExpect, _ := big.NewInt(0).SetString("2100125000000000000000", 10)
|
||||||
|
assert.Zero(t, totalMinted.Cmp(totalExpect), "statedb records wrong total minted")
|
||||||
|
lastEpochNum := state.GetLastEpochNum(statedb).Big().Int64()
|
||||||
|
assert.Equal(t, 3, int(lastEpochNum))
|
||||||
common.TIPUpgradeReward = backup
|
common.TIPUpgradeReward = backup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,3 +152,30 @@ func GetVoterCap(statedb *StateDB, candidate, voter common.Address) *big.Int {
|
||||||
ret := statedb.GetState(common.MasternodeVotingSMCBinary, common.BytesToHash(retByte))
|
ret := statedb.GetState(common.MasternodeVotingSMCBinary, common.BytesToHash(retByte))
|
||||||
return ret.Big()
|
return ret.Big()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
slotMintedRecordTotalMinted uint64 = 0
|
||||||
|
slotMintedRecordLastEpochNum uint64 = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTotalMinted(statedb *StateDB) common.Hash {
|
||||||
|
hash := GetLocSimpleVariable(slotMintedRecordTotalMinted)
|
||||||
|
totalMinted := statedb.GetState(common.MintedRecordAddressBinary, hash)
|
||||||
|
return totalMinted
|
||||||
|
}
|
||||||
|
|
||||||
|
func PutTotalMinted(statedb *StateDB, value common.Hash) {
|
||||||
|
hash := GetLocSimpleVariable(slotMintedRecordTotalMinted)
|
||||||
|
statedb.SetState(common.MintedRecordAddressBinary, hash, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLastEpochNum(statedb *StateDB) common.Hash {
|
||||||
|
hash := GetLocSimpleVariable(slotMintedRecordLastEpochNum)
|
||||||
|
totalMinted := statedb.GetState(common.MintedRecordAddressBinary, hash)
|
||||||
|
return totalMinted
|
||||||
|
}
|
||||||
|
|
||||||
|
func PutLastEpochNum(statedb *StateDB, value common.Hash) {
|
||||||
|
hash := GetLocSimpleVariable(slotMintedRecordLastEpochNum)
|
||||||
|
statedb.SetState(common.MintedRecordAddressBinary, hash, value)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,7 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
round, err := adaptor.EngineV2.GetRoundNumber(header)
|
round, err := adaptor.EngineV2.GetRoundNumber(header)
|
||||||
|
epochNum := chain.Config().XDPoS.V2.SwitchEpoch + uint64(round)/chain.Config().XDPoS.Epoch
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("[HookReward] Fail to get round", "error", err)
|
log.Error("[HookReward] Fail to get round", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -233,6 +234,7 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
|
||||||
} else {
|
} else {
|
||||||
rewardsMap["signersProtector"] = signers[ProtectorNodeBeneficiary]
|
rewardsMap["signersProtector"] = signers[ProtectorNodeBeneficiary]
|
||||||
rewardsMap["signersObserver"] = signers[ObserverNodeBeneficiary]
|
rewardsMap["signersObserver"] = signers[ObserverNodeBeneficiary]
|
||||||
|
rewardSum := new(big.Int)
|
||||||
type rewardWithType struct {
|
type rewardWithType struct {
|
||||||
r float64
|
r float64
|
||||||
t Beneficiary
|
t Beneficiary
|
||||||
|
|
@ -262,12 +264,32 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
|
||||||
if len(rewards) > 0 {
|
if len(rewards) > 0 {
|
||||||
for holder, reward := range rewards {
|
for holder, reward := range rewards {
|
||||||
stateBlock.AddBalance(holder, reward)
|
stateBlock.AddBalance(holder, reward)
|
||||||
|
rewardSum.Add(rewardSum, reward)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rewardResults[signer] = rewards
|
rewardResults[signer] = rewards
|
||||||
}
|
}
|
||||||
rewardsMap[rwt.key] = rewardResults
|
rewardsMap[rwt.key] = rewardResults
|
||||||
}
|
}
|
||||||
|
// record the total reward into state db
|
||||||
|
totalMinted := state.GetTotalMinted(stateBlock).Big()
|
||||||
|
lastEpochNum := state.GetLastEpochNum(stateBlock)
|
||||||
|
if lastEpochNum.IsZero() {
|
||||||
|
// if `lastEpochNum` is zero, the total minted has not included tokens before TIPUpgradeReward
|
||||||
|
// calculate the tokens before TIPUpgradeReward and set to totalMinted
|
||||||
|
// for now no-do
|
||||||
|
}
|
||||||
|
totalMinted.Add(totalMinted, rewardSum)
|
||||||
|
bigPower256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
||||||
|
bigMaxU256 := new(big.Int).Sub(bigPower256, big.NewInt(1))
|
||||||
|
// if overflow, set to maxU256 and log a warning
|
||||||
|
if totalMinted.Cmp(bigMaxU256) >= 0 {
|
||||||
|
totalMinted.Set(bigMaxU256)
|
||||||
|
log.Warn("[HookReward] total minted overflow max u256")
|
||||||
|
}
|
||||||
|
log.Debug("[HookReward] total minted in hook", "value", totalMinted)
|
||||||
|
state.PutTotalMinted(stateBlock, common.BigToHash(totalMinted))
|
||||||
|
state.PutLastEpochNum(stateBlock, common.Uint64ToHash(epochNum))
|
||||||
}
|
}
|
||||||
log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||||
return rewardsMap, nil
|
return rewardsMap, nil
|
||||||
|
|
|
||||||
|
|
@ -3639,3 +3639,26 @@ func (s *PublicBlockChainAPI) GetStakerROIMasternode(masternode common.Address)
|
||||||
|
|
||||||
return 100.0 / float64(totalCap.Div(totalCap, voterRewardAYear).Uint64())
|
return 100.0 / float64(totalCap.Div(totalCap, voterRewardAYear).Uint64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type currentTotalMinted struct {
|
||||||
|
TotalMinted *hexutil.Big `json:"totalMinted"`
|
||||||
|
LastEpochNum *hexutil.Big `json:"lastEpochNum"`
|
||||||
|
BlockHash common.Hash `json:"blockHash"`
|
||||||
|
BlockNumber *hexutil.Big `json:"blockNumber"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublicBlockChainAPI) GetCurrentTotalMinted(ctx context.Context) (*currentTotalMinted, error) {
|
||||||
|
statedb, header, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
totalMinted := state.GetTotalMinted(statedb).Big()
|
||||||
|
lastEpochNum := state.GetLastEpochNum(statedb).Big()
|
||||||
|
result := ¤tTotalMinted{
|
||||||
|
TotalMinted: (*hexutil.Big)(totalMinted),
|
||||||
|
LastEpochNum: (*hexutil.Big)(lastEpochNum),
|
||||||
|
BlockHash: header.Hash(),
|
||||||
|
BlockNumber: (*hexutil.Big)(header.Number),
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -555,6 +555,11 @@ web3._extend({
|
||||||
call: 'eth_getBlockReceipts',
|
call: 'eth_getBlockReceipts',
|
||||||
params: 1,
|
params: 1,
|
||||||
}),
|
}),
|
||||||
|
new web3._extend.Method({
|
||||||
|
name: 'getCurrentTotalMinted',
|
||||||
|
call: 'eth_getCurrentTotalMinted',
|
||||||
|
params: 0,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
properties: [
|
properties: [
|
||||||
new web3._extend.Property({
|
new web3._extend.Property({
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue