mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
Upgrade reward 2.0 (#865)
* refactor: reward hook gets prepared for upgrade * feat: new reward hook, config change, unit tests * add missing code * feat: filter penalty in reward. add unit test * update constant and config --------- Co-authored-by: liam.lai <liam.lai@us>
This commit is contained in:
parent
8bd1c9cee9
commit
c36e4d54c0
8 changed files with 578 additions and 63 deletions
|
|
@ -61,6 +61,7 @@ type constant struct {
|
|||
TIPV2SwitchBlock *big.Int
|
||||
tipXDCXMinerDisable *big.Int
|
||||
tipXDCXReceiverDisable *big.Int
|
||||
tipUpgradeReward *big.Int
|
||||
eip1559Block *big.Int
|
||||
cancunBlock *big.Int
|
||||
|
||||
|
|
@ -102,6 +103,7 @@ var (
|
|||
BlockNumberGas50x = MaintnetConstant.blockNumberGas50x
|
||||
TIPXDCXMinerDisable = MaintnetConstant.tipXDCXMinerDisable
|
||||
TIPXDCXReceiverDisable = MaintnetConstant.tipXDCXReceiverDisable
|
||||
TIPUpgradeReward = MaintnetConstant.tipUpgradeReward
|
||||
Eip1559Block = MaintnetConstant.eip1559Block
|
||||
CancunBlock = MaintnetConstant.cancunBlock
|
||||
|
||||
|
|
@ -167,6 +169,7 @@ func CopyConstans(chainID uint64) {
|
|||
BlockNumberGas50x = c.blockNumberGas50x
|
||||
TIPXDCXMinerDisable = c.tipXDCXMinerDisable
|
||||
TIPXDCXReceiverDisable = c.tipXDCXReceiverDisable
|
||||
TIPUpgradeReward = c.tipUpgradeReward
|
||||
Eip1559Block = c.eip1559Block
|
||||
CancunBlock = c.cancunBlock
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ var DevnetConstant = constant{
|
|||
TIPV2SwitchBlock: big.NewInt(1800),
|
||||
tipXDCXMinerDisable: big.NewInt(0),
|
||||
tipXDCXReceiverDisable: big.NewInt(0),
|
||||
tipUpgradeReward: big.NewInt(1773000),
|
||||
eip1559Block: big.NewInt(0),
|
||||
cancunBlock: big.NewInt(1702800),
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ var MaintnetConstant = constant{
|
|||
TIPV2SwitchBlock: big.NewInt(80370000), // Target 2nd Oct 2024
|
||||
tipXDCXMinerDisable: big.NewInt(80370000), // Target 2nd Oct 2024
|
||||
tipXDCXReceiverDisable: big.NewInt(80370900), // Target 2nd Oct 2024, safer to release after disable miner
|
||||
tipUpgradeReward: big.NewInt(9999999999),
|
||||
eip1559Block: big.NewInt(9999999999),
|
||||
cancunBlock: big.NewInt(9999999999),
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ var TestnetConstant = constant{
|
|||
shanghaiBlock: big.NewInt(61290000), // Target 31st March 2024
|
||||
tipXDCXMinerDisable: big.NewInt(61290000), // Target 31st March 2024
|
||||
tipXDCXReceiverDisable: big.NewInt(66825000), // Target 26 Aug 2024
|
||||
tipUpgradeReward: big.NewInt(9999999999),
|
||||
eip1559Block: big.NewInt(71550000), // Target 14th Feb 2025
|
||||
cancunBlock: big.NewInt(9999999999),
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,15 @@ var (
|
|||
acc3Addr = crypto.PubkeyToAddress(acc3Key.PublicKey) //xdc71562b71999873DB5b286dF957af199Ec94617F7
|
||||
voterAddr = crypto.PubkeyToAddress(voterKey.PublicKey) //xdc5F74529C0338546f82389402a01c31fB52c6f434
|
||||
chainID = int64(1337)
|
||||
|
||||
protector1Key, _ = crypto.HexToECDSA("071c71a67e127fad4e901695e1b4b9ee04ae0e301d1e14474d32c45c72ce7b70")
|
||||
protector1Addr = crypto.PubkeyToAddress(protector1Key.PublicKey)
|
||||
protector2Key, _ = crypto.HexToECDSA("1d1e144127fad4e9016a977b97b0c89921839df052d7adc2f789034678902378")
|
||||
protector2Addr = crypto.PubkeyToAddress(protector2Key.PublicKey)
|
||||
observer1Key, _ = crypto.HexToECDSA("71a67e127fad4e9016a977b97b0c89921839df052d7adc2f7890346789023789")
|
||||
observer1Addr = crypto.PubkeyToAddress(observer1Key.PublicKey)
|
||||
observer2Key, _ = crypto.HexToECDSA("789034678902378971a67e127fad4e9016a977b97b0c89921839df052d7adc2f")
|
||||
observer2Addr = crypto.PubkeyToAddress(observer2Key.PublicKey)
|
||||
)
|
||||
|
||||
func SignHashByPK(pk *ecdsa.PrivateKey, itemToSign []byte) []byte {
|
||||
|
|
@ -279,6 +288,91 @@ func getMultiCandidatesBackend(t *testing.T, chainConfig *params.ChainConfig, n
|
|||
return contractBackend2
|
||||
}
|
||||
|
||||
func getProtectorObserverBackend(t *testing.T, chainConfig *params.ChainConfig) *backends.SimulatedBackend {
|
||||
|
||||
// initial helper backend
|
||||
contractBackendForSC := backends.NewXDCSimulatedBackend(types.GenesisAlloc{
|
||||
voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
}, 10000000, chainConfig)
|
||||
|
||||
transactOpts := bind.NewKeyedTransactor(voterKey)
|
||||
|
||||
var candidates []common.Address
|
||||
var caps []*big.Int
|
||||
defalutCap := new(big.Int)
|
||||
defalutCap.SetString("1000000000", 10)
|
||||
|
||||
for i := 1; i <= 15; i++ {
|
||||
addr := fmt.Sprintf("%02d", i)
|
||||
candidates = append(candidates, common.StringToAddress(addr)) // StringToAddress does not exist
|
||||
caps = append(caps, defalutCap)
|
||||
}
|
||||
candidates = append(candidates, protector1Addr, protector2Addr, observer1Addr, observer2Addr)
|
||||
caps = append(caps, defalutCap, defalutCap, big.NewInt(999999), big.NewInt(999999)) // 99..9 is a small cap
|
||||
|
||||
acc1Cap, acc2Cap, acc3Cap, voterCap := new(big.Int), new(big.Int), new(big.Int), new(big.Int)
|
||||
|
||||
acc1Cap.SetString("10000001", 10)
|
||||
acc2Cap.SetString("10000002", 10)
|
||||
acc3Cap.SetString("10000003", 10)
|
||||
voterCap.SetString("1000000000", 10)
|
||||
|
||||
caps = append(caps, voterCap, acc1Cap, acc2Cap, acc3Cap)
|
||||
candidates = append(candidates, voterAddr, acc1Addr, acc2Addr, acc3Addr)
|
||||
// create validator smart contract
|
||||
validatorSCAddr, _, _, err := contractValidator.DeployXDCValidator(
|
||||
transactOpts,
|
||||
contractBackendForSC,
|
||||
candidates,
|
||||
caps,
|
||||
voterAddr, // first owner, not used
|
||||
big.NewInt(50000),
|
||||
big.NewInt(1),
|
||||
big.NewInt(99),
|
||||
big.NewInt(100),
|
||||
big.NewInt(100),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("can't deploy root registry: %v", err)
|
||||
}
|
||||
|
||||
contractBackendForSC.Commit() // Write into database(state)
|
||||
|
||||
// Prepare Code and Storage
|
||||
d := time.Now().Add(1000 * time.Millisecond)
|
||||
ctx, cancel := context.WithDeadline(context.Background(), d)
|
||||
defer cancel()
|
||||
|
||||
code, _ := contractBackendForSC.CodeAt(ctx, validatorSCAddr, nil)
|
||||
storage := make(map[common.Hash]common.Hash)
|
||||
f := func(key, val common.Hash) bool {
|
||||
decode := []byte{}
|
||||
trim := bytes.TrimLeft(val.Bytes(), "\x00")
|
||||
err := rlp.DecodeBytes(trim, &decode)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed while decode byte")
|
||||
}
|
||||
storage[key] = common.BytesToHash(decode)
|
||||
log.Info("DecodeBytes", "value", val.String(), "decode", storage[key].String())
|
||||
return true
|
||||
}
|
||||
err = contractBackendForSC.ForEachStorageAt(ctx, validatorSCAddr, nil, f)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed while trying to read all keys from SC")
|
||||
}
|
||||
|
||||
// create test backend with smart contract in it
|
||||
contractBackend2 := backends.NewXDCSimulatedBackend(types.GenesisAlloc{
|
||||
acc1Addr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
acc2Addr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
acc3Addr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
voterAddr: {Balance: new(big.Int).SetUint64(10000000000)},
|
||||
common.MasternodeVotingSMCBinary: {Balance: new(big.Int).SetUint64(1), Code: code, Storage: storage}, // Binding the MasternodeVotingSMC with newly created 'code' for SC execution
|
||||
}, 10000000, chainConfig)
|
||||
|
||||
return contractBackend2
|
||||
}
|
||||
|
||||
func signingTxWithKey(header *types.Header, nonce uint64, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) {
|
||||
tx := contracts.CreateTxSign(header.Number, header.Hash(), nonce, common.BlockSignersBinary)
|
||||
s := types.LatestSignerForChainID(big.NewInt(chainID))
|
||||
|
|
@ -483,7 +577,11 @@ func PrepareXDCTestBlockChainWithPenaltyForV2Engine(t *testing.T, numOfBlocks in
|
|||
}
|
||||
roundNumber := int64(i) - chainConfig.XDPoS.V2.SwitchBlock.Int64()
|
||||
// use signer itself as penalty
|
||||
block := CreateBlock(blockchain, chainConfig, currentBlock, i, roundNumber, blockCoinBase, signer, signFn, signer[:], nil, "")
|
||||
penalty := signer[:]
|
||||
if roundNumber%int64(chainConfig.XDPoS.Epoch) != 0 {
|
||||
penalty = nil
|
||||
}
|
||||
block := CreateBlock(blockchain, chainConfig, currentBlock, i, roundNumber, blockCoinBase, signer, signFn, penalty, nil, "")
|
||||
|
||||
err = blockchain.InsertBlock(block)
|
||||
if err != nil {
|
||||
|
|
@ -564,6 +662,78 @@ func PrepareXDCTestBlockChainWith128Candidates(t *testing.T, numOfBlocks int, ch
|
|||
return blockchain, backend, currentBlock, signer, signFn
|
||||
}
|
||||
|
||||
// V2 concensus engine
|
||||
func PrepareXDCTestBlockChainWithProtectorObserver(t *testing.T, numOfBlocks int, chainConfig *params.ChainConfig) (*core.BlockChain, *backends.SimulatedBackend, *types.Block, common.Address, func(account accounts.Account, hash []byte) ([]byte, error)) {
|
||||
// Preparation
|
||||
var err error
|
||||
signer, signFn, err := backends.SimulateWalletAddressAndSignFn()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error while creating simulated wallet for generating singer address and signer fn: %v", err))
|
||||
}
|
||||
backend := getProtectorObserverBackend(t, chainConfig)
|
||||
blockchain := backend.BlockChain()
|
||||
blockchain.Client = backend
|
||||
|
||||
engine := blockchain.Engine().(*XDPoS.XDPoS)
|
||||
|
||||
// Authorise
|
||||
engine.Authorize(signer, signFn)
|
||||
|
||||
currentBlock := blockchain.Genesis()
|
||||
|
||||
go func() {
|
||||
for range core.CheckpointCh {
|
||||
checkpointChanMsg := <-core.CheckpointCh
|
||||
log.Info("[V2] Got a message from core CheckpointChan!", "msg", checkpointChanMsg)
|
||||
}
|
||||
}()
|
||||
|
||||
// Insert initial blocks
|
||||
for i := 1; i <= numOfBlocks; i++ {
|
||||
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", i)
|
||||
// for v2 blocks, fill in correct coinbase
|
||||
if int64(i) > chainConfig.XDPoS.V2.SwitchBlock.Int64() {
|
||||
blockCoinBase = signer.Hex()
|
||||
}
|
||||
roundNumber := int64(i) - chainConfig.XDPoS.V2.SwitchBlock.Int64()
|
||||
// use observer2 as penalty and put in checkpoint block
|
||||
penalty := observer2Addr[:]
|
||||
if i != 900 {
|
||||
penalty = nil
|
||||
}
|
||||
block := CreateBlock(blockchain, chainConfig, currentBlock, i, roundNumber, blockCoinBase, signer, signFn, penalty, nil, "f11ec19df702aa6bd9b3b2186edbc66d6b50b06334455a4a2ae8d166f28a14ff")
|
||||
|
||||
if i == 900 {
|
||||
fmt.Println(block.Penalties())
|
||||
}
|
||||
err = blockchain.InsertBlock(block)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// First v2 block
|
||||
if (int64(i) - chainConfig.XDPoS.V2.SwitchBlock.Int64()) == 1 {
|
||||
lastv1BlockNumber := block.Header().Number.Uint64() - 1
|
||||
checkpointBlockNumber := lastv1BlockNumber - lastv1BlockNumber%chainConfig.XDPoS.Epoch
|
||||
checkpointHeader := blockchain.GetHeaderByNumber(checkpointBlockNumber)
|
||||
err := engine.EngineV2.Initial(blockchain, checkpointHeader)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
currentBlock = block
|
||||
}
|
||||
|
||||
// Update Signer as there is no previous signer assigned
|
||||
err = UpdateSigner(blockchain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return blockchain, backend, currentBlock, signer, signFn
|
||||
}
|
||||
|
||||
func CreateBlock(blockchain *core.BlockChain, chainConfig *params.ChainConfig, startingBlock *types.Block, blockNumber int, roundNumber int64, blockCoinBase string, signer common.Address, signFn func(account accounts.Account, hash []byte) ([]byte, error), penalties []byte, signersKey []*ecdsa.PrivateKey, merkleRoot string) *types.Block {
|
||||
currentBlock := startingBlock
|
||||
if len(merkleRoot) == 0 {
|
||||
|
|
@ -596,9 +766,6 @@ func CreateBlock(blockchain *core.BlockChain, chainConfig *params.ChainConfig, s
|
|||
for _, v := range masternodesFromV1LastEpoch {
|
||||
header.Validators = append(header.Validators, v[:]...)
|
||||
}
|
||||
if penalties != nil {
|
||||
header.Penalties = penalties
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// V1 block
|
||||
|
|
@ -634,6 +801,9 @@ func CreateBlock(blockchain *core.BlockChain, chainConfig *params.ChainConfig, s
|
|||
copy(header.Extra[len(header.Extra)-utils.ExtraSeal:], sighash)
|
||||
}
|
||||
}
|
||||
if penalties != nil {
|
||||
header.Penalties = penalties
|
||||
}
|
||||
block, err := createBlockFromHeader(blockchain, header, nil, signer, signFn, chainConfig)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("fail to create block in test helper, %v", err))
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ func TestHookRewardV2(t *testing.T) {
|
|||
a, _ := big.NewInt(0).SetString("225000000000000000000", 10)
|
||||
assert.Zero(t, a.Cmp(r[owner]))
|
||||
b, _ := big.NewInt(0).SetString("25000000000000000000", 10)
|
||||
assert.Zero(t, b.Cmp(r[common.HexToAddress("0x0000000000000000000000000000000000000068")]))
|
||||
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]))
|
||||
}
|
||||
header2685 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch*2 + 885)
|
||||
header2716 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch*3 + 16)
|
||||
|
|
@ -146,18 +146,154 @@ func TestHookRewardV2SplitReward(t *testing.T) {
|
|||
for addr, x := range result {
|
||||
if addr == acc1Addr {
|
||||
r := x.(map[common.Address]*big.Int)
|
||||
owner := state.GetCandidateOwner(parentState, acc1Addr)
|
||||
owner := state.GetCandidateOwner(parentState, addr)
|
||||
a, _ := big.NewInt(0).SetString("149999999999999999999", 10)
|
||||
assert.Zero(t, a.Cmp(r[owner]))
|
||||
b, _ := big.NewInt(0).SetString("16666666666666666666", 10)
|
||||
assert.Zero(t, b.Cmp(r[common.HexToAddress("0x0000000000000000000000000000000000000068")]))
|
||||
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]))
|
||||
} else if addr == signer {
|
||||
r := x.(map[common.Address]*big.Int)
|
||||
owner := state.GetCandidateOwner(parentState, signer)
|
||||
owner := state.GetCandidateOwner(parentState, addr)
|
||||
a, _ := big.NewInt(0).SetString("74999999999999999999", 10)
|
||||
assert.Zero(t, a.Cmp(r[owner]))
|
||||
b, _ := big.NewInt(0).SetString("8333333333333333333", 10)
|
||||
assert.Zero(t, b.Cmp(r[common.HexToAddress("0x0000000000000000000000000000000000000068")]))
|
||||
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]))
|
||||
} else {
|
||||
assert.Fail(t, "wrong reward")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHookRewardAfterUpgrade(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)
|
||||
// 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)
|
||||
header1801 := 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})
|
||||
|
||||
statedb, err := blockchain.StateAt(header1799.Root)
|
||||
assert.Nil(t, err)
|
||||
parentState := statedb.Copy()
|
||||
reward, err := adaptor.EngineV2.HookReward(blockchain, statedb, parentState, header1801)
|
||||
assert.Nil(t, err)
|
||||
assert.Zero(t, len(reward))
|
||||
header2699 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch*3 - 1)
|
||||
header2700 := blockchain.GetHeaderByNumber(config.XDPoS.Epoch * 3)
|
||||
statedb, err = blockchain.StateAt(header2699.Root)
|
||||
assert.Nil(t, err)
|
||||
parentState = statedb.Copy()
|
||||
reward, err = adaptor.EngineV2.HookReward(blockchain, statedb, parentState, header2700)
|
||||
assert.Nil(t, err)
|
||||
result := reward["rewards"].(map[common.Address]interface{})
|
||||
assert.Equal(t, 2, len(result))
|
||||
// two signing account, 3 txs, reward is split by 1:2 (total reward is 250...000)
|
||||
for addr, x := range result {
|
||||
if addr == acc1Addr {
|
||||
r := x.(map[common.Address]*big.Int)
|
||||
owner := state.GetCandidateOwner(parentState, addr)
|
||||
a, _ := big.NewInt(0).SetString("299999999999999999998", 10)
|
||||
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
||||
b, _ := big.NewInt(0).SetString("33333333333333333333", 10)
|
||||
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]), "real reward is", r[config.XDPoS.FoudationWalletAddr])
|
||||
} else if addr == signer {
|
||||
r := x.(map[common.Address]*big.Int)
|
||||
owner := state.GetCandidateOwner(parentState, addr)
|
||||
a, _ := big.NewInt(0).SetString("149999999999999999999", 10)
|
||||
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
||||
b, _ := big.NewInt(0).SetString("16666666666666666666", 10)
|
||||
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]), "real reward is", r[config.XDPoS.FoudationWalletAddr])
|
||||
} else {
|
||||
assert.Fail(t, "wrong reward")
|
||||
}
|
||||
}
|
||||
|
||||
// 5 master nodes inside header are:
|
||||
//xdc703c4b2bD70c169f5717101CaeE543299Fc946C7
|
||||
//xdc0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e
|
||||
//xdc71562b71999873DB5b286dF957af199Ec94617F7
|
||||
//xdc5F74529C0338546f82389402a01c31fB52c6f434
|
||||
//signer
|
||||
|
||||
// 20 master nodes candidate inside XDCValidator contract are:
|
||||
//xdc703c4b2bD70c169f5717101CaeE543299Fc946C7
|
||||
//xdc0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e
|
||||
//xdc71562b71999873DB5b286dF957af199Ec94617F7
|
||||
//xdc5F74529C0338546f82389402a01c31fB52c6f434
|
||||
// and xdc00...01, xdc00...02, ..., protector1 protector2 observer1 observer2
|
||||
// so xdc00...01, xdc00...02, ..., protector1 protector2 are protectors
|
||||
// only protector1 and 2 has signingtx.
|
||||
|
||||
resultProtector := reward["rewardsProtector"].(map[common.Address]interface{})
|
||||
// 2 protector and split by 1:2
|
||||
assert.Equal(t, 2, len(resultProtector))
|
||||
for addr, x := range resultProtector {
|
||||
if addr == protector1Addr {
|
||||
r := x.(map[common.Address]*big.Int)
|
||||
owner := state.GetCandidateOwner(parentState, addr)
|
||||
a, _ := big.NewInt(0).SetString("119999999999999999999", 10)
|
||||
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
||||
b, _ := big.NewInt(0).SetString("13333333333333333333", 10)
|
||||
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]), "real reward is", r[config.XDPoS.FoudationWalletAddr])
|
||||
} else if addr == protector2Addr {
|
||||
r := x.(map[common.Address]*big.Int)
|
||||
owner := state.GetCandidateOwner(parentState, addr)
|
||||
a, _ := big.NewInt(0).SetString("239999999999999999999", 10)
|
||||
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
||||
b, _ := big.NewInt(0).SetString("26666666666666666666", 10)
|
||||
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]), "real reward is", r[config.XDPoS.FoudationWalletAddr])
|
||||
} else {
|
||||
assert.Fail(t, "wrong reward")
|
||||
}
|
||||
|
||||
}
|
||||
resultObserver := reward["rewardsObserver"].(map[common.Address]interface{})
|
||||
// observer1 and it signs one tx, observer2 is inside penalty so no reward
|
||||
assert.Equal(t, 1, len(resultObserver))
|
||||
for addr, x := range resultObserver {
|
||||
assert.Equal(t, addr, observer1Addr)
|
||||
r := x.(map[common.Address]*big.Int)
|
||||
owner := state.GetCandidateOwner(parentState, addr)
|
||||
a, _ := big.NewInt(0).SetString("270000000000000000000", 10)
|
||||
assert.Zero(t, a.Cmp(r[owner]), "real reward is", r[owner])
|
||||
b, _ := big.NewInt(0).SetString("30000000000000000000", 10)
|
||||
assert.Zero(t, b.Cmp(r[config.XDPoS.FoudationWalletAddr]), "real reward is", r[config.XDPoS.FoudationWalletAddr])
|
||||
}
|
||||
common.TIPUpgradeReward = backup
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/sort"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/contracts"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
|
|
@ -17,6 +19,21 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
// Declaring an enum type Beneficiary of reward
|
||||
type Beneficiary int
|
||||
|
||||
// Enumerating reward beneficiary
|
||||
const (
|
||||
MasterNodeBeneficiary Beneficiary = iota
|
||||
ProtectorNodeBeneficiary
|
||||
ObserverNodeBeneficiary
|
||||
)
|
||||
|
||||
type RewardLog struct {
|
||||
Sign uint64 `json:"sign"`
|
||||
Reward *big.Int `json:"reward"`
|
||||
}
|
||||
|
||||
func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConfig *params.ChainConfig) {
|
||||
// Hook scans for bad masternodes and decide to penalty them
|
||||
adaptor.EngineV2.HookPenalty = func(chain consensus.ChainReader, number *big.Int, currentHash common.Hash, candidates []common.Address) ([]common.Address, error) {
|
||||
|
|
@ -165,61 +182,138 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
|
|||
log.Error("Foundation Wallet Address is empty", "error", foundationWalletAddr)
|
||||
return nil, errors.New("foundation wallet address is empty")
|
||||
}
|
||||
rewards := make(map[string]interface{})
|
||||
rewardsMap := make(map[string]interface{})
|
||||
// skip hook reward if this is the first v2
|
||||
if number == chain.Config().XDPoS.V2.SwitchBlock.Uint64()+1 {
|
||||
return rewards, nil
|
||||
return rewardsMap, nil
|
||||
}
|
||||
start := time.Now()
|
||||
// Get reward inflation.
|
||||
chainReward := 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)
|
||||
|
||||
round, err := adaptor.EngineV2.GetRoundNumber(header)
|
||||
if err != nil {
|
||||
log.Error("[HookReward] Fail to get round", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
currentConfig := chain.Config().XDPoS.V2.Config(uint64(round))
|
||||
// Get signers/signing tx count
|
||||
totalSigner := new(uint64)
|
||||
signers, err := GetSigningTxCount(adaptor, chain, header, totalSigner)
|
||||
signers, err := GetSigningTxCount(adaptor, chain, header, parentState, currentConfig)
|
||||
|
||||
log.Debug("Time Get Signers", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
if err != nil {
|
||||
log.Error("[HookReward] Fail to get signers count for reward checkpoint", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
rewards["signers"] = signers
|
||||
rewardSigners, err := contracts.CalculateRewardForSigner(chainReward, signers, *totalSigner)
|
||||
if err != nil {
|
||||
log.Error("[HookReward] Fail to calculate reward for signers", "error", err)
|
||||
return nil, err
|
||||
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) {
|
||||
// Get reward inflation.
|
||||
chainReward := 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)
|
||||
rewardSigners, err = CalculateRewardForSigner(chainReward, signers[MasterNodeBeneficiary])
|
||||
if err != nil {
|
||||
log.Error("[HookReward] Fail to calculate reward for masternode", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
rewardsMap["signersProtector"] = signers[ProtectorNodeBeneficiary]
|
||||
rewardsMap["signersObserver"] = signers[ObserverNodeBeneficiary]
|
||||
// Masternode rewards
|
||||
chainReward := new(big.Int).Mul(new(big.Int).SetUint64(currentConfig.MasternodeReward), new(big.Int).SetUint64(params.Ether))
|
||||
chainReward = util.RewardInflation(chain, chainReward, number, common.BlocksPerYear)
|
||||
rewardSigners, err = CalculateRewardForSigner(chainReward, signers[MasterNodeBeneficiary])
|
||||
if err != nil {
|
||||
log.Error("[HookReward] Fail to calculate reward for masternode", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Protector rewards
|
||||
chainReward = new(big.Int).Mul(new(big.Int).SetUint64(currentConfig.ProtectorReward), new(big.Int).SetUint64(params.Ether))
|
||||
chainReward = util.RewardInflation(chain, chainReward, number, common.BlocksPerYear)
|
||||
rewardSignersProtector, err = CalculateRewardForSigner(chainReward, signers[ProtectorNodeBeneficiary])
|
||||
if err != nil {
|
||||
log.Error("[HookReward] Fail to calculate reward for protector", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Observer rewards
|
||||
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{})
|
||||
if len(signers) > 0 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
voterResults[signer] = rewards
|
||||
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)
|
||||
}
|
||||
}
|
||||
voterResults[signer] = rewards
|
||||
}
|
||||
rewardsMap["rewards"] = voterResults
|
||||
|
||||
voterResultsProtector := make(map[common.Address]interface{})
|
||||
for signer, calcReward := range rewardSignersProtector {
|
||||
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)
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
rewards["rewards"] = voterResults
|
||||
log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
return rewards, nil
|
||||
return rewardsMap, nil
|
||||
}
|
||||
}
|
||||
|
||||
// get signing transaction sender count
|
||||
func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *types.Header, totalSigner *uint64) (map[common.Address]*contracts.RewardLog, error) {
|
||||
func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *types.Header, parentState *state.StateDB, currentConfig *params.V2Config) (map[Beneficiary]map[common.Address]*RewardLog, error) {
|
||||
// header should be a new epoch switch block
|
||||
number := header.Number.Uint64()
|
||||
rewardEpochCount := 2
|
||||
signEpochCount := 1
|
||||
signers := make(map[common.Address]*contracts.RewardLog)
|
||||
signers := make(map[Beneficiary]map[common.Address]*RewardLog)
|
||||
signers[MasterNodeBeneficiary] = make(map[common.Address]*RewardLog)
|
||||
signers[ProtectorNodeBeneficiary] = make(map[common.Address]*RewardLog)
|
||||
signers[ObserverNodeBeneficiary] = make(map[common.Address]*RewardLog)
|
||||
|
||||
mapBlkHash := map[uint64]common.Hash{}
|
||||
|
||||
// prevent overflow
|
||||
|
|
@ -229,32 +323,75 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type
|
|||
|
||||
data := make(map[common.Hash][]common.Address)
|
||||
epochCount := 0
|
||||
var masternodes []common.Address
|
||||
var startBlockNumber, endBlockNumber uint64
|
||||
|
||||
nodesToKeep := make(map[Beneficiary][]common.Address)
|
||||
|
||||
h := header
|
||||
for i := number - 1; ; i-- {
|
||||
header = chain.GetHeader(header.ParentHash, i)
|
||||
isEpochSwitch, _, err := c.IsEpochSwitch(header)
|
||||
h = chain.GetHeader(h.ParentHash, i)
|
||||
isEpochSwitch, _, err := c.IsEpochSwitch(h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isEpochSwitch && i != chain.Config().XDPoS.V2.SwitchBlock.Uint64()+1 {
|
||||
epochCount += 1
|
||||
if epochCount == signEpochCount {
|
||||
endBlockNumber = header.Number.Uint64() - 1
|
||||
endBlockNumber = h.Number.Uint64() - 1
|
||||
}
|
||||
if epochCount == rewardEpochCount {
|
||||
startBlockNumber = header.Number.Uint64() + 1
|
||||
masternodes = c.GetMasternodesFromCheckpointHeader(header)
|
||||
startBlockNumber = h.Number.Uint64() + 1
|
||||
nodesToKeep[MasterNodeBeneficiary] = c.GetMasternodesFromCheckpointHeader(h)
|
||||
// in reward upgrade, add protector and observer nodes
|
||||
if chain.Config().IsTIPUpgradeReward(header.Number) {
|
||||
candidates := state.GetCandidates(parentState)
|
||||
var ms []utils.Masternode
|
||||
for _, candidate := range candidates {
|
||||
// ignore "0x0000000000000000000000000000000000000000"
|
||||
if !candidate.IsZero() {
|
||||
v := state.GetCandidateCap(parentState, candidate)
|
||||
ms = append(ms, utils.Masternode{Address: candidate, Stake: v})
|
||||
}
|
||||
}
|
||||
sort.Slice(ms, func(i, j int) bool {
|
||||
return ms[i].Stake.Cmp(ms[j].Stake) >= 0
|
||||
})
|
||||
// find penalty and filter them out
|
||||
penalties := common.ExtractAddressFromBytes(h.Penalties)
|
||||
filterMap := make(map[common.Address]struct{})
|
||||
for _, addr := range penalties {
|
||||
filterMap[addr] = struct{}{}
|
||||
}
|
||||
for _, addr := range nodesToKeep[MasterNodeBeneficiary] {
|
||||
filterMap[addr] = struct{}{}
|
||||
}
|
||||
// find top candidates
|
||||
// maxMNP := currentConfig.MaxMasternodes + currentConfig.MaxProtectorNodes
|
||||
protector := []common.Address{}
|
||||
observer := []common.Address{}
|
||||
for _, node := range ms {
|
||||
if _, ok := filterMap[node.Address]; ok {
|
||||
continue
|
||||
}
|
||||
if len(protector) < currentConfig.MaxProtectorNodes {
|
||||
protector = append(protector, node.Address)
|
||||
} else {
|
||||
observer = append(observer, node.Address)
|
||||
}
|
||||
}
|
||||
nodesToKeep[ProtectorNodeBeneficiary] = protector
|
||||
nodesToKeep[ObserverNodeBeneficiary] = observer
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
mapBlkHash[i] = header.Hash()
|
||||
signingTxs, ok := c.GetCachedSigningTxs(header.Hash())
|
||||
mapBlkHash[i] = h.Hash()
|
||||
signingTxs, ok := c.GetCachedSigningTxs(h.Hash())
|
||||
if !ok {
|
||||
log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", i)
|
||||
block := chain.GetBlock(header.Hash(), i)
|
||||
log.Debug("Failed get from cached", "hash", h.Hash().String(), "number", i)
|
||||
block := chain.GetBlock(h.Hash(), i)
|
||||
txs := block.Transactions()
|
||||
signingTxs = c.CacheSigningTxs(header.Hash(), txs)
|
||||
signingTxs = c.CacheSigningTxs(h.Hash(), txs)
|
||||
}
|
||||
for _, tx := range signingTxs {
|
||||
blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:])
|
||||
|
|
@ -272,26 +409,35 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type
|
|||
addrs := data[mapBlkHash[i]]
|
||||
// Filter duplicate address.
|
||||
if len(addrs) > 0 {
|
||||
addrSigners := make(map[common.Address]bool)
|
||||
for _, masternode := range masternodes {
|
||||
for _, addr := range addrs {
|
||||
if addr == masternode {
|
||||
if _, ok := addrSigners[addr]; !ok {
|
||||
addrSigners[addr] = true
|
||||
addrSigners := make(map[Beneficiary]map[common.Address]bool)
|
||||
addrSigners[MasterNodeBeneficiary] = make(map[common.Address]bool)
|
||||
addrSigners[ProtectorNodeBeneficiary] = make(map[common.Address]bool)
|
||||
addrSigners[ObserverNodeBeneficiary] = make(map[common.Address]bool)
|
||||
|
||||
for _, addr := range addrs {
|
||||
for _, beneficiary := range []Beneficiary{MasterNodeBeneficiary, ProtectorNodeBeneficiary, ObserverNodeBeneficiary} {
|
||||
if _, ok := nodesToKeep[beneficiary]; ok {
|
||||
for _, protector := range nodesToKeep[beneficiary] {
|
||||
if addr == protector {
|
||||
if _, ok := addrSigners[beneficiary][addr]; !ok {
|
||||
addrSigners[beneficiary][addr] = true
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for addr := range addrSigners {
|
||||
_, exist := signers[addr]
|
||||
if exist {
|
||||
signers[addr].Sign++
|
||||
} else {
|
||||
signers[addr] = &contracts.RewardLog{Sign: 1, Reward: new(big.Int)}
|
||||
for _, beneficiary := range []Beneficiary{MasterNodeBeneficiary, ProtectorNodeBeneficiary, ObserverNodeBeneficiary} {
|
||||
for addr := range addrSigners[beneficiary] {
|
||||
_, exist := signers[beneficiary][addr]
|
||||
if exist {
|
||||
signers[beneficiary][addr].Sign++
|
||||
} else {
|
||||
signers[beneficiary][addr] = &RewardLog{Sign: 1, Reward: new(big.Int)}
|
||||
}
|
||||
}
|
||||
*totalSigner++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -301,3 +447,31 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type
|
|||
|
||||
return signers, nil
|
||||
}
|
||||
|
||||
// Calculate reward for signers.
|
||||
func CalculateRewardForSigner(chainReward *big.Int, signers map[common.Address]*RewardLog) (map[common.Address]*big.Int, error) {
|
||||
totalSignerCount := uint64(0)
|
||||
for _, rLog := range signers {
|
||||
totalSignerCount += rLog.Sign
|
||||
}
|
||||
resultSigners := make(map[common.Address]*big.Int)
|
||||
// Add reward for signers.
|
||||
if totalSignerCount > 0 {
|
||||
for signer, rLog := range signers {
|
||||
// Add reward for signer.
|
||||
calcReward := new(big.Int)
|
||||
calcReward.Div(chainReward, new(big.Int).SetUint64(totalSignerCount))
|
||||
calcReward.Mul(calcReward, new(big.Int).SetUint64(rLog.Sign))
|
||||
rLog.Reward = calcReward
|
||||
|
||||
resultSigners[signer] = calcReward
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Signers data", "totalSigner", totalSignerCount, "totalReward", chainReward)
|
||||
for addr, signer := range signers {
|
||||
log.Debug("Signer reward", "signer", addr, "sign", signer.Sign, "reward", signer.Reward)
|
||||
}
|
||||
|
||||
return resultSigners, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,22 @@ var (
|
|||
TimeoutPeriod: 5,
|
||||
MinePeriod: 2,
|
||||
ExpTimeoutConfig: ExpTimeoutConfig{Base: 2.0, MaxExponent: 5},
|
||||
MasternodeReward: 5000,
|
||||
ProtectorReward: 4000,
|
||||
ObserverReward: 1000,
|
||||
},
|
||||
9999999999: {
|
||||
MaxMasternodes: 15,
|
||||
MaxProtectorNodes: 2,
|
||||
SwitchRound: 9999999999,
|
||||
CertThreshold: 0.667,
|
||||
TimeoutSyncThreshold: 3,
|
||||
TimeoutPeriod: 5,
|
||||
MinePeriod: 2,
|
||||
ExpTimeoutConfig: ExpTimeoutConfig{Base: 2.0, MaxExponent: 5},
|
||||
MasternodeReward: 5000,
|
||||
ProtectorReward: 4000,
|
||||
ObserverReward: 1000,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -142,12 +158,16 @@ var (
|
|||
},
|
||||
900: {
|
||||
MaxMasternodes: 20,
|
||||
MaxProtectorNodes: 17,
|
||||
SwitchRound: 900,
|
||||
CertThreshold: 0.667,
|
||||
TimeoutSyncThreshold: 4,
|
||||
TimeoutPeriod: 5,
|
||||
MinePeriod: 2,
|
||||
ExpTimeoutConfig: ExpTimeoutConfig{Base: 1.0, MaxExponent: 0},
|
||||
MasternodeReward: 500, // double as Reward
|
||||
ProtectorReward: 400,
|
||||
ObserverReward: 300,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -421,12 +441,17 @@ type V2 struct {
|
|||
|
||||
type V2Config struct {
|
||||
MaxMasternodes int `json:"maxMasternodes"` // v2 max masternodes
|
||||
MaxProtectorNodes int `json:"maxProtectorNodes"` // v2 max ProtectorNodes
|
||||
SwitchRound uint64 `json:"switchRound"` // v1 to v2 switch block number
|
||||
MinePeriod int `json:"minePeriod"` // Miner mine period to mine a block
|
||||
TimeoutSyncThreshold int `json:"timeoutSyncThreshold"` // send syncInfo after number of timeout
|
||||
TimeoutPeriod int `json:"timeoutPeriod"` // Duration in ms
|
||||
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
|
||||
ProtectorReward uint64 `json:"protectorReward"` // Block reward for protectors - unit Ether
|
||||
ObserverReward uint64 `json:"observerReward"` // Block reward for observer - unit Ether
|
||||
|
||||
ExpTimeoutConfig ExpTimeoutConfig `json:"expTimeoutConfig"`
|
||||
}
|
||||
|
||||
|
|
@ -723,6 +748,10 @@ func (c *ChainConfig) IsTIPXDCXCancellationFee(num *big.Int) bool {
|
|||
return isForked(common.TIPXDCXCancellationFee, num)
|
||||
}
|
||||
|
||||
func (c *ChainConfig) IsTIPUpgradeReward(num *big.Int) bool {
|
||||
return isForked(common.TIPUpgradeReward, num)
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue