github.com/ethereum/go-ethereum@v1.14.3/ethclient/gethclient/gethclient_test.go (about)

     1  // Copyright 2021 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 gethclient
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"encoding/json"
    23  	"math/big"
    24  	"testing"
    25  
    26  	"github.com/ethereum/go-ethereum"
    27  	"github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/consensus/ethash"
    29  	"github.com/ethereum/go-ethereum/core"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/ethereum/go-ethereum/crypto"
    32  	"github.com/ethereum/go-ethereum/eth"
    33  	"github.com/ethereum/go-ethereum/eth/ethconfig"
    34  	"github.com/ethereum/go-ethereum/eth/filters"
    35  	"github.com/ethereum/go-ethereum/ethclient"
    36  	"github.com/ethereum/go-ethereum/node"
    37  	"github.com/ethereum/go-ethereum/params"
    38  	"github.com/ethereum/go-ethereum/rpc"
    39  )
    40  
    41  var (
    42  	testKey, _   = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    43  	testAddr     = crypto.PubkeyToAddress(testKey.PublicKey)
    44  	testContract = common.HexToAddress("0xbeef")
    45  	testEmpty    = common.HexToAddress("0xeeee")
    46  	testSlot     = common.HexToHash("0xdeadbeef")
    47  	testValue    = crypto.Keccak256Hash(testSlot[:])
    48  	testBalance  = big.NewInt(2e15)
    49  )
    50  
    51  func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
    52  	// Generate test chain.
    53  	genesis, blocks := generateTestChain()
    54  	// Create node
    55  	n, err := node.New(&node.Config{})
    56  	if err != nil {
    57  		t.Fatalf("can't create new node: %v", err)
    58  	}
    59  	// Create Ethereum Service
    60  	config := &ethconfig.Config{Genesis: genesis}
    61  	ethservice, err := eth.New(n, config)
    62  	if err != nil {
    63  		t.Fatalf("can't create new ethereum service: %v", err)
    64  	}
    65  	filterSystem := filters.NewFilterSystem(ethservice.APIBackend, filters.Config{})
    66  	n.RegisterAPIs([]rpc.API{{
    67  		Namespace: "eth",
    68  		Service:   filters.NewFilterAPI(filterSystem),
    69  	}})
    70  
    71  	// Import the test chain.
    72  	if err := n.Start(); err != nil {
    73  		t.Fatalf("can't start test node: %v", err)
    74  	}
    75  	if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil {
    76  		t.Fatalf("can't import test blocks: %v", err)
    77  	}
    78  	return n, blocks
    79  }
    80  
    81  func generateTestChain() (*core.Genesis, []*types.Block) {
    82  	genesis := &core.Genesis{
    83  		Config: params.AllEthashProtocolChanges,
    84  		Alloc: types.GenesisAlloc{
    85  			testAddr:     {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}},
    86  			testContract: {Nonce: 1, Code: []byte{0x13, 0x37}},
    87  			testEmpty:    {Balance: big.NewInt(1)},
    88  		},
    89  		ExtraData: []byte("test genesis"),
    90  		Timestamp: 9000,
    91  	}
    92  	generate := func(i int, g *core.BlockGen) {
    93  		g.OffsetTime(5)
    94  		g.SetExtra([]byte("test"))
    95  	}
    96  	_, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 1, generate)
    97  	blocks = append([]*types.Block{genesis.ToBlock()}, blocks...)
    98  	return genesis, blocks
    99  }
   100  
   101  func TestGethClient(t *testing.T) {
   102  	backend, _ := newTestBackend(t)
   103  	client := backend.Attach()
   104  	defer backend.Close()
   105  	defer client.Close()
   106  
   107  	tests := []struct {
   108  		name string
   109  		test func(t *testing.T)
   110  	}{
   111  		{
   112  			"TestGetProof1",
   113  			func(t *testing.T) { testGetProof(t, client, testAddr) },
   114  		}, {
   115  			"TestGetProof2",
   116  			func(t *testing.T) { testGetProof(t, client, testContract) },
   117  		}, {
   118  			"TestGetProofEmpty",
   119  			func(t *testing.T) { testGetProof(t, client, testEmpty) },
   120  		}, {
   121  			"TestGetProofNonExistent",
   122  			func(t *testing.T) { testGetProofNonExistent(t, client) },
   123  		}, {
   124  			"TestGetProofCanonicalizeKeys",
   125  			func(t *testing.T) { testGetProofCanonicalizeKeys(t, client) },
   126  		}, {
   127  			"TestGCStats",
   128  			func(t *testing.T) { testGCStats(t, client) },
   129  		}, {
   130  			"TestMemStats",
   131  			func(t *testing.T) { testMemStats(t, client) },
   132  		}, {
   133  			"TestGetNodeInfo",
   134  			func(t *testing.T) { testGetNodeInfo(t, client) },
   135  		}, {
   136  			"TestSubscribePendingTxHashes",
   137  			func(t *testing.T) { testSubscribePendingTransactions(t, client) },
   138  		}, {
   139  			"TestSubscribePendingTxs",
   140  			func(t *testing.T) { testSubscribeFullPendingTransactions(t, client) },
   141  		}, {
   142  			"TestCallContract",
   143  			func(t *testing.T) { testCallContract(t, client) },
   144  		}, {
   145  			"TestCallContractWithBlockOverrides",
   146  			func(t *testing.T) { testCallContractWithBlockOverrides(t, client) },
   147  		},
   148  		// The testaccesslist is a bit time-sensitive: the newTestBackend imports
   149  		// one block. The `testAccessList` fails if the miner has not yet created a
   150  		// new pending-block after the import event.
   151  		// Hence: this test should be last, execute the tests serially.
   152  		{
   153  			"TestAccessList",
   154  			func(t *testing.T) { testAccessList(t, client) },
   155  		}, {
   156  			"TestSetHead",
   157  			func(t *testing.T) { testSetHead(t, client) },
   158  		},
   159  	}
   160  	for _, tt := range tests {
   161  		t.Run(tt.name, tt.test)
   162  	}
   163  }
   164  
   165  func testAccessList(t *testing.T, client *rpc.Client) {
   166  	ec := New(client)
   167  	// Test transfer
   168  	msg := ethereum.CallMsg{
   169  		From:     testAddr,
   170  		To:       &common.Address{},
   171  		Gas:      21000,
   172  		GasPrice: big.NewInt(875000000),
   173  		Value:    big.NewInt(1),
   174  	}
   175  	al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
   176  	if err != nil {
   177  		t.Fatalf("unexpected error: %v", err)
   178  	}
   179  	if vmErr != "" {
   180  		t.Fatalf("unexpected vm error: %v", vmErr)
   181  	}
   182  	if gas != 21000 {
   183  		t.Fatalf("unexpected gas used: %v", gas)
   184  	}
   185  	if len(*al) != 0 {
   186  		t.Fatalf("unexpected length of accesslist: %v", len(*al))
   187  	}
   188  	// Test reverting transaction
   189  	msg = ethereum.CallMsg{
   190  		From:     testAddr,
   191  		To:       nil,
   192  		Gas:      100000,
   193  		GasPrice: big.NewInt(1000000000),
   194  		Value:    big.NewInt(1),
   195  		Data:     common.FromHex("0x608060806080608155fd"),
   196  	}
   197  	al, gas, vmErr, err = ec.CreateAccessList(context.Background(), msg)
   198  	if err != nil {
   199  		t.Fatalf("unexpected error: %v", err)
   200  	}
   201  	if vmErr == "" {
   202  		t.Fatalf("wanted vmErr, got none")
   203  	}
   204  	if gas == 21000 {
   205  		t.Fatalf("unexpected gas used: %v", gas)
   206  	}
   207  	if len(*al) != 1 || al.StorageKeys() != 1 {
   208  		t.Fatalf("unexpected length of accesslist: %v", len(*al))
   209  	}
   210  	// address changes between calls, so we can't test for it.
   211  	if (*al)[0].Address == common.HexToAddress("0x0") {
   212  		t.Fatalf("unexpected address: %v", (*al)[0].Address)
   213  	}
   214  	if (*al)[0].StorageKeys[0] != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000081") {
   215  		t.Fatalf("unexpected storage key: %v", (*al)[0].StorageKeys[0])
   216  	}
   217  }
   218  
   219  func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) {
   220  	ec := New(client)
   221  	ethcl := ethclient.NewClient(client)
   222  	result, err := ec.GetProof(context.Background(), addr, []string{testSlot.String()}, nil)
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  	if result.Address != addr {
   227  		t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr)
   228  	}
   229  	// test nonce
   230  	if nonce, _ := ethcl.NonceAt(context.Background(), addr, nil); result.Nonce != nonce {
   231  		t.Fatalf("invalid nonce, want: %v got: %v", nonce, result.Nonce)
   232  	}
   233  	// test balance
   234  	if balance, _ := ethcl.BalanceAt(context.Background(), addr, nil); result.Balance.Cmp(balance) != 0 {
   235  		t.Fatalf("invalid balance, want: %v got: %v", balance, result.Balance)
   236  	}
   237  	// test storage
   238  	if len(result.StorageProof) != 1 {
   239  		t.Fatalf("invalid storage proof, want 1 proof, got %v proof(s)", len(result.StorageProof))
   240  	}
   241  	for _, proof := range result.StorageProof {
   242  		if proof.Key != testSlot.String() {
   243  			t.Fatalf("invalid storage proof key, want: %q, got: %q", testSlot.String(), proof.Key)
   244  		}
   245  		slotValue, _ := ethcl.StorageAt(context.Background(), addr, common.HexToHash(proof.Key), nil)
   246  		if have, want := common.BigToHash(proof.Value), common.BytesToHash(slotValue); have != want {
   247  			t.Fatalf("addr %x, invalid storage proof value: have: %v, want: %v", addr, have, want)
   248  		}
   249  	}
   250  	// test code
   251  	code, _ := ethcl.CodeAt(context.Background(), addr, nil)
   252  	if have, want := result.CodeHash, crypto.Keccak256Hash(code); have != want {
   253  		t.Fatalf("codehash wrong, have %v want %v ", have, want)
   254  	}
   255  }
   256  
   257  func testGetProofCanonicalizeKeys(t *testing.T, client *rpc.Client) {
   258  	ec := New(client)
   259  
   260  	// Tests with non-canon input for storage keys.
   261  	// Here we check that the storage key is canonicalized.
   262  	result, err := ec.GetProof(context.Background(), testAddr, []string{"0x0dEadbeef"}, nil)
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  	if result.StorageProof[0].Key != "0xdeadbeef" {
   267  		t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key)
   268  	}
   269  	if result, err = ec.GetProof(context.Background(), testAddr, []string{"0x000deadbeef"}, nil); err != nil {
   270  		t.Fatal(err)
   271  	}
   272  	if result.StorageProof[0].Key != "0xdeadbeef" {
   273  		t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key)
   274  	}
   275  
   276  	// If the requested storage key is 32 bytes long, it will be returned as is.
   277  	hashSizedKey := "0x00000000000000000000000000000000000000000000000000000000deadbeef"
   278  	result, err = ec.GetProof(context.Background(), testAddr, []string{hashSizedKey}, nil)
   279  	if err != nil {
   280  		t.Fatal(err)
   281  	}
   282  	if result.StorageProof[0].Key != hashSizedKey {
   283  		t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key)
   284  	}
   285  }
   286  
   287  func testGetProofNonExistent(t *testing.T, client *rpc.Client) {
   288  	addr := common.HexToAddress("0x0001")
   289  	ec := New(client)
   290  	result, err := ec.GetProof(context.Background(), addr, nil, nil)
   291  	if err != nil {
   292  		t.Fatal(err)
   293  	}
   294  	if result.Address != addr {
   295  		t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr)
   296  	}
   297  	// test nonce
   298  	if result.Nonce != 0 {
   299  		t.Fatalf("invalid nonce, want: %v got: %v", 0, result.Nonce)
   300  	}
   301  	// test balance
   302  	if result.Balance.Sign() != 0 {
   303  		t.Fatalf("invalid balance, want: %v got: %v", 0, result.Balance)
   304  	}
   305  	// test storage
   306  	if have := len(result.StorageProof); have != 0 {
   307  		t.Fatalf("invalid storage proof, want 0 proof, got %v proof(s)", have)
   308  	}
   309  	// test codeHash
   310  	if have, want := result.CodeHash, (common.Hash{}); have != want {
   311  		t.Fatalf("codehash wrong, have %v want %v ", have, want)
   312  	}
   313  	// test codeHash
   314  	if have, want := result.StorageHash, (common.Hash{}); have != want {
   315  		t.Fatalf("storagehash wrong, have %v want %v ", have, want)
   316  	}
   317  }
   318  
   319  func testGCStats(t *testing.T, client *rpc.Client) {
   320  	ec := New(client)
   321  	_, err := ec.GCStats(context.Background())
   322  	if err != nil {
   323  		t.Fatal(err)
   324  	}
   325  }
   326  
   327  func testMemStats(t *testing.T, client *rpc.Client) {
   328  	ec := New(client)
   329  	stats, err := ec.MemStats(context.Background())
   330  	if err != nil {
   331  		t.Fatal(err)
   332  	}
   333  	if stats.Alloc == 0 {
   334  		t.Fatal("Invalid mem stats retrieved")
   335  	}
   336  }
   337  
   338  func testGetNodeInfo(t *testing.T, client *rpc.Client) {
   339  	ec := New(client)
   340  	info, err := ec.GetNodeInfo(context.Background())
   341  	if err != nil {
   342  		t.Fatal(err)
   343  	}
   344  
   345  	if info.Name == "" {
   346  		t.Fatal("Invalid node info retrieved")
   347  	}
   348  }
   349  
   350  func testSetHead(t *testing.T, client *rpc.Client) {
   351  	ec := New(client)
   352  	err := ec.SetHead(context.Background(), big.NewInt(0))
   353  	if err != nil {
   354  		t.Fatal(err)
   355  	}
   356  }
   357  
   358  func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) {
   359  	ec := New(client)
   360  	ethcl := ethclient.NewClient(client)
   361  	// Subscribe to Transactions
   362  	ch := make(chan common.Hash)
   363  	ec.SubscribePendingTransactions(context.Background(), ch)
   364  	// Send a transaction
   365  	chainID, err := ethcl.ChainID(context.Background())
   366  	if err != nil {
   367  		t.Fatal(err)
   368  	}
   369  	// Create transaction
   370  	tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
   371  	signer := types.LatestSignerForChainID(chainID)
   372  	signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
   373  	if err != nil {
   374  		t.Fatal(err)
   375  	}
   376  	signedTx, err := tx.WithSignature(signer, signature)
   377  	if err != nil {
   378  		t.Fatal(err)
   379  	}
   380  	// Send transaction
   381  	err = ethcl.SendTransaction(context.Background(), signedTx)
   382  	if err != nil {
   383  		t.Fatal(err)
   384  	}
   385  	// Check that the transaction was sent over the channel
   386  	hash := <-ch
   387  	if hash != signedTx.Hash() {
   388  		t.Fatalf("Invalid tx hash received, got %v, want %v", hash, signedTx.Hash())
   389  	}
   390  }
   391  
   392  func testSubscribeFullPendingTransactions(t *testing.T, client *rpc.Client) {
   393  	ec := New(client)
   394  	ethcl := ethclient.NewClient(client)
   395  	// Subscribe to Transactions
   396  	ch := make(chan *types.Transaction)
   397  	ec.SubscribeFullPendingTransactions(context.Background(), ch)
   398  	// Send a transaction
   399  	chainID, err := ethcl.ChainID(context.Background())
   400  	if err != nil {
   401  		t.Fatal(err)
   402  	}
   403  	// Create transaction
   404  	tx := types.NewTransaction(1, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
   405  	signer := types.LatestSignerForChainID(chainID)
   406  	signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
   407  	if err != nil {
   408  		t.Fatal(err)
   409  	}
   410  	signedTx, err := tx.WithSignature(signer, signature)
   411  	if err != nil {
   412  		t.Fatal(err)
   413  	}
   414  	// Send transaction
   415  	err = ethcl.SendTransaction(context.Background(), signedTx)
   416  	if err != nil {
   417  		t.Fatal(err)
   418  	}
   419  	// Check that the transaction was sent over the channel
   420  	tx = <-ch
   421  	if tx.Hash() != signedTx.Hash() {
   422  		t.Fatalf("Invalid tx hash received, got %v, want %v", tx.Hash(), signedTx.Hash())
   423  	}
   424  }
   425  
   426  func testCallContract(t *testing.T, client *rpc.Client) {
   427  	ec := New(client)
   428  	msg := ethereum.CallMsg{
   429  		From:     testAddr,
   430  		To:       &common.Address{},
   431  		Gas:      21000,
   432  		GasPrice: big.NewInt(1000000000),
   433  		Value:    big.NewInt(1),
   434  	}
   435  	// CallContract without override
   436  	if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), nil); err != nil {
   437  		t.Fatalf("unexpected error: %v", err)
   438  	}
   439  	// CallContract with override
   440  	override := OverrideAccount{
   441  		Nonce: 1,
   442  	}
   443  	mapAcc := make(map[common.Address]OverrideAccount)
   444  	mapAcc[testAddr] = override
   445  	if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), &mapAcc); err != nil {
   446  		t.Fatalf("unexpected error: %v", err)
   447  	}
   448  }
   449  
   450  func TestOverrideAccountMarshal(t *testing.T) {
   451  	om := map[common.Address]OverrideAccount{
   452  		{0x11}: {
   453  			// Zero-valued nonce is not overridden, but simply dropped by the encoder.
   454  			Nonce: 0,
   455  		},
   456  		{0xaa}: {
   457  			Nonce: 5,
   458  		},
   459  		{0xbb}: {
   460  			Code: []byte{1},
   461  		},
   462  		{0xcc}: {
   463  			// 'code', 'balance', 'state' should be set when input is
   464  			// a non-nil but empty value.
   465  			Code:    []byte{},
   466  			Balance: big.NewInt(0),
   467  			State:   map[common.Hash]common.Hash{},
   468  			// For 'stateDiff' the behavior is different, empty map
   469  			// is ignored because it makes no difference.
   470  			StateDiff: map[common.Hash]common.Hash{},
   471  		},
   472  	}
   473  
   474  	marshalled, err := json.MarshalIndent(&om, "", "  ")
   475  	if err != nil {
   476  		t.Fatalf("unexpected error: %v", err)
   477  	}
   478  
   479  	expected := `{
   480    "0x1100000000000000000000000000000000000000": {},
   481    "0xaa00000000000000000000000000000000000000": {
   482      "nonce": "0x5"
   483    },
   484    "0xbb00000000000000000000000000000000000000": {
   485      "code": "0x01"
   486    },
   487    "0xcc00000000000000000000000000000000000000": {
   488      "code": "0x",
   489      "balance": "0x0",
   490      "state": {}
   491    }
   492  }`
   493  
   494  	if string(marshalled) != expected {
   495  		t.Error("wrong output:", string(marshalled))
   496  		t.Error("want:", expected)
   497  	}
   498  }
   499  
   500  func TestBlockOverridesMarshal(t *testing.T) {
   501  	for i, tt := range []struct {
   502  		bo   BlockOverrides
   503  		want string
   504  	}{
   505  		{
   506  			bo:   BlockOverrides{},
   507  			want: `{}`,
   508  		},
   509  		{
   510  			bo: BlockOverrides{
   511  				Coinbase: common.HexToAddress("0x1111111111111111111111111111111111111111"),
   512  			},
   513  			want: `{"coinbase":"0x1111111111111111111111111111111111111111"}`,
   514  		},
   515  		{
   516  			bo: BlockOverrides{
   517  				Number:     big.NewInt(1),
   518  				Difficulty: big.NewInt(2),
   519  				Time:       3,
   520  				GasLimit:   4,
   521  				BaseFee:    big.NewInt(5),
   522  			},
   523  			want: `{"number":"0x1","difficulty":"0x2","time":"0x3","gasLimit":"0x4","baseFee":"0x5"}`,
   524  		},
   525  	} {
   526  		marshalled, err := json.Marshal(&tt.bo)
   527  		if err != nil {
   528  			t.Fatalf("unexpected error: %v", err)
   529  		}
   530  		if string(marshalled) != tt.want {
   531  			t.Errorf("Testcase #%d failed. expected\n%s\ngot\n%s", i, tt.want, string(marshalled))
   532  		}
   533  	}
   534  }
   535  
   536  func testCallContractWithBlockOverrides(t *testing.T, client *rpc.Client) {
   537  	ec := New(client)
   538  	msg := ethereum.CallMsg{
   539  		From:     testAddr,
   540  		To:       &common.Address{},
   541  		Gas:      50000,
   542  		GasPrice: big.NewInt(1000000000),
   543  		Value:    big.NewInt(1),
   544  	}
   545  	override := OverrideAccount{
   546  		// Returns coinbase address.
   547  		Code: common.FromHex("0x41806000526014600cf3"),
   548  	}
   549  	mapAcc := make(map[common.Address]OverrideAccount)
   550  	mapAcc[common.Address{}] = override
   551  	res, err := ec.CallContract(context.Background(), msg, big.NewInt(0), &mapAcc)
   552  	if err != nil {
   553  		t.Fatalf("unexpected error: %v", err)
   554  	}
   555  	if !bytes.Equal(res, common.FromHex("0x0000000000000000000000000000000000000000")) {
   556  		t.Fatalf("unexpected result: %x", res)
   557  	}
   558  
   559  	// Now test with block overrides
   560  	bo := BlockOverrides{
   561  		Coinbase: common.HexToAddress("0x1111111111111111111111111111111111111111"),
   562  	}
   563  	res, err = ec.CallContractWithBlockOverrides(context.Background(), msg, big.NewInt(0), &mapAcc, bo)
   564  	if err != nil {
   565  		t.Fatalf("unexpected error: %v", err)
   566  	}
   567  	if !bytes.Equal(res, common.FromHex("0x1111111111111111111111111111111111111111")) {
   568  		t.Fatalf("unexpected result: %x", res)
   569  	}
   570  }