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  }