From 2e0530d1e0a901524944d0505fdb81eb529a31fa Mon Sep 17 00:00:00 2001 From: kyrie-yl Date: Fri, 14 Jan 2022 11:32:19 +0800 Subject: [PATCH] fast node verification Signed-off-by: kyrie-yl --- cmd/geth/main.go | 4 +- cmd/geth/usage.go | 3 + cmd/utils/flags.go | 32 ++++++-- core/blockchain.go | 24 ++++++ core/rawdb/accessors_chain.go | 20 +++++ core/rawdb/schema.go | 7 ++ core/verify_manager.go | 133 ++++++++++++++++++++++++++++++++++ core/verify_modes.go | 69 ++++++++++++++++++ core/verify_peers.go | 12 +++ core/verify_task.go | 119 ++++++++++++++++++++++++++++++ eth/backend.go | 25 +++++-- eth/ethconfig/config.go | 6 +- eth/ethconfig/gen_config.go | 22 ++++-- eth/peerset.go | 12 +-- 14 files changed, 463 insertions(+), 25 deletions(-) create mode 100644 core/verify_manager.go create mode 100644 core/verify_modes.go create mode 100644 core/verify_peers.go create mode 100644 core/verify_task.go diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 1ab5e134ac..a2b1ca01df 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -71,6 +71,8 @@ var ( utils.NoUSBFlag, utils.DirectBroadcastFlag, utils.DisableSnapProtocolFlag, + utils.DisableDiffProtocolFlag, + utils.EnableTrustProtocolFlag, utils.DiffSyncFlag, utils.RangeLimitFlag, utils.USBFlag, @@ -97,6 +99,7 @@ var ( utils.TxPoolLifetimeFlag, utils.TxPoolReannounceTimeFlag, utils.SyncModeFlag, + utils.TriesVerifyModeFlag, utils.ExitWhenSyncedFlag, utils.GCModeFlag, utils.SnapshotFlag, @@ -114,7 +117,6 @@ var ( utils.WhitelistFlag, utils.BloomFilterSizeFlag, utils.TriesInMemoryFlag, - utils.AllowInsecureNoTriesFlag, utils.CacheFlag, utils.CacheDatabaseFlag, utils.CacheTrieFlag, diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go index fba14530b5..8cc4b5bd31 100644 --- a/cmd/geth/usage.go +++ b/cmd/geth/usage.go @@ -41,6 +41,8 @@ var AppHelpFlagGroups = []flags.FlagGroup{ utils.NoUSBFlag, utils.DirectBroadcastFlag, utils.DisableSnapProtocolFlag, + utils.DisableDiffProtocolFlag, + utils.EnableTrustProtocolFlag, utils.RangeLimitFlag, utils.SmartCardDaemonPathFlag, utils.NetworkIdFlag, @@ -50,6 +52,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{ utils.YoloV3Flag, utils.RopstenFlag, utils.SyncModeFlag, + utils.TriesVerifyModeFlag, utils.ExitWhenSyncedFlag, utils.GCModeFlag, utils.TxLookupLimitFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index e7336d73a9..463d56e93f 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -121,6 +121,14 @@ var ( Name: "disablesnapprotocol", Usage: "Disable snap protocol", } + DisableDiffProtocolFlag = cli.BoolFlag{ + Name: "disablediffprotocol", + Usage: "Disable diff protocol", + } + EnableTrustProtocolFlag = cli.BoolFlag{ + Name: "enabletrustprotocol", + Usage: "Enable trust protocol", + } DiffSyncFlag = cli.BoolFlag{ Name: "diffsync", Usage: "Enable diffy sync, Please note that enable diffsync will improve the syncing speed, " + @@ -259,9 +267,11 @@ var ( Usage: "The layer of tries trees that keep in memory", Value: 128, } - AllowInsecureNoTriesFlag = cli.BoolTFlag{ - Name: "allow-insecure-no-tries", - Usage: `Disable the tries state root verification, the state consistency is no longer 100% guaranteed, diffsync is not allowed if enabled. Do not enable it unless you know exactly what the consequence it will cause.`, + defaultVerifyMode = ethconfig.Defaults.TriesVerifyMode + TriesVerifyModeFlag = TextMarshalerFlag{ + Name: "tries-verify-mode", + Usage: `tries verify mode: "local", "full", "light", "insecure"`, + Value: &defaultVerifyMode, } OverrideBerlinFlag = cli.Uint64Flag{ Name: "override.berlin", @@ -1622,6 +1632,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if ctx.GlobalIsSet(DisableSnapProtocolFlag.Name) { cfg.DisableSnapProtocol = ctx.GlobalBool(DisableSnapProtocolFlag.Name) } + if ctx.GlobalIsSet(DisableDiffProtocolFlag.Name) { + cfg.DisableDiffProtocol = ctx.GlobalIsSet(DisableDiffProtocolFlag.Name) + } + if ctx.GlobalIsSet(EnableTrustProtocolFlag.Name) { + cfg.EnableTrustProtocol = ctx.GlobalIsSet(EnableTrustProtocolFlag.Name) + } if ctx.GlobalIsSet(DiffSyncFlag.Name) { cfg.DiffSync = ctx.GlobalBool(DiffSyncFlag.Name) } @@ -1652,8 +1668,14 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if ctx.GlobalIsSet(TriesInMemoryFlag.Name) { cfg.TriesInMemory = ctx.GlobalUint64(TriesInMemoryFlag.Name) } - if ctx.GlobalIsSet(AllowInsecureNoTriesFlag.Name) { - cfg.NoTries = ctx.GlobalBool(AllowInsecureNoTriesFlag.Name) + if ctx.GlobalIsSet(TriesVerifyModeFlag.Name) { + cfg.TriesVerifyMode = *GlobalTextMarshaler(ctx, TriesVerifyModeFlag.Name).(*core.VerifyMode) + if cfg.TriesVerifyMode == core.FullVerify || cfg.TriesVerifyMode == core.LightVerify { + cfg.EnableTrustProtocol = true + } + if cfg.TriesVerifyMode != core.LocalVerify { + cfg.DisableDiffProtocol = true + } } if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheSnapshotFlag.Name) { cfg.SnapshotCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheSnapshotFlag.Name) / 100 diff --git a/core/blockchain.go b/core/blockchain.go index dcac331149..6a56dd2ab4 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -239,6 +239,7 @@ type BlockChain struct { engine consensus.Engine validator Validator // Block and state validator interface processor Processor // Block transaction processor interface + verifyManager *VerifyManager vmConfig vm.Config shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block. @@ -462,6 +463,12 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par return bc, nil } +func (bc *BlockChain) StartVerify(peers VerifyPeers, allowUntrustedVerify bool) { + bc.verifyManager.peers = peers + bc.verifyManager.allowUntrustedVerify = allowUntrustedVerify + bc.verifyManager.Start() +} + // GetVMConfig returns the block chain VM config. func (bc *BlockChain) GetVMConfig() *vm.Config { return &bc.vmConfig @@ -1191,6 +1198,7 @@ func (bc *BlockChain) Stop() { close(bc.quit) bc.StopInsert() bc.wg.Wait() + bc.verifyManager.Stop() // Ensure that the entirety of the state snapshot is journalled to disk. var snapBase common.Hash @@ -2009,6 +2017,11 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er log.Debug("Abort during block processing") break } + if bc.verifyManager != nil { + for ; !bc.verifyManager.CheckAncestorVerified(block.Header()); { + log.Debug("Block ancestor has not been verified", "hash", block.Hash(), "number", block.Number()) + } + } // If the header is a banned one, straight out abort if BadHashes[block.Hash()] { bc.reportBlock(block, nil, ErrBlacklistedHash) @@ -2052,6 +2065,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er lastCanon = block continue } + + if bc.verifyManager != nil { + bc.verifyManager.NewBlockVerifyTask(block.Header()) + } // Retrieve the parent block and it's state to execute on top start := time.Now() @@ -3020,6 +3037,13 @@ func EnablePersistDiff(limit uint64) BlockChainOption { } } +func EnableVerifyManager() BlockChainOption { + return func(chain *BlockChain) *BlockChain { + chain.verifyManager = NewVerifyManager(chain) + return chain + } +} + func (bc *BlockChain) GetRootByDiffHash(blockNumber uint64, blockHash common.Hash, diffHash common.Hash) (*types.VerifyResult, error) { var res types.VerifyResult res.BlockNumber = blockNumber diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 6489a600fb..912a19f6ff 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -64,6 +64,26 @@ func DeleteCanonicalHash(db ethdb.KeyValueWriter, number uint64) { } } +func ReadTrustBlockHash(db ethdb.Reader, hash common.Hash) bool { + data, _ := db.Get(trustBlockHashKey(hash)) + if len(data) == 0 { + return false + } + return bytes.Equal(data,[]byte{0x01}) +} + +func WriteTrustBlockHash(db ethdb.KeyValueWriter, hashkey common.Hash) { + if err := db.Put(trustBlockHashKey(hashkey),[]byte{0x01}); err != nil { + log.Crit("Failed to store trust block hash") + } +} + +func DeleteTrustBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { + if err := db.Delete(trustBlockHashKey(hash)); err != nil { + log.Crit("Failed to delete trust block hash") + } +} + // ReadAllHashes retrieves all the hashes assigned to blocks at a certain heights, // both canonical and reorged forks included. func ReadAllHashes(db ethdb.Iteratee, number uint64) []common.Hash { diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index b4fb99e451..525614173c 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -93,6 +93,9 @@ var ( // difflayer database diffLayerPrefix = []byte("d") // diffLayerPrefix + hash -> diffLayer + // trust block database + trustBlockPrefix = []byte("tb") // trustBlockPrefix + hash -> verify result + preimagePrefix = []byte("secure-key-") // preimagePrefix + hash -> preimage configPrefix = []byte("ethereum-config-") // config prefix for the db @@ -164,6 +167,10 @@ func headerTDKey(number uint64, hash common.Hash) []byte { func headerHashKey(number uint64) []byte { return append(append(headerPrefix, encodeBlockNumber(number)...), headerHashSuffix...) } +// trustBlockHashKey = trustBlockPrefix + hash +func trustBlockHashKey(hash common.Hash) []byte { + return append(append(trustBlockPrefix, hash.Bytes()...)) +} // headerNumberKey = headerNumberPrefix + hash func headerNumberKey(hash common.Hash) []byte { diff --git a/core/verify_manager.go b/core/verify_manager.go new file mode 100644 index 0000000000..55d4646125 --- /dev/null +++ b/core/verify_manager.go @@ -0,0 +1,133 @@ +package core + +import ( + "fmt" + "time" + + lru "github.com/hashicorp/golang-lru" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" +) + +const verifiedCacheSize = 256 + +type VerifyManager struct { + bc *BlockChain + tasks map[common.Hash]*VerifyTask + peers VerifyPeers + verifiedCache *lru.Cache + allowUntrustedVerify bool + verifyCh chan common.Hash + exitCh chan struct{} +} + +func NewVerifyManager(blockchain *BlockChain) *VerifyManager { + verifiedCache, _ := lru.New(verifiedCacheSize) + vm := &VerifyManager{ + bc: blockchain, + tasks: make(map[common.Hash]*VerifyTask), + verifiedCache: verifiedCache, + verifyCh: make(chan common.Hash), + exitCh: make(chan struct{}), + } + return vm +} + +func (vm *VerifyManager) Start() { + //read disk store to initial verified cache + //load unverified blocks in a normalized chain and start a batch of verify task + header := vm.bc.CurrentHeader() + vm.NewBlockVerifyTask(header) + go vm.mainLoop() +} + +func (vm *VerifyManager) Stop() { + defer close(vm.exitCh) + vm.exitCh <- struct{}{} +} + +func (vm *VerifyManager) mainLoop() { + pruneTicker := time.NewTicker(time.Second) + for { + select { + case hash := <-vm.verifyCh: + vm.cacheBlockVerified(hash) + rawdb.WriteTrustBlockHash(vm.bc.db, hash) + delete(vm.tasks, hash) + case <-pruneTicker.C: + for hash, task := range vm.tasks { + if vm.bc.CurrentHeader().Number.Uint64()-task.blockHeader.Number.Uint64() > 15 { + task.terminalCh <- struct{}{} + delete(vm.tasks, hash) + } + } + case <-vm.exitCh: + return + } + } +} + +func (vm *VerifyManager) NewBlockVerifyTask(header *types.Header) { + for i := 0; i < 11; i++ { + hash := header.Hash() + diffLayer := vm.bc.GetTrustedDiffLayer(hash) + //if this block has no diff, there is no need to verify it. + if diffLayer == nil { + continue + } + //if verified cache record that this block has been verified, skip. + if _, ok := vm.verifiedCache.Get(hash); ok { + continue + } + //if verified storage record that this block has been verified, skip. + if rawdb.ReadTrustBlockHash(vm.bc.db, hash) { + vm.cacheBlockVerified(hash) + continue + } + //if there already has a verify task for this block, skip. + if _, ok := vm.tasks[hash]; ok { + continue + } + diffHash, err := GetTrustedDiffHash(diffLayer) + if err != nil { + log.Error("failed to get diff hash", "block", hash, "number", header.Number, "error:", err) + } + verifyTask := NewVerifyTask(diffHash, header, vm.peers, vm.bc.db, vm.verifyCh, vm.allowUntrustedVerify) + vm.tasks[hash] = verifyTask + header = vm.bc.GetHeaderByHash(header.ParentHash) + } +} + +func (vm *VerifyManager) cacheBlockVerified(hash common.Hash) { + if vm.verifiedCache.Len() >= verifiedCacheSize { + vm.verifiedCache.RemoveOldest() + } + vm.verifiedCache.Add(hash, true) +} + +//CheckAncestorVerified function check whether head 11 of this block has been verified. +//If not, the blockchain should stop to insert new block. +func (vm *VerifyManager) CheckAncestorVerified(header *types.Header) bool { + pHeader := header + for i := 0; i < 11; i++ { + pHeader = vm.bc.GetHeaderByHash(pHeader.ParentHash) + } + hash := pHeader.Hash() + if _, ok := vm.verifiedCache.Get(hash); ok { + return true + } else { + return rawdb.ReadTrustBlockHash(vm.bc.db, hash) + } + return false +} + +func (vm *VerifyManager) HandleRootResponse(vr *types.VerifyResult, pid string) error { + if vt, ok := vm.tasks[vr.BlockHash]; ok { + vt.messageCh <- VerifyMessage{verifyResult: vr, peerId: pid} + return nil + } + return fmt.Errorf("") +} diff --git a/core/verify_modes.go b/core/verify_modes.go new file mode 100644 index 0000000000..e736330866 --- /dev/null +++ b/core/verify_modes.go @@ -0,0 +1,69 @@ +package core + +import "fmt" + +type VerifyMode uint32 + +const ( + LocalVerify VerifyMode = iota // + FullVerify + LightVerify + InsecureVerify +) + +func (mode VerifyMode) IsValid() bool { + return mode >= LocalVerify && mode <= InsecureVerify +} + +func (mode VerifyMode) String() string { + switch mode { + case LocalVerify: + return "local" + case FullVerify: + return "full" + case LightVerify: + return "light" + case InsecureVerify: + return "insecure" + default: + return "unknown" + } +} + +func (mode VerifyMode) MarshalText() ([]byte, error) { + switch mode { + case LocalVerify: + return []byte("local"), nil + case FullVerify: + return []byte("full"), nil + case LightVerify: + return []byte("light"), nil + case InsecureVerify: + return []byte("insecure"), nil + default: + return nil, fmt.Errorf("unknown verify mode %d", mode) + } +} + +func (mode *VerifyMode) UnmarshalText(text []byte) error { + switch string(text) { + case "local": + *mode = LocalVerify + case "full": + *mode = FullVerify + case "light": + *mode = LightVerify + case "insecure": + *mode = InsecureVerify + default: + return fmt.Errorf(`unknown sync mode %q, want "full", "light" or "insecure"`, text) + } + return nil +} + +func (mode *VerifyMode) NeedRemoteVerify() bool { + if *mode == FullVerify || * mode == LightVerify { + return true + } + return false +} \ No newline at end of file diff --git a/core/verify_peers.go b/core/verify_peers.go new file mode 100644 index 0000000000..a1ea2eaa9c --- /dev/null +++ b/core/verify_peers.go @@ -0,0 +1,12 @@ +package core + +import "github.com/ethereum/go-ethereum/common" + +type VerifyPeer interface { + RequestRoot(blockNumber uint64, blockHash common.Hash, diffHash common.Hash) error + ID() string +} + +type VerifyPeers interface { + GetVerifyPeers() []VerifyPeer +} diff --git a/core/verify_task.go b/core/verify_task.go new file mode 100644 index 0000000000..4e07486da4 --- /dev/null +++ b/core/verify_task.go @@ -0,0 +1,119 @@ +package core + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" + + "math/rand" + "time" +) + +type VerifyMessage struct { + verifyResult *types.VerifyResult + peerId string +} + +type VerifyTask struct { + diffhash common.Hash + blockHeader *types.Header + candidatePeers VerifyPeers + BadPeers map[string]struct{} + startAt time.Time + db ethdb.Database + allowUntrustedVerify bool + + messageCh chan VerifyMessage + terminalCh chan struct{} +} + +func NewVerifyTask(diffhash common.Hash, header *types.Header, peers VerifyPeers, db ethdb.Database, verifyCh chan common.Hash, allowUntrustedVerify bool) *VerifyTask { + vt := &VerifyTask{ + diffhash: diffhash, + blockHeader: header, + candidatePeers: peers, + BadPeers: make(map[string]struct{}), + db: db, + allowUntrustedVerify: allowUntrustedVerify, + messageCh: make(chan VerifyMessage), + terminalCh: make(chan struct{}), + } + go vt.Start(verifyCh) + return vt +} + +func (vt *VerifyTask) Start(verifyCh chan common.Hash) { + vt.startAt = time.Now() + + vt.selectPeersToVerify(vt.candidatePeers.GetVerifyPeers(), 3) + resend := time.NewTicker(2 * time.Second) + defer resend.Stop() + for { + select { + case msg := <-vt.messageCh: + switch msg.verifyResult.Status { + case types.StatusFullVerified: + vt.compareRootHashAndWrite(msg, verifyCh) + case types.StatusUntrustedVerified: + log.Warn("block %s , num= %s is untrusted verified", msg.verifyResult.BlockHash, msg.verifyResult.BlockNumber) + if vt.allowUntrustedVerify { + vt.compareRootHashAndWrite(msg, verifyCh) + } + case types.StatusDiffHashMismatch, types.StatusImpossibleFork, types.StatusUnexpectedError: + vt.BadPeers[msg.peerId] = struct{}{} + case types.StatusBlockTooNew, types.StatusBlockNewer, types.StatusPossibleFork: + log.Info("return msg from peer %s for block %s is %s", msg.peerId, msg.verifyResult.BlockHash, msg.verifyResult.Status.Msg) + } + case <-resend.C: + //if a task has run over 300s, try all the vaild peers to verify. + if time.Now().Second()-vt.startAt.Second() < 300 { + vt.selectPeersToVerify(vt.candidatePeers.GetVerifyPeers(), 1) + } else { + vt.selectPeersToVerify(vt.candidatePeers.GetVerifyPeers(), -1) + } + case <-vt.terminalCh: + return + } + } +} + +//selectPeersAndVerify func select at most n peers from (candidatePeers-badPeers) randomly and send verify request. +//when n is -1, send to all the peers exclude badPeers. +func (vt *VerifyTask) selectPeersToVerify(candidatePeers []VerifyPeer, n int) { + var validPeers []VerifyPeer + for _, p := range candidatePeers { + if _, ok := vt.BadPeers[p.ID()]; !ok { + validPeers = append(validPeers, p) + } + } + if n < 0 || n >= len(validPeers) { + for _, p := range validPeers { + if _, ok := vt.BadPeers[p.ID()]; !ok { + p.RequestRoot(vt.blockHeader.Number.Uint64(), vt.blockHeader.Hash(), vt.diffhash) + } + } + } + + //if n < len(validPeers), select n peers from validPeers randomly. + for i := 0; i < n; i++ { + s := rand.NewSource(time.Now().Unix()) + r := rand.New(s) + p := validPeers[r.Intn(len(validPeers))] + p.RequestRoot(vt.blockHeader.Number.Uint64(), vt.blockHeader.Hash(), vt.diffhash) + } + +} + +func (vt *VerifyTask) compareRootHashAndWrite(msg VerifyMessage, verifyCh chan common.Hash) { + if msg.verifyResult.Root == vt.blockHeader.Root { + blockhash := msg.verifyResult.BlockHash + rawdb.WriteTrustBlockHash(vt.db, blockhash) + //write back to manager so that manager can cache the result and delete this task. + verifyCh <- blockhash + vt.terminalCh <- struct{}{} + } else { + vt.BadPeers[msg.peerId] = struct{}{} + } +} diff --git a/eth/backend.go b/eth/backend.go index 873980fc14..197eab608b 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -26,8 +26,6 @@ import ( "sync/atomic" "time" - "github.com/ethereum/go-ethereum/eth/protocols/trust" - "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -47,6 +45,7 @@ import ( "github.com/ethereum/go-ethereum/eth/protocols/diff" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" + "github.com/ethereum/go-ethereum/eth/protocols/trust" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/internal/ethapi" @@ -111,6 +110,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if !config.SyncMode.IsValid() { return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) } + if !config.TriesVerifyMode.IsValid() { + return nil, fmt.Errorf("invalid tries verify mode %d", config.TriesVerifyMode) + } if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 { log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice) config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice) @@ -196,19 +198,22 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { TrieDirtyLimit: config.TrieDirtyCache, TrieDirtyDisabled: config.NoPruning, TrieTimeLimit: config.TrieTimeout, - NoTries: config.NoTries, + NoTries: config.TriesVerifyMode != core.LocalVerify, SnapshotLimit: config.SnapshotCache, TriesInMemory: config.TriesInMemory, Preimages: config.Preimages, } ) bcOps := make([]core.BlockChainOption, 0) - if config.DiffSync && !config.NoTries { + if config.DiffSync && config.TriesVerifyMode == core.LocalVerify { bcOps = append(bcOps, core.EnableLightProcessor) } if config.PersistDiff { bcOps = append(bcOps, core.EnablePersistDiff(config.DiffBlock)) } + if config.TriesVerifyMode.NeedRemoteVerify() { + bcOps = append(bcOps, core.EnableVerifyManager()) + } eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit, bcOps...) if err != nil { return nil, err @@ -250,6 +255,10 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return nil, err } + if config.TriesVerifyMode.NeedRemoteVerify() { + eth.blockchain.StartVerify(eth.handler.peers, config.TriesVerifyMode == core.LightVerify) + } + eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock) eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) @@ -552,8 +561,12 @@ func (s *Ethereum) Protocols() []p2p.Protocol { protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler), s.snapDialCandidates)...) } // diff protocol can still open without snap protocol - protos = append(protos, diff.MakeProtocols((*diffHandler)(s.handler), s.snapDialCandidates)...) - protos = append(protos, trust.MakeProtocols((*trustHandler)(s.handler), s.snapDialCandidates)...) + if !s.config.DisableDiffProtocol { + protos = append(protos, diff.MakeProtocols((*diffHandler)(s.handler), s.snapDialCandidates)...) + } + if s.config.EnableTrustProtocol { + protos = append(protos, trust.MakeProtocols((*trustHandler)(s.handler), s.snapDialCandidates)...) + } return protos } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index d3e146aaaf..1ae713cfd1 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -79,7 +79,7 @@ var Defaults = Config{ TrieDirtyCache: 256, TrieTimeout: 60 * time.Minute, TriesInMemory: 128, - NoTries: false, + TriesVerifyMode: core.LocalVerify, SnapshotCache: 102, DiffBlock: uint64(86400), Miner: miner.Config{ @@ -137,6 +137,8 @@ type Config struct { NoPruning bool // Whether to disable pruning and flush everything to disk DirectBroadcast bool DisableSnapProtocol bool //Whether disable snap protocol + DisableDiffProtocol bool //Whether disable diff protocol + EnableTrustProtocol bool //Whether enable trust protocol DiffSync bool // Whether support diff sync RangeLimit bool @@ -175,7 +177,7 @@ type Config struct { TrieTimeout time.Duration SnapshotCache int TriesInMemory uint64 - NoTries bool + TriesVerifyMode core.VerifyMode Preimages bool // Mining options diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index ba2996279d..d26f206d83 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -28,6 +28,8 @@ func (c Config) MarshalTOML() (interface{}, error) { NoPrefetch bool DirectBroadcast bool DisableSnapProtocol bool + DisableDiffProtocol bool + EnableTrustProtocol bool DiffSync bool RangeLimit bool TxLookupLimit uint64 `toml:",omitempty"` @@ -56,7 +58,7 @@ func (c Config) MarshalTOML() (interface{}, error) { TrieTimeout time.Duration SnapshotCache int TriesInMemory uint64 - NoTries bool + TriesVerifyMode core.VerifyMode Preimages bool Miner miner.Config Ethash ethash.Config `toml:",omitempty"` @@ -82,6 +84,8 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.NoPruning = c.NoPruning enc.DirectBroadcast = c.DirectBroadcast enc.DisableSnapProtocol = c.DisableSnapProtocol + enc.DisableDiffProtocol = c.DisableDiffProtocol + enc.EnableTrustProtocol = c.EnableTrustProtocol enc.DiffSync = c.DiffSync enc.RangeLimit = c.RangeLimit enc.TxLookupLimit = c.TxLookupLimit @@ -110,7 +114,7 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.TrieTimeout = c.TrieTimeout enc.SnapshotCache = c.SnapshotCache enc.TriesInMemory = c.TriesInMemory - enc.NoTries = c.NoTries + enc.TriesVerifyMode = c.TriesVerifyMode enc.Preimages = c.Preimages enc.Miner = c.Miner enc.Ethash = c.Ethash @@ -141,6 +145,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { NoPrefetch *bool DirectBroadcast *bool DisableSnapProtocol *bool + DisableDiffProtocol *bool + EnableTrustProtocol *bool DiffSync *bool RangeLimit *bool TxLookupLimit *uint64 `toml:",omitempty"` @@ -169,7 +175,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { TrieTimeout *time.Duration SnapshotCache *int TriesInMemory *uint64 - NoTries *bool + TriesVerifyMode *core.VerifyMode Preimages *bool Miner *miner.Config Ethash *ethash.Config `toml:",omitempty"` @@ -216,6 +222,12 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.DisableSnapProtocol != nil { c.DisableSnapProtocol = *dec.DisableSnapProtocol } + if dec.DisableDiffProtocol != nil { + c.DisableDiffProtocol = *dec.DisableDiffProtocol + } + if dec.EnableTrustProtocol != nil { + c.EnableTrustProtocol = *dec.EnableTrustProtocol + } if dec.DiffSync != nil { c.DiffSync = *dec.DiffSync } @@ -300,8 +312,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.TriesInMemory != nil { c.TriesInMemory = *dec.TriesInMemory } - if dec.NoTries != nil { - c.NoTries = *dec.NoTries + if dec.TriesVerifyMode != nil { + c.TriesVerifyMode = *dec.TriesVerifyMode } if dec.Preimages != nil { c.Preimages = *dec.Preimages diff --git a/eth/peerset.go b/eth/peerset.go index dc1d7da45e..71b8e109ed 100644 --- a/eth/peerset.go +++ b/eth/peerset.go @@ -22,13 +22,13 @@ import ( "sync" "time" - "github.com/ethereum/go-ethereum/eth/protocols/trust" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/protocols/diff" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" + "github.com/ethereum/go-ethereum/eth/protocols/trust" "github.com/ethereum/go-ethereum/p2p" ) @@ -334,11 +334,11 @@ func (ps *peerSet) GetDiffPeer(pid string) downloader.IDiffPeer { } // GetVerifyPeers returns an array of verify nodes. -func (ps *peerSet) GetVerifyPeers() []*trustPeer { - res := make([]*trustPeer, 0) +func (ps *peerSet) GetVerifyPeers() []core.VerifyPeer { + res := make([]core.VerifyPeer, 0) for _, p := range ps.peers { - if p.trustExt != nil { - res = append(res, p.trustExt) + if p.trustExt != nil && p.trustExt.Peer != nil { + res = append(res, p.trustExt.Peer) } } return res