eth: use slices package for sorting (#27490)
Also adds Hash.Less method for sorting purposes. --------- Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
parent
9a167c45d1
commit
b1ef0bfe03
|
@ -65,6 +65,11 @@ func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
|
||||||
// If b is larger than len(h), b will be cropped from the left.
|
// If b is larger than len(h), b will be cropped from the left.
|
||||||
func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
|
func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
|
||||||
|
|
||||||
|
// Less compares two hashes.
|
||||||
|
func (h Hash) Less(other Hash) bool {
|
||||||
|
return bytes.Compare(h[:], other[:]) < 0
|
||||||
|
}
|
||||||
|
|
||||||
// Bytes gets the byte representation of the underlying hash.
|
// Bytes gets the byte representation of the underlying hash.
|
||||||
func (h Hash) Bytes() []byte { return h[:] }
|
func (h Hash) Bytes() []byte { return h[:] }
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
@ -31,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var dumper = spew.ConfigState{Indent: " "}
|
var dumper = spew.ConfigState{Indent: " "}
|
||||||
|
@ -58,12 +58,6 @@ func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, st
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
type resultHash []common.Hash
|
|
||||||
|
|
||||||
func (h resultHash) Len() int { return len(h) }
|
|
||||||
func (h resultHash) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
|
||||||
func (h resultHash) Less(i, j int) bool { return bytes.Compare(h[i].Bytes(), h[j].Bytes()) < 0 }
|
|
||||||
|
|
||||||
func TestAccountRange(t *testing.T) {
|
func TestAccountRange(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -97,7 +91,7 @@ func TestAccountRange(t *testing.T) {
|
||||||
firstResult := accountRangeTest(t, &trie, state, common.Hash{}, AccountRangeMaxResults, AccountRangeMaxResults)
|
firstResult := accountRangeTest(t, &trie, state, common.Hash{}, AccountRangeMaxResults, AccountRangeMaxResults)
|
||||||
secondResult := accountRangeTest(t, &trie, state, common.BytesToHash(firstResult.Next), AccountRangeMaxResults, AccountRangeMaxResults)
|
secondResult := accountRangeTest(t, &trie, state, common.BytesToHash(firstResult.Next), AccountRangeMaxResults, AccountRangeMaxResults)
|
||||||
|
|
||||||
hList := make(resultHash, 0)
|
hList := make([]common.Hash, 0)
|
||||||
for addr1 := range firstResult.Accounts {
|
for addr1 := range firstResult.Accounts {
|
||||||
// If address is empty, then it makes no sense to compare
|
// If address is empty, then it makes no sense to compare
|
||||||
// them as they might be two different accounts.
|
// them as they might be two different accounts.
|
||||||
|
@ -111,7 +105,7 @@ func TestAccountRange(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Test to see if it's possible to recover from the middle of the previous
|
// Test to see if it's possible to recover from the middle of the previous
|
||||||
// set and get an even split between the first and second sets.
|
// set and get an even split between the first and second sets.
|
||||||
sort.Sort(hList)
|
slices.SortFunc(hList, common.Hash.Less)
|
||||||
middleH := hList[AccountRangeMaxResults/2]
|
middleH := hList[AccountRangeMaxResults/2]
|
||||||
middleResult := accountRangeTest(t, &trie, state, middleH, AccountRangeMaxResults, AccountRangeMaxResults)
|
middleResult := accountRangeTest(t, &trie, state, middleH, AccountRangeMaxResults, AccountRangeMaxResults)
|
||||||
missing, infirst, insecond := 0, 0, 0
|
missing, infirst, insecond := 0, 0, 0
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
@ -31,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -69,20 +69,9 @@ type processedFees struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// txGasAndReward is sorted in ascending order based on reward
|
// txGasAndReward is sorted in ascending order based on reward
|
||||||
type (
|
type txGasAndReward struct {
|
||||||
txGasAndReward struct {
|
gasUsed uint64
|
||||||
gasUsed uint64
|
reward *big.Int
|
||||||
reward *big.Int
|
|
||||||
}
|
|
||||||
sortGasAndReward []txGasAndReward
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s sortGasAndReward) Len() int { return len(s) }
|
|
||||||
func (s sortGasAndReward) Swap(i, j int) {
|
|
||||||
s[i], s[j] = s[j], s[i]
|
|
||||||
}
|
|
||||||
func (s sortGasAndReward) Less(i, j int) bool {
|
|
||||||
return s[i].reward.Cmp(s[j].reward) < 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// processBlock takes a blockFees structure with the blockNumber, the header and optionally
|
// processBlock takes a blockFees structure with the blockNumber, the header and optionally
|
||||||
|
@ -117,12 +106,14 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sorter := make(sortGasAndReward, len(bf.block.Transactions()))
|
sorter := make([]txGasAndReward, len(bf.block.Transactions()))
|
||||||
for i, tx := range bf.block.Transactions() {
|
for i, tx := range bf.block.Transactions() {
|
||||||
reward, _ := tx.EffectiveGasTip(bf.block.BaseFee())
|
reward, _ := tx.EffectiveGasTip(bf.block.BaseFee())
|
||||||
sorter[i] = txGasAndReward{gasUsed: bf.receipts[i].GasUsed, reward: reward}
|
sorter[i] = txGasAndReward{gasUsed: bf.receipts[i].GasUsed, reward: reward}
|
||||||
}
|
}
|
||||||
sort.Stable(sorter)
|
slices.SortStableFunc(sorter, func(a, b txGasAndReward) bool {
|
||||||
|
return a.reward.Cmp(b.reward) < 0
|
||||||
|
})
|
||||||
|
|
||||||
var txIndex int
|
var txIndex int
|
||||||
sumGasUsed := sorter[0].gasUsed
|
sumGasUsed := sorter[0].gasUsed
|
||||||
|
|
|
@ -19,7 +19,6 @@ package gasprice
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
@ -30,6 +29,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
const sampleNumber = 3 // Number of transactions sampled in a block
|
const sampleNumber = 3 // Number of transactions sampled in a block
|
||||||
|
@ -208,7 +208,7 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) {
|
||||||
}
|
}
|
||||||
price := lastPrice
|
price := lastPrice
|
||||||
if len(results) > 0 {
|
if len(results) > 0 {
|
||||||
sort.Sort(bigIntArray(results))
|
slices.SortFunc(results, func(a, b *big.Int) bool { return a.Cmp(b) < 0 })
|
||||||
price = results[(len(results)-1)*oracle.percentile/100]
|
price = results[(len(results)-1)*oracle.percentile/100]
|
||||||
}
|
}
|
||||||
if price.Cmp(oracle.maxPrice) > 0 {
|
if price.Cmp(oracle.maxPrice) > 0 {
|
||||||
|
@ -227,30 +227,6 @@ type results struct {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
type txSorter struct {
|
|
||||||
txs []*types.Transaction
|
|
||||||
baseFee *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSorter(txs []*types.Transaction, baseFee *big.Int) *txSorter {
|
|
||||||
return &txSorter{
|
|
||||||
txs: txs,
|
|
||||||
baseFee: baseFee,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *txSorter) Len() int { return len(s.txs) }
|
|
||||||
func (s *txSorter) Swap(i, j int) {
|
|
||||||
s.txs[i], s.txs[j] = s.txs[j], s.txs[i]
|
|
||||||
}
|
|
||||||
func (s *txSorter) Less(i, j int) bool {
|
|
||||||
// It's okay to discard the error because a tx would never be
|
|
||||||
// accepted into a block with an invalid effective tip.
|
|
||||||
tip1, _ := s.txs[i].EffectiveGasTip(s.baseFee)
|
|
||||||
tip2, _ := s.txs[j].EffectiveGasTip(s.baseFee)
|
|
||||||
return tip1.Cmp(tip2) < 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// getBlockValues calculates the lowest transaction gas price in a given block
|
// getBlockValues calculates the lowest transaction gas price in a given block
|
||||||
// and sends it to the result channel. If the block is empty or all transactions
|
// and sends it to the result channel. If the block is empty or all transactions
|
||||||
// are sent by the miner itself(it doesn't make any sense to include this kind of
|
// are sent by the miner itself(it doesn't make any sense to include this kind of
|
||||||
|
@ -267,14 +243,21 @@ func (oracle *Oracle) getBlockValues(ctx context.Context, blockNum uint64, limit
|
||||||
signer := types.MakeSigner(oracle.backend.ChainConfig(), block.Number(), block.Time())
|
signer := types.MakeSigner(oracle.backend.ChainConfig(), block.Number(), block.Time())
|
||||||
|
|
||||||
// Sort the transaction by effective tip in ascending sort.
|
// Sort the transaction by effective tip in ascending sort.
|
||||||
txs := make([]*types.Transaction, len(block.Transactions()))
|
txs := block.Transactions()
|
||||||
copy(txs, block.Transactions())
|
sortedTxs := make([]*types.Transaction, len(txs))
|
||||||
sorter := newSorter(txs, block.BaseFee())
|
copy(sortedTxs, txs)
|
||||||
sort.Sort(sorter)
|
baseFee := block.BaseFee()
|
||||||
|
slices.SortFunc(sortedTxs, func(a, b *types.Transaction) bool {
|
||||||
|
// It's okay to discard the error because a tx would never be
|
||||||
|
// accepted into a block with an invalid effective tip.
|
||||||
|
tip1, _ := a.EffectiveGasTip(baseFee)
|
||||||
|
tip2, _ := b.EffectiveGasTip(baseFee)
|
||||||
|
return tip1.Cmp(tip2) < 0
|
||||||
|
})
|
||||||
|
|
||||||
var prices []*big.Int
|
var prices []*big.Int
|
||||||
for _, tx := range sorter.txs {
|
for _, tx := range sortedTxs {
|
||||||
tip, _ := tx.EffectiveGasTip(block.BaseFee())
|
tip, _ := tx.EffectiveGasTip(baseFee)
|
||||||
if ignoreUnder != nil && tip.Cmp(ignoreUnder) == -1 {
|
if ignoreUnder != nil && tip.Cmp(ignoreUnder) == -1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -291,9 +274,3 @@ func (oracle *Oracle) getBlockValues(ctx context.Context, blockNum uint64, limit
|
||||||
case <-quit:
|
case <-quit:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type bigIntArray []*big.Int
|
|
||||||
|
|
||||||
func (s bigIntArray) Len() int { return len(s) }
|
|
||||||
func (s bigIntArray) Less(i, j int) bool { return s[i].Cmp(s[j]) < 0 }
|
|
||||||
func (s bigIntArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -38,6 +37,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHashing(t *testing.T) {
|
func TestHashing(t *testing.T) {
|
||||||
|
@ -127,9 +127,9 @@ type testPeer struct {
|
||||||
remote *Syncer
|
remote *Syncer
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
accountTrie *trie.Trie
|
accountTrie *trie.Trie
|
||||||
accountValues entrySlice
|
accountValues []*kv
|
||||||
storageTries map[common.Hash]*trie.Trie
|
storageTries map[common.Hash]*trie.Trie
|
||||||
storageValues map[common.Hash]entrySlice
|
storageValues map[common.Hash][]*kv
|
||||||
|
|
||||||
accountRequestHandler accountHandlerFunc
|
accountRequestHandler accountHandlerFunc
|
||||||
storageRequestHandler storageHandlerFunc
|
storageRequestHandler storageHandlerFunc
|
||||||
|
@ -1321,12 +1321,9 @@ type kv struct {
|
||||||
k, v []byte
|
k, v []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some helpers for sorting
|
func (k *kv) less(other *kv) bool {
|
||||||
type entrySlice []*kv
|
return bytes.Compare(k.k, other.k) < 0
|
||||||
|
}
|
||||||
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] }
|
|
||||||
|
|
||||||
func key32(i uint64) []byte {
|
func key32(i uint64) []byte {
|
||||||
key := make([]byte, 32)
|
key := make([]byte, 32)
|
||||||
|
@ -1367,11 +1364,11 @@ func getCodeByHash(hash common.Hash) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeAccountTrieNoStorage spits out a trie, along with the leafs
|
// makeAccountTrieNoStorage spits out a trie, along with the leafs
|
||||||
func makeAccountTrieNoStorage(n int) (string, *trie.Trie, entrySlice) {
|
func makeAccountTrieNoStorage(n int) (string, *trie.Trie, []*kv) {
|
||||||
var (
|
var (
|
||||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||||
accTrie = trie.NewEmpty(db)
|
accTrie = trie.NewEmpty(db)
|
||||||
entries entrySlice
|
entries []*kv
|
||||||
)
|
)
|
||||||
for i := uint64(1); i <= uint64(n); i++ {
|
for i := uint64(1); i <= uint64(n); i++ {
|
||||||
value, _ := rlp.EncodeToBytes(&types.StateAccount{
|
value, _ := rlp.EncodeToBytes(&types.StateAccount{
|
||||||
|
@ -1385,7 +1382,7 @@ func makeAccountTrieNoStorage(n int) (string, *trie.Trie, entrySlice) {
|
||||||
accTrie.MustUpdate(elem.k, elem.v)
|
accTrie.MustUpdate(elem.k, elem.v)
|
||||||
entries = append(entries, elem)
|
entries = append(entries, elem)
|
||||||
}
|
}
|
||||||
sort.Sort(entries)
|
slices.SortFunc(entries, (*kv).less)
|
||||||
|
|
||||||
// Commit the state changes into db and re-create the trie
|
// Commit the state changes into db and re-create the trie
|
||||||
// for accessing later.
|
// for accessing later.
|
||||||
|
@ -1399,9 +1396,9 @@ func makeAccountTrieNoStorage(n int) (string, *trie.Trie, entrySlice) {
|
||||||
// makeBoundaryAccountTrie constructs an account trie. Instead of filling
|
// makeBoundaryAccountTrie constructs an account trie. Instead of filling
|
||||||
// accounts normally, this function will fill a few accounts which have
|
// accounts normally, this function will fill a few accounts which have
|
||||||
// boundary hash.
|
// boundary hash.
|
||||||
func makeBoundaryAccountTrie(n int) (string, *trie.Trie, entrySlice) {
|
func makeBoundaryAccountTrie(n int) (string, *trie.Trie, []*kv) {
|
||||||
var (
|
var (
|
||||||
entries entrySlice
|
entries []*kv
|
||||||
boundaries []common.Hash
|
boundaries []common.Hash
|
||||||
|
|
||||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||||
|
@ -1447,7 +1444,7 @@ func makeBoundaryAccountTrie(n int) (string, *trie.Trie, entrySlice) {
|
||||||
accTrie.MustUpdate(elem.k, elem.v)
|
accTrie.MustUpdate(elem.k, elem.v)
|
||||||
entries = append(entries, elem)
|
entries = append(entries, elem)
|
||||||
}
|
}
|
||||||
sort.Sort(entries)
|
slices.SortFunc(entries, (*kv).less)
|
||||||
|
|
||||||
// Commit the state changes into db and re-create the trie
|
// Commit the state changes into db and re-create the trie
|
||||||
// for accessing later.
|
// for accessing later.
|
||||||
|
@ -1460,14 +1457,14 @@ func makeBoundaryAccountTrie(n int) (string, *trie.Trie, entrySlice) {
|
||||||
|
|
||||||
// makeAccountTrieWithStorageWithUniqueStorage creates an account trie where each accounts
|
// makeAccountTrieWithStorageWithUniqueStorage creates an account trie where each accounts
|
||||||
// has a unique storage set.
|
// has a unique storage set.
|
||||||
func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool) (string, *trie.Trie, entrySlice, map[common.Hash]*trie.Trie, map[common.Hash]entrySlice) {
|
func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
|
||||||
var (
|
var (
|
||||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||||
accTrie = trie.NewEmpty(db)
|
accTrie = trie.NewEmpty(db)
|
||||||
entries entrySlice
|
entries []*kv
|
||||||
storageRoots = make(map[common.Hash]common.Hash)
|
storageRoots = make(map[common.Hash]common.Hash)
|
||||||
storageTries = make(map[common.Hash]*trie.Trie)
|
storageTries = make(map[common.Hash]*trie.Trie)
|
||||||
storageEntries = make(map[common.Hash]entrySlice)
|
storageEntries = make(map[common.Hash][]*kv)
|
||||||
nodes = trienode.NewMergedNodeSet()
|
nodes = trienode.NewMergedNodeSet()
|
||||||
)
|
)
|
||||||
// Create n accounts in the trie
|
// Create n accounts in the trie
|
||||||
|
@ -1494,7 +1491,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool)
|
||||||
storageRoots[common.BytesToHash(key)] = stRoot
|
storageRoots[common.BytesToHash(key)] = stRoot
|
||||||
storageEntries[common.BytesToHash(key)] = stEntries
|
storageEntries[common.BytesToHash(key)] = stEntries
|
||||||
}
|
}
|
||||||
sort.Sort(entries)
|
slices.SortFunc(entries, (*kv).less)
|
||||||
|
|
||||||
// Commit account trie
|
// Commit account trie
|
||||||
root, set := accTrie.Commit(true)
|
root, set := accTrie.Commit(true)
|
||||||
|
@ -1515,14 +1512,14 @@ func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeAccountTrieWithStorage spits out a trie, along with the leafs
|
// makeAccountTrieWithStorage spits out a trie, along with the leafs
|
||||||
func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (string, *trie.Trie, entrySlice, map[common.Hash]*trie.Trie, map[common.Hash]entrySlice) {
|
func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
|
||||||
var (
|
var (
|
||||||
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
db = trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||||
accTrie = trie.NewEmpty(db)
|
accTrie = trie.NewEmpty(db)
|
||||||
entries entrySlice
|
entries []*kv
|
||||||
storageRoots = make(map[common.Hash]common.Hash)
|
storageRoots = make(map[common.Hash]common.Hash)
|
||||||
storageTries = make(map[common.Hash]*trie.Trie)
|
storageTries = make(map[common.Hash]*trie.Trie)
|
||||||
storageEntries = make(map[common.Hash]entrySlice)
|
storageEntries = make(map[common.Hash][]*kv)
|
||||||
nodes = trienode.NewMergedNodeSet()
|
nodes = trienode.NewMergedNodeSet()
|
||||||
)
|
)
|
||||||
// Create n accounts in the trie
|
// Create n accounts in the trie
|
||||||
|
@ -1536,7 +1533,7 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin
|
||||||
var (
|
var (
|
||||||
stRoot common.Hash
|
stRoot common.Hash
|
||||||
stNodes *trienode.NodeSet
|
stNodes *trienode.NodeSet
|
||||||
stEntries entrySlice
|
stEntries []*kv
|
||||||
)
|
)
|
||||||
if boundary {
|
if boundary {
|
||||||
stRoot, stNodes, stEntries = makeBoundaryStorageTrie(common.BytesToHash(key), slots, db)
|
stRoot, stNodes, stEntries = makeBoundaryStorageTrie(common.BytesToHash(key), slots, db)
|
||||||
|
@ -1559,7 +1556,7 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin
|
||||||
storageRoots[common.BytesToHash(key)] = stRoot
|
storageRoots[common.BytesToHash(key)] = stRoot
|
||||||
storageEntries[common.BytesToHash(key)] = stEntries
|
storageEntries[common.BytesToHash(key)] = stEntries
|
||||||
}
|
}
|
||||||
sort.Sort(entries)
|
slices.SortFunc(entries, (*kv).less)
|
||||||
|
|
||||||
// Commit account trie
|
// Commit account trie
|
||||||
root, set := accTrie.Commit(true)
|
root, set := accTrie.Commit(true)
|
||||||
|
@ -1588,9 +1585,9 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin
|
||||||
// makeStorageTrieWithSeed fills a storage trie with n items, returning the
|
// makeStorageTrieWithSeed fills a storage trie with n items, returning the
|
||||||
// not-yet-committed trie and the sorted entries. The seeds can be used to ensure
|
// not-yet-committed trie and the sorted entries. The seeds can be used to ensure
|
||||||
// that tries are unique.
|
// that tries are unique.
|
||||||
func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *trie.Database) (common.Hash, *trienode.NodeSet, entrySlice) {
|
func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *trie.Database) (common.Hash, *trienode.NodeSet, []*kv) {
|
||||||
trie, _ := trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db)
|
trie, _ := trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db)
|
||||||
var entries entrySlice
|
var entries []*kv
|
||||||
for i := uint64(1); i <= n; i++ {
|
for i := uint64(1); i <= n; i++ {
|
||||||
// store 'x' at slot 'x'
|
// store 'x' at slot 'x'
|
||||||
slotValue := key32(i + seed)
|
slotValue := key32(i + seed)
|
||||||
|
@ -1603,7 +1600,7 @@ func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *trie.Databas
|
||||||
trie.MustUpdate(elem.k, elem.v)
|
trie.MustUpdate(elem.k, elem.v)
|
||||||
entries = append(entries, elem)
|
entries = append(entries, elem)
|
||||||
}
|
}
|
||||||
sort.Sort(entries)
|
slices.SortFunc(entries, (*kv).less)
|
||||||
root, nodes := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
return root, nodes, entries
|
return root, nodes, entries
|
||||||
}
|
}
|
||||||
|
@ -1611,9 +1608,9 @@ func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *trie.Databas
|
||||||
// makeBoundaryStorageTrie constructs a storage trie. Instead of filling
|
// makeBoundaryStorageTrie constructs a storage trie. Instead of filling
|
||||||
// storage slots normally, this function will fill a few slots which have
|
// storage slots normally, this function will fill a few slots which have
|
||||||
// boundary hash.
|
// boundary hash.
|
||||||
func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (common.Hash, *trienode.NodeSet, entrySlice) {
|
func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (common.Hash, *trienode.NodeSet, []*kv) {
|
||||||
var (
|
var (
|
||||||
entries entrySlice
|
entries []*kv
|
||||||
boundaries []common.Hash
|
boundaries []common.Hash
|
||||||
trie, _ = trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db)
|
trie, _ = trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db)
|
||||||
)
|
)
|
||||||
|
@ -1654,7 +1651,7 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (commo
|
||||||
trie.MustUpdate(elem.k, elem.v)
|
trie.MustUpdate(elem.k, elem.v)
|
||||||
entries = append(entries, elem)
|
entries = append(entries, elem)
|
||||||
}
|
}
|
||||||
sort.Sort(entries)
|
slices.SortFunc(entries, (*kv).less)
|
||||||
root, nodes := trie.Commit(false)
|
root, nodes := trie.Commit(false)
|
||||||
return root, nodes, entries
|
return root, nodes, entries
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package tracers
|
package tracers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -25,7 +24,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -45,6 +43,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -785,19 +784,13 @@ type Account struct {
|
||||||
addr common.Address
|
addr common.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
type Accounts []Account
|
func newAccounts(n int) (accounts []Account) {
|
||||||
|
|
||||||
func (a Accounts) Len() int { return len(a) }
|
|
||||||
func (a Accounts) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
||||||
func (a Accounts) Less(i, j int) bool { return bytes.Compare(a[i].addr.Bytes(), a[j].addr.Bytes()) < 0 }
|
|
||||||
|
|
||||||
func newAccounts(n int) (accounts Accounts) {
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
accounts = append(accounts, Account{key: key, addr: addr})
|
accounts = append(accounts, Account{key: key, addr: addr})
|
||||||
}
|
}
|
||||||
sort.Sort(accounts)
|
slices.SortFunc(accounts, func(a, b Account) bool { return a.addr.Less(b.addr) })
|
||||||
return accounts
|
return accounts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue