mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 18:30:45 +00:00
Switch LazyTransaction gas caps from *big.Int to *uint256.Int and convert once at pending retrieval time. In miner ordering, keep fee comparisons on uint256 and precompute TRC21 gas price in uint256 form to avoid repeated big-int conversions in heap comparisons. Also update affected tests and call sites in legacypool/worker/helper paths. Compatibility: LazyTransaction exported field types changed (GasFeeCap/GasTipCap).
This commit is contained in:
parent
b5eec529d0
commit
8850835f6b
7 changed files with 45 additions and 35 deletions
|
|
@ -618,8 +618,8 @@ func (pool *LegacyPool) Pending(minTip *uint256.Int, baseFee *uint256.Int) map[c
|
||||||
Hash: txs[i].Hash(),
|
Hash: txs[i].Hash(),
|
||||||
Tx: txs[i],
|
Tx: txs[i],
|
||||||
Time: txs[i].Time(),
|
Time: txs[i].Time(),
|
||||||
GasFeeCap: txs[i].GasFeeCap(),
|
GasFeeCap: uint256.MustFromBig(txs[i].GasFeeCap()),
|
||||||
GasTipCap: txs[i].GasTipCap(),
|
GasTipCap: uint256.MustFromBig(txs[i].GasTipCap()),
|
||||||
Gas: txs[i].Gas(),
|
Gas: txs[i].Gas(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ type LazyTransaction struct {
|
||||||
Hash common.Hash // Transaction hash to pull up if needed
|
Hash common.Hash // Transaction hash to pull up if needed
|
||||||
Tx *types.Transaction // Transaction if already resolved
|
Tx *types.Transaction // Transaction if already resolved
|
||||||
|
|
||||||
Time time.Time // Time when the transaction was first seen
|
Time time.Time // Time when the transaction was first seen
|
||||||
GasFeeCap *big.Int // Maximum fee per gas the transaction may consume
|
GasFeeCap *uint256.Int // Maximum fee per gas the transaction may consume
|
||||||
GasTipCap *big.Int // Maximum miner tip per gas the transaction can pay
|
GasTipCap *uint256.Int // Maximum miner tip per gas the transaction can pay
|
||||||
|
|
||||||
Gas uint64 // Amount of gas required by the transaction
|
Gas uint64 // Amount of gas required by the transaction
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,8 +166,8 @@ func (p *testTxPool) Pending(minTip *uint256.Int, baseFee *uint256.Int) map[comm
|
||||||
Hash: tx.Hash(),
|
Hash: tx.Hash(),
|
||||||
Tx: tx,
|
Tx: tx,
|
||||||
Time: tx.Time(),
|
Time: tx.Time(),
|
||||||
GasFeeCap: tx.GasFeeCap(),
|
GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
|
||||||
GasTipCap: tx.GasTipCap(),
|
GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,27 +23,30 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var trc21GasPriceUint = uint256.MustFromBig(common.TRC21GasPrice)
|
||||||
|
|
||||||
// txWithMinerFee wraps a transaction with its gas price or effective miner gasTipCap
|
// txWithMinerFee wraps a transaction with its gas price or effective miner gasTipCap
|
||||||
type txWithMinerFee struct {
|
type txWithMinerFee struct {
|
||||||
tx *txpool.LazyTransaction
|
tx *txpool.LazyTransaction
|
||||||
from common.Address
|
from common.Address
|
||||||
fees *big.Int
|
fees *uint256.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTxWithMinerFee creates a wrapped transaction, calculating the effective
|
// newTxWithMinerFee creates a wrapped transaction, calculating the effective
|
||||||
// miner gasTipCap if a base fee is provided.
|
// miner gasTipCap if a base fee is provided.
|
||||||
// Returns error in case of a negative effective miner gasTipCap.
|
// Returns error in case of a negative effective miner gasTipCap.
|
||||||
func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee *big.Int) (*txWithMinerFee, error) {
|
func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee *uint256.Int) (*txWithMinerFee, error) {
|
||||||
tip := new(big.Int).Set(tx.GasTipCap)
|
tip := new(uint256.Int).Set(tx.GasTipCap)
|
||||||
if baseFee != nil {
|
if baseFee != nil {
|
||||||
if tx.GasFeeCap.Cmp(baseFee) < 0 {
|
if tx.GasFeeCap.Cmp(baseFee) < 0 {
|
||||||
return nil, types.ErrGasFeeCapTooLow
|
return nil, types.ErrGasFeeCapTooLow
|
||||||
}
|
}
|
||||||
effectiveTip := new(big.Int).Sub(tx.GasFeeCap, baseFee)
|
tip = new(uint256.Int).Sub(tx.GasFeeCap, baseFee)
|
||||||
if tip.Cmp(effectiveTip) > 0 {
|
if tip.Gt(tx.GasTipCap) {
|
||||||
tip = effectiveTip
|
tip = tx.GasTipCap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &txWithMinerFee{
|
return &txWithMinerFee{
|
||||||
|
|
@ -68,14 +71,14 @@ func (s txByPriceAndTime) Less(i, j int) bool {
|
||||||
i_price := s.txs[i].fees
|
i_price := s.txs[i].fees
|
||||||
if tx := s.txs[i].tx.Resolve(); tx != nil && tx.To() != nil {
|
if tx := s.txs[i].tx.Resolve(); tx != nil && tx.To() != nil {
|
||||||
if _, ok := s.payersSwap[*tx.To()]; ok {
|
if _, ok := s.payersSwap[*tx.To()]; ok {
|
||||||
i_price = common.TRC21GasPrice
|
i_price = trc21GasPriceUint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
j_price := s.txs[j].fees
|
j_price := s.txs[j].fees
|
||||||
if tx := s.txs[j].tx.Resolve(); tx != nil && tx.To() != nil {
|
if tx := s.txs[j].tx.Resolve(); tx != nil && tx.To() != nil {
|
||||||
if _, ok := s.payersSwap[*tx.To()]; ok {
|
if _, ok := s.payersSwap[*tx.To()]; ok {
|
||||||
j_price = common.TRC21GasPrice
|
j_price = trc21GasPriceUint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +115,7 @@ type transactionsByPriceAndNonce struct {
|
||||||
txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions
|
txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions
|
||||||
heads txByPriceAndTime // Next transaction for each unique account (price heap)
|
heads txByPriceAndTime // Next transaction for each unique account (price heap)
|
||||||
signer types.Signer // Signer for the set of transactions
|
signer types.Signer // Signer for the set of transactions
|
||||||
baseFee *big.Int // Current base fee
|
baseFee *uint256.Int // Current base fee
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTransactionsByPriceAndNonce creates a transaction set that can retrieve
|
// newTransactionsByPriceAndNonce creates a transaction set that can retrieve
|
||||||
|
|
@ -121,6 +124,11 @@ type transactionsByPriceAndNonce struct {
|
||||||
// Note, the input map is reowned so the caller should not interact any more with
|
// Note, the input map is reowned so the caller should not interact any more with
|
||||||
// if after providing it to the constructor.
|
// if after providing it to the constructor.
|
||||||
func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, payersSwap map[common.Address]*big.Int, baseFee *big.Int) (*transactionsByPriceAndNonce, types.Transactions) {
|
func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, payersSwap map[common.Address]*big.Int, baseFee *big.Int) (*transactionsByPriceAndNonce, types.Transactions) {
|
||||||
|
// Convert the basefee from header format to uint256 format
|
||||||
|
var baseFeeUint *uint256.Int
|
||||||
|
if baseFee != nil {
|
||||||
|
baseFeeUint = uint256.MustFromBig(baseFee)
|
||||||
|
}
|
||||||
// Initialize a price and received time based heap with the head transactions
|
// Initialize a price and received time based heap with the head transactions
|
||||||
heads := txByPriceAndTime{
|
heads := txByPriceAndTime{
|
||||||
txs: make([]*txWithMinerFee, 0, len(txs)),
|
txs: make([]*txWithMinerFee, 0, len(txs)),
|
||||||
|
|
@ -137,7 +145,7 @@ func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(normalTxs) > 0 {
|
if len(normalTxs) > 0 {
|
||||||
wrapped, err := newTxWithMinerFee(normalTxs[0], from, baseFee)
|
wrapped, err := newTxWithMinerFee(normalTxs[0], from, baseFeeUint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
delete(txs, from)
|
delete(txs, from)
|
||||||
continue
|
continue
|
||||||
|
|
@ -157,7 +165,7 @@ func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address]
|
||||||
txs: txs,
|
txs: txs,
|
||||||
heads: heads,
|
heads: heads,
|
||||||
signer: signer,
|
signer: signer,
|
||||||
baseFee: baseFee,
|
baseFee: baseFeeUint,
|
||||||
}, specialTxs
|
}, specialTxs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
"github.com/XinFinOrg/XDPoSChain/core/txpool"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTransactionPriceNonceSortLegacy(t *testing.T) {
|
func TestTransactionPriceNonceSortLegacy(t *testing.T) {
|
||||||
|
|
@ -90,8 +91,8 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) {
|
||||||
Hash: tx.Hash(),
|
Hash: tx.Hash(),
|
||||||
Tx: tx,
|
Tx: tx,
|
||||||
Time: tx.Time(),
|
Time: tx.Time(),
|
||||||
GasFeeCap: tx.GasFeeCap(),
|
GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
|
||||||
GasTipCap: tx.GasTipCap(),
|
GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
expectedCount += count
|
expectedCount += count
|
||||||
|
|
@ -155,8 +156,8 @@ func TestTransactionTimeSort(t *testing.T) {
|
||||||
Hash: tx.Hash(),
|
Hash: tx.Hash(),
|
||||||
Tx: tx,
|
Tx: tx,
|
||||||
Time: tx.Time(),
|
Time: tx.Time(),
|
||||||
GasFeeCap: tx.GasFeeCap(),
|
GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
|
||||||
GasTipCap: tx.GasTipCap(),
|
GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Sort the transactions and cross check the nonce ordering
|
// Sort the transactions and cross check the nonce ordering
|
||||||
|
|
@ -193,11 +194,11 @@ func TestNewTransactionsByPriceAndNonce_SpecialSeparation(t *testing.T) {
|
||||||
|
|
||||||
genNormalTx := func(nonce uint64, key *ecdsa.PrivateKey) *txpool.LazyTransaction {
|
genNormalTx := func(nonce uint64, key *ecdsa.PrivateKey) *txpool.LazyTransaction {
|
||||||
tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0x1234567890123456789012345678901234567890"), big.NewInt(1), 21000, big.NewInt(1), nil), signer, key)
|
tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0x1234567890123456789012345678901234567890"), big.NewInt(1), 21000, big.NewInt(1), nil), signer, key)
|
||||||
return &txpool.LazyTransaction{Tx: tx, Hash: tx.Hash(), Time: tx.Time(), GasFeeCap: tx.GasFeeCap(), GasTipCap: tx.GasTipCap()}
|
return &txpool.LazyTransaction{Tx: tx, Hash: tx.Hash(), Time: tx.Time(), GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()), GasTipCap: uint256.MustFromBig(tx.GasTipCap())}
|
||||||
}
|
}
|
||||||
genSpecialTx := func(nonce uint64, key *ecdsa.PrivateKey) *txpool.LazyTransaction {
|
genSpecialTx := func(nonce uint64, key *ecdsa.PrivateKey) *txpool.LazyTransaction {
|
||||||
tx, _ := types.SignTx(types.NewTransaction(nonce, common.BlockSignersBinary, big.NewInt(1), 21000, big.NewInt(1), nil), signer, key)
|
tx, _ := types.SignTx(types.NewTransaction(nonce, common.BlockSignersBinary, big.NewInt(1), 21000, big.NewInt(1), nil), signer, key)
|
||||||
return &txpool.LazyTransaction{Tx: tx, Hash: tx.Hash(), Time: tx.Time(), GasFeeCap: tx.GasFeeCap(), GasTipCap: tx.GasTipCap()}
|
return &txpool.LazyTransaction{Tx: tx, Hash: tx.Hash(), Time: tx.Time(), GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()), GasTipCap: uint256.MustFromBig(tx.GasTipCap())}
|
||||||
}
|
}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ type worker struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
coinbase common.Address
|
coinbase common.Address
|
||||||
extra []byte
|
extra []byte
|
||||||
tip *big.Int // Minimum tip needed for non-local transaction to include them
|
tip *uint256.Int // Minimum tip needed for non-local transaction to include them
|
||||||
|
|
||||||
snapshotMu sync.RWMutex // The lock used to protect the block snapshot and state snapshot
|
snapshotMu sync.RWMutex // The lock used to protect the block snapshot and state snapshot
|
||||||
snapshotBlock *types.Block
|
snapshotBlock *types.Block
|
||||||
|
|
@ -176,7 +176,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
|
||||||
mux: mux,
|
mux: mux,
|
||||||
coinbase: config.Etherbase,
|
coinbase: config.Etherbase,
|
||||||
extra: config.ExtraData,
|
extra: config.ExtraData,
|
||||||
tip: config.GasPrice,
|
tip: uint256.MustFromBig(config.GasPrice),
|
||||||
txsCh: make(chan core.NewTxsEvent, txChanSize),
|
txsCh: make(chan core.NewTxsEvent, txChanSize),
|
||||||
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
|
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
|
||||||
chainSideCh: make(chan core.ChainSideEvent, chainSideChanSize),
|
chainSideCh: make(chan core.ChainSideEvent, chainSideChanSize),
|
||||||
|
|
@ -233,7 +233,7 @@ func (w *worker) setGasTip(tip *big.Int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the value to avoid external mutation through shared pointers.
|
// Copy the value to avoid external mutation through shared pointers.
|
||||||
w.tip = new(big.Int).Set(tip)
|
w.tip = uint256.MustFromBig(tip)
|
||||||
log.Info("Worker tip updated", "tip", w.tip)
|
log.Info("Worker tip updated", "tip", w.tip)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -404,8 +404,8 @@ func (w *worker) update() {
|
||||||
Hash: tx.Hash(),
|
Hash: tx.Hash(),
|
||||||
Tx: tx,
|
Tx: tx,
|
||||||
Time: tx.Time(),
|
Time: tx.Time(),
|
||||||
GasFeeCap: tx.GasFeeCap(),
|
GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
|
||||||
GasTipCap: tx.GasTipCap(),
|
GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
feeCapacity := w.current.state.GetTRC21FeeCapacityFromState()
|
feeCapacity := w.current.state.GetTRC21FeeCapacityFromState()
|
||||||
|
|
@ -866,7 +866,7 @@ func (w *worker) commitNewWork() {
|
||||||
if header.BaseFee != nil {
|
if header.BaseFee != nil {
|
||||||
baseFee = uint256.MustFromBig(header.BaseFee)
|
baseFee = uint256.MustFromBig(header.BaseFee)
|
||||||
}
|
}
|
||||||
pending := w.eth.TxPool().Pending(uint256.MustFromBig(w.tip), baseFee)
|
pending := w.eth.TxPool().Pending(w.tip, baseFee)
|
||||||
txs, specialTxs = newTransactionsByPriceAndNonce(w.current.signer, pending, feeCapacity, header.BaseFee)
|
txs, specialTxs = newTransactionsByPriceAndNonce(w.current.signer, pending, feeCapacity, header.BaseFee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/event"
|
"github.com/XinFinOrg/XDPoSChain/event"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newBlockingSubscription() event.Subscription {
|
func newBlockingSubscription() event.Subscription {
|
||||||
|
|
@ -132,8 +133,8 @@ func TestWorkerCheckPreCommitXDPoSMismatch(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWorkerSetGasTipValidation(t *testing.T) {
|
func TestWorkerSetGasTipValidation(t *testing.T) {
|
||||||
w := &worker{tip: big.NewInt(1)}
|
w := &worker{tip: uint256.NewInt(1)}
|
||||||
old := new(big.Int).Set(w.tip)
|
old := new(uint256.Int).Set(w.tip)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
@ -163,12 +164,12 @@ func TestWorkerSetGasTipCopiesValue(t *testing.T) {
|
||||||
if err := w.setGasTip(input); err != nil {
|
if err := w.setGasTip(input); err != nil {
|
||||||
t.Fatalf("setGasTip failed: %v", err)
|
t.Fatalf("setGasTip failed: %v", err)
|
||||||
}
|
}
|
||||||
if w.tip == input {
|
if w.tip == nil {
|
||||||
t.Fatal("worker tip shares pointer with input")
|
t.Fatal("worker tip was not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
input.Add(input, big.NewInt(1))
|
input.Add(input, big.NewInt(1))
|
||||||
if w.tip.Cmp(big.NewInt(2*params.GWei)) != 0 {
|
if w.tip.Cmp(uint256.NewInt(2*params.GWei)) != 0 {
|
||||||
t.Fatalf("worker tip mutated via input pointer: have %v", w.tip)
|
t.Fatalf("worker tip mutated via input pointer: have %v", w.tip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue