mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 19:00:46 +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/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
|
|
@ -46,16 +47,14 @@ type XDPoS struct {
|
||||||
config *params.XDPoSConfig // Consensus engine configuration parameters
|
config *params.XDPoSConfig // Consensus engine configuration parameters
|
||||||
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
||||||
|
|
||||||
BlockSigners *lru.Cache
|
// Transaction cache, only make sense for adaptor level
|
||||||
HookReward func(chain consensus.ChainReader, state *state.StateDB, parentState *state.StateDB, header *types.Header) (error, map[string]interface{})
|
signingTxsCache *lru.Cache
|
||||||
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
|
||||||
HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]common.Address, error)
|
// Trading and lending service
|
||||||
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
|
|
||||||
HookVerifyMNs func(header *types.Header, signers []common.Address) error
|
|
||||||
GetXDCXService func() utils.TradingService
|
GetXDCXService func() utils.TradingService
|
||||||
GetLendingService func() utils.LendingService
|
GetLendingService func() utils.LendingService
|
||||||
HookGetSignersFromContract func(blockHash common.Hash) ([]common.Address, error)
|
|
||||||
|
|
||||||
|
// The exact consensus engine with different versions
|
||||||
EngineV1 engine_v1.XDPoS_v1
|
EngineV1 engine_v1.XDPoS_v1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,12 +68,12 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the snapshot caches and create the engine
|
// Allocate the snapshot caches and create the engine
|
||||||
BlockSigners, _ := lru.New(utils.BlockSignersCacheLimit)
|
signingTxsCache, _ := lru.New(utils.BlockSignersCacheLimit)
|
||||||
|
|
||||||
return &XDPoS{
|
return &XDPoS{
|
||||||
config: &conf,
|
config: &conf,
|
||||||
|
|
||||||
BlockSigners: BlockSigners,
|
signingTxsCache: signingTxsCache,
|
||||||
EngineV1: *engine_v1.New(&conf, db),
|
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
|
// Same DB across all consensus engines
|
||||||
func (c *XDPoS) GetDb() ethdb.Database {
|
func (c *XDPoS) GetDb() ethdb.Database {
|
||||||
return c.db
|
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
|
// TODO: (Hashlab) Can be further refactored
|
||||||
func (c *XDPoS) CheckMNTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) bool {
|
func (c *XDPoS) CheckMNTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) bool {
|
||||||
switch params.BlockConsensusVersion(parent.Number) {
|
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
|
// TODO: (Hashlab)Get signer coinbase
|
||||||
func (c *XDPoS) Signer() common.Address {
|
func (c *XDPoS) Signer() common.Address {
|
||||||
return c.EngineV1.Signer()
|
return c.EngineV1.Signer()
|
||||||
|
|
|
||||||
|
|
@ -112,14 +112,12 @@ type XDPoS_v1 struct {
|
||||||
signFn clique.SignerFn // Signer function to authorize hashes with
|
signFn clique.SignerFn // Signer function to authorize hashes with
|
||||||
lock sync.RWMutex // Protects the signer fields
|
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{})
|
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)
|
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
||||||
HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]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)
|
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
|
||||||
HookVerifyMNs func(header *types.Header, signers []common.Address) 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)
|
HookGetSignersFromContract func(blockHash common.Hash) ([]common.Address, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,8 +129,7 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS_v1 {
|
||||||
if conf.Epoch == 0 {
|
if conf.Epoch == 0 {
|
||||||
conf.Epoch = utils.EpochLength
|
conf.Epoch = utils.EpochLength
|
||||||
}
|
}
|
||||||
// Allocate the snapshot caches and create the engine
|
|
||||||
BlockSigners, _ := lru.New(utils.BlockSignersCacheLimit)
|
|
||||||
recents, _ := lru.NewARC(utils.InmemorySnapshots)
|
recents, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||||
signatures, _ := lru.NewARC(utils.InmemorySnapshots)
|
signatures, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||||
validatorSignatures, _ := lru.NewARC(utils.InmemorySnapshots)
|
validatorSignatures, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||||
|
|
@ -140,7 +137,7 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS_v1 {
|
||||||
return &XDPoS_v1{
|
return &XDPoS_v1{
|
||||||
config: &conf,
|
config: &conf,
|
||||||
db: db,
|
db: db,
|
||||||
BlockSigners: BlockSigners,
|
|
||||||
recents: recents,
|
recents: recents,
|
||||||
signatures: signatures,
|
signatures: signatures,
|
||||||
verifiedHeaders: verifiedHeaders,
|
verifiedHeaders: verifiedHeaders,
|
||||||
|
|
@ -989,48 +986,6 @@ func (c *XDPoS_v1) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types
|
||||||
return masternodes
|
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 {
|
func (c *XDPoS_v1) GetDb() ethdb.Database {
|
||||||
return c.db
|
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-- {
|
for i := prevCheckpoint + (rCheckpoint * 2) - 1; i >= startBlockNumber; i-- {
|
||||||
header = chain.GetHeader(header.ParentHash, i)
|
header = chain.GetHeader(header.ParentHash, i)
|
||||||
mapBlkHash[i] = header.Hash()
|
mapBlkHash[i] = header.Hash()
|
||||||
signData, ok := c.BlockSigners.Get(header.Hash())
|
signData, ok := c.GetCachedSignerData(header.Hash())
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", i)
|
log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", i)
|
||||||
block := chain.GetBlock(header.Hash(), i)
|
block := chain.GetBlock(header.Hash(), i)
|
||||||
txs := block.Transactions()
|
txs := block.Transactions()
|
||||||
if !chain.Config().IsTIPSigning(header.Number) {
|
if !chain.Config().IsTIPSigning(header.Number) {
|
||||||
receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i)
|
receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i)
|
||||||
signData = c.CacheData(header, txs, receipts)
|
signData = c.CacheNoneTIPSigningTxs(header, txs, receipts)
|
||||||
} else {
|
} else {
|
||||||
signData = c.CacheSigner(header.Hash(), txs)
|
signData = c.CacheSigningTxs(header.Hash(), txs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
txs := signData.([]*types.Transaction)
|
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()) {
|
if bc.chainConfig.XDPoS != nil && !bc.chainConfig.IsTIPSigning(block.Number()) {
|
||||||
engine, ok := bc.Engine().(*XDPoS.XDPoS)
|
engine, ok := bc.Engine().(*XDPoS.XDPoS)
|
||||||
if ok {
|
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()) {
|
if bc.chainConfig.XDPoS != nil && bc.chainConfig.IsTIPSigning(block.Number()) {
|
||||||
engine, ok := bc.Engine().(*XDPoS.XDPoS)
|
engine, ok := bc.Engine().(*XDPoS.XDPoS)
|
||||||
if ok {
|
if ok {
|
||||||
engine.CacheSigner(block.Header().Hash(), block.Transactions())
|
engine.CacheSigningTxs(block.Header().Hash(), block.Transactions())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bc.futureBlocks.Remove(block.Hash())
|
bc.futureBlocks.Remove(block.Hash())
|
||||||
|
|
|
||||||
5511
coverage.txt
5511
coverage.txt
File diff suppressed because it is too large
Load diff
228
eth/backend.go
228
eth/backend.go
|
|
@ -48,7 +48,6 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/bloombits"
|
"github.com/XinFinOrg/XDPoSChain/core/bloombits"
|
||||||
|
|
||||||
//"github.com/XinFinOrg/XDPoSChain/core/state"
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/XDCx"
|
"github.com/XinFinOrg/XDPoSChain/XDCx"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
"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.SetSignHook(signHook)
|
||||||
eth.protocolManager.fetcher.SetAppendM2HeaderHook(appendM2HeaderHook)
|
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) {
|
XDPoS1.0 Specific hooks
|
||||||
start := time.Now()
|
*/
|
||||||
validators, err := GetValidators(eth.blockchain, signers)
|
|
||||||
if err != nil {
|
// Hook calculates reward for masternodes
|
||||||
return []byte{}, err
|
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
|
rewards := make(map[string]interface{})
|
||||||
log.Debug("Time Calculated HookValidator ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
if number > 0 && number-rCheckpoint > 0 && foundationWalletAddr != (common.Address{}) {
|
||||||
return validators, nil
|
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
|
// 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()
|
canonicalState, err := eth.blockchain.State()
|
||||||
if canonicalState == nil || err != nil {
|
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)
|
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
|
// 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
|
prevEpoc := header.Number.Uint64() - chain.Config().XDPoS.Epoch
|
||||||
combackEpoch := uint64(0)
|
combackEpoch := uint64(0)
|
||||||
comebackLength := (common.LimitPenaltyEpoch + 1) * chain.Config().XDPoS.Epoch
|
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 {
|
if blockNumber%common.MergeSignRange == 0 {
|
||||||
mapBlockHash[bhash] = true
|
mapBlockHash[bhash] = true
|
||||||
}
|
}
|
||||||
signData, ok := c.BlockSigners.Get(bhash)
|
signData, ok := c.GetCachedSignerData(bhash)
|
||||||
if !ok {
|
if !ok {
|
||||||
block := chain.GetBlock(bhash, blockNumber)
|
block := chain.GetBlock(bhash, blockNumber)
|
||||||
txs := block.Transactions()
|
txs := block.Transactions()
|
||||||
signData = c.CacheSigner(bhash, txs)
|
signData = c.CacheSigningTxs(bhash, txs)
|
||||||
}
|
}
|
||||||
txs := signData.([]*types.Transaction)
|
txs := signData.([]*types.Transaction)
|
||||||
// Check signer signed?
|
// Check signer signed?
|
||||||
|
|
@ -454,113 +545,24 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
||||||
}
|
}
|
||||||
return []common.Address{}, nil
|
return []common.Address{}, nil
|
||||||
}
|
}
|
||||||
|
// Hook prepares validators M2 for the current epoch at checkpoint block
|
||||||
/*
|
c.EngineV1.HookValidator = func(header *types.Header, signers []common.Address) ([]byte, error) {
|
||||||
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()
|
|
||||||
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 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()
|
start := time.Now()
|
||||||
// Get signers in blockSigner smartcontract.
|
validators, err := getValidators(eth.blockchain, signers)
|
||||||
// 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 {
|
if err != nil {
|
||||||
log.Crit("Fail to get signers for reward checkpoint", "error", err)
|
return []byte{}, err
|
||||||
}
|
}
|
||||||
rewards["signers"] = signers
|
header.Validators = validators
|
||||||
rewardSigners, err := contracts.CalculateRewardForSigner(chainReward, signers, *totalSigner)
|
log.Debug("Time Calculated HookValidator ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||||
if err != nil {
|
return validators, 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook verifies masternodes set
|
// 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()
|
number := header.Number.Int64()
|
||||||
if number > 0 && number%common.EpocBlockRandomize == 0 {
|
if number > 0 && number%common.EpocBlockRandomize == 0 {
|
||||||
start := time.Now()
|
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)))
|
log.Debug("Time Calculated HookVerifyMNs ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -881,7 +883,7 @@ func (s *Ethereum) Stop() error {
|
||||||
return nil
|
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 {
|
if bc.Config().XDPoS == nil {
|
||||||
return nil, core.ErrNotXDPoS
|
return nil, core.ErrNotXDPoS
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2953,7 +2953,7 @@ func GetSignersFromBlocks(b Backend, blockNumber uint64, blockHash common.Hash,
|
||||||
return addrs, err
|
return addrs, err
|
||||||
}
|
}
|
||||||
blockData, err := b.BlockByNumber(nil, rpc.BlockNumber(i))
|
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 {
|
for _, signtx := range signTxs {
|
||||||
blkHash := common.BytesToHash(signtx.Data()[len(signtx.Data())-32:])
|
blkHash := common.BytesToHash(signtx.Data()[len(signtx.Data())-32:])
|
||||||
from, _ := types.Sender(signer, signtx)
|
from, _ := types.Sender(signer, signtx)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue