cmd/geth: extend traverseRawState command (#24954)
This PR adds node verification into traverseRawState command, so corrupted trie nodes can also be detected.
This commit is contained in:
parent
86af788790
commit
a10660b7f8
@ -307,7 +307,7 @@ func checkStateContent(ctx *cli.Context) error {
|
||||
start []byte
|
||||
)
|
||||
if ctx.NArg() > 1 {
|
||||
return fmt.Errorf("Max 1 argument: %v", ctx.Command.ArgsUsage)
|
||||
return fmt.Errorf("max 1 argument: %v", ctx.Command.ArgsUsage)
|
||||
}
|
||||
if ctx.NArg() > 0 {
|
||||
if d, err := hexutil.Decode(ctx.Args().First()); err != nil {
|
||||
@ -332,8 +332,8 @@ func checkStateContent(ctx *cli.Context) error {
|
||||
)
|
||||
for it.Next() {
|
||||
count++
|
||||
v := it.Value()
|
||||
k := it.Key()
|
||||
v := it.Value()
|
||||
hasher.Reset()
|
||||
hasher.Write(v)
|
||||
hasher.Read(got)
|
||||
|
@ -105,7 +105,7 @@ data, and verifies that all snapshot storage data has a corresponding account.
|
||||
},
|
||||
{
|
||||
Name: "traverse-state",
|
||||
Usage: "Traverse the state with given root hash for verification",
|
||||
Usage: "Traverse the state with given root hash and perform quick verification",
|
||||
ArgsUsage: "<root>",
|
||||
Action: utils.MigrateFlags(traverseState),
|
||||
Category: "MISCELLANEOUS COMMANDS",
|
||||
@ -121,7 +121,7 @@ It's also usable without snapshot enabled.
|
||||
},
|
||||
{
|
||||
Name: "traverse-rawstate",
|
||||
Usage: "Traverse the state with given root hash for verification",
|
||||
Usage: "Traverse the state with given root hash and perform detailed verification",
|
||||
ArgsUsage: "<root>",
|
||||
Action: utils.MigrateFlags(traverseRawState),
|
||||
Category: "MISCELLANEOUS COMMANDS",
|
||||
@ -367,6 +367,8 @@ func traverseRawState(ctx *cli.Context) error {
|
||||
codes int
|
||||
lastReport time.Time
|
||||
start = time.Now()
|
||||
hasher = crypto.NewKeccakState()
|
||||
got = make([]byte, 32)
|
||||
)
|
||||
accIter := t.NodeIterator(nil)
|
||||
for accIter.Next(true) {
|
||||
@ -376,10 +378,18 @@ func traverseRawState(ctx *cli.Context) error {
|
||||
// Check the present for non-empty hash node(embedded node doesn't
|
||||
// have their own hash).
|
||||
if node != (common.Hash{}) {
|
||||
if !rawdb.HasTrieNode(chaindb, node) {
|
||||
blob := rawdb.ReadTrieNode(chaindb, node)
|
||||
if len(blob) == 0 {
|
||||
log.Error("Missing trie node(account)", "hash", node)
|
||||
return errors.New("missing account")
|
||||
}
|
||||
hasher.Reset()
|
||||
hasher.Write(blob)
|
||||
hasher.Read(got)
|
||||
if !bytes.Equal(got, node.Bytes()) {
|
||||
log.Error("Invalid trie node(account)", "hash", node.Hex(), "value", blob)
|
||||
return errors.New("invalid account node")
|
||||
}
|
||||
}
|
||||
// If it's a leaf node, yes we are touching an account,
|
||||
// dig into the storage trie further.
|
||||
@ -404,10 +414,18 @@ func traverseRawState(ctx *cli.Context) error {
|
||||
// Check the present for non-empty hash node(embedded node doesn't
|
||||
// have their own hash).
|
||||
if node != (common.Hash{}) {
|
||||
if !rawdb.HasTrieNode(chaindb, node) {
|
||||
blob := rawdb.ReadTrieNode(chaindb, node)
|
||||
if len(blob) == 0 {
|
||||
log.Error("Missing trie node(storage)", "hash", node)
|
||||
return errors.New("missing storage")
|
||||
}
|
||||
hasher.Reset()
|
||||
hasher.Write(blob)
|
||||
hasher.Read(got)
|
||||
if !bytes.Equal(got, node.Bytes()) {
|
||||
log.Error("Invalid trie node(storage)", "hash", node.Hex(), "value", blob)
|
||||
return errors.New("invalid storage node")
|
||||
}
|
||||
}
|
||||
// Bump the counter if it's leaf node.
|
||||
if storageIter.Leaf() {
|
||||
|
Loading…
Reference in New Issue
Block a user