eth/gasprice: use slices package for sorting (#27490 #27909 #29314)

This commit is contained in:
Daniel Liu 2024-11-13 09:30:55 +08:00
parent 4dbed3582f
commit d3eaeb9381
3 changed files with 49 additions and 58 deletions

View file

@ -17,6 +17,7 @@
package common package common
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"math/big" "math/big"
@ -77,23 +78,44 @@ type Vote struct {
Voter Address Voter Address
} }
// BytesToHash sets b to hash.
// If b is larger than len(h), b will be cropped from the left.
func BytesToHash(b []byte) Hash { func BytesToHash(b []byte) Hash {
var h Hash var h Hash
h.SetBytes(b) h.SetBytes(b)
return h return h
} }
func StringToHash(s string) Hash { return BytesToHash([]byte(s)) } func StringToHash(s string) Hash { return BytesToHash([]byte(s)) }
func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
// BigToHash sets byte representation of b to hash.
// If b is larger than len(h), b will be cropped from the left.
func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
func Uint64ToHash(b uint64) Hash { return BytesToHash(new(big.Int).SetUint64(b).Bytes()) } func Uint64ToHash(b uint64) Hash { return BytesToHash(new(big.Int).SetUint64(b).Bytes()) }
func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
// HexToHash sets byte representation of s to hash.
// If b is larger than len(h), b will be cropped from the left.
func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
// Cmp compares two hashes.
func (h Hash) Cmp(other Hash) int {
return bytes.Compare(h[:], other[:])
}
// IsZero returns if a Hash is empty // IsZero returns if a Hash is empty
func (h Hash) IsZero() bool { return h == Hash{} } func (h Hash) IsZero() bool { return h == Hash{} }
// Get the string representation of the underlying hash // Get the string representation of the underlying hash
func (h Hash) Str() string { return string(h[:]) } func (h Hash) Str() string { return string(h[:]) }
// Bytes gets the byte representation of the underlying hash.
func (h Hash) Bytes() []byte { return h[:] } func (h Hash) Bytes() []byte { return h[:] }
// Big converts a hash to a big integer.
func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) }
// Hex converts a hash to a hex string.
func (h Hash) Hex() string { return hexutil.Encode(h[:]) } func (h Hash) Hex() string { return hexutil.Encode(h[:]) }
// TerminalString implements log.TerminalStringer, formatting a string for console // TerminalString implements log.TerminalStringer, formatting a string for console
@ -129,7 +151,8 @@ func (h Hash) MarshalText() ([]byte, error) {
return hexutil.Bytes(h[:]).MarshalText() return hexutil.Bytes(h[:]).MarshalText()
} }
// Sets the hash to the value of b. If b is larger than len(h), 'b' will be cropped (from the left). // SetBytes sets the hash to the value of b.
// If b is larger than len(h), b will be cropped from the left.
func (h *Hash) SetBytes(b []byte) { func (h *Hash) SetBytes(b []byte) {
if len(b) > len(h) { if len(b) > len(h) {
b = b[len(b)-HashLength:] b = b[len(b)-HashLength:]

View file

@ -23,7 +23,7 @@ import (
"fmt" "fmt"
"math" "math"
"math/big" "math/big"
"sort" "slices"
"sync/atomic" "sync/atomic"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
@ -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) int {
return a.reward.Cmp(b.reward)
})
var txIndex int var txIndex int
sumGasUsed := sorter[0].gasUsed sumGasUsed := sorter[0].gasUsed

View file

@ -19,7 +19,7 @@ package gasprice
import ( import (
"context" "context"
"math/big" "math/big"
"sort" "slices"
"sync" "sync"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
@ -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) int { return a.Cmp(b) })
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 {
@ -236,30 +236,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
@ -276,14 +252,21 @@ func (oracle *Oracle) getBlockValues(ctx context.Context, blockNum uint64, limit
signer := types.MakeSigner(oracle.backend.ChainConfig(), block.Number()) signer := types.MakeSigner(oracle.backend.ChainConfig(), block.Number())
// 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) int {
// 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)
})
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
} }
@ -300,9 +283,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] }