mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
Seperate hooks from XDPoS adaptor
This commit is contained in:
parent
30811ee58c
commit
0aec2a1e9e
7 changed files with 1449 additions and 4446 deletions
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
|
|
@ -46,16 +47,14 @@ type XDPoS struct {
|
|||
config *params.XDPoSConfig // Consensus engine configuration parameters
|
||||
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
||||
|
||||
BlockSigners *lru.Cache
|
||||
HookReward func(chain consensus.ChainReader, state *state.StateDB, parentState *state.StateDB, header *types.Header) (error, map[string]interface{})
|
||||
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
||||
HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]common.Address, error)
|
||||
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
|
||||
HookVerifyMNs func(header *types.Header, signers []common.Address) error
|
||||
GetXDCXService func() utils.TradingService
|
||||
GetLendingService func() utils.LendingService
|
||||
HookGetSignersFromContract func(blockHash common.Hash) ([]common.Address, error)
|
||||
// Transaction cache, only make sense for adaptor level
|
||||
signingTxsCache *lru.Cache
|
||||
|
||||
// Trading and lending service
|
||||
GetXDCXService func() utils.TradingService
|
||||
GetLendingService func() utils.LendingService
|
||||
|
||||
// The exact consensus engine with different versions
|
||||
EngineV1 engine_v1.XDPoS_v1
|
||||
}
|
||||
|
||||
|
|
@ -69,13 +68,13 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
|
|||
}
|
||||
|
||||
// Allocate the snapshot caches and create the engine
|
||||
BlockSigners, _ := lru.New(utils.BlockSignersCacheLimit)
|
||||
signingTxsCache, _ := lru.New(utils.BlockSignersCacheLimit)
|
||||
|
||||
return &XDPoS{
|
||||
config: &conf,
|
||||
|
||||
BlockSigners: BlockSigners,
|
||||
EngineV1: *engine_v1.New(&conf, db),
|
||||
signingTxsCache: signingTxsCache,
|
||||
EngineV1: *engine_v1.New(&conf, db),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -248,13 +247,6 @@ func (c *XDPoS) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.He
|
|||
}
|
||||
}
|
||||
|
||||
func (c *XDPoS) CacheData(header *types.Header, txs []*types.Transaction, receipts []*types.Receipt) []*types.Transaction {
|
||||
switch params.BlockConsensusVersion(header.Number) {
|
||||
default: // Default "1.0"
|
||||
return c.EngineV1.CacheData(header, txs, receipts)
|
||||
}
|
||||
}
|
||||
|
||||
// Same DB across all consensus engines
|
||||
func (c *XDPoS) GetDb() ethdb.Database {
|
||||
return c.db
|
||||
|
|
@ -283,6 +275,58 @@ func (c *XDPoS) GetAuthorisedSignersFromSnapshot(chain consensus.ChainReader, he
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Caching
|
||||
*/
|
||||
|
||||
// Cache signing transaction data into BlockSingers cache object
|
||||
func (c *XDPoS) CacheNoneTIPSigningTxs(header *types.Header, txs []*types.Transaction, receipts []*types.Receipt) []*types.Transaction {
|
||||
signTxs := []*types.Transaction{}
|
||||
for _, tx := range txs {
|
||||
if tx.IsSigningTransaction() {
|
||||
var b uint
|
||||
for _, r := range receipts {
|
||||
if r.TxHash == tx.Hash() {
|
||||
if len(r.PostState) > 0 {
|
||||
b = types.ReceiptStatusSuccessful
|
||||
} else {
|
||||
b = r.Status
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if b == types.ReceiptStatusFailed {
|
||||
continue
|
||||
}
|
||||
|
||||
signTxs = append(signTxs, tx)
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug("Save tx signers to cache", "hash", header.Hash().String(), "number", header.Number, "len(txs)", len(signTxs))
|
||||
c.signingTxsCache.Add(header.Hash(), signTxs)
|
||||
|
||||
return signTxs
|
||||
}
|
||||
|
||||
// Cache
|
||||
func (c *XDPoS) CacheSigningTxs(hash common.Hash, txs []*types.Transaction) []*types.Transaction {
|
||||
signTxs := []*types.Transaction{}
|
||||
for _, tx := range txs {
|
||||
if tx.IsSigningTransaction() {
|
||||
signTxs = append(signTxs, tx)
|
||||
}
|
||||
}
|
||||
log.Debug("Save tx signers to cache", "hash", hash.String(), "len(txs)", len(signTxs))
|
||||
c.signingTxsCache.Add(hash, signTxs)
|
||||
return signTxs
|
||||
}
|
||||
|
||||
func (c *XDPoS) GetCachedSignerData(hash common.Hash) (interface{}, bool) {
|
||||
return c.signingTxsCache.Get(hash)
|
||||
}
|
||||
|
||||
// TODO: (Hashlab) Can be further refactored
|
||||
func (c *XDPoS) CheckMNTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) bool {
|
||||
switch params.BlockConsensusVersion(parent.Number) {
|
||||
|
|
@ -291,11 +335,6 @@ func (c *XDPoS) CheckMNTurn(chain consensus.ChainReader, parent *types.Header, s
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: (Hashlab) Need further work on refactor this method
|
||||
func (c *XDPoS) CacheSigner(hash common.Hash, txs []*types.Transaction) []*types.Transaction {
|
||||
return c.EngineV1.CacheSigner(hash, txs)
|
||||
}
|
||||
|
||||
// TODO: (Hashlab)Get signer coinbase
|
||||
func (c *XDPoS) Signer() common.Address {
|
||||
return c.EngineV1.Signer()
|
||||
|
|
|
|||
|
|
@ -112,14 +112,12 @@ type XDPoS_v1 struct {
|
|||
signFn clique.SignerFn // Signer function to authorize hashes with
|
||||
lock sync.RWMutex // Protects the signer fields
|
||||
|
||||
BlockSigners *lru.Cache
|
||||
HookReward func(chain consensus.ChainReader, state *state.StateDB, parentState *state.StateDB, header *types.Header) (error, map[string]interface{})
|
||||
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
||||
HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]common.Address, error)
|
||||
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
|
||||
HookVerifyMNs func(header *types.Header, signers []common.Address) error
|
||||
// GetXDCXService func() utils.TradingService
|
||||
// GetLendingService func() utils.LendingService
|
||||
|
||||
HookGetSignersFromContract func(blockHash common.Hash) ([]common.Address, error)
|
||||
}
|
||||
|
||||
|
|
@ -131,16 +129,15 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS_v1 {
|
|||
if conf.Epoch == 0 {
|
||||
conf.Epoch = utils.EpochLength
|
||||
}
|
||||
// Allocate the snapshot caches and create the engine
|
||||
BlockSigners, _ := lru.New(utils.BlockSignersCacheLimit)
|
||||
|
||||
recents, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||
signatures, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||
validatorSignatures, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||
verifiedHeaders, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||
return &XDPoS_v1{
|
||||
config: &conf,
|
||||
db: db,
|
||||
BlockSigners: BlockSigners,
|
||||
config: &conf,
|
||||
db: db,
|
||||
|
||||
recents: recents,
|
||||
signatures: signatures,
|
||||
verifiedHeaders: verifiedHeaders,
|
||||
|
|
@ -989,48 +986,6 @@ func (c *XDPoS_v1) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types
|
|||
return masternodes
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) CacheData(header *types.Header, txs []*types.Transaction, receipts []*types.Receipt) []*types.Transaction {
|
||||
signTxs := []*types.Transaction{}
|
||||
for _, tx := range txs {
|
||||
if tx.IsSigningTransaction() {
|
||||
var b uint
|
||||
for _, r := range receipts {
|
||||
if r.TxHash == tx.Hash() {
|
||||
if len(r.PostState) > 0 {
|
||||
b = types.ReceiptStatusSuccessful
|
||||
} else {
|
||||
b = r.Status
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if b == types.ReceiptStatusFailed {
|
||||
continue
|
||||
}
|
||||
|
||||
signTxs = append(signTxs, tx)
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug("Save tx signers to cache", "hash", header.Hash().String(), "number", header.Number, "len(txs)", len(signTxs))
|
||||
c.BlockSigners.Add(header.Hash(), signTxs)
|
||||
|
||||
return signTxs
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) CacheSigner(hash common.Hash, txs []*types.Transaction) []*types.Transaction {
|
||||
signTxs := []*types.Transaction{}
|
||||
for _, tx := range txs {
|
||||
if tx.IsSigningTransaction() {
|
||||
signTxs = append(signTxs, tx)
|
||||
}
|
||||
}
|
||||
log.Debug("Save tx signers to cache", "hash", hash.String(), "len(txs)", len(signTxs))
|
||||
c.BlockSigners.Add(hash, signTxs)
|
||||
return signTxs
|
||||
}
|
||||
|
||||
func (c *XDPoS_v1) GetDb() ethdb.Database {
|
||||
return c.db
|
||||
}
|
||||
|
|
|
|||
|
|
@ -332,16 +332,16 @@ func GetRewardForCheckpoint(c *XDPoS.XDPoS, chain consensus.ChainReader, header
|
|||
for i := prevCheckpoint + (rCheckpoint * 2) - 1; i >= startBlockNumber; i-- {
|
||||
header = chain.GetHeader(header.ParentHash, i)
|
||||
mapBlkHash[i] = header.Hash()
|
||||
signData, ok := c.BlockSigners.Get(header.Hash())
|
||||
signData, ok := c.GetCachedSignerData(header.Hash())
|
||||
if !ok {
|
||||
log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", i)
|
||||
block := chain.GetBlock(header.Hash(), i)
|
||||
txs := block.Transactions()
|
||||
if !chain.Config().IsTIPSigning(header.Number) {
|
||||
receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i)
|
||||
signData = c.CacheData(header, txs, receipts)
|
||||
signData = c.CacheNoneTIPSigningTxs(header, txs, receipts)
|
||||
} else {
|
||||
signData = c.CacheSigner(header.Hash(), txs)
|
||||
signData = c.CacheSigningTxs(header.Hash(), txs)
|
||||
}
|
||||
}
|
||||
txs := signData.([]*types.Transaction)
|
||||
|
|
|
|||
|
|
@ -674,7 +674,7 @@ func (bc *BlockChain) insert(block *types.Block) {
|
|||
if bc.chainConfig.XDPoS != nil && !bc.chainConfig.IsTIPSigning(block.Number()) {
|
||||
engine, ok := bc.Engine().(*XDPoS.XDPoS)
|
||||
if ok {
|
||||
engine.CacheData(block.Header(), block.Transactions(), bc.GetReceiptsByHash(block.Hash()))
|
||||
engine.CacheNoneTIPSigningTxs(block.Header(), block.Transactions(), bc.GetReceiptsByHash(block.Hash()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1375,7 +1375,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
|
|||
if bc.chainConfig.XDPoS != nil && bc.chainConfig.IsTIPSigning(block.Number()) {
|
||||
engine, ok := bc.Engine().(*XDPoS.XDPoS)
|
||||
if ok {
|
||||
engine.CacheSigner(block.Header().Hash(), block.Transactions())
|
||||
engine.CacheSigningTxs(block.Header().Hash(), block.Transactions())
|
||||
}
|
||||
}
|
||||
bc.futureBlocks.Remove(block.Hash())
|
||||
|
|
|
|||
5511
coverage.txt
5511
coverage.txt
File diff suppressed because it is too large
Load diff
230
eth/backend.go
230
eth/backend.go
|
|
@ -48,7 +48,6 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/bloombits"
|
||||
|
||||
//"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||
|
|
@ -288,20 +287,112 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
|||
eth.protocolManager.fetcher.SetSignHook(signHook)
|
||||
eth.protocolManager.fetcher.SetAppendM2HeaderHook(appendM2HeaderHook)
|
||||
|
||||
// Hook prepares validators M2 for the current epoch at checkpoint block
|
||||
c.HookValidator = func(header *types.Header, signers []common.Address) ([]byte, error) {
|
||||
start := time.Now()
|
||||
validators, err := GetValidators(eth.blockchain, signers)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
/*
|
||||
XDPoS1.0 Specific hooks
|
||||
*/
|
||||
|
||||
// Hook calculates reward for masternodes
|
||||
c.EngineV1.HookReward = func(chain consensus.ChainReader, stateBlock *state.StateDB, parentState *state.StateDB, header *types.Header) (error, map[string]interface{}) {
|
||||
number := header.Number.Uint64()
|
||||
rCheckpoint := chain.Config().XDPoS.RewardCheckpoint
|
||||
foundationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr
|
||||
if foundationWalletAddr == (common.Address{}) {
|
||||
log.Error("Foundation Wallet Address is empty", "error", foundationWalletAddr)
|
||||
return errors.New("Foundation Wallet Address is empty"), nil
|
||||
}
|
||||
header.Validators = validators
|
||||
log.Debug("Time Calculated HookValidator ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
return validators, nil
|
||||
rewards := make(map[string]interface{})
|
||||
if number > 0 && number-rCheckpoint > 0 && foundationWalletAddr != (common.Address{}) {
|
||||
start := time.Now()
|
||||
// Get signers in blockSigner smartcontract.
|
||||
// Get reward inflation.
|
||||
chainReward := new(big.Int).Mul(new(big.Int).SetUint64(chain.Config().XDPoS.Reward), new(big.Int).SetUint64(params.Ether))
|
||||
chainReward = rewardInflation(chain, chainReward, number, common.BlocksPerYear)
|
||||
|
||||
totalSigner := new(uint64)
|
||||
signers, err := contracts.GetRewardForCheckpoint(c, chain, header, rCheckpoint, totalSigner)
|
||||
|
||||
log.Debug("Time Get Signers", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
if err != nil {
|
||||
log.Crit("Fail to get signers for reward checkpoint", "error", err)
|
||||
}
|
||||
rewards["signers"] = signers
|
||||
rewardSigners, err := contracts.CalculateRewardForSigner(chainReward, signers, *totalSigner)
|
||||
if err != nil {
|
||||
log.Crit("Fail to calculate reward for signers", "error", err)
|
||||
}
|
||||
// Add reward for coin holders.
|
||||
voterResults := make(map[common.Address]interface{})
|
||||
if len(signers) > 0 {
|
||||
for signer, calcReward := range rewardSigners {
|
||||
err, rewards := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
|
||||
if err != nil {
|
||||
log.Crit("Fail to calculate reward for holders.", "error", err)
|
||||
}
|
||||
if len(rewards) > 0 {
|
||||
for holder, reward := range rewards {
|
||||
stateBlock.AddBalance(holder, reward)
|
||||
}
|
||||
}
|
||||
voterResults[signer] = rewards
|
||||
}
|
||||
}
|
||||
rewards["rewards"] = voterResults
|
||||
log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
}
|
||||
return nil, rewards
|
||||
}
|
||||
|
||||
/*
|
||||
HookGetSignersFromContract return list masternode for current state (block)
|
||||
This is a solution for work around issue return wrong list signers from snapshot
|
||||
*/
|
||||
c.EngineV1.HookGetSignersFromContract = func(block common.Hash) ([]common.Address, error) {
|
||||
client, err := eth.blockchain.GetClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addr := common.HexToAddress(common.MasternodeVotingSMC)
|
||||
validator, err := contractValidator.NewXDCValidator(addr, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts := new(bind.CallOpts)
|
||||
var (
|
||||
candidateAddresses []common.Address
|
||||
candidates []utils.Masternode
|
||||
)
|
||||
|
||||
stateDB, err := eth.blockchain.StateAt(eth.blockchain.GetBlockByHash(block).Root())
|
||||
candidateAddresses = state.GetCandidates(stateDB)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, address := range candidateAddresses {
|
||||
v, err := validator.GetCandidateCap(opts, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if address.String() != "0x0000000000000000000000000000000000000000" {
|
||||
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
|
||||
}
|
||||
}
|
||||
// sort candidates by stake descending
|
||||
sort.Slice(candidates, func(i, j int) bool {
|
||||
return candidates[i].Stake.Cmp(candidates[j].Stake) >= 0
|
||||
})
|
||||
if len(candidates) > 150 {
|
||||
candidates = candidates[:150]
|
||||
}
|
||||
result := []common.Address{}
|
||||
for _, candidate := range candidates {
|
||||
result = append(result, candidate.Address)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Hook scans for bad masternodes and decide to penalty them
|
||||
c.HookPenalty = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) {
|
||||
c.EngineV1.HookPenalty = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) {
|
||||
canonicalState, err := eth.blockchain.State()
|
||||
if canonicalState == nil || err != nil {
|
||||
log.Crit("Can't get state at head of canonical chain", "head number", eth.blockchain.CurrentHeader().Number.Uint64(), "err", err)
|
||||
|
|
@ -347,7 +438,7 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
|||
}
|
||||
|
||||
// Hook scans for bad masternodes and decide to penalty them
|
||||
c.HookPenaltyTIPSigning = func(chain consensus.ChainReader, header *types.Header, candidates []common.Address) ([]common.Address, error) {
|
||||
c.EngineV1.HookPenaltyTIPSigning = func(chain consensus.ChainReader, header *types.Header, candidates []common.Address) ([]common.Address, error) {
|
||||
prevEpoc := header.Number.Uint64() - chain.Config().XDPoS.Epoch
|
||||
combackEpoch := uint64(0)
|
||||
comebackLength := (common.LimitPenaltyEpoch + 1) * chain.Config().XDPoS.Epoch
|
||||
|
|
@ -419,11 +510,11 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
|||
if blockNumber%common.MergeSignRange == 0 {
|
||||
mapBlockHash[bhash] = true
|
||||
}
|
||||
signData, ok := c.BlockSigners.Get(bhash)
|
||||
signData, ok := c.GetCachedSignerData(bhash)
|
||||
if !ok {
|
||||
block := chain.GetBlock(bhash, blockNumber)
|
||||
txs := block.Transactions()
|
||||
signData = c.CacheSigner(bhash, txs)
|
||||
signData = c.CacheSigningTxs(bhash, txs)
|
||||
}
|
||||
txs := signData.([]*types.Transaction)
|
||||
// Check signer signed?
|
||||
|
|
@ -454,113 +545,24 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
|||
}
|
||||
return []common.Address{}, nil
|
||||
}
|
||||
|
||||
/*
|
||||
HookGetSignersFromContract return list masternode for current state (block)
|
||||
This is a solution for work around issue return wrong list signers from snapshot
|
||||
*/
|
||||
c.HookGetSignersFromContract = func(block common.Hash) ([]common.Address, error) {
|
||||
client, err := eth.blockchain.GetClient()
|
||||
// Hook prepares validators M2 for the current epoch at checkpoint block
|
||||
c.EngineV1.HookValidator = func(header *types.Header, signers []common.Address) ([]byte, error) {
|
||||
start := time.Now()
|
||||
validators, err := getValidators(eth.blockchain, signers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return []byte{}, err
|
||||
}
|
||||
addr := common.HexToAddress(common.MasternodeVotingSMC)
|
||||
validator, err := contractValidator.NewXDCValidator(addr, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts := new(bind.CallOpts)
|
||||
var (
|
||||
candidateAddresses []common.Address
|
||||
candidates []utils.Masternode
|
||||
)
|
||||
|
||||
stateDB, err := eth.blockchain.StateAt(eth.blockchain.GetBlockByHash(block).Root())
|
||||
candidateAddresses = state.GetCandidates(stateDB)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, address := range candidateAddresses {
|
||||
v, err := validator.GetCandidateCap(opts, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if address.String() != "0x0000000000000000000000000000000000000000" {
|
||||
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
|
||||
}
|
||||
}
|
||||
// sort candidates by stake descending
|
||||
sort.Slice(candidates, func(i, j int) bool {
|
||||
return candidates[i].Stake.Cmp(candidates[j].Stake) >= 0
|
||||
})
|
||||
if len(candidates) > 150 {
|
||||
candidates = candidates[:150]
|
||||
}
|
||||
result := []common.Address{}
|
||||
for _, candidate := range candidates {
|
||||
result = append(result, candidate.Address)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Hook calculates reward for masternodes
|
||||
c.HookReward = func(chain consensus.ChainReader, stateBlock *state.StateDB, parentState *state.StateDB, header *types.Header) (error, map[string]interface{}) {
|
||||
number := header.Number.Uint64()
|
||||
rCheckpoint := chain.Config().XDPoS.RewardCheckpoint
|
||||
foundationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr
|
||||
if foundationWalletAddr == (common.Address{}) {
|
||||
log.Error("Foundation Wallet Address is empty", "error", foundationWalletAddr)
|
||||
return errors.New("Foundation Wallet Address is empty"), nil
|
||||
}
|
||||
rewards := make(map[string]interface{})
|
||||
if number > 0 && number-rCheckpoint > 0 && foundationWalletAddr != (common.Address{}) {
|
||||
start := time.Now()
|
||||
// Get signers in blockSigner smartcontract.
|
||||
// Get reward inflation.
|
||||
chainReward := new(big.Int).Mul(new(big.Int).SetUint64(chain.Config().XDPoS.Reward), new(big.Int).SetUint64(params.Ether))
|
||||
chainReward = rewardInflation(chain, chainReward, number, common.BlocksPerYear)
|
||||
|
||||
totalSigner := new(uint64)
|
||||
signers, err := contracts.GetRewardForCheckpoint(c, chain, header, rCheckpoint, totalSigner)
|
||||
|
||||
log.Debug("Time Get Signers", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
if err != nil {
|
||||
log.Crit("Fail to get signers for reward checkpoint", "error", err)
|
||||
}
|
||||
rewards["signers"] = signers
|
||||
rewardSigners, err := contracts.CalculateRewardForSigner(chainReward, signers, *totalSigner)
|
||||
if err != nil {
|
||||
log.Crit("Fail to calculate reward for signers", "error", err)
|
||||
}
|
||||
// Add reward for coin holders.
|
||||
voterResults := make(map[common.Address]interface{})
|
||||
if len(signers) > 0 {
|
||||
for signer, calcReward := range rewardSigners {
|
||||
err, rewards := contracts.CalculateRewardForHolders(foundationWalletAddr, parentState, signer, calcReward, number)
|
||||
if err != nil {
|
||||
log.Crit("Fail to calculate reward for holders.", "error", err)
|
||||
}
|
||||
if len(rewards) > 0 {
|
||||
for holder, reward := range rewards {
|
||||
stateBlock.AddBalance(holder, reward)
|
||||
}
|
||||
}
|
||||
voterResults[signer] = rewards
|
||||
}
|
||||
}
|
||||
rewards["rewards"] = voterResults
|
||||
log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
}
|
||||
return nil, rewards
|
||||
header.Validators = validators
|
||||
log.Debug("Time Calculated HookValidator ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
return validators, nil
|
||||
}
|
||||
|
||||
// Hook verifies masternodes set
|
||||
c.HookVerifyMNs = func(header *types.Header, signers []common.Address) error {
|
||||
c.EngineV1.HookVerifyMNs = func(header *types.Header, signers []common.Address) error {
|
||||
number := header.Number.Int64()
|
||||
if number > 0 && number%common.EpocBlockRandomize == 0 {
|
||||
start := time.Now()
|
||||
validators, err := GetValidators(eth.blockchain, signers)
|
||||
validators, err := getValidators(eth.blockchain, signers)
|
||||
log.Debug("Time Calculated HookVerifyMNs ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -881,7 +883,7 @@ func (s *Ethereum) Stop() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func GetValidators(bc *core.BlockChain, masternodes []common.Address) ([]byte, error) {
|
||||
func getValidators(bc *core.BlockChain, masternodes []common.Address) ([]byte, error) {
|
||||
if bc.Config().XDPoS == nil {
|
||||
return nil, core.ErrNotXDPoS
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2953,7 +2953,7 @@ func GetSignersFromBlocks(b Backend, blockNumber uint64, blockHash common.Hash,
|
|||
return addrs, err
|
||||
}
|
||||
blockData, err := b.BlockByNumber(nil, rpc.BlockNumber(i))
|
||||
signTxs := engine.CacheSigner(header.Hash(), blockData.Transactions())
|
||||
signTxs := engine.CacheSigningTxs(header.Hash(), blockData.Transactions())
|
||||
for _, signtx := range signTxs {
|
||||
blkHash := common.BytesToHash(signtx.Data()[len(signtx.Data())-32:])
|
||||
from, _ := types.Sender(signer, signtx)
|
||||
|
|
|
|||
Loading…
Reference in a new issue