Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

feat(all): use an unified transaction sender implementation #560

Merged
merged 34 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2211f3e
add sender
mask-pp Feb 18, 2024
fa750f9
Merge branch 'main' into sender
mask-pp Feb 19, 2024
1ffb231
update sender
mask-pp Feb 20, 2024
a122b25
update sender
mask-pp Feb 21, 2024
29b2f82
use sender in proposer module
mask-pp Feb 21, 2024
297465b
use sender in proposer module
mask-pp Feb 21, 2024
44ad23e
Merge branch 'main' into sender
davidtaikocha Feb 21, 2024
c873b75
fix bug
mask-pp Feb 21, 2024
e2b702f
Add max transaction waiting time
mask-pp Feb 21, 2024
aadd533
add blob tx operation
mask-pp Feb 21, 2024
9ba8629
update bindings
mask-pp Feb 22, 2024
d6f6ad5
update sender
mask-pp Feb 22, 2024
968344a
use uuid in sender
mask-pp Feb 22, 2024
e234883
use uuid in sender
mask-pp Feb 22, 2024
3c5a531
add GetUnconfirmedTx api
mask-pp Feb 22, 2024
4d13ff7
update gastipcap
mask-pp Feb 22, 2024
8461019
fix bug
mask-pp Feb 22, 2024
84d77bc
Merge branch 'main' into sender
mask-pp Feb 22, 2024
f4e40cb
fix bug
mask-pp Feb 22, 2024
33ec603
upgrade sender test
mask-pp Feb 22, 2024
bf22201
order import
mask-pp Feb 22, 2024
18f29a1
upgrade sender
mask-pp Feb 22, 2024
d244ddc
fix bug
mask-pp Feb 22, 2024
1b20ab4
expose GetSender
mask-pp Feb 23, 2024
f2ac262
merge main branch
mask-pp Feb 23, 2024
836da00
merge main branch
mask-pp Feb 23, 2024
d90e81a
Merge branch 'main' into sender
davidtaikocha Feb 23, 2024
dc42922
upgrade sender
mask-pp Feb 23, 2024
71d0975
Merge branch 'main' into sender
davidtaikocha Feb 23, 2024
0eabc3c
upgrade sender
mask-pp Feb 23, 2024
f7768c9
update some English wordings in transaction sender, no logic change
mask-pp Feb 23, 2024
b91e747
chore(internal): update some English wordings in transaction sender, …
mask-pp Feb 23, 2024
6c5c7ee
fix mistake changes
mask-pp Feb 23, 2024
f255da3
Merge branch 'main' into sender
mask-pp Feb 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions driver/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@ func (s *DriverTestSuite) TestProcessL1Blocks() {
}

func (s *DriverTestSuite) TestCheckL1ReorgToHigherFork() {
var testnetL1SnapshotID = s.SetL1Snapshot()

var (
testnetL1SnapshotID = s.SetL1Snapshot()
sender = s.p.GetSender()
)
l1Head1, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
l2Head1, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
Expand Down Expand Up @@ -164,6 +166,8 @@ func (s *DriverTestSuite) TestCheckL1ReorgToHigherFork() {
s.Equal(l1Head3.Number.Uint64(), l1Head1.Number.Uint64())
s.Equal(l1Head3.Hash(), l1Head1.Hash())

// Because of evm_revert operation, the nonce of the proposer need to be adjusted.
sender.AdjustNonce(nil)
// Propose ten blocks on another fork
for i := 0; i < 10; i++ {
s.ProposeInvalidTxListBytes(s.p)
Expand All @@ -188,8 +192,10 @@ func (s *DriverTestSuite) TestCheckL1ReorgToHigherFork() {
}

func (s *DriverTestSuite) TestCheckL1ReorgToLowerFork() {
var testnetL1SnapshotID = s.SetL1Snapshot()

var (
testnetL1SnapshotID = s.SetL1Snapshot()
sender = s.p.GetSender()
)
l1Head1, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
l2Head1, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
Expand Down Expand Up @@ -223,6 +229,7 @@ func (s *DriverTestSuite) TestCheckL1ReorgToLowerFork() {
s.Equal(l1Head3.Number.Uint64(), l1Head1.Number.Uint64())
s.Equal(l1Head3.Hash(), l1Head1.Hash())

sender.AdjustNonce(nil)
// Propose one blocks on another fork
s.ProposeInvalidTxListBytes(s.p)

Expand All @@ -244,8 +251,10 @@ func (s *DriverTestSuite) TestCheckL1ReorgToLowerFork() {
}

func (s *DriverTestSuite) TestCheckL1ReorgToSameHeightFork() {
var testnetL1SnapshotID = s.SetL1Snapshot()

var (
testnetL1SnapshotID = s.SetL1Snapshot()
sender = s.p.GetSender()
)
l1Head1, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
l2Head1, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
Expand Down Expand Up @@ -279,6 +288,7 @@ func (s *DriverTestSuite) TestCheckL1ReorgToSameHeightFork() {
s.Equal(l1Head3.Number.Uint64(), l1Head1.Number.Uint64())
s.Equal(l1Head3.Hash(), l1Head1.Hash())

sender.AdjustNonce(nil)
// Propose two blocks on another fork
s.ProposeInvalidTxListBytes(s.p)
time.Sleep(3 * time.Second)
Expand Down
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ require (
github.com/joho/godotenv v1.5.1
github.com/labstack/echo/v4 v4.11.1
github.com/modern-go/reflect2 v1.0.2
github.com/orcaman/concurrent-map/v2 v2.0.1
github.com/pborman/uuid v1.2.1
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
github.com/prysmaticlabs/prysm/v4 v4.2.0
github.com/stretchr/testify v1.8.4
github.com/swaggo/swag v1.16.2
github.com/urfave/cli/v2 v2.25.7
golang.org/x/sync v0.5.0
modernc.org/mathutil v1.6.0
)

require (
Expand Down Expand Up @@ -79,7 +82,7 @@ require (
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 // indirect
Expand Down Expand Up @@ -164,6 +167,7 @@ require (
github.com/quic-go/quic-go v0.39.3 // indirect
github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/rs/cors v1.7.0 // indirect
Expand Down
12 changes: 10 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,8 @@ github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
Expand Down Expand Up @@ -797,13 +797,17 @@ github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTm
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c=
github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
Expand Down Expand Up @@ -887,6 +891,8 @@ github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtB
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
Expand Down Expand Up @@ -1648,6 +1654,8 @@ k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
202 changes: 202 additions & 0 deletions internal/sender/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
package sender

import (
"fmt"
"math/big"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/holiman/uint256"
"github.com/pborman/uuid"
"modernc.org/mathutil"

"github.com/taikoxyz/taiko-client/pkg/rpc"
)

// adjustGas adjusts the gas fee cap and gas tip cap of the given transaction with the configured
// growth rate.
func (s *Sender) adjustGas(txData types.TxData) {
rate := s.GasGrowthRate + 100
switch baseTx := txData.(type) {
case *types.DynamicFeeTx:
gasFeeCap := baseTx.GasFeeCap.Int64()
gasFeeCap = gasFeeCap / 100 * int64(rate)
gasFeeCap = mathutil.MinInt64(gasFeeCap, int64(s.MaxGasFee))
baseTx.GasFeeCap = big.NewInt(gasFeeCap)

gasTipCap := baseTx.GasTipCap.Int64()
gasTipCap = gasTipCap / 100 * int64(rate)
gasTipCap = mathutil.MinInt64(gasFeeCap, mathutil.MinInt64(gasTipCap, int64(s.MaxGasFee)))
baseTx.GasTipCap = big.NewInt(gasTipCap)
case *types.BlobTx:
gasFeeCap := baseTx.GasFeeCap.Uint64()
gasFeeCap = gasFeeCap / 100 * rate
gasFeeCap = mathutil.MinUint64(gasFeeCap, s.MaxGasFee)
baseTx.GasFeeCap = uint256.NewInt(gasFeeCap)

gasTipCap := baseTx.GasTipCap.Uint64()
gasTipCap = gasTipCap / 100 * rate
gasTipCap = mathutil.MinUint64(gasFeeCap, mathutil.MinUint64(gasTipCap, s.MaxGasFee))
baseTx.GasTipCap = uint256.NewInt(gasTipCap)

blobFeeCap := baseTx.BlobFeeCap.Uint64()
blobFeeCap = blobFeeCap / 100 * rate
blobFeeCap = mathutil.MinUint64(blobFeeCap, s.MaxBlobFee)
baseTx.BlobFeeCap = uint256.NewInt(blobFeeCap)
}
}

// AdjustNonce adjusts the nonce of the given transaction with the current nonce of the sender.
func (s *Sender) AdjustNonce(txData types.TxData) {
nonce, err := s.client.NonceAt(s.ctx, s.Opts.From, nil)
if err != nil {
log.Warn("Failed to get the nonce", "from", s.Opts.From, "err", err)
return
}
s.Opts.Nonce = new(big.Int).SetUint64(nonce)

switch tx := txData.(type) {
case *types.DynamicFeeTx:
tx.Nonce = nonce
case *types.BlobTx:
tx.Nonce = nonce
default:
log.Warn("Unsupported transaction type", "from", s.Opts.From)
}
}

// updateGasTipGasFee updates the gas tip cap and gas fee cap of the sender with the given chain head info.
func (s *Sender) updateGasTipGasFee(head *types.Header) error {
// Get the gas tip cap
gasTipCap, err := s.client.SuggestGasTipCap(s.ctx)
if err != nil {
return err
}

// Get the gas fee cap
gasFeeCap := new(big.Int).Add(gasTipCap, new(big.Int).Mul(head.BaseFee, big.NewInt(2)))
// Check if the gas fee cap is less than the gas tip cap
if gasFeeCap.Cmp(gasTipCap) < 0 {
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", gasFeeCap, gasTipCap)
}
maxGasFee := new(big.Int).SetUint64(s.MaxGasFee)
if gasFeeCap.Cmp(maxGasFee) > 0 {
gasFeeCap = new(big.Int).Set(maxGasFee)
gasTipCap = new(big.Int).Set(maxGasFee)
}

s.Opts.GasTipCap = gasTipCap
s.Opts.GasFeeCap = gasFeeCap

return nil
}

// buildTxData assembles the transaction data from the given transaction.
func (s *Sender) buildTxData(tx *types.Transaction) (types.TxData, error) {
switch tx.Type() {
case types.DynamicFeeTxType:
return &types.DynamicFeeTx{
ChainID: s.client.ChainID,
To: tx.To(),
Nonce: tx.Nonce(),
GasFeeCap: s.Opts.GasFeeCap,
GasTipCap: s.Opts.GasTipCap,
Gas: tx.Gas(),
Value: tx.Value(),
Data: tx.Data(),
AccessList: tx.AccessList(),
}, nil
case types.BlobTxType:
var to common.Address
if tx.To() != nil {
to = *tx.To()
}
return &types.BlobTx{
ChainID: uint256.MustFromBig(s.client.ChainID),
To: to,
Nonce: tx.Nonce(),
GasFeeCap: uint256.MustFromBig(s.Opts.GasFeeCap),
GasTipCap: uint256.MustFromBig(s.Opts.GasTipCap),
Gas: tx.Gas(),
Value: uint256.MustFromBig(tx.Value()),
Data: tx.Data(),
AccessList: tx.AccessList(),
BlobFeeCap: uint256.MustFromBig(tx.BlobGasFeeCap()),
BlobHashes: tx.BlobHashes(),
Sidecar: tx.BlobTxSidecar(),
}, nil
default:
return nil, fmt.Errorf("unsupported transaction type: %v", tx.Type())
}
}

// handleReorgTransactions handles the transactions which are backed to the mempool due to reorg.
func (s *Sender) handleReorgTransactions() { // nolint: unused
content, err := rpc.Content(s.ctx, s.client)
if err != nil {
log.Warn("failed to get the unconfirmed transactions", "address", s.Opts.From.String(), "err", err)
return
}
if len(content) == 0 {
return
}

txs := map[common.Hash]*types.Transaction{}
for _, txMapStatus := range content {
for key, txMapNonce := range txMapStatus {
addr := common.HexToAddress(key)
if addr != s.Opts.From {
continue
}
for _, tx := range txMapNonce {
txs[tx.Hash()] = tx
}
}
}
// Remove the already handled transactions.
for _, confirm := range s.unconfirmedTxs.Items() {
delete(txs, confirm.CurrentTx.Hash())
}
for _, tx := range txs {
baseTx, err := s.buildTxData(tx)
if err != nil {
log.Warn("failed to make the transaction data when handle reorg txs", "tx_hash", tx.Hash().String(), "err", err)
return
}
txID := uuid.New()
confirm := &TxToConfirm{
ID: txID,
CurrentTx: tx,
originalTx: baseTx,
}
s.unconfirmedTxs.Set(txID, confirm)
s.txToConfirmCh.Set(txID, make(chan *TxToConfirm, 1))
log.Info("handle reorg tx", "tx_hash", tx.Hash().String(), "tx_id", txID)
}
}

// setDefault sets the default value if the given value is 0.
func setDefault[T uint64 | time.Duration](src, dest T) T {
if src == 0 {
return dest
}
return src
}

// setConfigWithDefaultValues sets the config with default values if the given config is nil.
func setConfigWithDefaultValues(config *Config) *Config {
if config == nil {
return DefaultConfig
}
return &Config{
ConfirmationDepth: setDefault(config.ConfirmationDepth, DefaultConfig.ConfirmationDepth),
MaxRetrys: setDefault(config.MaxRetrys, DefaultConfig.MaxRetrys),
MaxWaitingTime: setDefault(config.MaxWaitingTime, DefaultConfig.MaxWaitingTime),
GasLimit: setDefault(config.GasLimit, DefaultConfig.GasLimit),
GasGrowthRate: setDefault(config.GasGrowthRate, DefaultConfig.GasGrowthRate),
MaxGasFee: setDefault(config.MaxGasFee, DefaultConfig.MaxGasFee),
MaxBlobFee: setDefault(config.MaxBlobFee, DefaultConfig.MaxBlobFee),
}
}
Loading
Loading