Skip to content

fast node verification#4

Open
kyrie-yl wants to merge 4 commits intoseparate-nodesfrom
fastnode-v1
Open

fast node verification#4
kyrie-yl wants to merge 4 commits intoseparate-nodesfrom
fastnode-v1

Conversation

@kyrie-yl
Copy link
Copy Markdown
Collaborator

No description provided.

Comment thread cmd/utils/flags.go Outdated
Comment thread core/blockchain.go Outdated
Comment thread core/blockchain.go Outdated
Comment thread core/verify_manager.go Outdated
Comment thread core/verify_manager.go Outdated
Comment thread core/verify_manager.go Outdated
Comment thread core/verify_manager.go Outdated
Comment thread core/verify_manager.go Outdated
Comment thread core/verify_manager.go Outdated
Comment thread core/verify_modes.go Outdated
Comment thread core/verify_modes.go Outdated
Comment thread core/verify_peers.go Outdated
Comment thread core/verify_task.go Outdated
Comment thread core/verify_task.go Outdated
Comment thread core/verify_task.go Outdated
Comment thread core/verify_task.go Outdated
Comment thread core/verify_task.go Outdated
Comment thread core/verify_task.go Outdated
Comment thread core/verify_manager.go Outdated
Signed-off-by: kyrie-yl <yl.on.the.way@gmail.com>
Comment thread cmd/geth/main.go
utils.NoUSBFlag,
utils.DirectBroadcastFlag,
utils.DisableSnapProtocolFlag,
utils.DisableDiffProtocolFlag,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean it is not proper to introduce such low level flag. Especially it is related with other flags.
For example: when TriesVerifyModeFlag need trust protocol while EnableTrustProtocolFlag is false, it is become complicated.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider we should disable diff protocol in verify node, and enable trust protocol, we didn't have better solution temporary.

Comment thread cmd/utils/flags.go Outdated
defaultVerifyMode = ethconfig.Defaults.TriesVerifyMode
TriesVerifyModeFlag = TextMarshalerFlag{
Name: "tries-verify-mode",
Usage: `tries verify mode: "local", "full", "light", "insecure"`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please explain in details what the each mode means in the usage so that the user can understand

Comment thread core/verify_modes.go Outdated
Comment thread core/verify_modes.go Outdated
}

func (mode *VerifyMode) NeedRemoteVerify() bool {
if *mode == FullVerify || *mode == LightVerify {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return *mode == FullVerify || *mode == LightVerify directly?

Comment thread core/blockchain.go Outdated
engine consensus.Engine
validator Validator // Block and state validator interface
processor Processor // Block transaction processor interface
verifyManager *VerifyManager
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we use interface here, like validator, processor ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verifyManager is not a good name, we need distinguish it from validator here.

Comment thread eth/backend.go Outdated
Comment thread core/blockchain.go Outdated
return bc, nil
}

func (bc *BlockChain) StartVerify(peers VerifyPeers, allowUntrustedVerify bool) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not pass allowUntrustedVerify when StartVerify, but pass it when new the verifyManager.

Comment thread core/trie_verify.go Outdated
header := vm.bc.CurrentHeader()
// Start verify task from H to H-11 if need.
vm.NewBlockVerifyTask(header)
prune := time.NewTicker(time.Second)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prune --> pruneTicker

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 second is too short for pruneTicker, I will suggest 5 seconds

Comment thread core/trie_verify.go Outdated
}
case <-prune.C:
for hash, task := range vm.tasks {
if vm.bc.CurrentHeader().Number.Uint64()-task.blockHeader.Number.Uint64() > 15 {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

15 is magic number here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The subtraction here may overflow.

Comment thread core/trie_verify.go Outdated

func (vm *VerifyManager) Stop() {
// stop all the tasks
for _, task := range vm.tasks {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

race condition on vm.tasks, it may double close task.terminalCh and cause panic

Comment thread core/trie_verify.go Outdated
func (vt *VerifyTask) Start(verifyCh chan common.Hash) {
vt.startAt = time.Now()

vt.selectPeersToVerify(defaultPeerNumber)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try better name thanselectPeersToVerify. 主语是select,就是挑选,实际上会把请求发出去。

Comment thread core/trie_verify.go Outdated
validPeers = append(validPeers, p)
}
}
// if
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clean the code.

Comment thread core/trie_verify.go
}

// if n < len(validPeers), select n peers from validPeers randomly.
rand.Seed(time.Now().UnixNano())
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please log(warn) if there is no node to request.

Comment thread core/trie_verify.go Outdated
func (vt *VerifyTask) compareRootHashAndWrite(msg VerifyMessage, verifyCh chan common.Hash) {
if msg.verifyResult.Root == vt.blockHeader.Root {
blockhash := msg.verifyResult.BlockHash
rawdb.MarkTrustBlock(vt.db, blockhash)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have done MarkTrustBlock twice, I think we can delete here, but let VerifyManager to do it.

Comment thread core/types.go Outdated
// VerifyBlock verify the given blcok.
VerifyBlock(header *types.Header)
// ValidateBlockVerify validate the given block has been verified.
ValidateBlockVerify(block *types.Block) error
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ValidateBlockVerify is too confusing...

Comment thread core/types.go Outdated
ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error

// StartRemoteVerify start the remote verify routine for given peers.
StartRemoteVerify(peers VerifyPeers)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is some way to hide StartRemoteVerify and StopRemoteVerify, we should expose as less interface as possible.

Comment thread core/types.go Outdated
// StopRemoteVerify stop the remote verify routine.
StopRemoteVerify()
// VerifyBlock verify the given blcok.
VerifyBlock(header *types.Header)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can merge VerifyBlock and ValidateBody into one.

Comment thread core/block_validator.go Outdated
bc: blockchain,
}
if mode.NeedRemoteVerify() {
remoteValidator := NewVerifyManager(blockchain, peers, *mode == InsecureVerify)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should assign validator's remoteValidator, not just a local variable.

Comment thread core/block_validator.go Outdated
if !v.remoteValidator.AncestorVerified(v.bc.GetHeaderByNumber(header.Number.Uint64())) {
return fmt.Errorf("block's ancessor %x has not been verified", block.Hash())
}
}
Copy link
Copy Markdown
Owner

@keefel keefel Feb 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap these code as a new validateFunc is better? Can run concurrently with above another two validateFuncs

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please run concurrently like another two validateFuncs.

Comment thread core/trie_verify.go
if diffLayer, err = vm.bc.GenerateDiffLayer(hash); err != nil {
log.Error("failed to get diff layer", "block", hash, "number", header.Number, "error", err)
return
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a case if the block is an empty block, the error is nil and difflayer is nil too. So, add another branch to test if difflayer == nil, if so, return directly.

Comment thread core/trie_verify.go Outdated
if header.TxHash == types.EmptyRootHash {
parent := vm.bc.GetHeaderByHash(header.ParentHash)
if header.Root == parent.Root {
return true
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need use if branch, actually if you use if branch, when not equal, you should use else branch to return false here, so recommend to return header.Root == parent.Root directly.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think when header.Root == parent.Root, we should check whether the parent has been verified, if not, this empty block is not verified, if the parent has been verified already, this empty block is verified. So maybe here should be
if header.Root != parent.Root { return false }

Comment thread core/trie_verify.go Outdated
allowUntrusted: allowUntrusted,

newTaskCh: make(chan *types.Header),
verifyCh: make(chan common.Hash),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will suggest verifyCh have some buffer, like 11, so than the main process will not been blocked.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do newTaskCh, please allocate some buffer.

Comment thread cmd/utils/flags.go
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",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better description is needed to let users understand the meaning of each mode

Comment thread cmd/utils/flags.go Outdated
}
// If a node sets verify mode but not local, it's a fast node whose difflayer is not integral.
// So fast node should disable diff protocol.
if cfg.TriesVerifyMode != core.LocalVerify {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After discuss with nash, we can delete flag DisableDiffProtocol, even fast node can provide difflayer for diff sync.

Comment thread core/rawdb/schema.go Outdated
diffLayerPrefix = []byte("d") // diffLayerPrefix + hash -> diffLayer

// trust block database
trustBlockPrefix = []byte("trust-block-") // trustBlockPrefix + hash -> verify result
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please delete useless code

Comment thread core/rawdb/schema.go Outdated
}

// trustBlockHashKey = trustBlockPrefix + hash
func trustBlockHashKey(hash common.Hash) []byte {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please delete useless code

Comment thread core/trie_verify.go Outdated
tryAllPeersTime = 15 * time.Second
)

type verifyManager struct {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename verifyManager to remoteVerifyManager

Comment thread core/trie_verify.go
@@ -0,0 +1,345 @@
package core
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file name trie_verify can rename to remote_state_verifier

Comment thread core/trie_verify.go Outdated
return nil
}

func (mode *VerifyMode) NeedRemoteVerify() bool {
Copy link
Copy Markdown

@unclezoro unclezoro Feb 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change func (mode *VerifyMode) NeedRemoteVerify() bool to func (mode VerifyMode) NeedRemoteVerify() bool, so that you can change

func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine, mode *VerifyMode, peers verifyPeers) *BlockValidator

to

func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine, mode VerifyMode, peers verifyPeers) *BlockValidator {

Comment thread core/block_validator.go Outdated
return err
}

func (v *BlockValidator) VerifyBlockTrie(header *types.Header) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us try subscribe the header info rather than called in main process.

Comment thread core/trie_verify.go Outdated
tasks map[common.Hash]*verifyTask
peers verifyPeers
verifiedCache *lru.Cache
allowUntrusted bool
Copy link
Copy Markdown

@unclezoro unclezoro Feb 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we rename it to allowInsecure, since the peer is still trusted, but the result is not insecure

@unclezoro
Copy link
Copy Markdown

unclezoro commented Feb 14, 2022

Please add promethus metrics

Signed-off-by: kyrie-yl <yl.on.the.way@gmail.com>
Signed-off-by: kyrie-yl <yl.on.the.way@gmail.com>
keefel pushed a commit that referenced this pull request Jun 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants