mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 22:56:43 +00:00
core/types: Add allocation-free EffectiveGasTipInto method
This commit is contained in:
parent
a7f24c26c0
commit
d1a6f5d81e
2 changed files with 125 additions and 11 deletions
|
|
@ -355,28 +355,37 @@ func (tx *Transaction) GasTipCapIntCmp(other *big.Int) int {
|
||||||
// Note: if the effective gasTipCap is negative, this method returns both error
|
// Note: if the effective gasTipCap is negative, this method returns both error
|
||||||
// the actual negative value, _and_ ErrGasFeeCapTooLow
|
// the actual negative value, _and_ ErrGasFeeCapTooLow
|
||||||
func (tx *Transaction) EffectiveGasTip(baseFee *big.Int) (*big.Int, error) {
|
func (tx *Transaction) EffectiveGasTip(baseFee *big.Int) (*big.Int, error) {
|
||||||
|
dst := new(big.Int)
|
||||||
|
err := tx.EffectiveGasTipInto(dst, baseFee)
|
||||||
|
return dst, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *Transaction) EffectiveGasTipInto(dst *big.Int, baseFee *big.Int) error {
|
||||||
if baseFee == nil {
|
if baseFee == nil {
|
||||||
return tx.GasTipCap(), nil
|
dst.Set(tx.inner.gasTipCap())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
gasFeeCap := tx.GasFeeCap()
|
gasFeeCap := tx.inner.gasFeeCap()
|
||||||
if gasFeeCap.Cmp(baseFee) < 0 {
|
if gasFeeCap.Cmp(baseFee) < 0 {
|
||||||
err = ErrGasFeeCapTooLow
|
err = ErrGasFeeCapTooLow
|
||||||
}
|
}
|
||||||
gasFeeCap = gasFeeCap.Sub(gasFeeCap, baseFee)
|
|
||||||
|
|
||||||
gasTipCap := tx.GasTipCap()
|
dst.Sub(gasFeeCap, baseFee)
|
||||||
if gasTipCap.Cmp(gasFeeCap) < 0 {
|
gasTipCap := tx.inner.gasTipCap()
|
||||||
return gasTipCap, err
|
if gasTipCap.Cmp(dst) < 0 {
|
||||||
|
dst.Set(gasTipCap)
|
||||||
}
|
}
|
||||||
return gasFeeCap, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// EffectiveGasTipValue is identical to EffectiveGasTip, but does not return an
|
// EffectiveGasTipValue is identical to EffectiveGasTip, but does not return an
|
||||||
// error in case the effective gasTipCap is negative
|
// error in case the effective gasTipCap is negative
|
||||||
func (tx *Transaction) EffectiveGasTipValue(baseFee *big.Int) *big.Int {
|
func (tx *Transaction) EffectiveGasTipValue(baseFee *big.Int) *big.Int {
|
||||||
effectiveTip, _ := tx.EffectiveGasTip(baseFee)
|
dst := new(big.Int)
|
||||||
return effectiveTip
|
tx.EffectiveGasTipInto(dst, baseFee)
|
||||||
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
// EffectiveGasTipCmp compares the effective gasTipCap of two transactions assuming the given base fee.
|
// EffectiveGasTipCmp compares the effective gasTipCap of two transactions assuming the given base fee.
|
||||||
|
|
@ -384,7 +393,11 @@ func (tx *Transaction) EffectiveGasTipCmp(other *Transaction, baseFee *big.Int)
|
||||||
if baseFee == nil {
|
if baseFee == nil {
|
||||||
return tx.GasTipCapCmp(other)
|
return tx.GasTipCapCmp(other)
|
||||||
}
|
}
|
||||||
return tx.EffectiveGasTipValue(baseFee).Cmp(other.EffectiveGasTipValue(baseFee))
|
txTip := new(big.Int)
|
||||||
|
otherTip := new(big.Int)
|
||||||
|
tx.EffectiveGasTipInto(txTip, baseFee)
|
||||||
|
other.EffectiveGasTipInto(otherTip, baseFee)
|
||||||
|
return txTip.Cmp(otherTip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EffectiveGasTipIntCmp compares the effective gasTipCap of a transaction to the given gasTipCap.
|
// EffectiveGasTipIntCmp compares the effective gasTipCap of a transaction to the given gasTipCap.
|
||||||
|
|
@ -392,7 +405,9 @@ func (tx *Transaction) EffectiveGasTipIntCmp(other *big.Int, baseFee *big.Int) i
|
||||||
if baseFee == nil {
|
if baseFee == nil {
|
||||||
return tx.GasTipCapIntCmp(other)
|
return tx.GasTipCapIntCmp(other)
|
||||||
}
|
}
|
||||||
return tx.EffectiveGasTipValue(baseFee).Cmp(other)
|
txTip := new(big.Int)
|
||||||
|
tx.EffectiveGasTipInto(txTip, baseFee)
|
||||||
|
return txTip.Cmp(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlobGas returns the blob gas limit of the transaction for blob transactions, 0 otherwise.
|
// BlobGas returns the blob gas limit of the transaction for blob transactions, 0 otherwise.
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -593,3 +594,101 @@ func BenchmarkHash(b *testing.B) {
|
||||||
signer.Hash(tx)
|
signer.Hash(tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkEffectiveGasTip(b *testing.B) {
|
||||||
|
signer := LatestSigner(params.TestChainConfig)
|
||||||
|
key, _ := crypto.GenerateKey()
|
||||||
|
txdata := &DynamicFeeTx{
|
||||||
|
ChainID: big.NewInt(1),
|
||||||
|
Nonce: 0,
|
||||||
|
GasTipCap: big.NewInt(2000000000),
|
||||||
|
GasFeeCap: big.NewInt(3000000000),
|
||||||
|
Gas: 21000,
|
||||||
|
To: &common.Address{},
|
||||||
|
Value: big.NewInt(0),
|
||||||
|
Data: nil,
|
||||||
|
}
|
||||||
|
tx, _ := SignNewTx(key, signer, txdata)
|
||||||
|
baseFee := big.NewInt(1000000000) // 1 gwei
|
||||||
|
|
||||||
|
b.Run("Original", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := tx.EffectiveGasTip(baseFee)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("IntoMethod", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
dst := new(big.Int)
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
err := tx.EffectiveGasTipInto(dst, baseFee)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEffectiveGasTipInto(t *testing.T) {
|
||||||
|
signer := LatestSigner(params.TestChainConfig)
|
||||||
|
key, _ := crypto.GenerateKey()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
tipCap int64
|
||||||
|
feeCap int64
|
||||||
|
baseFee *int64
|
||||||
|
}{
|
||||||
|
{tipCap: 1, feeCap: 100, baseFee: intPtr(50)},
|
||||||
|
{tipCap: 10, feeCap: 100, baseFee: intPtr(50)},
|
||||||
|
{tipCap: 50, feeCap: 100, baseFee: intPtr(50)},
|
||||||
|
{tipCap: 100, feeCap: 100, baseFee: intPtr(50)},
|
||||||
|
{tipCap: 1, feeCap: 50, baseFee: intPtr(50)},
|
||||||
|
{tipCap: 1, feeCap: 20, baseFee: intPtr(50)}, // Base fee higher than fee cap
|
||||||
|
{tipCap: 50, feeCap: 100, baseFee: intPtr(0)},
|
||||||
|
{tipCap: 50, feeCap: 100, baseFee: nil}, // nil base fee
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range testCases {
|
||||||
|
txdata := &DynamicFeeTx{
|
||||||
|
ChainID: big.NewInt(1),
|
||||||
|
Nonce: 0,
|
||||||
|
GasTipCap: big.NewInt(tc.tipCap),
|
||||||
|
GasFeeCap: big.NewInt(tc.feeCap),
|
||||||
|
Gas: 21000,
|
||||||
|
To: &common.Address{},
|
||||||
|
Value: big.NewInt(0),
|
||||||
|
Data: nil,
|
||||||
|
}
|
||||||
|
tx, _ := SignNewTx(key, signer, txdata)
|
||||||
|
|
||||||
|
var baseFee *big.Int
|
||||||
|
if tc.baseFee != nil {
|
||||||
|
baseFee = big.NewInt(*tc.baseFee)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get result from original method
|
||||||
|
orig, origErr := tx.EffectiveGasTip(baseFee)
|
||||||
|
|
||||||
|
// Get result from new method
|
||||||
|
dst := new(big.Int)
|
||||||
|
newErr := tx.EffectiveGasTipInto(dst, baseFee)
|
||||||
|
|
||||||
|
// Compare results
|
||||||
|
if (origErr != nil) != (newErr != nil) {
|
||||||
|
t.Fatalf("case %d: error mismatch: orig %v, new %v", i, origErr, newErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if orig.Cmp(dst) != 0 {
|
||||||
|
t.Fatalf("case %d: result mismatch: orig %v, new %v", i, orig, dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to create integer pointer
|
||||||
|
func intPtr(i int64) *int64 {
|
||||||
|
return &i
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue