github.com/ethereum/go-ethereum@v1.16.1/eth/api_backend_test.go (about) 1 // Copyright 2025 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package eth 18 19 import ( 20 "context" 21 "crypto/ecdsa" 22 "errors" 23 "math/big" 24 "testing" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/consensus/beacon" 29 "github.com/ethereum/go-ethereum/consensus/ethash" 30 "github.com/ethereum/go-ethereum/core" 31 "github.com/ethereum/go-ethereum/core/rawdb" 32 "github.com/ethereum/go-ethereum/core/txpool" 33 "github.com/ethereum/go-ethereum/core/txpool/blobpool" 34 "github.com/ethereum/go-ethereum/core/txpool/legacypool" 35 "github.com/ethereum/go-ethereum/core/txpool/locals" 36 "github.com/ethereum/go-ethereum/core/types" 37 "github.com/ethereum/go-ethereum/crypto" 38 "github.com/ethereum/go-ethereum/params" 39 "github.com/holiman/uint256" 40 ) 41 42 var ( 43 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 44 address = crypto.PubkeyToAddress(key.PublicKey) 45 funds = big.NewInt(1000_000_000_000_000) 46 gspec = &core.Genesis{ 47 Config: params.MergedTestChainConfig, 48 Alloc: types.GenesisAlloc{ 49 address: {Balance: funds}, 50 }, 51 Difficulty: common.Big0, 52 BaseFee: big.NewInt(params.InitialBaseFee), 53 } 54 signer = types.LatestSignerForChainID(gspec.Config.ChainID) 55 ) 56 57 func initBackend(withLocal bool) *EthAPIBackend { 58 var ( 59 // Create a database pre-initialize with a genesis block 60 db = rawdb.NewMemoryDatabase() 61 engine = beacon.New(ethash.NewFaker()) 62 ) 63 chain, _ := core.NewBlockChain(db, gspec, engine, nil) 64 65 txconfig := legacypool.DefaultConfig 66 txconfig.Journal = "" // Don't litter the disk with test journals 67 68 blobPool := blobpool.New(blobpool.Config{Datadir: ""}, chain, nil) 69 legacyPool := legacypool.New(txconfig, chain) 70 txpool, _ := txpool.New(txconfig.PriceLimit, chain, []txpool.SubPool{legacyPool, blobPool}) 71 72 eth := &Ethereum{ 73 blockchain: chain, 74 txPool: txpool, 75 } 76 if withLocal { 77 eth.localTxTracker = locals.New("", time.Minute, gspec.Config, txpool) 78 } 79 return &EthAPIBackend{ 80 eth: eth, 81 } 82 } 83 84 func makeTx(nonce uint64, gasPrice *big.Int, amount *big.Int, key *ecdsa.PrivateKey) *types.Transaction { 85 if gasPrice == nil { 86 gasPrice = big.NewInt(params.GWei) 87 } 88 if amount == nil { 89 amount = big.NewInt(1000) 90 } 91 tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{0x00}, amount, params.TxGas, gasPrice, nil), signer, key) 92 return tx 93 } 94 95 type unsignedAuth struct { 96 nonce uint64 97 key *ecdsa.PrivateKey 98 } 99 100 func pricedSetCodeTx(nonce uint64, gaslimit uint64, gasFee, tip *uint256.Int, key *ecdsa.PrivateKey, unsigned []unsignedAuth) *types.Transaction { 101 var authList []types.SetCodeAuthorization 102 for _, u := range unsigned { 103 auth, _ := types.SignSetCode(u.key, types.SetCodeAuthorization{ 104 ChainID: *uint256.MustFromBig(gspec.Config.ChainID), 105 Address: common.Address{0x42}, 106 Nonce: u.nonce, 107 }) 108 authList = append(authList, auth) 109 } 110 return pricedSetCodeTxWithAuth(nonce, gaslimit, gasFee, tip, key, authList) 111 } 112 113 func pricedSetCodeTxWithAuth(nonce uint64, gaslimit uint64, gasFee, tip *uint256.Int, key *ecdsa.PrivateKey, authList []types.SetCodeAuthorization) *types.Transaction { 114 return types.MustSignNewTx(key, signer, &types.SetCodeTx{ 115 ChainID: uint256.MustFromBig(gspec.Config.ChainID), 116 Nonce: nonce, 117 GasTipCap: tip, 118 GasFeeCap: gasFee, 119 Gas: gaslimit, 120 To: common.Address{}, 121 Value: uint256.NewInt(100), 122 Data: nil, 123 AccessList: nil, 124 AuthList: authList, 125 }) 126 } 127 128 func TestSendTx(t *testing.T) { 129 testSendTx(t, false) 130 testSendTx(t, true) 131 } 132 133 func testSendTx(t *testing.T, withLocal bool) { 134 b := initBackend(withLocal) 135 136 txA := pricedSetCodeTx(0, 250000, uint256.NewInt(params.GWei), uint256.NewInt(params.GWei), key, []unsignedAuth{{nonce: 0, key: key}}) 137 if err := b.SendTx(context.Background(), txA); err != nil { 138 t.Fatalf("Failed to submit tx: %v", err) 139 } 140 for { 141 pending, _ := b.TxPool().ContentFrom(address) 142 if len(pending) == 1 { 143 break 144 } 145 time.Sleep(100 * time.Millisecond) 146 } 147 148 txB := makeTx(1, nil, nil, key) 149 err := b.SendTx(context.Background(), txB) 150 151 if withLocal { 152 if err != nil { 153 t.Fatalf("Unexpected error sending tx: %v", err) 154 } 155 } else { 156 if !errors.Is(err, txpool.ErrInflightTxLimitReached) { 157 t.Fatalf("Unexpected error, want: %v, got: %v", txpool.ErrInflightTxLimitReached, err) 158 } 159 } 160 }