Skip to content

Commit

Permalink
trie: make rhs-proof align with last key in range proofs
Browse files Browse the repository at this point in the history
  • Loading branch information
holiman committed Oct 13, 2023
1 parent 1cb3b6a commit 11703d9
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 166 deletions.
6 changes: 1 addition & 5 deletions cmd/devp2p/internal/ethtest/snap.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,11 +536,7 @@ func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error {
}
proofdb := nodes.Set()

var end []byte
if len(keys) > 0 {
end = keys[len(keys)-1]
}
_, err = trie.VerifyRangeProof(tc.root, tc.origin[:], end, keys, accounts, proofdb)
_, err = trie.VerifyRangeProof(tc.root, tc.origin[:], keys, accounts, proofdb)
return err
}

Expand Down
13 changes: 4 additions & 9 deletions core/state/snapshot/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,6 @@ func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix [
ctx.stats.Log("Trie missing, state snapshotting paused", dl.root, dl.genMarker)
return nil, errMissingTrie
}
// Firstly find out the key of last iterated element.
var last []byte
if len(keys) > 0 {
last = keys[len(keys)-1]
}
// Generate the Merkle proofs for the first and last element
if origin == nil {
origin = common.Hash{}.Bytes()
Expand All @@ -266,9 +261,9 @@ func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix [
tr: tr,
}, nil
}
if last != nil {
if err := tr.Prove(last, proof); err != nil {
log.Debug("Failed to prove range", "kind", kind, "last", last, "err", err)
if len(keys) > 0 {
if err := tr.Prove(keys[len(keys)-1], proof); err != nil {
log.Debug("Failed to prove range", "kind", kind, "last", keys[len(keys)-1], "err", err)
return &proofResult{
keys: keys,
vals: vals,
Expand All @@ -280,7 +275,7 @@ func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix [
}
// Verify the snapshot segment with range prover, ensure that all flat states
// in this range correspond to merkle trie.
cont, err := trie.VerifyRangeProof(root, origin, last, keys, vals, proof)
cont, err := trie.VerifyRangeProof(root, origin, keys, vals, proof)
return &proofResult{
keys: keys,
vals: vals,
Expand Down
16 changes: 3 additions & 13 deletions eth/protocols/snap/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -2401,13 +2401,7 @@ func (s *Syncer) OnAccounts(peer SyncPeer, id uint64, hashes []common.Hash, acco
for i, node := range proof {
nodes[i] = node
}
proofdb := nodes.Set()

var end []byte
if len(keys) > 0 {
end = keys[len(keys)-1]
}
cont, err := trie.VerifyRangeProof(root, req.origin[:], end, keys, accounts, proofdb)
cont, err := trie.VerifyRangeProof(root, req.origin[:], keys, accounts, nodes.Set())
if err != nil {
logger.Warn("Account range failed proof", "err", err)
// Signal this request as failed, and ready for rescheduling
Expand Down Expand Up @@ -2659,7 +2653,7 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
if len(nodes) == 0 {
// No proof has been attached, the response must cover the entire key
// space and hash to the origin root.
_, err = trie.VerifyRangeProof(req.roots[i], nil, nil, keys, slots[i], nil)
_, err = trie.VerifyRangeProof(req.roots[i], nil, keys, slots[i], nil)
if err != nil {
s.scheduleRevertStorageRequest(req) // reschedule request
logger.Warn("Storage slots failed proof", "err", err)
Expand All @@ -2670,11 +2664,7 @@ func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slo
// returned data is indeed part of the storage trie
proofdb := nodes.Set()

var end []byte
if len(keys) > 0 {
end = keys[len(keys)-1]
}
cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], end, keys, slots[i], proofdb)
cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], keys, slots[i], proofdb)
if err != nil {
s.scheduleRevertStorageRequest(req) // reschedule request
logger.Warn("Storage range failed proof", "err", err)
Expand Down
4 changes: 2 additions & 2 deletions tests/fuzzers/rangeproof/rangeproof-fuzzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (f *fuzzer) fuzz() int {
if len(keys) == 0 {
return 0
}
var first, last = keys[0], keys[len(keys)-1]
var first = keys[0]
testcase %= 6
switch testcase {
case 0:
Expand Down Expand Up @@ -165,7 +165,7 @@ func (f *fuzzer) fuzz() int {
}
ok = 1
//nodes, subtrie
hasMore, err := trie.VerifyRangeProof(tr.Hash(), first, last, keys, vals, proof)
hasMore, err := trie.VerifyRangeProof(tr.Hash(), first, keys, vals, proof)
if err != nil {
if hasMore {
panic("err != nil && hasMore == true")
Expand Down
3 changes: 2 additions & 1 deletion trie/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ func hasRightElement(node node, key []byte) bool {
// Note: This method does not verify that the proof is of minimal form. If the input
// proofs are 'bloated' with neighbour leaves or random data, aside from the 'useful'
// data, then the proof will still be accepted.
func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, keys [][]byte, values [][]byte, proof ethdb.KeyValueReader) (bool, error) {
func VerifyRangeProof(rootHash common.Hash, firstKey []byte, keys [][]byte, values [][]byte, proof ethdb.KeyValueReader) (bool, error) {
if len(keys) != len(values) {
return false, fmt.Errorf("inconsistent proof data, keys: %d, values: %d", len(keys), len(values))
}
Expand Down Expand Up @@ -520,6 +520,7 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, key
}
return false, nil
}
var lastKey = keys[len(keys)-1]
// Special case, there is only one element and two edge keys are same.
// In this case, we can't construct two edge paths. So handle it here.
if len(keys) == 1 && bytes.Equal(firstKey, lastKey) {
Expand Down
Loading

0 comments on commit 11703d9

Please sign in to comment.