From b978ed3d0351c962fd2696824eca39f46729f103 Mon Sep 17 00:00:00 2001 From: j75689 Date: Wed, 13 Apr 2022 18:40:49 +0800 Subject: [PATCH] put difflayer into verifyManage cache when node restart --- core/block_validator.go | 10 ++++--- core/blockchain.go | 49 +++++++++++++++++++---------------- core/blockchain_diff_test.go | 9 ++++--- core/blockchain_test.go | 2 +- core/error.go | 3 +++ core/remote_state_verifier.go | 34 +++++++++++++++++++----- 6 files changed, 70 insertions(+), 37 deletions(-) diff --git a/core/block_validator.go b/core/block_validator.go index 29ee2ec348..56f609f41a 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -41,17 +41,21 @@ type BlockValidator struct { } // NewBlockValidator returns a new block validator which is safe for re-use -func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine, mode VerifyMode, peers verifyPeers) *BlockValidator { +func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine, mode VerifyMode, peers verifyPeers) (*BlockValidator, error) { validator := &BlockValidator{ config: config, engine: engine, bc: blockchain, } if mode.NeedRemoteVerify() { - validator.remoteValidator = NewVerifyManager(blockchain, peers, mode == InsecureVerify) + remoteValidator, err := NewVerifyManager(blockchain, peers, mode == InsecureVerify) + if err != nil { + return nil, err + } + validator.remoteValidator = remoteValidator go validator.remoteValidator.mainLoop() } - return validator + return validator, nil } // ValidateBody validates the given block's uncles and verifies the block diff --git a/core/blockchain.go b/core/blockchain.go index 0776a2d637..3097d9d537 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -164,7 +164,7 @@ var defaultCacheConfig = &CacheConfig{ SnapshotWait: true, } -type BlockChainOption func(*BlockChain) *BlockChain +type BlockChainOption func(*BlockChain) (*BlockChain, error) // BlockChain represents the canonical chain given a database with a genesis // block. The Blockchain manages chain imports, reverts, chain reorganisations. @@ -198,16 +198,16 @@ type BlockChain struct { txLookupLimit uint64 triesInMemory uint64 - hc *HeaderChain - rmLogsFeed event.Feed - chainFeed event.Feed - chainSideFeed event.Feed - chainHeadFeed event.Feed + hc *HeaderChain + rmLogsFeed event.Feed + chainFeed event.Feed + chainSideFeed event.Feed + chainHeadFeed event.Feed chainBlockFeed event.Feed - logsFeed event.Feed - blockProcFeed event.Feed - scope event.SubscriptionScope - genesisBlock *types.Block + logsFeed event.Feed + blockProcFeed event.Feed + scope event.SubscriptionScope + genesisBlock *types.Block chainmu sync.RWMutex // blockchain insertion lock @@ -451,7 +451,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par } // do options before start any routine for _, option := range options { - bc = option(bc) + bc, err = option(bc) + if err != nil { + return nil, err + } } // Take ownership of this particular state go bc.update() @@ -525,7 +528,6 @@ func (bc *BlockChain) cacheDiffLayer(diffLayer *types.DiffLayer, sorted bool) { bc.diffLayerCache.RemoveOldest() } - //json.MarshalIndent() bc.diffLayerCache.Add(diffLayer.BlockHash, diffLayer) if cached, ok := bc.diffLayerChanCache.Get(diffLayer.BlockHash); ok { diffLayerCh := cached.(chan struct{}) @@ -3145,27 +3147,31 @@ func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscr } // Options -func EnableLightProcessor(bc *BlockChain) *BlockChain { +func EnableLightProcessor(bc *BlockChain) (*BlockChain, error) { bc.processor = NewLightStateProcessor(bc.Config(), bc, bc.engine) - return bc + return bc, nil } -func EnablePipelineCommit(bc *BlockChain) *BlockChain { +func EnablePipelineCommit(bc *BlockChain) (*BlockChain, error) { bc.pipeCommit = true - return bc + return bc, nil } func EnablePersistDiff(limit uint64) BlockChainOption { - return func(chain *BlockChain) *BlockChain { + return func(chain *BlockChain) (*BlockChain, error) { chain.diffLayerFreezerBlockLimit = limit - return chain + return chain, nil } } func EnableBlockValidator(chainConfig *params.ChainConfig, engine consensus.Engine, mode VerifyMode, peers verifyPeers) BlockChainOption { - return func(bc *BlockChain) *BlockChain { - bc.validator = NewBlockValidator(chainConfig, bc, engine, mode, peers) - return bc + return func(bc *BlockChain) (*BlockChain, error) { + validator, err := NewBlockValidator(chainConfig, bc, engine, mode, peers) + if err != nil { + return bc, err + } + bc.validator = validator + return bc, nil } } @@ -3289,7 +3295,6 @@ func (bc *BlockChain) GenerateDiffLayer(blockHash common.Hash) (*types.DiffLayer if diffLayer != nil { diffLayer.BlockHash = blockHash diffLayer.Number = block.NumberU64() - bc.cacheDiffLayer(diffLayer, true) } diff --git a/core/blockchain_diff_test.go b/core/blockchain_diff_test.go index c4eeccda45..c245d71883 100644 --- a/core/blockchain_diff_test.go +++ b/core/blockchain_diff_test.go @@ -499,8 +499,8 @@ func newTwoForkedBlockchains(len1, len2 int) (chain1 *BlockChain, chain2 *BlockC Config: params.TestChainConfig, Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}}, }).MustCommit(db1) - - chain1, _ = NewBlockChain(db1, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, EnablePersistDiff(860000)) + engine1 := ethash.NewFaker() + chain1, _ = NewBlockChain(db1, nil, params.TestChainConfig, engine1, vm.Config{}, nil, nil, EnablePersistDiff(860000), EnableBlockValidator(params.TestChainConfig, engine1, 0, nil)) generator1 := func(i int, block *BlockGen) { // The chain maker doesn't have access to a chain, so the difficulty will be // lets unset (nil). Set it here to the correct value. @@ -555,7 +555,8 @@ func newTwoForkedBlockchains(len1, len2 int) (chain1 *BlockChain, chain2 *BlockC Config: params.TestChainConfig, Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}}, }).MustCommit(db2) - chain2, _ = NewBlockChain(db2, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, EnablePersistDiff(860000)) + engine2 := ethash.NewFaker() + chain2, _ = NewBlockChain(db2, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, EnablePersistDiff(860000), EnableBlockValidator(params.TestChainConfig, engine2, 0, nil)) generator2 := func(i int, block *BlockGen) { // The chain maker doesn't have access to a chain, so the difficulty will be // lets unset (nil). Set it here to the correct value. @@ -659,7 +660,7 @@ func newBlockChainWithCliqueEngine(blocks int) *BlockChain { copy(genspec.ExtraData[32:], testAddr[:]) genesis := genspec.MustCommit(db) - chain, _ := NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil) + chain, _ := NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil, EnableBlockValidator(params.AllCliqueProtocolChanges, engine, 0 /*LocalVerify*/, nil)) generator := func(i int, block *BlockGen) { // The chain maker doesn't have access to a chain, so the difficulty will be // lets unset (nil). Set it here to the correct value. diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 50d02e0acc..8a7581016a 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -252,7 +252,7 @@ func TestBlockImportVerification(t *testing.T) { } defer processor.Stop() // Start fork from current height - processor = EnablePipelineCommit(processor) + processor, _ = EnablePipelineCommit(processor) testInvalidStateRootBlockImport(t, processor, length, 10, true) } diff --git a/core/error.go b/core/error.go index 0830a699fe..75fa6a205e 100644 --- a/core/error.go +++ b/core/error.go @@ -35,6 +35,9 @@ var ( // ErrDiffLayerNotFound is returned when diff layer not found. ErrDiffLayerNotFound = errors.New("diff layer not found") + // ErrCurrentBlockNotFound is returned when current block not found. + ErrCurrentBlockNotFound = errors.New("current block not found") + // ErrKnownBadBlock is return when the block is a known bad block ErrKnownBadBlock = errors.New("already known bad block") ) diff --git a/core/remote_state_verifier.go b/core/remote_state_verifier.go index 3481113112..bd85b46eff 100644 --- a/core/remote_state_verifier.go +++ b/core/remote_state_verifier.go @@ -2,6 +2,7 @@ package core import ( "fmt" + "math/big" "math/rand" "time" @@ -45,7 +46,7 @@ type remoteVerifyManager struct { allowInsecure bool // Subscription - chainBlockCh chan ChainHeadEvent + chainBlockCh chan ChainHeadEvent chainHeadSub event.Subscription // Channels @@ -53,8 +54,27 @@ type remoteVerifyManager struct { messageCh chan verifyMessage } -func NewVerifyManager(blockchain *BlockChain, peers verifyPeers, allowInsecure bool) *remoteVerifyManager { +func NewVerifyManager(blockchain *BlockChain, peers verifyPeers, allowInsecure bool) (*remoteVerifyManager, error) { verifiedCache, _ := lru.New(verifiedCacheSize) + block := blockchain.CurrentBlock() + if block == nil { + return nil, ErrCurrentBlockNotFound + } + number := block.Number() + for i := maxForkHeight; i >= 0; i-- { + if new(big.Int).Sub(number, big.NewInt(int64(i))).Cmp(common.Big0) <= 0 { + continue + } + oldBlock := blockchain.GetBlockByNumber(number.Uint64() - uint64(i)) + if oldBlock == nil { + return nil, fmt.Errorf("block is nil, number: %d", number) + } + _, err := blockchain.GenerateDiffLayer(oldBlock.Hash()) + if err != nil { + return nil, err + } + } + vm := &remoteVerifyManager{ bc: blockchain, tasks: make(map[common.Hash]*verifyTask), @@ -63,11 +83,11 @@ func NewVerifyManager(blockchain *BlockChain, peers verifyPeers, allowInsecure b allowInsecure: allowInsecure, chainBlockCh: make(chan ChainHeadEvent, chainHeadChanSize), - verifyCh: make(chan common.Hash, maxForkHeight), - messageCh: make(chan verifyMessage), + verifyCh: make(chan common.Hash, maxForkHeight), + messageCh: make(chan verifyMessage), } vm.chainHeadSub = blockchain.SubscribeChainBlockEvent(vm.chainBlockCh) - return vm + return vm, nil } func (vm *remoteVerifyManager) mainLoop() { @@ -219,7 +239,7 @@ type verifyTask struct { candidatePeers verifyPeers badPeers map[string]struct{} startAt time.Time - allowInsecure bool + allowInsecure bool messageCh chan verifyMessage terminalCh chan struct{} @@ -288,7 +308,7 @@ func (vt *verifyTask) sendVerifyRequest(n int) { } // if has not valid peer, log warning. if len(validPeers) == 0 { - log.Warn("there is no valid peer for block", vt.blockHeader.Number) + log.Warn("there is no valid peer for block", "number", vt.blockHeader.Number) return }