|
|
|
@ -22,13 +22,13 @@ import ( |
|
|
|
|
"encoding/binary" |
|
|
|
|
"fmt" |
|
|
|
|
mrand "math/rand" |
|
|
|
|
"sort" |
|
|
|
|
"testing" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
|
"github.com/ethereum/go-ethereum/core/rawdb" |
|
|
|
|
"github.com/ethereum/go-ethereum/crypto" |
|
|
|
|
"github.com/ethereum/go-ethereum/ethdb/memorydb" |
|
|
|
|
"golang.org/x/exp/slices" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Prng is a pseudo random number generator seeded by strong randomness.
|
|
|
|
@ -165,21 +165,15 @@ func TestMissingKeyProof(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type entrySlice []*kv |
|
|
|
|
|
|
|
|
|
func (p entrySlice) Len() int { return len(p) } |
|
|
|
|
func (p entrySlice) Less(i, j int) bool { return bytes.Compare(p[i].k, p[j].k) < 0 } |
|
|
|
|
func (p entrySlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } |
|
|
|
|
|
|
|
|
|
// TestRangeProof tests normal range proof with both edge proofs
|
|
|
|
|
// as the existent proof. The test cases are generated randomly.
|
|
|
|
|
func TestRangeProof(t *testing.T) { |
|
|
|
|
trie, vals := randomTrie(4096) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
for i := 0; i < 500; i++ { |
|
|
|
|
start := mrand.Intn(len(entries)) |
|
|
|
|
end := mrand.Intn(len(entries)-start) + start + 1 |
|
|
|
@ -208,11 +202,11 @@ func TestRangeProof(t *testing.T) { |
|
|
|
|
// The test cases are generated randomly.
|
|
|
|
|
func TestRangeProofWithNonExistentProof(t *testing.T) { |
|
|
|
|
trie, vals := randomTrie(4096) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
for i := 0; i < 500; i++ { |
|
|
|
|
start := mrand.Intn(len(entries)) |
|
|
|
|
end := mrand.Intn(len(entries)-start) + start + 1 |
|
|
|
@ -280,11 +274,11 @@ func TestRangeProofWithNonExistentProof(t *testing.T) { |
|
|
|
|
// - There exists a gap between the last element and the right edge proof
|
|
|
|
|
func TestRangeProofWithInvalidNonExistentProof(t *testing.T) { |
|
|
|
|
trie, vals := randomTrie(4096) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
// Case 1
|
|
|
|
|
start, end := 100, 200 |
|
|
|
@ -337,11 +331,11 @@ func TestRangeProofWithInvalidNonExistentProof(t *testing.T) { |
|
|
|
|
// non-existent one.
|
|
|
|
|
func TestOneElementRangeProof(t *testing.T) { |
|
|
|
|
trie, vals := randomTrie(4096) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
// One element with existent edge proof, both edge proofs
|
|
|
|
|
// point to the SAME key.
|
|
|
|
@ -424,11 +418,11 @@ func TestOneElementRangeProof(t *testing.T) { |
|
|
|
|
// The edge proofs can be nil.
|
|
|
|
|
func TestAllElementsProof(t *testing.T) { |
|
|
|
|
trie, vals := randomTrie(4096) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
var k [][]byte |
|
|
|
|
var v [][]byte |
|
|
|
@ -474,13 +468,13 @@ func TestAllElementsProof(t *testing.T) { |
|
|
|
|
func TestSingleSideRangeProof(t *testing.T) { |
|
|
|
|
for i := 0; i < 64; i++ { |
|
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for i := 0; i < 4096; i++ { |
|
|
|
|
value := &kv{randBytes(32), randBytes(20), false} |
|
|
|
|
trie.MustUpdate(value.k, value.v) |
|
|
|
|
entries = append(entries, value) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
var cases = []int{0, 1, 50, 100, 1000, 2000, len(entries) - 1} |
|
|
|
|
for _, pos := range cases { |
|
|
|
@ -509,13 +503,13 @@ func TestSingleSideRangeProof(t *testing.T) { |
|
|
|
|
func TestReverseSingleSideRangeProof(t *testing.T) { |
|
|
|
|
for i := 0; i < 64; i++ { |
|
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for i := 0; i < 4096; i++ { |
|
|
|
|
value := &kv{randBytes(32), randBytes(20), false} |
|
|
|
|
trie.MustUpdate(value.k, value.v) |
|
|
|
|
entries = append(entries, value) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
var cases = []int{0, 1, 50, 100, 1000, 2000, len(entries) - 1} |
|
|
|
|
for _, pos := range cases { |
|
|
|
@ -545,11 +539,11 @@ func TestReverseSingleSideRangeProof(t *testing.T) { |
|
|
|
|
// The prover is expected to detect the error.
|
|
|
|
|
func TestBadRangeProof(t *testing.T) { |
|
|
|
|
trie, vals := randomTrie(4096) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
for i := 0; i < 500; i++ { |
|
|
|
|
start := mrand.Intn(len(entries)) |
|
|
|
@ -648,11 +642,11 @@ func TestGappedRangeProof(t *testing.T) { |
|
|
|
|
// TestSameSideProofs tests the element is not in the range covered by proofs
|
|
|
|
|
func TestSameSideProofs(t *testing.T) { |
|
|
|
|
trie, vals := randomTrie(4096) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
pos := 1000 |
|
|
|
|
first := decreaseKey(common.CopyBytes(entries[pos].k)) |
|
|
|
@ -690,13 +684,13 @@ func TestSameSideProofs(t *testing.T) { |
|
|
|
|
|
|
|
|
|
func TestHasRightElement(t *testing.T) { |
|
|
|
|
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for i := 0; i < 4096; i++ { |
|
|
|
|
value := &kv{randBytes(32), randBytes(20), false} |
|
|
|
|
trie.MustUpdate(value.k, value.v) |
|
|
|
|
entries = append(entries, value) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
var cases = []struct { |
|
|
|
|
start int |
|
|
|
@ -764,11 +758,11 @@ func TestHasRightElement(t *testing.T) { |
|
|
|
|
// The first edge proof must be a non-existent proof.
|
|
|
|
|
func TestEmptyRangeProof(t *testing.T) { |
|
|
|
|
trie, vals := randomTrie(4096) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
var cases = []struct { |
|
|
|
|
pos int |
|
|
|
@ -799,11 +793,11 @@ func TestEmptyRangeProof(t *testing.T) { |
|
|
|
|
func TestBloatedProof(t *testing.T) { |
|
|
|
|
// Use a small trie
|
|
|
|
|
trie, kvs := nonRandomTrie(100) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range kvs { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
var keys [][]byte |
|
|
|
|
var vals [][]byte |
|
|
|
|
|
|
|
|
@ -833,11 +827,11 @@ func TestBloatedProof(t *testing.T) { |
|
|
|
|
// noop technically, but practically should be rejected.
|
|
|
|
|
func TestEmptyValueRangeProof(t *testing.T) { |
|
|
|
|
trie, values := randomTrie(512) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range values { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
// Create a new entry with a slightly modified key
|
|
|
|
|
mid := len(entries) / 2 |
|
|
|
@ -877,11 +871,11 @@ func TestEmptyValueRangeProof(t *testing.T) { |
|
|
|
|
// practically should be rejected.
|
|
|
|
|
func TestAllElementsEmptyValueRangeProof(t *testing.T) { |
|
|
|
|
trie, values := randomTrie(512) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range values { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
// Create a new entry with a slightly modified key
|
|
|
|
|
mid := len(entries) / 2 |
|
|
|
@ -983,11 +977,11 @@ func BenchmarkVerifyRangeProof5000(b *testing.B) { benchmarkVerifyRangeProof(b, |
|
|
|
|
|
|
|
|
|
func benchmarkVerifyRangeProof(b *testing.B, size int) { |
|
|
|
|
trie, vals := randomTrie(8192) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
start := 2 |
|
|
|
|
end := start + size |
|
|
|
@ -1020,11 +1014,11 @@ func BenchmarkVerifyRangeNoProof1000(b *testing.B) { benchmarkVerifyRangeNoProof |
|
|
|
|
|
|
|
|
|
func benchmarkVerifyRangeNoProof(b *testing.B, size int) { |
|
|
|
|
trie, vals := randomTrie(size) |
|
|
|
|
var entries entrySlice |
|
|
|
|
var entries []*kv |
|
|
|
|
for _, kv := range vals { |
|
|
|
|
entries = append(entries, kv) |
|
|
|
|
} |
|
|
|
|
sort.Sort(entries) |
|
|
|
|
slices.SortFunc(entries, (*kv).less) |
|
|
|
|
|
|
|
|
|
var keys [][]byte |
|
|
|
|
var values [][]byte |
|
|
|
|