mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 02:10:46 +00:00
Merge pull request #924 from XinFinOrg/update-reward-percapita
Update reward percapita
This commit is contained in:
commit
b8a9a8bfb1
8 changed files with 180 additions and 94 deletions
|
|
@ -62,6 +62,7 @@ type constant struct {
|
||||||
tipXDCXMinerDisable *big.Int
|
tipXDCXMinerDisable *big.Int
|
||||||
tipXDCXReceiverDisable *big.Int
|
tipXDCXReceiverDisable *big.Int
|
||||||
tipUpgradeReward *big.Int
|
tipUpgradeReward *big.Int
|
||||||
|
tipEpochHalving *big.Int
|
||||||
eip1559Block *big.Int
|
eip1559Block *big.Int
|
||||||
cancunBlock *big.Int
|
cancunBlock *big.Int
|
||||||
|
|
||||||
|
|
@ -104,6 +105,7 @@ var (
|
||||||
TIPXDCXMinerDisable = MaintnetConstant.tipXDCXMinerDisable
|
TIPXDCXMinerDisable = MaintnetConstant.tipXDCXMinerDisable
|
||||||
TIPXDCXReceiverDisable = MaintnetConstant.tipXDCXReceiverDisable
|
TIPXDCXReceiverDisable = MaintnetConstant.tipXDCXReceiverDisable
|
||||||
TIPUpgradeReward = MaintnetConstant.tipUpgradeReward
|
TIPUpgradeReward = MaintnetConstant.tipUpgradeReward
|
||||||
|
TIPEpochHalving = MaintnetConstant.tipEpochHalving
|
||||||
Eip1559Block = MaintnetConstant.eip1559Block
|
Eip1559Block = MaintnetConstant.eip1559Block
|
||||||
CancunBlock = MaintnetConstant.cancunBlock
|
CancunBlock = MaintnetConstant.cancunBlock
|
||||||
|
|
||||||
|
|
@ -170,6 +172,7 @@ func CopyConstans(chainID uint64) {
|
||||||
TIPXDCXMinerDisable = c.tipXDCXMinerDisable
|
TIPXDCXMinerDisable = c.tipXDCXMinerDisable
|
||||||
TIPXDCXReceiverDisable = c.tipXDCXReceiverDisable
|
TIPXDCXReceiverDisable = c.tipXDCXReceiverDisable
|
||||||
TIPUpgradeReward = c.tipUpgradeReward
|
TIPUpgradeReward = c.tipUpgradeReward
|
||||||
|
TIPEpochHalving = c.tipEpochHalving
|
||||||
Eip1559Block = c.eip1559Block
|
Eip1559Block = c.eip1559Block
|
||||||
CancunBlock = c.cancunBlock
|
CancunBlock = c.cancunBlock
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ var DevnetConstant = constant{
|
||||||
eip1559Block: big.NewInt(0),
|
eip1559Block: big.NewInt(0),
|
||||||
cancunBlock: big.NewInt(1702800),
|
cancunBlock: big.NewInt(1702800),
|
||||||
tipUpgradeReward: big.NewInt(1773000),
|
tipUpgradeReward: big.NewInt(1773000),
|
||||||
|
tipEpochHalving: big.NewInt(9999999999),
|
||||||
|
|
||||||
trc21IssuerSMCTestNet: HexToAddress("0x0E2C88753131CE01c7551B726b28BFD04e44003F"),
|
trc21IssuerSMCTestNet: HexToAddress("0x0E2C88753131CE01c7551B726b28BFD04e44003F"),
|
||||||
trc21IssuerSMC: HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
|
trc21IssuerSMC: HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ var MaintnetConstant = constant{
|
||||||
eip1559Block: big.NewInt(9999999999),
|
eip1559Block: big.NewInt(9999999999),
|
||||||
cancunBlock: big.NewInt(9999999999),
|
cancunBlock: big.NewInt(9999999999),
|
||||||
tipUpgradeReward: big.NewInt(9999999999),
|
tipUpgradeReward: big.NewInt(9999999999),
|
||||||
|
tipEpochHalving: big.NewInt(9999999999),
|
||||||
|
|
||||||
trc21IssuerSMCTestNet: HexToAddress("0x0E2C88753131CE01c7551B726b28BFD04e44003F"),
|
trc21IssuerSMCTestNet: HexToAddress("0x0E2C88753131CE01c7551B726b28BFD04e44003F"),
|
||||||
trc21IssuerSMC: HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
|
trc21IssuerSMC: HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ var TestnetConstant = constant{
|
||||||
eip1559Block: big.NewInt(71550000), // Target 14th Feb 2025
|
eip1559Block: big.NewInt(71550000), // Target 14th Feb 2025
|
||||||
cancunBlock: big.NewInt(9999999999),
|
cancunBlock: big.NewInt(9999999999),
|
||||||
tipUpgradeReward: big.NewInt(9999999999),
|
tipUpgradeReward: big.NewInt(9999999999),
|
||||||
|
tipEpochHalving: big.NewInt(9999999999),
|
||||||
|
|
||||||
trc21IssuerSMCTestNet: HexToAddress("0x0E2C88753131CE01c7551B726b28BFD04e44003F"),
|
trc21IssuerSMCTestNet: HexToAddress("0x0E2C88753131CE01c7551B726b28BFD04e44003F"),
|
||||||
trc21IssuerSMC: HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
|
trc21IssuerSMC: HexToAddress("0x8c0faeb5C6bEd2129b8674F262Fd45c4e9468bee"),
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/hooks"
|
"github.com/XinFinOrg/XDPoSChain/eth/hooks"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/eth/util"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
@ -223,21 +224,21 @@ func TestHookRewardAfterUpgrade(t *testing.T) {
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
result := reward["rewards"].(map[common.Address]interface{})
|
result := reward["rewards"].(map[common.Address]interface{})
|
||||||
assert.Equal(t, 2, len(result))
|
assert.Equal(t, 2, len(result))
|
||||||
// two signing account, 3 txs, reward is split by 1:2 (total reward is 250...000)
|
// two signing account, both get fixed reward
|
||||||
for addr, x := range result {
|
for addr, x := range result {
|
||||||
if addr == acc1Addr {
|
if addr == acc1Addr {
|
||||||
r := x.(map[common.Address]*big.Int)
|
r := x.(map[common.Address]*big.Int)
|
||||||
owner := state.GetCandidateOwner(parentState, addr)
|
owner := state.GetCandidateOwner(parentState, addr)
|
||||||
a, _ := big.NewInt(0).SetString("299999999999999999998", 10)
|
a, _ := big.NewInt(0).SetString("450000000000000000000", 10)
|
||||||
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
||||||
b, _ := big.NewInt(0).SetString("33333333333333333333", 10)
|
b, _ := big.NewInt(0).SetString("50000000000000000000", 10)
|
||||||
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])
|
||||||
} else if addr == signer {
|
} else if addr == signer {
|
||||||
r := x.(map[common.Address]*big.Int)
|
r := x.(map[common.Address]*big.Int)
|
||||||
owner := state.GetCandidateOwner(parentState, addr)
|
owner := state.GetCandidateOwner(parentState, addr)
|
||||||
a, _ := big.NewInt(0).SetString("149999999999999999999", 10)
|
a, _ := big.NewInt(0).SetString("450000000000000000000", 10)
|
||||||
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
||||||
b, _ := big.NewInt(0).SetString("16666666666666666666", 10)
|
b, _ := big.NewInt(0).SetString("50000000000000000000", 10)
|
||||||
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])
|
||||||
} else {
|
} else {
|
||||||
assert.Fail(t, "wrong reward")
|
assert.Fail(t, "wrong reward")
|
||||||
|
|
@ -261,22 +262,22 @@ func TestHookRewardAfterUpgrade(t *testing.T) {
|
||||||
// only protector1 and 2 has signingtx.
|
// only protector1 and 2 has signingtx.
|
||||||
|
|
||||||
resultProtector := reward["rewardsProtector"].(map[common.Address]interface{})
|
resultProtector := reward["rewardsProtector"].(map[common.Address]interface{})
|
||||||
// 2 protector and split by 1:2
|
// 2 protector both get fixed reward
|
||||||
assert.Equal(t, 2, len(resultProtector))
|
assert.Equal(t, 2, len(resultProtector))
|
||||||
for addr, x := range resultProtector {
|
for addr, x := range resultProtector {
|
||||||
if addr == protector1Addr {
|
if addr == protector1Addr {
|
||||||
r := x.(map[common.Address]*big.Int)
|
r := x.(map[common.Address]*big.Int)
|
||||||
owner := state.GetCandidateOwner(parentState, addr)
|
owner := state.GetCandidateOwner(parentState, addr)
|
||||||
a, _ := big.NewInt(0).SetString("119999999999999999999", 10)
|
a, _ := big.NewInt(0).SetString("360000000000000000000", 10)
|
||||||
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
||||||
b, _ := big.NewInt(0).SetString("13333333333333333333", 10)
|
b, _ := big.NewInt(0).SetString("40000000000000000000", 10)
|
||||||
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])
|
||||||
} else if addr == protector2Addr {
|
} else if addr == protector2Addr {
|
||||||
r := x.(map[common.Address]*big.Int)
|
r := x.(map[common.Address]*big.Int)
|
||||||
owner := state.GetCandidateOwner(parentState, addr)
|
owner := state.GetCandidateOwner(parentState, addr)
|
||||||
a, _ := big.NewInt(0).SetString("239999999999999999999", 10)
|
a, _ := big.NewInt(0).SetString("360000000000000000000", 10)
|
||||||
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
||||||
b, _ := big.NewInt(0).SetString("26666666666666666666", 10)
|
b, _ := big.NewInt(0).SetString("40000000000000000000", 10)
|
||||||
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])
|
||||||
} else {
|
} else {
|
||||||
assert.Fail(t, "wrong reward")
|
assert.Fail(t, "wrong reward")
|
||||||
|
|
@ -297,3 +298,57 @@ func TestHookRewardAfterUpgrade(t *testing.T) {
|
||||||
}
|
}
|
||||||
common.TIPUpgradeReward = backup
|
common.TIPUpgradeReward = backup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRewardHalvingVanishing(t *testing.T) {
|
||||||
|
billion := big.NewInt(1000000000)
|
||||||
|
epochRewardTotal := big.NewInt(16000)
|
||||||
|
epochRewardTotal.Mul(epochRewardTotal, billion)
|
||||||
|
epochReward1 := big.NewInt(10000)
|
||||||
|
epochReward1.Mul(epochReward1, billion)
|
||||||
|
epochReward2 := big.NewInt(4000)
|
||||||
|
epochReward2.Mul(epochReward2, billion)
|
||||||
|
epochReward3 := big.NewInt(2000)
|
||||||
|
epochReward3.Mul(epochReward3, billion)
|
||||||
|
// 45 Billion - 39 Billion XDC (1 XDC = 10^9 wei)
|
||||||
|
halvingSupply := big.NewInt(6000000000)
|
||||||
|
halvingSupply.Mul(halvingSupply, billion)
|
||||||
|
sum := big.NewInt(0)
|
||||||
|
iterMax := uint64(30000000)
|
||||||
|
for i := uint64(0); i < iterMax; i++ {
|
||||||
|
r := new(big.Int).Add(util.RewardHalving(epochReward1, epochRewardTotal, halvingSupply, i), util.RewardHalving(epochReward2, epochRewardTotal, halvingSupply, i))
|
||||||
|
r.Add(r, util.RewardHalving(epochReward3, epochRewardTotal, halvingSupply, i))
|
||||||
|
if r.BitLen() == 0 {
|
||||||
|
t.Log("reward be 0 at i=", i) // reward be 0 at i= 11225088, wich is more than 200 years in the future
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sum.Add(sum, r)
|
||||||
|
if i == iterMax-1 {
|
||||||
|
t.Fatal("reward should be 0 at end")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Log("sum", sum) // sum 5999999999982635022, which is less than total, and never reach totoal
|
||||||
|
assert.True(t, sum.Cmp(halvingSupply) < 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRewardHalvingSplit(t *testing.T) {
|
||||||
|
billion := big.NewInt(1000000000)
|
||||||
|
epochRewardTotal := big.NewInt(16000)
|
||||||
|
epochRewardTotal.Mul(epochRewardTotal, billion)
|
||||||
|
epochReward1 := big.NewInt(10000)
|
||||||
|
epochReward1.Mul(epochReward1, billion)
|
||||||
|
epochReward2 := big.NewInt(4000)
|
||||||
|
epochReward2.Mul(epochReward2, billion)
|
||||||
|
epochReward3 := big.NewInt(2000)
|
||||||
|
epochReward3.Mul(epochReward3, billion)
|
||||||
|
// 45 Billion - 39 Billion XDC (1 XDC = 10^9 wei)
|
||||||
|
halvingSupply := big.NewInt(6000000000)
|
||||||
|
halvingSupply.Mul(halvingSupply, billion)
|
||||||
|
i := uint64(50000) // a random number suffice
|
||||||
|
r1 := util.RewardHalving(epochReward1, epochRewardTotal, halvingSupply, i)
|
||||||
|
r2 := util.RewardHalving(epochReward2, epochRewardTotal, halvingSupply, i)
|
||||||
|
r3 := util.RewardHalving(epochReward3, epochRewardTotal, halvingSupply, i)
|
||||||
|
t.Log(r1, r2, r3)
|
||||||
|
|
||||||
|
assert.Equal(t, int64(5), r1.Div(r1, r3).Int64()) // since epochReward1/epochReward3=5
|
||||||
|
assert.Equal(t, int64(2), r2.Div(r2, r3).Int64()) // since epochReward2/epochReward3=2
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,98 +205,68 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
|
||||||
}
|
}
|
||||||
rewardsMap["signers"] = signers[MasterNodeBeneficiary]
|
rewardsMap["signers"] = signers[MasterNodeBeneficiary]
|
||||||
|
|
||||||
rewardSigners := make(map[common.Address]*big.Int)
|
|
||||||
rewardSignersProtector := make(map[common.Address]*big.Int)
|
|
||||||
rewardSignersObserver := make(map[common.Address]*big.Int)
|
|
||||||
if !chain.Config().IsTIPUpgradeReward(header.Number) {
|
if !chain.Config().IsTIPUpgradeReward(header.Number) {
|
||||||
// Get reward inflation.
|
// Get reward inflation.
|
||||||
chainReward := new(big.Int).Mul(new(big.Int).SetUint64(chain.Config().XDPoS.Reward), new(big.Int).SetUint64(params.Ether))
|
originalReward := new(big.Int).Mul(new(big.Int).SetUint64(chain.Config().XDPoS.Reward), new(big.Int).SetUint64(params.Ether))
|
||||||
chainReward = util.RewardInflation(chain, chainReward, number, common.BlocksPerYear)
|
chainReward := util.RewardInflation(chain, originalReward, number, common.BlocksPerYear)
|
||||||
rewardSigners, err = CalculateRewardForSigner(chainReward, signers[MasterNodeBeneficiary])
|
rewardSigners, err := CalculateRewardForSigner(chainReward, signers[MasterNodeBeneficiary])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("[HookReward] Fail to calculate reward for masternode", "error", err)
|
log.Error("[HookReward] Fail to calculate reward for masternode", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// Add reward for coin holders.
|
||||||
|
rewardResults := make(map[common.Address]interface{})
|
||||||
|
for signer, calcReward := range rewardSigners {
|
||||||
|
rewards, err := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("[HookReward] Fail to calculate reward for holders.", "error", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(rewards) > 0 {
|
||||||
|
for holder, reward := range rewards {
|
||||||
|
stateBlock.AddBalance(holder, reward)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rewardResults[signer] = rewards
|
||||||
|
}
|
||||||
|
rewardsMap["rewards"] = rewardResults
|
||||||
} else {
|
} else {
|
||||||
rewardsMap["signersProtector"] = signers[ProtectorNodeBeneficiary]
|
rewardsMap["signersProtector"] = signers[ProtectorNodeBeneficiary]
|
||||||
rewardsMap["signersObserver"] = signers[ObserverNodeBeneficiary]
|
rewardsMap["signersObserver"] = signers[ObserverNodeBeneficiary]
|
||||||
// Masternode rewards
|
type rewardWithType struct {
|
||||||
chainReward := new(big.Int).Mul(new(big.Int).SetUint64(currentConfig.MasternodeReward), new(big.Int).SetUint64(params.Ether))
|
r uint64
|
||||||
chainReward = util.RewardInflation(chain, chainReward, number, common.BlocksPerYear)
|
t Beneficiary
|
||||||
rewardSigners, err = CalculateRewardForSigner(chainReward, signers[MasterNodeBeneficiary])
|
key string
|
||||||
if err != nil {
|
|
||||||
log.Error("[HookReward] Fail to calculate reward for masternode", "error", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
for _, rwt := range []rewardWithType{
|
||||||
// Protector rewards
|
{currentConfig.MasternodeReward, MasterNodeBeneficiary, "rewards"},
|
||||||
chainReward = new(big.Int).Mul(new(big.Int).SetUint64(currentConfig.ProtectorReward), new(big.Int).SetUint64(params.Ether))
|
{currentConfig.ProtectorReward, ProtectorNodeBeneficiary, "rewardsProtector"},
|
||||||
chainReward = util.RewardInflation(chain, chainReward, number, common.BlocksPerYear)
|
{currentConfig.ObserverReward, ObserverNodeBeneficiary, "rewardsObserver"},
|
||||||
rewardSignersProtector, err = CalculateRewardForSigner(chainReward, signers[ProtectorNodeBeneficiary])
|
} {
|
||||||
if err != nil {
|
originalReward := new(big.Int).Mul(new(big.Int).SetUint64(rwt.r), new(big.Int).SetUint64(params.Ether))
|
||||||
log.Error("[HookReward] Fail to calculate reward for protector", "error", err)
|
chainReward := util.RewardInflation(chain, originalReward, number, common.BlocksPerYear)
|
||||||
return nil, err
|
rewardSigners, err := CalculateRewardForSignerFixed(chainReward, signers[rwt.t])
|
||||||
}
|
if err != nil {
|
||||||
|
log.Error("[HookReward] Fail to calculate reward type 0 for masternode, 1 for protector, 2 for observer", "error", err, "type", rwt.t)
|
||||||
// Observer rewards
|
return nil, err
|
||||||
chainReward = new(big.Int).Mul(new(big.Int).SetUint64(currentConfig.ObserverReward), new(big.Int).SetUint64(params.Ether))
|
|
||||||
chainReward = util.RewardInflation(chain, chainReward, number, common.BlocksPerYear)
|
|
||||||
rewardSignersObserver, err = CalculateRewardForSigner(chainReward, signers[ObserverNodeBeneficiary])
|
|
||||||
if err != nil {
|
|
||||||
log.Error("[HookReward] Fail to calculate reward for observer", "error", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add reward for coin holders.
|
|
||||||
voterResults := make(map[common.Address]interface{})
|
|
||||||
for signer, calcReward := range rewardSigners {
|
|
||||||
rewards, err := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("[HookReward] Fail to calculate reward for holders.", "error", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(rewards) > 0 {
|
|
||||||
for holder, reward := range rewards {
|
|
||||||
stateBlock.AddBalance(holder, reward)
|
|
||||||
}
|
}
|
||||||
}
|
// Add reward for coin holders.
|
||||||
voterResults[signer] = rewards
|
rewardResults := make(map[common.Address]interface{})
|
||||||
}
|
for signer, calcReward := range rewardSigners {
|
||||||
rewardsMap["rewards"] = voterResults
|
rewards, err := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
|
||||||
|
if err != nil {
|
||||||
voterResultsProtector := make(map[common.Address]interface{})
|
log.Error("[HookReward] Fail to calculate reward for holders.", "error", err)
|
||||||
for signer, calcReward := range rewardSignersProtector {
|
return nil, err
|
||||||
rewards, err := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
|
}
|
||||||
if err != nil {
|
if len(rewards) > 0 {
|
||||||
log.Error("[HookReward] Fail to calculate reward for holders.", "error", err)
|
for holder, reward := range rewards {
|
||||||
return nil, err
|
stateBlock.AddBalance(holder, reward)
|
||||||
}
|
}
|
||||||
if len(rewards) > 0 {
|
}
|
||||||
for holder, reward := range rewards {
|
rewardResults[signer] = rewards
|
||||||
stateBlock.AddBalance(holder, reward)
|
|
||||||
}
|
}
|
||||||
|
rewardsMap[rwt.key] = rewardResults
|
||||||
}
|
}
|
||||||
voterResultsProtector[signer] = rewards
|
|
||||||
}
|
|
||||||
if len(voterResultsProtector) > 0 {
|
|
||||||
rewardsMap["rewardsProtector"] = voterResultsProtector
|
|
||||||
}
|
|
||||||
voterResultsObserver := make(map[common.Address]interface{})
|
|
||||||
for signer, calcReward := range rewardSignersObserver {
|
|
||||||
rewards, err := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("[HookReward] Fail to calculate reward for holders.", "error", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(rewards) > 0 {
|
|
||||||
for holder, reward := range rewards {
|
|
||||||
stateBlock.AddBalance(holder, reward)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
voterResultsObserver[signer] = rewards
|
|
||||||
}
|
|
||||||
if len(voterResultsObserver) > 0 {
|
|
||||||
rewardsMap["rewardsObserver"] = voterResultsObserver
|
|
||||||
}
|
}
|
||||||
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
|
||||||
|
|
@ -366,7 +336,6 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type
|
||||||
filterMap[addr] = struct{}{}
|
filterMap[addr] = struct{}{}
|
||||||
}
|
}
|
||||||
// find top candidates
|
// find top candidates
|
||||||
// maxMNP := currentConfig.MaxMasternodes + currentConfig.MaxProtectorNodes
|
|
||||||
protector := []common.Address{}
|
protector := []common.Address{}
|
||||||
observer := []common.Address{}
|
observer := []common.Address{}
|
||||||
for _, node := range ms {
|
for _, node := range ms {
|
||||||
|
|
@ -375,7 +344,7 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type
|
||||||
}
|
}
|
||||||
if len(protector) < currentConfig.MaxProtectorNodes {
|
if len(protector) < currentConfig.MaxProtectorNodes {
|
||||||
protector = append(protector, node.Address)
|
protector = append(protector, node.Address)
|
||||||
} else {
|
} else if len(observer) < currentConfig.MaxObverserNodes {
|
||||||
observer = append(observer, node.Address)
|
observer = append(observer, node.Address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -475,3 +444,22 @@ func CalculateRewardForSigner(chainReward *big.Int, signers map[common.Address]*
|
||||||
|
|
||||||
return resultSigners, nil
|
return resultSigners, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate reward for signers with fixed reward.
|
||||||
|
func CalculateRewardForSignerFixed(chainReward *big.Int, signers map[common.Address]*RewardLog) (map[common.Address]*big.Int, error) {
|
||||||
|
resultSigners := make(map[common.Address]*big.Int)
|
||||||
|
// Add reward for signers.
|
||||||
|
for signer, rLog := range signers {
|
||||||
|
// Add reward for signer.
|
||||||
|
calcReward := new(big.Int).SetBytes(chainReward.Bytes())
|
||||||
|
rLog.Reward = calcReward
|
||||||
|
resultSigners[signer] = calcReward
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Signers data", "percapitaReward", chainReward)
|
||||||
|
for addr, signer := range signers {
|
||||||
|
log.Debug("Signer reward", "signer", addr, "sign", signer.Sign, "reward", signer.Reward)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultSigners, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,34 @@ func RewardInflation(chain consensus.ChainReader, chainReward *big.Int, number u
|
||||||
|
|
||||||
return chainReward
|
return chainReward
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RewardHalving computes the reward for Masternode/Protector/Observer based on epoch total reward, supply after halving is enabled, and epoch after halving is enabled
|
||||||
|
// The sequence is a geometric sequence in order to make supply be limited
|
||||||
|
func RewardHalving(epochRewardSingle *big.Int, epochRewardTotal *big.Int, halvingSupply *big.Int, epochSinceHalving uint64) *big.Int {
|
||||||
|
rt := new(big.Float).SetInt(epochRewardTotal)
|
||||||
|
hs := new(big.Float).SetInt(halvingSupply)
|
||||||
|
// zero cause Quo panic so return early
|
||||||
|
// or epoch reward > halving supply, return early
|
||||||
|
if halvingSupply.BitLen() == 0 || epochRewardTotal.Cmp(halvingSupply) > 0 {
|
||||||
|
return big.NewInt(0)
|
||||||
|
}
|
||||||
|
quo := new(big.Float).Quo(rt, hs)
|
||||||
|
// base = 1- reward/supply
|
||||||
|
base := new(big.Float).Sub(big.NewFloat(1), quo)
|
||||||
|
r := new(big.Float).SetInt(epochRewardSingle)
|
||||||
|
result := new(big.Float).Mul(r, FloatPower(base, epochSinceHalving))
|
||||||
|
resultInt, _ := result.Int(nil)
|
||||||
|
return resultInt
|
||||||
|
}
|
||||||
|
|
||||||
|
func FloatPower(base *big.Float, exp uint64) *big.Float {
|
||||||
|
result := big.NewFloat(1)
|
||||||
|
for exp > 0 {
|
||||||
|
if exp%2 == 1 {
|
||||||
|
result.Mul(result, base)
|
||||||
|
}
|
||||||
|
base.Mul(base, base)
|
||||||
|
exp >>= 1 // same as: exp = exp / 2
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,7 @@ var (
|
||||||
900: {
|
900: {
|
||||||
MaxMasternodes: 20,
|
MaxMasternodes: 20,
|
||||||
MaxProtectorNodes: 17,
|
MaxProtectorNodes: 17,
|
||||||
|
MaxObverserNodes: 1,
|
||||||
SwitchRound: 900,
|
SwitchRound: 900,
|
||||||
CertThreshold: 0.667,
|
CertThreshold: 0.667,
|
||||||
TimeoutSyncThreshold: 4,
|
TimeoutSyncThreshold: 4,
|
||||||
|
|
@ -454,15 +455,16 @@ type V2 struct {
|
||||||
type V2Config struct {
|
type V2Config struct {
|
||||||
MaxMasternodes int `json:"maxMasternodes"` // v2 max masternodes
|
MaxMasternodes int `json:"maxMasternodes"` // v2 max masternodes
|
||||||
MaxProtectorNodes int `json:"maxProtectorNodes"` // v2 max ProtectorNodes
|
MaxProtectorNodes int `json:"maxProtectorNodes"` // v2 max ProtectorNodes
|
||||||
|
MaxObverserNodes int `json:"maxObserverNodes"` // v2 max ObserverNodes
|
||||||
SwitchRound uint64 `json:"switchRound"` // v1 to v2 switch block number
|
SwitchRound uint64 `json:"switchRound"` // v1 to v2 switch block number
|
||||||
MinePeriod int `json:"minePeriod"` // Miner mine period to mine a block
|
MinePeriod int `json:"minePeriod"` // Miner mine period to mine a block
|
||||||
TimeoutSyncThreshold int `json:"timeoutSyncThreshold"` // send syncInfo after number of timeout
|
TimeoutSyncThreshold int `json:"timeoutSyncThreshold"` // send syncInfo after number of timeout
|
||||||
TimeoutPeriod int `json:"timeoutPeriod"` // Duration in ms
|
TimeoutPeriod int `json:"timeoutPeriod"` // Duration in ms
|
||||||
CertThreshold float64 `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
|
CertThreshold float64 `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
|
||||||
|
|
||||||
MasternodeReward uint64 `json:"masternodeReward"` // Block reward for master nodes (core validators) - unit Ether
|
MasternodeReward uint64 `json:"masternodeReward"` // Block reward per master node (core validator) - unit Ether
|
||||||
ProtectorReward uint64 `json:"protectorReward"` // Block reward for protectors - unit Ether
|
ProtectorReward uint64 `json:"protectorReward"` // Block reward per protector - unit Ether
|
||||||
ObserverReward uint64 `json:"observerReward"` // Block reward for observer - unit Ether
|
ObserverReward uint64 `json:"observerReward"` // Block reward per observer - unit Ether
|
||||||
|
|
||||||
ExpTimeoutConfig ExpTimeoutConfig `json:"expTimeoutConfig"`
|
ExpTimeoutConfig ExpTimeoutConfig `json:"expTimeoutConfig"`
|
||||||
}
|
}
|
||||||
|
|
@ -764,6 +766,10 @@ func (c *ChainConfig) IsTIPUpgradeReward(num *big.Int) bool {
|
||||||
return isForked(common.TIPUpgradeReward, num)
|
return isForked(common.TIPUpgradeReward, num)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ChainConfig) IsTIPEpochHalving(num *big.Int) bool {
|
||||||
|
return isForked(common.TIPEpochHalving, num)
|
||||||
|
}
|
||||||
|
|
||||||
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
|
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
|
||||||
//
|
//
|
||||||
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
|
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue