mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-23 23:24:30 +00:00
fix error double validation : m2 not validate body before verify block
This commit is contained in:
parent
05ea5f10f7
commit
5111364215
2 changed files with 37 additions and 16 deletions
|
|
@ -24,6 +24,7 @@ import (
|
|||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"bytes"
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
|
|
@ -188,6 +189,14 @@ 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()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Can't verify masternode permission: %v", err)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
|
@ -224,6 +233,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
|
||||
// Hook prepares validators M2 for the current epoch
|
||||
c.HookValidator = func(header *types.Header, signers []common.Address) error {
|
||||
start := time.Now()
|
||||
number := header.Number.Int64()
|
||||
if number > 0 && number%common.EpocBlockRandomize == 0 {
|
||||
validators, err := GetValidators(eth.blockchain, signers)
|
||||
|
|
@ -232,6 +242,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
}
|
||||
header.Validators = validators
|
||||
}
|
||||
log.Debug("Time Calculated HookValidator ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -243,6 +254,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
}
|
||||
prevEpoc := blockNumberEpoc - chain.Config().XDPoS.Epoch
|
||||
if prevEpoc >= 0 {
|
||||
start := time.Now()
|
||||
prevHeader := chain.GetHeaderByNumber(prevEpoc)
|
||||
penSigners := c.GetMasternodes(chain, prevHeader)
|
||||
if len(penSigners) > 0 {
|
||||
|
|
@ -271,6 +283,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
log.Debug("Time Calculated HookPenalty ", "block", blockNumberEpoc, "time", common.PrettyDuration(time.Since(start)))
|
||||
return penSigners, nil
|
||||
}
|
||||
return []common.Address{}, nil
|
||||
|
|
@ -288,13 +301,14 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
if foudationWalletAddr == (common.Address{}) {
|
||||
log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr)
|
||||
}
|
||||
start := time.Now()
|
||||
if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) {
|
||||
// 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)
|
||||
if err != nil {
|
||||
|
|
@ -321,7 +335,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -329,7 +343,9 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
c.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)
|
||||
log.Debug("Time Calculated HookVerifyMNs ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -497,8 +513,8 @@ func (self *Ethereum) SetEtherbase(etherbase common.Address) {
|
|||
self.miner.SetEtherbase(etherbase)
|
||||
}
|
||||
|
||||
// ValidateMiner checks if node's address is in set of validators
|
||||
func (s *Ethereum) ValidateStaker() (bool, error) {
|
||||
// ValidateMasternode checks if node's address is in set of masternodes
|
||||
func (s *Ethereum) ValidateMasternode() (bool, error) {
|
||||
eb, err := s.Etherbase()
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
|
@ -508,14 +524,14 @@ func (s *Ethereum) ValidateStaker() (bool, error) {
|
|||
c := s.engine.(*XDPoS.XDPoS)
|
||||
snap, err := c.GetSnapshot(s.blockchain, s.blockchain.CurrentHeader())
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Can't verify miner: %v", err)
|
||||
return false, fmt.Errorf("Can't verify masternode permission: %v", err)
|
||||
}
|
||||
if _, authorized := snap.Signers[eb]; !authorized {
|
||||
//This miner doesn't belong to set of validators
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
return false, fmt.Errorf("Only verify miners in XDPoS protocol")
|
||||
return false, fmt.Errorf("Only verify masternode permission in XDPoS protocol")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package fetcher
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
|
|
@ -62,7 +63,7 @@ type blockBroadcasterFn func(block *types.Block, propagate bool)
|
|||
type chainHeightFn func() uint64
|
||||
|
||||
// chainInsertFn is a callback type to insert a batch of blocks into the local chain.
|
||||
type chainInsertFn func(types.Blocks) (int, error)
|
||||
type chainInsertFn func(blocks types.Blocks) (int, error)
|
||||
|
||||
// peerDropFn is a callback type for dropping a peer detected as malicious.
|
||||
type peerDropFn func(id string)
|
||||
|
|
@ -128,7 +129,7 @@ type Fetcher struct {
|
|||
queue *prque.Prque // Queue containing the import operations (block number sorted)
|
||||
queues map[string]int // Per peer block counts to prevent memory exhaustion
|
||||
queued map[common.Hash]*inject // Set of already queued blocks (to dedup imports)
|
||||
|
||||
knowns *lru.ARCCache
|
||||
// Callbacks
|
||||
getBlock blockRetrievalFn // Retrieves a block from the local chain
|
||||
verifyHeader headerVerifierFn // Checks if a block's headers have a valid proof of work
|
||||
|
|
@ -148,6 +149,7 @@ type Fetcher struct {
|
|||
|
||||
// New creates a block fetcher to retrieve blocks based on hash announcements.
|
||||
func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertChain chainInsertFn, dropPeer peerDropFn) *Fetcher {
|
||||
knownBlocks, _ := lru.NewARC(blockLimit)
|
||||
return &Fetcher{
|
||||
notify: make(chan *announce),
|
||||
inject: make(chan *inject),
|
||||
|
|
@ -164,6 +166,7 @@ func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBloc
|
|||
queue: prque.New(),
|
||||
queues: make(map[string]int),
|
||||
queued: make(map[common.Hash]*inject),
|
||||
knowns: knownBlocks,
|
||||
getBlock: getBlock,
|
||||
verifyHeader: verifyHeader,
|
||||
broadcastBlock: broadcastBlock,
|
||||
|
|
@ -441,7 +444,7 @@ func (f *Fetcher) loop() {
|
|||
headerFilterInMeter.Mark(int64(len(task.headers)))
|
||||
|
||||
// Split the batch of headers into unknown ones (to return to the caller),
|
||||
// known incomplete ones (requiring body retrievals) and completed blocks.
|
||||
// knowns incomplete ones (requiring body retrievals) and completed blocks.
|
||||
unknown, incomplete, complete := []*types.Header{}, []*announce{}, []*types.Block{}
|
||||
for _, header := range task.headers {
|
||||
hash := header.Hash()
|
||||
|
|
@ -601,7 +604,10 @@ func (f *Fetcher) rescheduleComplete(complete *time.Timer) {
|
|||
// has not yet been seen.
|
||||
func (f *Fetcher) enqueue(peer string, block *types.Block) {
|
||||
hash := block.Hash()
|
||||
|
||||
if f.knowns.Contains(hash) {
|
||||
log.Debug("Discarded propagated block, knowns block", "peer", peer, "number", block.Number(), "hash", hash, "limit", blockLimit)
|
||||
return
|
||||
}
|
||||
// Ensure the peer isn't DOSing us
|
||||
count := f.queues[peer] + 1
|
||||
if count > blockLimit {
|
||||
|
|
@ -625,6 +631,7 @@ func (f *Fetcher) enqueue(peer string, block *types.Block) {
|
|||
}
|
||||
f.queues[peer] = count
|
||||
f.queued[hash] = op
|
||||
f.knowns.Add(hash, true)
|
||||
f.queue.Push(op, -float32(block.NumberU64()))
|
||||
if f.queueChangeHook != nil {
|
||||
f.queueChangeHook(op.block.Hash(), true)
|
||||
|
|
@ -650,7 +657,7 @@ func (f *Fetcher) insert(peer string, block *types.Block) {
|
|||
log.Debug("Unknown parent of propagated block", "peer", peer, "number", block.Number(), "hash", hash, "parent", block.ParentHash())
|
||||
return
|
||||
}
|
||||
again:
|
||||
again:
|
||||
// Quickly validate the header and propagate the block if it passes
|
||||
switch err := f.verifyHeader(block.Header()); err {
|
||||
case nil:
|
||||
|
|
@ -660,7 +667,7 @@ func (f *Fetcher) insert(peer string, block *types.Block) {
|
|||
case consensus.ErrFutureBlock:
|
||||
delay := time.Unix(block.Time().Int64(), 0).Sub(time.Now()) // nolint: gosimple
|
||||
time.Sleep(delay)
|
||||
log.Info("Receive futrue block", "number", block.NumberU64(), "hash", block.Hash().Hex(), "delay", delay)
|
||||
log.Info("Receive future block", "number", block.NumberU64(), "hash", block.Hash().Hex(), "delay", delay)
|
||||
goto again
|
||||
case consensus.ErrMissingValidatorSignature:
|
||||
newBlock := block
|
||||
|
|
@ -674,8 +681,7 @@ func (f *Fetcher) insert(peer string, block *types.Block) {
|
|||
go f.broadcastBlock(block, true)
|
||||
return
|
||||
}
|
||||
f.Enqueue(peer, newBlock)
|
||||
return
|
||||
block = newBlock
|
||||
default:
|
||||
// Something went very wrong, drop the peer
|
||||
log.Debug("Propagated block verification failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err)
|
||||
|
|
@ -695,11 +701,10 @@ func (f *Fetcher) insert(peer string, block *types.Block) {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If import succeeded, broadcast the block
|
||||
propAnnounceOutTimer.UpdateSince(block.ReceivedAt)
|
||||
go f.broadcastBlock(block, true)
|
||||
go f.broadcastBlock(block, false)
|
||||
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue