fix error double validation : m2 not validate body before verify block

This commit is contained in:
Nguyen Ba Tam 2018-11-13 17:46:29 +07:00
parent 4758613394
commit 36692df383
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 { select {
case <-stop: case <-stop:
return nil, nil return nil, nil
case <-time.After(delay): default:
} }
// Sign all the things! // Sign all the things!
sighash, err := signFn(accounts.Account{Address: signer}, sigHash(header).Bytes()) sighash, err := signFn(accounts.Account{Address: signer}, sigHash(header).Bytes())

View file

@ -24,6 +24,7 @@ import (
"runtime" "runtime"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time"
"bytes" "bytes"
"github.com/ethereum/go-ethereum/accounts" "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 // Hook prepares validators M2 for the current epoch
c.HookValidator = func(header *types.Header, signers []common.Address) error { c.HookValidator = func(header *types.Header, signers []common.Address) error {
start := time.Now()
number := header.Number.Int64() number := header.Number.Int64()
if number > 0 && number%common.EpocBlockRandomize == 0 { if number > 0 && number%common.EpocBlockRandomize == 0 {
validators, err := GetValidators(eth.blockchain, signers) validators, err := GetValidators(eth.blockchain, signers)
@ -240,6 +242,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
} }
header.Validators = validators header.Validators = validators
} }
log.Debug("Time Calculated HookValidator ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
return nil return nil
} }
@ -251,6 +254,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
} }
prevEpoc := blockNumberEpoc - chain.Config().Posv.Epoch prevEpoc := blockNumberEpoc - chain.Config().Posv.Epoch
if prevEpoc >= 0 { if prevEpoc >= 0 {
start := time.Now()
prevHeader := chain.GetHeaderByNumber(prevEpoc) prevHeader := chain.GetHeaderByNumber(prevEpoc)
penSigners := c.GetMasternodes(chain, prevHeader) penSigners := c.GetMasternodes(chain, prevHeader)
if len(penSigners) > 0 { 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 penSigners, nil
} }
return []common.Address{}, nil return []common.Address{}, nil
@ -296,6 +301,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
if foudationWalletAddr == (common.Address{}) { if foudationWalletAddr == (common.Address{}) {
log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr) log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr)
} }
start := time.Now()
if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) { if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) {
// Get signers in blockSigner smartcontract. // Get signers in blockSigner smartcontract.
addr := common.HexToAddress(common.BlockSigners) 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 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 { c.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()
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 { if err != nil {
return err return err
} }

View file

@ -19,6 +19,7 @@ package fetcher
import ( import (
"errors" "errors"
"github.com/hashicorp/golang-lru"
"math/rand" "math/rand"
"time" "time"
@ -62,7 +63,7 @@ type blockBroadcasterFn func(block *types.Block, propagate bool)
type chainHeightFn func() uint64 type chainHeightFn func() uint64
// chainInsertFn is a callback type to insert a batch of blocks into the local chain. // 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. // peerDropFn is a callback type for dropping a peer detected as malicious.
type peerDropFn func(id string) type peerDropFn func(id string)
@ -128,7 +129,7 @@ type Fetcher struct {
queue *prque.Prque // Queue containing the import operations (block number sorted) queue *prque.Prque // Queue containing the import operations (block number sorted)
queues map[string]int // Per peer block counts to prevent memory exhaustion 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) queued map[common.Hash]*inject // Set of already queued blocks (to dedup imports)
knowns *lru.ARCCache
// Callbacks // Callbacks
getBlock blockRetrievalFn // Retrieves a block from the local chain getBlock blockRetrievalFn // Retrieves a block from the local chain
verifyHeader headerVerifierFn // Checks if a block's headers have a valid proof of work 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. // 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 { func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertChain chainInsertFn, dropPeer peerDropFn) *Fetcher {
knownBlocks, _ := lru.NewARC(blockLimit)
return &Fetcher{ return &Fetcher{
notify: make(chan *announce), notify: make(chan *announce),
inject: make(chan *inject), inject: make(chan *inject),
@ -164,6 +166,7 @@ func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBloc
queue: prque.New(), queue: prque.New(),
queues: make(map[string]int), queues: make(map[string]int),
queued: make(map[common.Hash]*inject), queued: make(map[common.Hash]*inject),
knowns: knownBlocks,
getBlock: getBlock, getBlock: getBlock,
verifyHeader: verifyHeader, verifyHeader: verifyHeader,
broadcastBlock: broadcastBlock, broadcastBlock: broadcastBlock,
@ -441,7 +444,7 @@ func (f *Fetcher) loop() {
headerFilterInMeter.Mark(int64(len(task.headers))) headerFilterInMeter.Mark(int64(len(task.headers)))
// Split the batch of headers into unknown ones (to return to the caller), // 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{} unknown, incomplete, complete := []*types.Header{}, []*announce{}, []*types.Block{}
for _, header := range task.headers { for _, header := range task.headers {
hash := header.Hash() hash := header.Hash()
@ -601,7 +604,10 @@ func (f *Fetcher) rescheduleComplete(complete *time.Timer) {
// has not yet been seen. // has not yet been seen.
func (f *Fetcher) enqueue(peer string, block *types.Block) { func (f *Fetcher) enqueue(peer string, block *types.Block) {
hash := block.Hash() 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 // Ensure the peer isn't DOSing us
count := f.queues[peer] + 1 count := f.queues[peer] + 1
if count > blockLimit { if count > blockLimit {
@ -625,6 +631,7 @@ func (f *Fetcher) enqueue(peer string, block *types.Block) {
} }
f.queues[peer] = count f.queues[peer] = count
f.queued[hash] = op f.queued[hash] = op
f.knowns.Add(hash, true)
f.queue.Push(op, -float32(block.NumberU64())) f.queue.Push(op, -float32(block.NumberU64()))
if f.queueChangeHook != nil { if f.queueChangeHook != nil {
f.queueChangeHook(op.block.Hash(), true) f.queueChangeHook(op.block.Hash(), true)
@ -660,7 +667,7 @@ func (f *Fetcher) insert(peer string, block *types.Block) {
case consensus.ErrFutureBlock: case consensus.ErrFutureBlock:
delay := time.Unix(block.Time().Int64(), 0).Sub(time.Now()) // nolint: gosimple delay := time.Unix(block.Time().Int64(), 0).Sub(time.Now()) // nolint: gosimple
time.Sleep(delay) 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 goto again
case consensus.ErrMissingValidatorSignature: case consensus.ErrMissingValidatorSignature:
newBlock := block newBlock := block
@ -674,8 +681,7 @@ func (f *Fetcher) insert(peer string, block *types.Block) {
go f.broadcastBlock(block, true) go f.broadcastBlock(block, true)
return return
} }
f.Enqueue(peer, newBlock) block = newBlock
return
default: default:
// Something went very wrong, drop the peer // Something went very wrong, drop the peer
log.Debug("Propagated block verification failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) 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 return
} }
} }
// If import succeeded, broadcast the block // If import succeeded, broadcast the block
propAnnounceOutTimer.UpdateSince(block.ReceivedAt) propAnnounceOutTimer.UpdateSince(block.ReceivedAt)
go f.broadcastBlock(block, true)
go f.broadcastBlock(block, false) go f.broadcastBlock(block, false)
}() }()
} }