This commit is contained in:
colinlyguo
2024-03-08 23:15:29 +08:00
parent 748fa692bb
commit 30667f9ed1
5 changed files with 83 additions and 46 deletions

View File

@@ -1,4 +1,4 @@
FROM ethereum/client-go
FROM ethereum/client-go:v1.13.14
COPY password /l1geth/
COPY genesis.json /l1geth/

View File

@@ -4,6 +4,8 @@ go 1.20
require (
github.com/agiledragon/gomonkey/v2 v2.9.0
github.com/consensys/gnark-crypto v0.12.1
github.com/crate-crypto/go-kzg-4844 v0.7.0
github.com/gin-gonic/gin v1.9.1
github.com/go-resty/resty/v2 v2.7.0
github.com/holiman/uint256 v1.2.4
@@ -25,9 +27,7 @@ require (
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 // indirect

View File

@@ -69,16 +69,16 @@ func (s *Sender) estimateDynamicGas(to *common.Address, data []byte, baseFee uin
return feeData, nil
}
func (s *Sender) estimateBlobGas(to *common.Address, data []byte, sideCar *gethTypes.BlobTxSidecar, baseFee, blobBaseFee uint64, fallbackGasLimit uint64) (*FeeData, error) {
func (s *Sender) estimateBlobGas(to *common.Address, data []byte, sidecar *gethTypes.BlobTxSidecar, baseFee, blobBaseFee uint64, fallbackGasLimit uint64) (*FeeData, error) {
gasTipCap, err := s.client.SuggestGasTipCap(s.ctx)
if err != nil {
log.Error("estimateBlobGas SuggestGasTipCap failure", "error", err)
return nil, err
}
gasFeeCap := getBaseFeeCap(new(big.Int).SetUint64(baseFee), gasTipCap)
blobFeeCap := getBlobBaseFeeCap(new(big.Int).SetUint64(blobBaseFee))
gasLimit, accessList, err := s.estimateGasLimit(to, data, sideCar, nil, gasTipCap, gasFeeCap, blobFeeCap)
gasFeeCap := getGasFeeCap(new(big.Int).SetUint64(baseFee), gasTipCap)
blobGasFeeCap := getBlobGasFeeCap(new(big.Int).SetUint64(blobBaseFee))
gasLimit, accessList, err := s.estimateGasLimit(to, data, sidecar, nil, gasTipCap, gasFeeCap, blobGasFeeCap)
if err != nil {
log.Error("estimateBlobGas estimateGasLimit failure",
"from", s.auth.From.String(), "nonce", s.auth.Nonce.Uint64(), "to address", to.String(),
@@ -101,7 +101,7 @@ func (s *Sender) estimateBlobGas(to *common.Address, data []byte, sideCar *gethT
return feeData, nil
}
func (s *Sender) estimateGasLimit(to *common.Address, data []byte, sideCar *gethTypes.BlobTxSidecar, gasPrice, gasTipCap, gasFeeCap, blobFeeCap *big.Int) (uint64, *types.AccessList, error) {
func (s *Sender) estimateGasLimit(to *common.Address, data []byte, sidecar *gethTypes.BlobTxSidecar, gasPrice, gasTipCap, gasFeeCap, blobGasFeeCap *big.Int) (uint64, *types.AccessList, error) {
msg := ethereum.CallMsg{
From: s.auth.From,
To: to,
@@ -111,9 +111,9 @@ func (s *Sender) estimateGasLimit(to *common.Address, data []byte, sideCar *geth
Data: data,
}
if sideCar != nil {
msg.BlobHashes = sideCar.BlobHashes()
msg.BlobGasFeeCap = blobFeeCap
if sidecar != nil {
msg.BlobHashes = sidecar.BlobHashes()
msg.BlobGasFeeCap = blobGasFeeCap
}
gasLimitWithoutAccessList, err := s.client.EstimateGas(s.ctx, msg)
@@ -173,14 +173,14 @@ func finetuneAccessList(accessList *types.AccessList, gasLimitWithAccessList uin
return &newAccessList, gasLimitWithAccessList
}
func getBaseFeeCap(baseFee, gasTipCap *big.Int) *big.Int {
func getGasFeeCap(baseFee, gasTipCap *big.Int) *big.Int {
// gasFeeCap = baseFee * 2 + gasTipCap
gasFeeCap := new(big.Int).Mul(baseFee, big.NewInt(2))
gasFeeCap = new(big.Int).Add(gasFeeCap, gasTipCap)
return gasFeeCap
}
func getBlobBaseFeeCap(blobBaseFee *big.Int) *big.Int {
func getBlobGasFeeCap(blobBaseFee *big.Int) *big.Int {
// blobGasFeeCap = blobBaseFee * 2
blobGasFeeCap := new(big.Int).Mul(blobBaseFee, big.NewInt(2))
return blobGasFeeCap

View File

@@ -56,7 +56,7 @@ type FeeData struct {
gasTipCap *big.Int
gasPrice *big.Int
blobFeeCap *big.Int
blobGasFeeCap *big.Int
accessList gethTypes.AccessList
@@ -158,14 +158,14 @@ func (s *Sender) SendConfirmation(cfm *Confirmation) {
s.confirmCh <- cfm
}
func (s *Sender) getFeeData(target *common.Address, data []byte, sideCar *gethTypes.BlobTxSidecar, fallbackGasLimit uint64, baseFee, blobBaseFee uint64) (*FeeData, error) {
func (s *Sender) getFeeData(target *common.Address, data []byte, sidecar *gethTypes.BlobTxSidecar, fallbackGasLimit uint64, baseFee, blobBaseFee uint64) (*FeeData, error) {
switch s.config.TxType {
case LegacyTxType:
return s.estimateLegacyGas(target, data, fallbackGasLimit)
case DynamicFeeTxType:
return s.estimateDynamicGas(target, data, baseFee, fallbackGasLimit)
case BlobTxType:
return s.estimateBlobGas(target, data, sideCar, baseFee, blobBaseFee, fallbackGasLimit)
return s.estimateBlobGas(target, data, sidecar, baseFee, blobBaseFee, fallbackGasLimit)
default:
return nil, fmt.Errorf("unsupported transaction type: %s", s.config.TxType)
}
@@ -177,15 +177,15 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
var (
feeData *FeeData
tx *gethTypes.Transaction
sideCar *gethTypes.BlobTxSidecar
sidecar *gethTypes.BlobTxSidecar
err error
)
if s.config.TxType == BlobTxType {
sideCar, err = makeSidecar(blob)
sidecar, err = makeSidecar(blob)
if err != nil {
log.Error("failed to make side car for blob transaction", "error", err)
return common.Hash{}, fmt.Errorf("failed to make side car for blob transaction, err: %w", err)
log.Error("failed to make sidecar for blob transaction", "error", err)
return common.Hash{}, fmt.Errorf("failed to make sidecar for blob transaction, err: %w", err)
}
}
@@ -195,13 +195,13 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
return common.Hash{}, fmt.Errorf("failed to get block number and base fee, err: %w", err)
}
if feeData, err = s.getFeeData(target, data, sideCar, fallbackGasLimit, baseFee, blobBaseFee); err != nil {
if feeData, err = s.getFeeData(target, data, sidecar, fallbackGasLimit, baseFee, blobBaseFee); err != nil {
s.metrics.sendTransactionFailureGetFee.WithLabelValues(s.service, s.name).Inc()
log.Error("failed to get fee data", "from", s.auth.From.String(), "nonce", s.auth.Nonce.Uint64(), "fallback gas limit", fallbackGasLimit, "err", err)
return common.Hash{}, fmt.Errorf("failed to get fee data, err: %w", err)
}
if tx, err = s.createAndSendTx(feeData, target, data, nil, nil); err != nil {
if tx, err = s.createAndSendTx(feeData, target, data, sidecar, nil); err != nil {
s.metrics.sendTransactionFailureSendTx.WithLabelValues(s.service, s.name).Inc()
log.Error("failed to create and send tx (non-resubmit case)", "from", s.auth.From.String(), "nonce", s.auth.Nonce.Uint64(), "err", err)
return common.Hash{}, fmt.Errorf("failed to create and send transaction, err: %w", err)
@@ -214,7 +214,7 @@ func (s *Sender) SendTransaction(contextID string, target *common.Address, data
return tx.Hash(), nil
}
func (s *Sender) createAndSendTx(feeData *FeeData, target *common.Address, data []byte, sideCar *gethTypes.BlobTxSidecar, overrideNonce *uint64) (*gethTypes.Transaction, error) {
func (s *Sender) createAndSendTx(feeData *FeeData, target *common.Address, data []byte, sidecar *gethTypes.BlobTxSidecar, overrideNonce *uint64) (*gethTypes.Transaction, error) {
var (
nonce = s.auth.Nonce.Uint64()
txData gethTypes.TxData
@@ -251,9 +251,9 @@ func (s *Sender) createAndSendTx(feeData *FeeData, target *common.Address, data
return nil, errors.New("blob transaction to address cannot be nil")
}
if sideCar == nil {
log.Error("blob transaction sideCar cannot be nil", "address", s.auth.From.String(), "chainID", s.chainID.Uint64(), "nonce", s.auth.Nonce.Uint64())
return nil, errors.New("blob transaction sideCar cannot be nil")
if sidecar == nil {
log.Error("blob transaction sidecar cannot be nil", "address", s.auth.From.String(), "chainID", s.chainID.Uint64(), "nonce", s.auth.Nonce.Uint64())
return nil, errors.New("blob transaction sidecar cannot be nil")
}
txData = &gethTypes.BlobTx{
@@ -265,9 +265,9 @@ func (s *Sender) createAndSendTx(feeData *FeeData, target *common.Address, data
To: *target,
Data: data,
AccessList: feeData.accessList,
BlobFeeCap: uint256.MustFromBig(feeData.blobFeeCap),
BlobHashes: sideCar.BlobHashes(),
Sidecar: sideCar,
BlobFeeCap: uint256.MustFromBig(feeData.blobGasFeeCap),
BlobHashes: sidecar.BlobHashes(),
Sidecar: sidecar,
}
}
@@ -300,8 +300,8 @@ func (s *Sender) createAndSendTx(feeData *FeeData, target *common.Address, data
s.metrics.currentGasPrice.WithLabelValues(s.service, s.name).Set(float64(feeData.gasPrice.Uint64()))
}
if feeData.blobFeeCap != nil {
s.metrics.currentBlobGasFeeCap.WithLabelValues(s.service, s.name).Set(float64(feeData.blobFeeCap.Uint64()))
if feeData.blobGasFeeCap != nil {
s.metrics.currentBlobGasFeeCap.WithLabelValues(s.service, s.name).Set(float64(feeData.blobGasFeeCap.Uint64()))
}
s.metrics.currentGasLimit.WithLabelValues(s.service, s.name).Set(float64(feeData.gasLimit))
@@ -340,7 +340,7 @@ func (s *Sender) resubmitTransaction(tx *gethTypes.Transaction, baseFee, blobBas
switch s.config.TxType {
case LegacyTxType:
originalGasPrice := tx.GasPrice()
gasPrice := new(big.Int).Mul(escalateMultipleNum, originalGasPrice)
gasPrice := new(big.Int).Mul(originalGasPrice, escalateMultipleNum)
gasPrice = new(big.Int).Div(gasPrice, escalateMultipleDen)
if gasPrice.Cmp(maxGasPrice) > 0 {
gasPrice = maxGasPrice
@@ -365,7 +365,7 @@ func (s *Sender) resubmitTransaction(tx *gethTypes.Transaction, baseFee, blobBas
gasFeeCap = new(big.Int).Div(gasFeeCap, escalateMultipleDen)
// adjust for rising basefee
currentGasFeeCap := getBaseFeeCap(new(big.Int).SetUint64(baseFee), gasTipCap)
currentGasFeeCap := getGasFeeCap(new(big.Int).SetUint64(baseFee), gasTipCap)
if gasFeeCap.Cmp(currentGasFeeCap) < 0 {
gasFeeCap = currentGasFeeCap
}
@@ -405,10 +405,10 @@ func (s *Sender) resubmitTransaction(tx *gethTypes.Transaction, baseFee, blobBas
// bumping at least 100%
gasTipCap := new(big.Int).Mul(originalGasTipCap, big.NewInt(2))
gasFeeCap := new(big.Int).Mul(originalGasFeeCap, big.NewInt(2))
blobGasFeeCap := new(big.Int).Div(originalBlobGasFeeCap, big.NewInt(2))
blobGasFeeCap := new(big.Int).Mul(originalBlobGasFeeCap, big.NewInt(2))
// adjust for rising basefee
currentGasFeeCap := getBaseFeeCap(new(big.Int).SetUint64(baseFee), gasTipCap)
currentGasFeeCap := getGasFeeCap(new(big.Int).SetUint64(baseFee), gasTipCap)
if gasFeeCap.Cmp(currentGasFeeCap) < 0 {
gasFeeCap = currentGasFeeCap
}
@@ -424,7 +424,7 @@ func (s *Sender) resubmitTransaction(tx *gethTypes.Transaction, baseFee, blobBas
}
// adjust for rising blobbasefee
currentBlobGasFeeCap := getBlobBaseFeeCap(new(big.Int).SetUint64(baseFee))
currentBlobGasFeeCap := getBlobGasFeeCap(new(big.Int).SetUint64(blobBaseFee))
if blobGasFeeCap.Cmp(currentBlobGasFeeCap) < 0 {
blobGasFeeCap = currentBlobGasFeeCap
}
@@ -436,11 +436,13 @@ func (s *Sender) resubmitTransaction(tx *gethTypes.Transaction, baseFee, blobBas
feeData.gasFeeCap = gasFeeCap
feeData.gasTipCap = gasTipCap
feeData.blobFeeCap = blobGasFeeCap
feeData.blobGasFeeCap = blobGasFeeCap
txInfo["original_gas_tip_cap"] = originalGasTipCap.Uint64()
txInfo["adjusted_gas_tip_cap"] = gasTipCap.Uint64()
txInfo["original_gas_fee_cap"] = originalGasFeeCap.Uint64()
txInfo["adjusted_gas_fee_cap"] = gasFeeCap.Uint64()
txInfo["original_blob_gas_fee_cap"] = originalBlobGasFeeCap.Uint64()
txInfo["adjusted_blob_gas_fee_cap"] = blobGasFeeCap.Uint64()
default:
return nil, fmt.Errorf("unsupported transaction type: %s", s.config.TxType)
@@ -602,12 +604,12 @@ func (s *Sender) getBlockNumberAndBaseFeeAndBlobFee(ctx context.Context) (uint64
baseFee = header.BaseFee.Uint64()
}
var blobFee uint64
var blobBaseFee uint64
if header.ExcessBlobGas != nil && header.BlobGasUsed != nil {
parentExcessBlobGas := misc.CalcExcessBlobGas(*header.ExcessBlobGas, *header.BlobGasUsed)
blobFee = misc.CalcBlobFee(parentExcessBlobGas).Uint64()
blobBaseFee = misc.CalcBlobFee(parentExcessBlobGas).Uint64()
}
return header.Number.Uint64(), baseFee, blobFee, nil
return header.Number.Uint64(), baseFee, blobBaseFee, nil
}
func makeSidecar(blob *kzg4844.Blob) (*gethTypes.BlobTxSidecar, error) {

View File

@@ -3,6 +3,7 @@ package sender
import (
"context"
"crypto/ecdsa"
"crypto/rand"
"errors"
"fmt"
"math/big"
@@ -10,10 +11,13 @@ import (
"testing"
"github.com/agiledragon/gomonkey/v2"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
gokzg4844 "github.com/crate-crypto/go-kzg-4844"
"github.com/scroll-tech/go-ethereum/accounts/abi/bind"
"github.com/scroll-tech/go-ethereum/common"
gethTypes "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/crypto/kzg4844"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/rpc"
@@ -37,7 +41,7 @@ var (
cfg *config.Config
base *docker.App
txTypes = []string{"LegacyTx", "DynamicFeeTx"}
txUint8Types = []uint8{0, 2}
txUint8Types = []uint8{0, 2, 3}
db *gorm.DB
mockL1ContractsAddress common.Address
)
@@ -144,7 +148,12 @@ func testSendAndRetrieveTransaction(t *testing.T) {
s, err := NewSender(context.Background(), &cfgCopy, privateKey, "test", "test", types.SenderTypeUnknown, db, nil)
assert.NoError(t, err)
hash, err := s.SendTransaction("0", &common.Address{}, nil, nil, 0)
var blob *kzg4844.Blob
if txType == BlobTxType {
blob = randBlob()
}
hash, err := s.SendTransaction("0", &common.Address{}, nil, blob, 0)
assert.NoError(t, err)
txs, err := s.pendingTransactionOrm.GetPendingOrReplacedTransactionsBySenderType(context.Background(), s.senderType, 1)
assert.NoError(t, err)
@@ -176,8 +185,13 @@ func testFallbackGasLimit(t *testing.T) {
client, err := ethclient.Dial(cfgCopy.Endpoint)
assert.NoError(t, err)
var blob *kzg4844.Blob
if txType == BlobTxType {
blob = randBlob()
}
// FallbackGasLimit = 0
txHash0, err := s.SendTransaction("0", &common.Address{}, nil, nil, 0)
txHash0, err := s.SendTransaction("0", &common.Address{}, nil, blob, 0)
assert.NoError(t, err)
tx0, _, err := client.TransactionByHash(context.Background(), txHash0)
assert.NoError(t, err)
@@ -185,12 +199,12 @@ func testFallbackGasLimit(t *testing.T) {
// FallbackGasLimit = 100000
patchGuard := gomonkey.ApplyPrivateMethod(s, "estimateGasLimit",
func(contract *common.Address, data []byte, sideCar *gethTypes.BlobTxSidecar, gasPrice, gasTipCap, gasFeeCap, blobFeeCap *big.Int) (uint64, *gethTypes.AccessList, error) {
func(contract *common.Address, data []byte, sidecar *gethTypes.BlobTxSidecar, gasPrice, gasTipCap, gasFeeCap, blobGasFeeCap *big.Int) (uint64, *gethTypes.AccessList, error) {
return 0, nil, errors.New("estimateGasLimit error")
},
)
txHash1, err := s.SendTransaction("1", &common.Address{}, nil, nil, 100000)
txHash1, err := s.SendTransaction("1", &common.Address{}, nil, blob, 100000)
assert.NoError(t, err)
tx1, _, err := client.TransactionByHash(context.Background(), txHash1)
assert.NoError(t, err)
@@ -335,7 +349,7 @@ func testResubmitTransactionWithRisingBaseFee(t *testing.T) {
assert.NoError(t, err)
maxGasPrice := new(big.Int).SetUint64(s.config.MaxGasPrice)
expectedGasFeeCap := getBaseFeeCap(new(big.Int).SetUint64(baseFeePerGas), tx.GasTipCap())
expectedGasFeeCap := getGasFeeCap(new(big.Int).SetUint64(baseFeePerGas), tx.GasTipCap())
if expectedGasFeeCap.Cmp(maxGasPrice) > 0 {
expectedGasFeeCap = maxGasPrice
}
@@ -542,3 +556,24 @@ func testCheckPendingTransactionTxMultipleTimesWithOnlyOneTxPending(t *testing.T
patchGuard.Reset()
}
}
func randBlob() *kzg4844.Blob {
var blob kzg4844.Blob
for i := 0; i < len(blob); i += gokzg4844.SerializedScalarSize {
fieldElementBytes := randFieldElement()
copy(blob[i:i+gokzg4844.SerializedScalarSize], fieldElementBytes[:])
}
return &blob
}
func randFieldElement() [32]byte {
bytes := make([]byte, 32)
_, err := rand.Read(bytes)
if err != nil {
panic("failed to get random field element")
}
var r fr.Element
r.SetBytes(bytes)
return gokzg4844.SerializeScalar(r)
}