diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index 82d6c4f164..43c9cf893a 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -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()) diff --git a/eth/backend.go b/eth/backend.go index 174f7a5b90..6e6c127cc4 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -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 } diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go index 7fcae57006..01f8748c5f 100644 --- a/eth/fetcher/fetcher.go +++ b/eth/fetcher/fetcher.go @@ -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) - }() }