From 339796446eac47be562eff5810ca42f9e83b8c50 Mon Sep 17 00:00:00 2001 From: devopsbo3 <69951731+devopsbo3@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:27:53 -0600 Subject: [PATCH] Revert "tests, trie: use slices package for sorting (#27496)" This reverts commit ad4c89228cb32e1c49921bf8bff748d8f26a6280. --- tests/fuzzers/rangeproof/rangeproof-fuzzer.go | 14 ++-- tests/fuzzers/stacktrie/trie_fuzzer.go | 21 ++++-- trie/iterator_test.go | 4 -- trie/proof_test.go | 72 ++++++++++--------- trie/trienode/node.go | 8 +-- 5 files changed, 67 insertions(+), 52 deletions(-) diff --git a/tests/fuzzers/rangeproof/rangeproof-fuzzer.go b/tests/fuzzers/rangeproof/rangeproof-fuzzer.go index 19bd39df98..2881c7a7c2 100644 --- a/tests/fuzzers/rangeproof/rangeproof-fuzzer.go +++ b/tests/fuzzers/rangeproof/rangeproof-fuzzer.go @@ -21,12 +21,12 @@ import ( "encoding/binary" "fmt" "io" + "sort" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/trie" - "golang.org/x/exp/slices" ) type kv struct { @@ -34,6 +34,12 @@ type kv struct { t bool } +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] } + type fuzzer struct { input io.Reader exhausted bool @@ -91,16 +97,14 @@ func (f *fuzzer) fuzz() int { if f.exhausted { return 0 // input too short } - var entries []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } if len(entries) <= 1 { return 0 } - slices.SortFunc(entries, func(a, b *kv) bool { - return bytes.Compare(a.k, b.k) < 0 - }) + sort.Sort(entries) var ok = 0 for { diff --git a/tests/fuzzers/stacktrie/trie_fuzzer.go b/tests/fuzzers/stacktrie/trie_fuzzer.go index 77e602f807..0099e9e169 100644 --- a/tests/fuzzers/stacktrie/trie_fuzzer.go +++ b/tests/fuzzers/stacktrie/trie_fuzzer.go @@ -23,6 +23,7 @@ import ( "fmt" "hash" "io" + "sort" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -32,7 +33,6 @@ import ( "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie/trienode" "golang.org/x/crypto/sha3" - "golang.org/x/exp/slices" ) type fuzzer struct { @@ -104,6 +104,19 @@ func (b *spongeBatch) Replay(w ethdb.KeyValueWriter) error { return nil } type kv struct { k, v []byte } +type kvs []kv + +func (k kvs) Len() int { + return len(k) +} + +func (k kvs) Less(i, j int) bool { + return bytes.Compare(k[i].k, k[j].k) < 0 +} + +func (k kvs) Swap(i, j int) { + k[j], k[i] = k[i], k[j] +} // Fuzz is the fuzzing entry-point. // The function must return @@ -143,7 +156,7 @@ func (f *fuzzer) fuzz() int { trieB = trie.NewStackTrie(func(owner common.Hash, path []byte, hash common.Hash, blob []byte) { rawdb.WriteTrieNode(spongeB, owner, path, hash, blob, dbB.Scheme()) }) - vals []kv + vals kvs useful bool maxElements = 10000 // operate on unique keys only @@ -179,9 +192,7 @@ func (f *fuzzer) fuzz() int { dbA.Commit(rootA, false) // Stacktrie requires sorted insertion - slices.SortFunc(vals, func(a, b kv) bool { - return bytes.Compare(a.k, b.k) < 0 - }) + sort.Sort(vals) for _, kv := range vals { if f.debugging { fmt.Printf("{\"%#x\" , \"%#x\"} // stacktrie.Update\n", kv.k, kv.v) diff --git a/trie/iterator_test.go b/trie/iterator_test.go index ccf5ea0258..8003858e5b 100644 --- a/trie/iterator_test.go +++ b/trie/iterator_test.go @@ -84,10 +84,6 @@ type kv struct { t bool } -func (k *kv) less(other *kv) bool { - return bytes.Compare(k.k, other.k) < 0 -} - func TestIteratorLargeData(t *testing.T) { trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) vals := make(map[string]*kv) diff --git a/trie/proof_test.go b/trie/proof_test.go index 015df39751..69e3f8e9ce 100644 --- a/trie/proof_test.go +++ b/trie/proof_test.go @@ -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,15 +165,21 @@ 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 []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) for i := 0; i < 500; i++ { start := mrand.Intn(len(entries)) end := mrand.Intn(len(entries)-start) + start + 1 @@ -202,11 +208,11 @@ func TestRangeProof(t *testing.T) { // The test cases are generated randomly. func TestRangeProofWithNonExistentProof(t *testing.T) { trie, vals := randomTrie(4096) - var entries []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) for i := 0; i < 500; i++ { start := mrand.Intn(len(entries)) end := mrand.Intn(len(entries)-start) + start + 1 @@ -274,11 +280,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 []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) // Case 1 start, end := 100, 200 @@ -331,11 +337,11 @@ func TestRangeProofWithInvalidNonExistentProof(t *testing.T) { // non-existent one. func TestOneElementRangeProof(t *testing.T) { trie, vals := randomTrie(4096) - var entries []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) // One element with existent edge proof, both edge proofs // point to the SAME key. @@ -418,11 +424,11 @@ func TestOneElementRangeProof(t *testing.T) { // The edge proofs can be nil. func TestAllElementsProof(t *testing.T) { trie, vals := randomTrie(4096) - var entries []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) var k [][]byte var v [][]byte @@ -468,13 +474,13 @@ func TestAllElementsProof(t *testing.T) { func TestSingleSideRangeProof(t *testing.T) { for i := 0; i < 64; i++ { trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) - var entries []*kv + var entries entrySlice for i := 0; i < 4096; i++ { value := &kv{randBytes(32), randBytes(20), false} trie.MustUpdate(value.k, value.v) entries = append(entries, value) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) var cases = []int{0, 1, 50, 100, 1000, 2000, len(entries) - 1} for _, pos := range cases { @@ -503,13 +509,13 @@ func TestSingleSideRangeProof(t *testing.T) { func TestReverseSingleSideRangeProof(t *testing.T) { for i := 0; i < 64; i++ { trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) - var entries []*kv + var entries entrySlice for i := 0; i < 4096; i++ { value := &kv{randBytes(32), randBytes(20), false} trie.MustUpdate(value.k, value.v) entries = append(entries, value) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) var cases = []int{0, 1, 50, 100, 1000, 2000, len(entries) - 1} for _, pos := range cases { @@ -539,11 +545,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 []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) for i := 0; i < 500; i++ { start := mrand.Intn(len(entries)) @@ -642,11 +648,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 []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) pos := 1000 first := decreaseKey(common.CopyBytes(entries[pos].k)) @@ -684,13 +690,13 @@ func TestSameSideProofs(t *testing.T) { func TestHasRightElement(t *testing.T) { trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) - var entries []*kv + var entries entrySlice for i := 0; i < 4096; i++ { value := &kv{randBytes(32), randBytes(20), false} trie.MustUpdate(value.k, value.v) entries = append(entries, value) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) var cases = []struct { start int @@ -758,11 +764,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 []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) var cases = []struct { pos int @@ -793,11 +799,11 @@ func TestEmptyRangeProof(t *testing.T) { func TestBloatedProof(t *testing.T) { // Use a small trie trie, kvs := nonRandomTrie(100) - var entries []*kv + var entries entrySlice for _, kv := range kvs { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) var keys [][]byte var vals [][]byte @@ -827,11 +833,11 @@ func TestBloatedProof(t *testing.T) { // noop technically, but practically should be rejected. func TestEmptyValueRangeProof(t *testing.T) { trie, values := randomTrie(512) - var entries []*kv + var entries entrySlice for _, kv := range values { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) // Create a new entry with a slightly modified key mid := len(entries) / 2 @@ -871,11 +877,11 @@ func TestEmptyValueRangeProof(t *testing.T) { // practically should be rejected. func TestAllElementsEmptyValueRangeProof(t *testing.T) { trie, values := randomTrie(512) - var entries []*kv + var entries entrySlice for _, kv := range values { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) // Create a new entry with a slightly modified key mid := len(entries) / 2 @@ -977,11 +983,11 @@ func BenchmarkVerifyRangeProof5000(b *testing.B) { benchmarkVerifyRangeProof(b, func benchmarkVerifyRangeProof(b *testing.B, size int) { trie, vals := randomTrie(8192) - var entries []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) start := 2 end := start + size @@ -1014,11 +1020,11 @@ func BenchmarkVerifyRangeNoProof1000(b *testing.B) { benchmarkVerifyRangeNoProof func benchmarkVerifyRangeNoProof(b *testing.B, size int) { trie, vals := randomTrie(size) - var entries []*kv + var entries entrySlice for _, kv := range vals { entries = append(entries, kv) } - slices.SortFunc(entries, (*kv).less) + sort.Sort(entries) var keys [][]byte var values [][]byte diff --git a/trie/trienode/node.go b/trie/trienode/node.go index b233f517f0..8152eab6c0 100644 --- a/trie/trienode/node.go +++ b/trie/trienode/node.go @@ -18,10 +18,10 @@ package trienode import ( "fmt" + "sort" "strings" "github.com/ethereum/go-ethereum/common" - "golang.org/x/exp/slices" ) // Node is a wrapper which contains the encoded blob of the trie node and its @@ -100,14 +100,12 @@ func NewNodeSet(owner common.Hash) *NodeSet { // ForEachWithOrder iterates the nodes with the order from bottom to top, // right to left, nodes with the longest path will be iterated first. func (set *NodeSet) ForEachWithOrder(callback func(path string, n *Node)) { - var paths []string + var paths sort.StringSlice for path := range set.Nodes { paths = append(paths, path) } // Bottom-up, longest path first - slices.SortFunc(paths, func(a, b string) bool { - return a > b // Sort in reverse order - }) + sort.Sort(sort.Reverse(paths)) for _, path := range paths { callback(path, set.Nodes[path].Unwrap()) }