Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fast node verification #4

Open
wants to merge 4 commits into
base: separate-nodes
Choose a base branch
from
Open

fast node verification #4

wants to merge 4 commits into from

Conversation

kyrie-yl
Copy link
Collaborator

No description provided.

cmd/utils/flags.go Outdated Show resolved Hide resolved
core/blockchain.go Outdated Show resolved Hide resolved
core/blockchain.go Outdated Show resolved Hide resolved
core/verify_manager.go Outdated Show resolved Hide resolved
core/verify_manager.go Outdated Show resolved Hide resolved
core/verify_manager.go Outdated Show resolved Hide resolved
core/verify_manager.go Outdated Show resolved Hide resolved
core/verify_manager.go Outdated Show resolved Hide resolved
core/verify_manager.go Outdated Show resolved Hide resolved
core/verify_modes.go Outdated Show resolved Hide resolved
core/verify_modes.go Outdated Show resolved Hide resolved
core/verify_peers.go Outdated Show resolved Hide resolved
core/verify_task.go Outdated Show resolved Hide resolved
core/verify_task.go Outdated Show resolved Hide resolved
core/verify_task.go Outdated Show resolved Hide resolved
core/verify_task.go Outdated Show resolved Hide resolved
core/verify_task.go Outdated Show resolved Hide resolved
core/verify_task.go Outdated Show resolved Hide resolved
core/verify_manager.go Outdated Show resolved Hide resolved
Signed-off-by: kyrie-yl <[email protected]>
@@ -71,6 +71,8 @@ var (
utils.NoUSBFlag,
utils.DirectBroadcastFlag,
utils.DisableSnapProtocolFlag,
utils.DisableDiffProtocolFlag,

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
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.

defaultVerifyMode = ethconfig.Defaults.TriesVerifyMode
TriesVerifyModeFlag = TextMarshalerFlag{
Name: "tries-verify-mode",
Usage: `tries verify mode: "local", "full", "light", "insecure"`,

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

core/verify_modes.go Outdated Show resolved Hide resolved
}

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

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?

@@ -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

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 ?

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.

eth/backend.go Outdated Show resolved Hide resolved
@@ -462,6 +463,16 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
return bc, nil
}

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

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.

header := vm.bc.CurrentHeader()
// Start verify task from H to H-11 if need.
vm.NewBlockVerifyTask(header)
prune := time.NewTicker(time.Second)

Choose a reason for hiding this comment

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

prune --> pruneTicker

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

}
case <-prune.C:
for hash, task := range vm.tasks {
if vm.bc.CurrentHeader().Number.Uint64()-task.blockHeader.Number.Uint64() > 15 {

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.

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.


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

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

func (vt *VerifyTask) Start(verifyCh chan common.Hash) {
vt.startAt = time.Now()

vt.selectPeersToVerify(defaultPeerNumber)

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,就是挑选,实际上会把请求发出去。

validPeers = append(validPeers, p)
}
}
// if

Choose a reason for hiding this comment

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

clean the code.

}

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

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.

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)

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.

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

Choose a reason for hiding this comment

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

ValidateBlockVerify is too confusing...

core/types.go Outdated
@@ -32,6 +32,17 @@ type Validator interface {
// ValidateState validates the given statedb and optionally the receipts and
// gas used.
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)

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.

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

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.

validator := &BlockValidator{
config: config,
engine: engine,
bc: blockchain,
}
if mode.NeedRemoteVerify() {
remoteValidator := NewVerifyManager(blockchain, peers, *mode == InsecureVerify)
Copy link
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.

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
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

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.

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
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.

if header.TxHash == types.EmptyRootHash {
parent := vm.bc.GetHeaderByHash(header.ParentHash)
if header.Root == parent.Root {
return true
Copy link
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
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 }

allowUntrusted: allowUntrusted,

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

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.

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.

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",

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

}
// 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 {

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.

@@ -93,6 +93,9 @@ var (
// difflayer database
diffLayerPrefix = []byte("d") // diffLayerPrefix + hash -> diffLayer

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

Choose a reason for hiding this comment

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

Please delete useless code

@@ -165,6 +168,11 @@ func headerHashKey(number uint64) []byte {
return append(append(headerPrefix, encodeBlockNumber(number)...), headerHashSuffix...)
}

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

Choose a reason for hiding this comment

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

Please delete useless code

tryAllPeersTime = 15 * time.Second
)

type verifyManager struct {

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

@@ -0,0 +1,345 @@
package core

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

return nil
}

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

@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 {

@@ -149,6 +160,16 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
return err
}

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

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.

tasks map[common.Hash]*verifyTask
peers verifyPeers
verifiedCache *lru.Cache
allowUntrusted bool
Copy link

@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

unclezoro commented Feb 14, 2022

Please add promethus metrics

Signed-off-by: kyrie-yl <[email protected]>
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