Merge pull request #281 from nguyenbatam/fix_error_double_validation

fix error double validation : M2 don't validate body,state,.. before verify block
This commit is contained in:
Tam Nguyen 2018-11-14 13:37:53 +07:00 committed by GitHub
commit c0584b6612
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 15 deletions

View file

@ -899,14 +899,10 @@ func (c *Posv) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan
}
}
}
// Sweet, the protocol permits us to sign the block, wait for our time
delay := time.Unix(header.Time.Int64(), 0).Sub(time.Now()) // nolint: gosimple
log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
select {
case <-stop:
return nil, nil
case <-time.After(delay):
default:
}
// Sign all the things!
sighash, err := signFn(accounts.Account{Address: signer}, sigHash(header).Bytes())

View file

@ -24,6 +24,7 @@ import (
"runtime"
"sync"
"sync/atomic"
"time"
"bytes"
"github.com/ethereum/go-ethereum/accounts"
@ -232,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)
@ -240,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
}
@ -251,6 +254,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
}
prevEpoc := blockNumberEpoc - chain.Config().Posv.Epoch
if prevEpoc >= 0 {
start := time.Now()
prevHeader := chain.GetHeaderByNumber(prevEpoc)
penSigners := c.GetMasternodes(chain, prevHeader)
if len(penSigners) > 0 {
@ -279,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
@ -296,6 +301,7 @@ 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)
@ -329,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
}
@ -337,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
}

View file

@ -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)
@ -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)
}()
}