mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
handle SignHash error
This commit is contained in:
parent
6af0f56740
commit
6adee64867
1 changed files with 234 additions and 84 deletions
318
eth/backend.go
318
eth/backend.go
|
|
@ -18,12 +18,13 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/eth/filters"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"math/big"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
|
@ -32,19 +33,16 @@ import (
|
|||
"bytes"
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
"github.com/ethereum/go-ethereum/consensus/XDPoS"
|
||||
"github.com/ethereum/go-ethereum/contracts"
|
||||
"github.com/ethereum/go-ethereum/contracts/validator/contract"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/bloombits"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
//"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/filters"
|
||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
|
|
@ -54,7 +52,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
|
|
@ -173,6 +170,25 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
}
|
||||
eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain)
|
||||
|
||||
if common.RollbackHash != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") {
|
||||
curBlock := eth.blockchain.CurrentBlock()
|
||||
prevBlock := eth.blockchain.GetBlockByHash(common.RollbackHash)
|
||||
|
||||
if curBlock.NumberU64() > prevBlock.NumberU64() {
|
||||
for ; curBlock != nil && curBlock.NumberU64() != prevBlock.NumberU64(); curBlock = eth.blockchain.GetBlock(curBlock.ParentHash(), curBlock.NumberU64()-1) {
|
||||
eth.blockchain.Rollback([]common.Hash{curBlock.Hash()})
|
||||
}
|
||||
}
|
||||
|
||||
if prevBlock != nil {
|
||||
err := eth.blockchain.SetHead(prevBlock.NumberU64())
|
||||
if err != nil {
|
||||
log.Crit("Err Rollback", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -192,16 +208,19 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
if eth.chainConfig.XDPoS != nil {
|
||||
c := eth.engine.(*XDPoS.XDPoS)
|
||||
signHook := func(block *types.Block) error {
|
||||
ok, err := eth.ValidateMasternode()
|
||||
eb, err := eth.Etherbase()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Can't verify masternode permission: %v", err)
|
||||
log.Error("Cannot get etherbase for append m2 header", "err", err)
|
||||
return fmt.Errorf("etherbase missing: %v", err)
|
||||
}
|
||||
ok := eth.txPool.IsSigner != nil && eth.txPool.IsSigner(eb)
|
||||
if !ok {
|
||||
// silently return as this node doesn't have masternode permission to sign block
|
||||
return nil
|
||||
}
|
||||
if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil {
|
||||
return fmt.Errorf("Fail to create tx sign for importing block: %v", err)
|
||||
if block.NumberU64()%common.MergeSignRange == 0 || !eth.chainConfig.IsTIP2019(block.Number()) {
|
||||
if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil {
|
||||
return fmt.Errorf("Fail to create tx sign for importing block: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -221,9 +240,15 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
return block, false, fmt.Errorf("can't get block validator: %v", err)
|
||||
}
|
||||
if m2 == eb {
|
||||
wallet, _ := eth.accountManager.Find(accounts.Account{Address: eb})
|
||||
wallet, err := eth.accountManager.Find(accounts.Account{Address: eb})
|
||||
if err != nil {
|
||||
return block, false, err
|
||||
}
|
||||
header := block.Header()
|
||||
sighash, _ := wallet.SignHash(accounts.Account{Address: eb}, XDPoS.SigHash(header).Bytes())
|
||||
sighash, err := wallet.SignHash(accounts.Account{Address: eb}, XDPoS.SigHash(header).Bytes())
|
||||
if err != nil {
|
||||
return block, false, err
|
||||
}
|
||||
header.Validator = sighash
|
||||
return types.NewBlockWithHeader(header).WithBody(block.Transactions(), block.Uncles()), true, nil
|
||||
}
|
||||
|
|
@ -247,9 +272,9 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
|
||||
// Hook scans for bad masternodes and decide to penalty them
|
||||
c.HookPenalty = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) {
|
||||
client, err := eth.blockchain.GetClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
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)
|
||||
}
|
||||
prevEpoc := blockNumberEpoc - chain.Config().XDPoS.Epoch
|
||||
if prevEpoc >= 0 {
|
||||
|
|
@ -257,28 +282,31 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
prevHeader := chain.GetHeaderByNumber(prevEpoc)
|
||||
penSigners := c.GetMasternodes(chain, prevHeader)
|
||||
if len(penSigners) > 0 {
|
||||
blockSignerAddr := common.HexToAddress(common.BlockSigners)
|
||||
// Loop for each block to check missing sign.
|
||||
for i := prevEpoc; i < blockNumberEpoc; i++ {
|
||||
blockHeader := chain.GetHeaderByNumber(i)
|
||||
if len(penSigners) > 0 {
|
||||
signedMasternodes, err := contracts.GetSignersFromContract(blockSignerAddr, client, blockHeader.Hash())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(signedMasternodes) > 0 {
|
||||
// Check signer signed?
|
||||
for _, signed := range signedMasternodes {
|
||||
for j, addr := range penSigners {
|
||||
if signed == addr {
|
||||
// Remove it from dupSigners.
|
||||
penSigners = append(penSigners[:j], penSigners[j+1:]...)
|
||||
if i%common.MergeSignRange == 0 || !chainConfig.IsTIP2019(big.NewInt(int64(i))) {
|
||||
bheader := chain.GetHeaderByNumber(i)
|
||||
bhash := bheader.Hash()
|
||||
block := chain.GetBlock(bhash, i)
|
||||
if len(penSigners) > 0 {
|
||||
signedMasternodes, err := contracts.GetSignersFromContract(canonicalState, block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(signedMasternodes) > 0 {
|
||||
// Check signer signed?
|
||||
for _, signed := range signedMasternodes {
|
||||
for j, addr := range penSigners {
|
||||
if signed == addr {
|
||||
// Remove it from dupSigners.
|
||||
penSigners = append(penSigners[:j], penSigners[j+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -288,54 +316,159 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
return []common.Address{}, nil
|
||||
}
|
||||
|
||||
// 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) {
|
||||
prevEpoc := header.Number.Uint64() - chain.Config().XDPoS.Epoch
|
||||
combackEpoch := uint64(0)
|
||||
comebackLength := uint64((common.LimitPenaltyEpoch + 1) * chain.Config().XDPoS.Epoch)
|
||||
if header.Number.Uint64() > comebackLength {
|
||||
combackEpoch = header.Number.Uint64() - comebackLength
|
||||
}
|
||||
if prevEpoc >= 0 {
|
||||
start := time.Now()
|
||||
|
||||
listBlockHash := make([]common.Hash, chain.Config().XDPoS.Epoch)
|
||||
|
||||
// get list block hash & stats total created block
|
||||
statMiners := make(map[common.Address]int)
|
||||
listBlockHash[0] = header.ParentHash
|
||||
parentnumber := header.Number.Uint64() - 1
|
||||
parentHash := header.ParentHash
|
||||
for i := uint64(1); i < chain.Config().XDPoS.Epoch; i++ {
|
||||
parentHeader := chain.GetHeader(parentHash, parentnumber)
|
||||
miner, _ := c.RecoverSigner(parentHeader)
|
||||
value, exist := statMiners[miner]
|
||||
if exist {
|
||||
value = value + 1
|
||||
} else {
|
||||
value = 1
|
||||
}
|
||||
statMiners[miner] = value
|
||||
parentHash = parentHeader.ParentHash
|
||||
parentnumber--
|
||||
listBlockHash[i] = parentHash
|
||||
}
|
||||
|
||||
// add list not miner to penalties
|
||||
prevHeader := chain.GetHeaderByNumber(prevEpoc)
|
||||
preMasternodes := c.GetMasternodes(chain, prevHeader)
|
||||
penalties := []common.Address{}
|
||||
for miner, total := range statMiners {
|
||||
if total < common.MinimunMinerBlockPerEpoch {
|
||||
log.Debug("Find a node not enough requirement create block", "addr", miner.Hex(), "total", total)
|
||||
penalties = append(penalties, miner)
|
||||
}
|
||||
}
|
||||
for _, addr := range preMasternodes {
|
||||
if _, exist := statMiners[addr]; !exist {
|
||||
log.Debug("Find a node don't create block", "addr", addr.Hex())
|
||||
penalties = append(penalties, addr)
|
||||
}
|
||||
}
|
||||
|
||||
// get list check penalties signing block & list master nodes wil comeback
|
||||
penComebacks := []common.Address{}
|
||||
if combackEpoch > 0 {
|
||||
combackHeader := chain.GetHeaderByNumber(combackEpoch)
|
||||
penalties := common.ExtractAddressFromBytes(combackHeader.Penalties)
|
||||
for _, penaltie := range penalties {
|
||||
for _, addr := range candidates {
|
||||
if penaltie == addr {
|
||||
penComebacks = append(penComebacks, penaltie)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop for each block to check missing sign. with comeback nodes
|
||||
mapBlockHash := map[common.Hash]bool{}
|
||||
for i := common.RangeReturnSigner - 1; i >= 0; i-- {
|
||||
if len(penComebacks) > 0 {
|
||||
blockNumber := header.Number.Uint64() - uint64(i) - 1
|
||||
bhash := listBlockHash[i]
|
||||
if blockNumber%common.MergeSignRange == 0 {
|
||||
mapBlockHash[bhash] = true
|
||||
}
|
||||
signData, ok := c.BlockSigners.Get(bhash)
|
||||
if !ok {
|
||||
block := chain.GetBlock(bhash, blockNumber)
|
||||
txs := block.Transactions()
|
||||
signData = c.CacheSigner(bhash, txs)
|
||||
}
|
||||
txs := signData.([]*types.Transaction)
|
||||
// Check signer signed?
|
||||
for _, tx := range txs {
|
||||
blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:])
|
||||
from := *tx.From()
|
||||
if mapBlockHash[blkHash] {
|
||||
for j, addr := range penComebacks {
|
||||
if from == addr {
|
||||
// Remove it from dupSigners.
|
||||
penComebacks = append(penComebacks[:j], penComebacks[j+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug("Time Calculated HookPenaltyTIPSigning ", "block", header.Number, "hash", header.Hash().Hex(), "pen comeback nodes", len(penComebacks), "not enough miner", len(penalties), "time", common.PrettyDuration(time.Since(start)))
|
||||
penalties = append(penalties, penComebacks...)
|
||||
return penComebacks, nil
|
||||
|
||||
}
|
||||
return []common.Address{}, nil
|
||||
}
|
||||
|
||||
// Hook calculates reward for masternodes
|
||||
c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) {
|
||||
client, err := eth.blockchain.GetClient()
|
||||
if err != nil {
|
||||
log.Error("Fail to connect IPC client for blockSigner", "error", err)
|
||||
return err, nil
|
||||
c.HookReward = func(chain consensus.ChainReader, stateBlock *state.StateDB, header *types.Header) (error, map[string]interface{}) {
|
||||
parentHeader := eth.blockchain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
|
||||
canonicalState, err := eth.blockchain.StateAt(parentHeader.Root)
|
||||
if canonicalState == nil || err != nil {
|
||||
log.Crit("Can't get state at head of canonical chain", "head number", header.Number.Uint64(), "err", err)
|
||||
}
|
||||
number := header.Number.Uint64()
|
||||
rCheckpoint := chain.Config().XDPoS.RewardCheckpoint
|
||||
foudationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr
|
||||
if foudationWalletAddr == (common.Address{}) {
|
||||
log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr)
|
||||
foundationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr
|
||||
if foundationWalletAddr == (common.Address{}) {
|
||||
log.Error("Foundation Wallet Address is empty", "error", foundationWalletAddr)
|
||||
return err, nil
|
||||
}
|
||||
rewards := make(map[string]interface{})
|
||||
if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) {
|
||||
if number > 0 && number-rCheckpoint > 0 && foundationWalletAddr != (common.Address{}) {
|
||||
start := time.Now()
|
||||
// Get signers in blockSigner smartcontract.
|
||||
addr := common.HexToAddress(common.BlockSigners)
|
||||
// Get reward inflation.
|
||||
chainReward := new(big.Int).Mul(new(big.Int).SetUint64(chain.Config().XDPoS.Reward), new(big.Int).SetUint64(params.Ether))
|
||||
chainReward = rewardInflation(chainReward, number, common.BlocksPerYear)
|
||||
|
||||
totalSigner := new(uint64)
|
||||
signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner)
|
||||
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.Error("Fail to get signers for reward checkpoint", "error", err)
|
||||
return 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.Error("Fail to calculate reward for signers", "error", err)
|
||||
return err, nil
|
||||
}
|
||||
// Get validator.
|
||||
validator, err := contract.NewXDCValidator(common.HexToAddress(common.MasternodeVotingSMC), client)
|
||||
if err != nil {
|
||||
log.Error("Fail get instance of XDC Validator", "error", err)
|
||||
return 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(foudationWalletAddr, validator, state, signer, calcReward)
|
||||
err, rewards := contracts.CalculateRewardForHolders(foundationWalletAddr, canonicalState, signer, calcReward, number)
|
||||
if err != nil {
|
||||
log.Error("Fail to calculate reward for holders.", "error", err)
|
||||
return 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
|
||||
}
|
||||
|
|
@ -362,11 +495,20 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
eth.txPool.IsMasterNode = func(address common.Address) bool {
|
||||
|
||||
eth.txPool.IsSigner = func(address common.Address) bool {
|
||||
currentHeader := eth.blockchain.CurrentHeader()
|
||||
snap, err := c.GetSnapshot(eth.blockchain, currentHeader)
|
||||
header := currentHeader
|
||||
// Sometimes, the latest block hasn't been inserted to chain yet
|
||||
// getSnapshot from parent block if it exists
|
||||
parentHeader := eth.blockchain.GetHeader(currentHeader.ParentHash, currentHeader.Number.Uint64()-1)
|
||||
if parentHeader != nil {
|
||||
// not genesis block
|
||||
header = parentHeader
|
||||
}
|
||||
snap, err := c.GetSnapshot(eth.blockchain, header)
|
||||
if err != nil {
|
||||
log.Error("Can't get snapshot with current header ", "number", currentHeader.Number, "hash", currentHeader.Hash().Hex(), "err", err)
|
||||
log.Error("Can't get snapshot with at ", "number", header.Number, "hash", header.Hash().Hex(), "err", err)
|
||||
return false
|
||||
}
|
||||
if _, ok := snap.Signers[address]; ok {
|
||||
|
|
@ -374,27 +516,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
}
|
||||
return false
|
||||
}
|
||||
eth.blockchain.HookWriteRewards = func(header *types.Header) {
|
||||
if len(config.StoreRewardFolder) > 0 {
|
||||
rewards := c.GetRewards(header.Hash())
|
||||
if rewards == nil {
|
||||
rewards = c.GetRewards(header.HashNoValidator())
|
||||
if rewards != nil {
|
||||
c.InsertRewards(header.Hash(), rewards)
|
||||
}
|
||||
}
|
||||
if rewards == nil {
|
||||
return
|
||||
}
|
||||
data, err := json.Marshal(rewards)
|
||||
if err == nil {
|
||||
err = ioutil.WriteFile(filepath.Join(config.StoreRewardFolder, header.Number.String()+"."+header.Hash().Hex()), data, 0644)
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("Error when save reward info ", "number", header.Number, "hash", header.Hash().Hex(), "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return eth, nil
|
||||
}
|
||||
|
|
@ -430,10 +551,11 @@ func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Data
|
|||
|
||||
// CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service
|
||||
func CreateConsensusEngine(ctx *node.ServiceContext, config *ethash.Config, chainConfig *params.ChainConfig, db ethdb.Database) consensus.Engine {
|
||||
// If XinFin-DPoS is requested, set it up
|
||||
// If Xinfin-XDPoS voting is requested, set it up
|
||||
if chainConfig.XDPoS != nil {
|
||||
return XDPoS.New(chainConfig.XDPoS, db)
|
||||
}
|
||||
|
||||
// Otherwise assume proof-of-work
|
||||
switch {
|
||||
case config.PowMode == ethash.ModeFake:
|
||||
|
|
@ -575,6 +697,28 @@ func (s *Ethereum) ValidateMasternode() (bool, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// ValidateMasternodeTestNet checks if node's address is in set of masternodes in Testnet
|
||||
func (s *Ethereum) ValidateMasternodeTestnet() (bool, error) {
|
||||
eb, err := s.Etherbase()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if s.chainConfig.XDPoS == nil {
|
||||
return false, fmt.Errorf("Only verify masternode permission in XDPoS protocol")
|
||||
}
|
||||
masternodes := []common.Address{
|
||||
common.HexToAddress("0xfFC679Dcdf444D2eEb0491A998E7902B411CcF20"),
|
||||
common.HexToAddress("0xd76fd76F7101811726DCE9E43C2617706a4c45c8"),
|
||||
common.HexToAddress("0x8A97753311aeAFACfd76a68Cf2e2a9808d3e65E8"),
|
||||
}
|
||||
for _, m := range masternodes {
|
||||
if m == eb {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (s *Ethereum) StartStaking(local bool) error {
|
||||
eb, err := s.Etherbase()
|
||||
if err != nil {
|
||||
|
|
@ -600,7 +744,9 @@ func (s *Ethereum) StartStaking(local bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Ethereum) StopStaking() { s.miner.Stop() }
|
||||
func (s *Ethereum) StopStaking() {
|
||||
s.miner.Stop()
|
||||
}
|
||||
func (s *Ethereum) IsStaking() bool { return s.miner.Mining() }
|
||||
func (s *Ethereum) Miner() *miner.Miner { return s.miner }
|
||||
|
||||
|
|
@ -715,3 +861,7 @@ func rewardInflation(chainReward *big.Int, number uint64, blockPerYear uint64) *
|
|||
|
||||
return chainReward
|
||||
}
|
||||
|
||||
func (s *Ethereum) GetPeer() int {
|
||||
return len(s.protocolManager.peers.peers)
|
||||
}
|
||||
Loading…
Reference in a new issue