trie: add edgecase for rangeproof correctness-testing

This commit is contained in:
Martin Holst Swende 2025-04-17 20:42:08 +02:00
parent 074da25f66
commit c0ecc3a661
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
2 changed files with 44 additions and 3 deletions

View file

@ -485,10 +485,19 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, keys [][]byte, valu
if len(keys) != len(values) { if len(keys) != len(values) {
return false, fmt.Errorf("inconsistent proof data, keys: %d, values: %d", len(keys), len(values)) return false, fmt.Errorf("inconsistent proof data, keys: %d, values: %d", len(keys), len(values))
} }
// Ensure the received batch is monotonic increasing and contains no deletions // Ensure the received batch is
// - monotonically increasing,
// - not expanding down prefix-paths
// - and contains no deletions
//last := []byte{0}
for i := 0; i < len(keys); i++ { for i := 0; i < len(keys); i++ {
if i < len(keys)-1 && bytes.Compare(keys[i], keys[i+1]) >= 0 { if i < len(keys)-1 {
return false, errors.New("range is not monotonically increasing") if bytes.Compare(keys[i], keys[i+1]) >= 0 {
return false, errors.New("range is not monotonically increasing")
}
if bytes.HasPrefix(keys[i+1], keys[i]) {
return false, errors.New("range contains path prefixes")
}
} }
if len(values[i]) == 0 { if len(values[i]) == 0 {
return false, errors.New("range contains deletion") return false, errors.New("range contains deletion")

View file

@ -1000,3 +1000,35 @@ func TestRangeProofKeysWithSharedPrefix(t *testing.T) {
t.Error("expected more to be false") t.Error("expected more to be false")
} }
} }
// TestRangeProofErrors tests a few cases where the prover is supposed
// to exit with errors
func TestRangeProofErrors(t *testing.T) {
// Different number of keys to values
_, err := VerifyRangeProof((common.Hash{}), []byte{}, make([][]byte, 5), make([][]byte, 4), nil)
if have, want := err.Error(), "inconsistent proof data, keys: 5, values: 4"; have != want {
t.Fatalf("wrong error, have %q, want %q", err.Error(), want)
}
// Non-increasing paths
_, err = VerifyRangeProof((common.Hash{}), []byte{},
[][]byte{[]byte{2, 1}, []byte{2, 1}}, make([][]byte, 2), nil)
if have, want := err.Error(), "range is not monotonically increasing"; have != want {
t.Fatalf("wrong error, have %q, want %q", err.Error(), want)
}
// A prefixed path is never motivated. Inserting the second element will
// require rewriting/overwriting the previous value-node, thus can only
// happen if the data is corrupt.
_, err = VerifyRangeProof((common.Hash{}), []byte{},
[][]byte{[]byte{2, 1}, []byte{2, 1, 2}},
[][]byte{[]byte{1}, []byte{1}}, nil)
if have, want := err.Error(), "range contains path prefixes"; have != want {
t.Fatalf("wrong error, have %q, want %q", err.Error(), want)
}
// Empty values (deletions)
_, err = VerifyRangeProof((common.Hash{}), []byte{},
[][]byte{[]byte{2, 1}, []byte{2, 2}},
[][]byte{[]byte{1}, []byte{}}, nil)
if have, want := err.Error(), "range contains deletion"; have != want {
t.Fatalf("wrong error, have %q, want %q", err.Error(), want)
}
}