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
|
start []byte
|
||||||
)
|
)
|
||||||
if ctx.NArg() > 1 {
|
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 ctx.NArg() > 0 {
|
||||||
if d, err := hexutil.Decode(ctx.Args().First()); err != nil {
|
if d, err := hexutil.Decode(ctx.Args().First()); err != nil {
|
||||||
|
@ -332,8 +332,8 @@ func checkStateContent(ctx *cli.Context) error {
|
||||||
)
|
)
|
||||||
for it.Next() {
|
for it.Next() {
|
||||||
count++
|
count++
|
||||||
v := it.Value()
|
|
||||||
k := it.Key()
|
k := it.Key()
|
||||||
|
v := it.Value()
|
||||||
hasher.Reset()
|
hasher.Reset()
|
||||||
hasher.Write(v)
|
hasher.Write(v)
|
||||||
hasher.Read(got)
|
hasher.Read(got)
|
||||||
|
|
|
@ -105,7 +105,7 @@ data, and verifies that all snapshot storage data has a corresponding account.
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "traverse-state",
|
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>",
|
ArgsUsage: "<root>",
|
||||||
Action: utils.MigrateFlags(traverseState),
|
Action: utils.MigrateFlags(traverseState),
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
Category: "MISCELLANEOUS COMMANDS",
|
||||||
|
@ -121,7 +121,7 @@ It's also usable without snapshot enabled.
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "traverse-rawstate",
|
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>",
|
ArgsUsage: "<root>",
|
||||||
Action: utils.MigrateFlags(traverseRawState),
|
Action: utils.MigrateFlags(traverseRawState),
|
||||||
Category: "MISCELLANEOUS COMMANDS",
|
Category: "MISCELLANEOUS COMMANDS",
|
||||||
|
@ -367,6 +367,8 @@ func traverseRawState(ctx *cli.Context) error {
|
||||||
codes int
|
codes int
|
||||||
lastReport time.Time
|
lastReport time.Time
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
|
hasher = crypto.NewKeccakState()
|
||||||
|
got = make([]byte, 32)
|
||||||
)
|
)
|
||||||
accIter := t.NodeIterator(nil)
|
accIter := t.NodeIterator(nil)
|
||||||
for accIter.Next(true) {
|
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
|
// Check the present for non-empty hash node(embedded node doesn't
|
||||||
// have their own hash).
|
// have their own hash).
|
||||||
if node != (common.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)
|
log.Error("Missing trie node(account)", "hash", node)
|
||||||
return errors.New("missing account")
|
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,
|
// If it's a leaf node, yes we are touching an account,
|
||||||
// dig into the storage trie further.
|
// 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
|
// Check the present for non-empty hash node(embedded node doesn't
|
||||||
// have their own hash).
|
// have their own hash).
|
||||||
if node != (common.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)
|
log.Error("Missing trie node(storage)", "hash", node)
|
||||||
return errors.New("missing storage")
|
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.
|
// Bump the counter if it's leaf node.
|
||||||
if storageIter.Leaf() {
|
if storageIter.Leaf() {
|
||||||
|
|
Loading…
Reference in New Issue