From d572f4c412e59094ea9a4c5ff0b0667c9c04bd66 Mon Sep 17 00:00:00 2001 From: maskpp Date: Thu, 24 Oct 2024 20:56:31 +0800 Subject: [PATCH] test(taiko-client): introduce TestTxPoolContentWithMinTip test case (#18285) --- go.mod | 8 +- go.sum | 4 +- packages/eventindexer/.golangci.yml | 2 +- packages/relayer/.golangci.yml | 8 +- packages/relayer/pkg/mock/mock_tx_sender.go | 19 +++ .../internal/docker/nodes/docker-compose.yml | 2 +- .../taiko-client/internal/testutils/helper.go | 44 +++++++ .../taiko-client/proposer/proposer_test.go | 110 ++++++++++++++++++ 8 files changed, 181 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 4c5ee52f39..31dcefa4c8 100644 --- a/go.mod +++ b/go.mod @@ -235,13 +235,7 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect ) -exclude ( - github.com/ethereum/go-ethereum v1.14.5 - github.com/ethereum/go-ethereum v1.14.6 - github.com/ethereum/go-ethereum v1.14.7 -) - -replace github.com/ethereum/go-ethereum v1.14.11 => github.com/taikoxyz/taiko-geth v1.8.1-0.20241003040603-5c84a2082747 +replace github.com/ethereum/go-ethereum v1.14.11 => github.com/taikoxyz/taiko-geth v1.11.1 replace github.com/ethereum-optimism/optimism v1.7.4 => github.com/taikoxyz/optimism v0.0.0-20241003061504-cdf8af288f39 diff --git a/go.sum b/go.sum index 9ddee77dab..f7be24097e 100644 --- a/go.sum +++ b/go.sum @@ -610,8 +610,8 @@ github.com/taikoxyz/hive v0.0.0-20240827015317-405b241dd082 h1:ymZR+Y88LOnA8i3Ke github.com/taikoxyz/hive v0.0.0-20240827015317-405b241dd082/go.mod h1:RHnIu3EFehrWX3JhFAMQSXD5uz7l0xaNroTzXrap7EQ= github.com/taikoxyz/optimism v0.0.0-20241003061504-cdf8af288f39 h1:JssMxaDmORjQ9RPZNulVJhAD8zSPd6LZFq5wsr6Nwz8= github.com/taikoxyz/optimism v0.0.0-20241003061504-cdf8af288f39/go.mod h1:ym7scR7ZHvEmwx1DLGVDzFlAdR+uhP1+Z4XCiFuSD5s= -github.com/taikoxyz/taiko-geth v1.8.1-0.20241003040603-5c84a2082747 h1:QRB8VHGmlRgm7ze/4Fzuce08Ypbq5Mr5q/piTfsck1A= -github.com/taikoxyz/taiko-geth v1.8.1-0.20241003040603-5c84a2082747/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E= +github.com/taikoxyz/taiko-geth v1.11.1 h1:pur1WP6YJkwKhLVeN3Zf7dOwbPq6tS88gYod6QKlJc4= +github.com/taikoxyz/taiko-geth v1.11.1/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E= github.com/testcontainers/testcontainers-go v0.30.0 h1:jmn/XS22q4YRrcMwWg0pAwlClzs/abopbsBzrepyc4E= github.com/testcontainers/testcontainers-go v0.30.0/go.mod h1:K+kHNGiM5zjklKjgTtcrEetF3uhWbMUyqAQoyoh8Pf0= github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e h1:cR8/SYRgyQCt5cNCMniB/ZScMkhI9nk8U5C7SbISXjo= diff --git a/packages/eventindexer/.golangci.yml b/packages/eventindexer/.golangci.yml index 2f3a3d4742..f8f1767ce3 100644 --- a/packages/eventindexer/.golangci.yml +++ b/packages/eventindexer/.golangci.yml @@ -9,7 +9,7 @@ # ], output: - format: colored-line-number + formats: colored-line-number linters: enable: diff --git a/packages/relayer/.golangci.yml b/packages/relayer/.golangci.yml index 56dcebe883..f47cd722a6 100644 --- a/packages/relayer/.golangci.yml +++ b/packages/relayer/.golangci.yml @@ -9,7 +9,7 @@ # ], output: - format: colored-line-number + formats: colored-line-number linters: enable: @@ -34,6 +34,8 @@ linters-settings: min-complexity: 75 issues: + exclude-dirs: + - contracts/* exclude-rules: # Exclude some linters from running on tests files. - path: _test\.go @@ -42,7 +44,3 @@ issues: - path: / linters: - typecheck - -run: - skip-dirs: - - contracts/* diff --git a/packages/relayer/pkg/mock/mock_tx_sender.go b/packages/relayer/pkg/mock/mock_tx_sender.go index df88966b6a..5dd941b5fd 100644 --- a/packages/relayer/pkg/mock/mock_tx_sender.go +++ b/packages/relayer/pkg/mock/mock_tx_sender.go @@ -2,10 +2,12 @@ package mock import ( "context" + "math/big" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rpc" ) type TxManager struct { @@ -34,3 +36,20 @@ func (t *TxManager) Close() { func (t *TxManager) IsClosed() bool { return false } + +func (t *TxManager) SendAsync(ctx context.Context, candidate txmgr.TxCandidate, ch chan txmgr.SendResponse) { + panic("unimplemented") +} + +func (t *TxManager) SuggestGasPriceCaps(ctx context.Context) ( + tipCap *big.Int, + baseFee *big.Int, + blobBaseFee *big.Int, + err error, +) { + panic("unimplemented") +} + +func (t *TxManager) API() rpc.API { + panic("unimplemented") +} diff --git a/packages/taiko-client/internal/docker/nodes/docker-compose.yml b/packages/taiko-client/internal/docker/nodes/docker-compose.yml index 1c81f01f92..429595fbf2 100644 --- a/packages/taiko-client/internal/docker/nodes/docker-compose.yml +++ b/packages/taiko-client/internal/docker/nodes/docker-compose.yml @@ -1,7 +1,7 @@ services: l1_node: container_name: l1_node - image: ghcr.io/foundry-rs/foundry:nightly + image: ghcr.io/foundry-rs/foundry:nightly-2044faec64f99a21f0e5f0094458a973612d0712 restart: unless-stopped platform: linux/amd64 pull_policy: always diff --git a/packages/taiko-client/internal/testutils/helper.go b/packages/taiko-client/internal/testutils/helper.go index d93e3499f1..36d7adc933 100644 --- a/packages/taiko-client/internal/testutils/helper.go +++ b/packages/taiko-client/internal/testutils/helper.go @@ -282,6 +282,50 @@ func SignatureFromRSV(r, s string, v byte) []byte { return append(append(hexutil.MustDecode(r), hexutil.MustDecode(s)...), v) } +func AssembleTestTx( + client *rpc.EthClient, + priv *ecdsa.PrivateKey, + nonce uint64, + to *common.Address, + value *big.Int, + data []byte, +) (*types.Transaction, error) { + head, err := client.HeaderByNumber(context.Background(), nil) + if err != nil { + return nil, err + } + + auth, err := bind.NewKeyedTransactorWithChainID(priv, client.ChainID) + if err != nil { + return nil, err + } + + gasTipCap, err := client.SuggestGasTipCap(context.Background()) + if err != nil { + return nil, err + } + + tx, err := auth.Signer(auth.From, types.NewTx(&types.DynamicFeeTx{ + To: to, + Nonce: nonce, + Value: value, + GasTipCap: gasTipCap, + GasFeeCap: new(big.Int).Add( + gasTipCap, + new(big.Int).Mul(head.BaseFee, big.NewInt(2)), + ), + Gas: 2100_000, + Data: data, + })) + if err != nil { + return nil, err + } + if err = client.SendTransaction(context.Background(), tx); err != nil { + return nil, err + } + return tx, nil +} + // SendDynamicFeeTx sends a dynamic transaction, used for tests. func SendDynamicFeeTx( client *rpc.EthClient, diff --git a/packages/taiko-client/proposer/proposer_test.go b/packages/taiko-client/proposer/proposer_test.go index f3a968a375..3f3d4e6ed3 100644 --- a/packages/taiko-client/proposer/proposer_test.go +++ b/packages/taiko-client/proposer/proposer_test.go @@ -2,12 +2,16 @@ package proposer import ( "context" + "crypto/ecdsa" + "fmt" + "maps" "math/big" "os" "testing" "time" "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" @@ -119,6 +123,112 @@ func (s *ProposerTestSuite) SetupTest() { s.cancel = cancel } +func (s *ProposerTestSuite) TestTxPoolContentWithMinTip() { + if os.Getenv("L2_NODE") == "l2_reth" { + s.T().Skip() + } + defer s.Nil(s.s.ProcessL1Blocks(context.Background())) + + privetKeyHexList := []string{ + "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", // 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 + "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", // 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC + "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", // 0x90F79bf6EB2c4f870365E785982E1f101E93b906 + "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", // 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 + "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", // 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc + } + + var ( + p = s.p + privKeys []*ecdsa.PrivateKey + l2Cli = s.RPCClient.L2 + chainID = l2Cli.ChainID + ) + + for _, sk := range privetKeyHexList { + priv, err := crypto.ToECDSA(common.FromHex(sk)) + s.Nil(err) + privKeys = append(privKeys, priv) + } + + originNonces := make(map[common.Address]uint64) + for _, priv := range privKeys { + auth, err := bind.NewKeyedTransactorWithChainID(priv, chainID) + s.Nil(err) + nonce, err := l2Cli.PendingNonceAt(context.Background(), auth.From) + s.Nil(err) + originNonces[auth.From] = nonce + for i := 0; i < 300; i++ { + _, err = testutils.AssembleTestTx(s.RPCClient.L2, priv, nonce+uint64(i), &auth.From, big.NewInt(1), nil) + s.Nil(err) + } + } + + signer := types.LatestSignerForChainID(chainID) + for _, testCase := range []struct { + blockMaxGasLimit uint32 + blockMaxTxListBytes uint64 + maxTransactionsLists uint64 + + txLengthList []int + }{ + { + p.protocolConfigs.BlockMaxGasLimit, + rpc.BlockMaxTxListBytes, + p.MaxProposedTxListsPerEpoch, + []int{1500}, + }, + { + p.protocolConfigs.BlockMaxGasLimit, + rpc.BlockMaxTxListBytes, + p.MaxProposedTxListsPerEpoch * 5, + []int{1500}, + }, + { + p.protocolConfigs.BlockMaxGasLimit / 50, + rpc.BlockMaxTxListBytes, + 200, + []int{129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 81}, + }, + } { + res, err := s.RPCClient.GetPoolContent( + context.Background(), + p.proposerAddress, + testCase.blockMaxGasLimit, + testCase.blockMaxTxListBytes, + p.LocalAddresses, + testCase.maxTransactionsLists, + 0, + p.chainConfig, + ) + s.Nil(err) + + checkNonces := maps.Clone(originNonces) + // Make sure all the nonce are in order. + for _, txList := range res { + for _, tx := range txList.TxList { + sender, err := types.Sender(signer, tx) + s.Nil(err) + s.Equalf(checkNonces[sender], tx.Nonce(), + fmt.Sprintf("%s nonce check, expect: %d, actual: %d", + sender.String(), + checkNonces[sender], + tx.Nonce(), + )) + checkNonces[sender]++ + } + } + + s.GreaterOrEqual(int(testCase.maxTransactionsLists), len(res)) + for i, txsLen := range testCase.txLengthList { + s.Equal(txsLen, res[i].TxList.Len()) + s.GreaterOrEqual(uint64(testCase.blockMaxGasLimit), res[i].EstimatedGasUsed) + s.GreaterOrEqual(testCase.blockMaxTxListBytes, res[i].BytesLength) + } + } + + s.Nil(p.ProposeOp(context.Background())) +} + func (s *ProposerTestSuite) TestProposeTxLists() { p := s.p ctx := p.ctx