Skip to content

Commit 7322b25

Browse files
authored
Merge pull request #23960 from karalabe/verify-range-deletion
trie: reject deletions when verifying range proofs
2 parents d15e423 + 743769f commit 7322b25

File tree

2 files changed

+85
-1
lines changed

2 files changed

+85
-1
lines changed

trie/proof.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -472,12 +472,17 @@ func VerifyRangeProof(rootHash common.Hash, firstKey []byte, lastKey []byte, key
472472
if len(keys) != len(values) {
473473
return false, fmt.Errorf("inconsistent proof data, keys: %d, values: %d", len(keys), len(values))
474474
}
475-
// Ensure the received batch is monotonic increasing.
475+
// Ensure the received batch is monotonic increasing and contains no deletions
476476
for i := 0; i < len(keys)-1; i++ {
477477
if bytes.Compare(keys[i], keys[i+1]) >= 0 {
478478
return false, errors.New("range is not monotonically increasing")
479479
}
480480
}
481+
for _, value := range values {
482+
if len(value) == 0 {
483+
return false, errors.New("range contains deletion")
484+
}
485+
}
481486
// Special case, there is no edge proof at all. The given range is expected
482487
// to be the whole leaf-set in the trie.
483488
if proof == nil {

trie/proof_test.go

+79
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,85 @@ func TestBloatedProof(t *testing.T) {
813813
}
814814
}
815815

816+
// TestEmptyValueRangeProof tests normal range proof with both edge proofs
817+
// as the existent proof, but with an extra empty value included, which is a
818+
// noop technically, but practically should be rejected.
819+
func TestEmptyValueRangeProof(t *testing.T) {
820+
trie, values := randomTrie(512)
821+
var entries entrySlice
822+
for _, kv := range values {
823+
entries = append(entries, kv)
824+
}
825+
sort.Sort(entries)
826+
827+
// Create a new entry with a slightly modified key
828+
mid := len(entries) / 2
829+
key := common.CopyBytes(entries[mid-1].k)
830+
for n := len(key) - 1; n >= 0; n-- {
831+
if key[n] < 0xff {
832+
key[n]++
833+
break
834+
}
835+
}
836+
noop := &kv{key, []byte{}, false}
837+
entries = append(append(append([]*kv{}, entries[:mid]...), noop), entries[mid:]...)
838+
839+
start, end := 1, len(entries)-1
840+
841+
proof := memorydb.New()
842+
if err := trie.Prove(entries[start].k, 0, proof); err != nil {
843+
t.Fatalf("Failed to prove the first node %v", err)
844+
}
845+
if err := trie.Prove(entries[end-1].k, 0, proof); err != nil {
846+
t.Fatalf("Failed to prove the last node %v", err)
847+
}
848+
var keys [][]byte
849+
var vals [][]byte
850+
for i := start; i < end; i++ {
851+
keys = append(keys, entries[i].k)
852+
vals = append(vals, entries[i].v)
853+
}
854+
_, err := VerifyRangeProof(trie.Hash(), keys[0], keys[len(keys)-1], keys, vals, proof)
855+
if err == nil {
856+
t.Fatalf("Expected failure on noop entry")
857+
}
858+
}
859+
860+
// TestAllElementsEmptyValueRangeProof tests the range proof with all elements,
861+
// but with an extra empty value included, which is a noop technically, but
862+
// practically should be rejected.
863+
func TestAllElementsEmptyValueRangeProof(t *testing.T) {
864+
trie, values := randomTrie(512)
865+
var entries entrySlice
866+
for _, kv := range values {
867+
entries = append(entries, kv)
868+
}
869+
sort.Sort(entries)
870+
871+
// Create a new entry with a slightly modified key
872+
mid := len(entries) / 2
873+
key := common.CopyBytes(entries[mid-1].k)
874+
for n := len(key) - 1; n >= 0; n-- {
875+
if key[n] < 0xff {
876+
key[n]++
877+
break
878+
}
879+
}
880+
noop := &kv{key, []byte{}, false}
881+
entries = append(append(append([]*kv{}, entries[:mid]...), noop), entries[mid:]...)
882+
883+
var keys [][]byte
884+
var vals [][]byte
885+
for i := 0; i < len(entries); i++ {
886+
keys = append(keys, entries[i].k)
887+
vals = append(vals, entries[i].v)
888+
}
889+
_, err := VerifyRangeProof(trie.Hash(), nil, nil, keys, vals, nil)
890+
if err == nil {
891+
t.Fatalf("Expected failure on noop entry")
892+
}
893+
}
894+
816895
// mutateByte changes one byte in b.
817896
func mutateByte(b []byte) {
818897
for r := mrand.Intn(len(b)); ; {

0 commit comments

Comments
 (0)