Skip to content

Commit

Permalink
put difflayer into verifyManage cache when node restart
Browse files Browse the repository at this point in the history
  • Loading branch information
j75689 committed Apr 13, 2022
1 parent 1aaab76 commit b978ed3
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 37 deletions.
10 changes: 7 additions & 3 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
49 changes: 27 additions & 22 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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{})
Expand Down Expand Up @@ -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
}
}

Expand Down Expand Up @@ -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)
}

Expand Down
9 changes: 5 additions & 4 deletions core/blockchain_diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
3 changes: 3 additions & 0 deletions core/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
)
Expand Down
34 changes: 27 additions & 7 deletions core/remote_state_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package core

import (
"fmt"
"math/big"
"math/rand"
"time"

Expand Down Expand Up @@ -45,16 +46,35 @@ type remoteVerifyManager struct {
allowInsecure bool

// Subscription
chainBlockCh chan ChainHeadEvent
chainBlockCh chan ChainHeadEvent
chainHeadSub event.Subscription

// Channels
verifyCh chan common.Hash
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),
Expand All @@ -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() {
Expand Down Expand Up @@ -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{}
Expand Down Expand Up @@ -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
}

Expand Down

0 comments on commit b978ed3

Please sign in to comment.