github.com/shrimpyuk/bor@v0.2.15-0.20220224151350-fb4ec6020bae/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  	"math/big"
    23  	"testing"
    24  
    25  	"github.com/ethereum/go-ethereum"
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/consensus/ethash"
    28  	"github.com/ethereum/go-ethereum/core"
    29  	"github.com/ethereum/go-ethereum/core/rawdb"
    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/ethclient"
    35  	"github.com/ethereum/go-ethereum/node"
    36  	"github.com/ethereum/go-ethereum/params"
    37  	"github.com/ethereum/go-ethereum/rpc"
    38  )
    39  
    40  var (
    41  	testKey, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    42  	testAddr    = crypto.PubkeyToAddress(testKey.PublicKey)
    43  	testBalance = big.NewInt(2e15)
    44  )
    45  
    46  func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
    47  	// Generate test chain.
    48  	genesis, blocks := generateTestChain()
    49  	// Create node
    50  	n, err := node.New(&node.Config{})
    51  	if err != nil {
    52  		t.Fatalf("can't create new node: %v", err)
    53  	}
    54  	// Create Ethereum Service
    55  	config := &ethconfig.Config{Genesis: genesis}
    56  	config.Ethash.PowMode = ethash.ModeFake
    57  	ethservice, err := eth.New(n, config)
    58  	if err != nil {
    59  		t.Fatalf("can't create new ethereum service: %v", err)
    60  	}
    61  	// Import the test chain.
    62  	if err := n.Start(); err != nil {
    63  		t.Fatalf("can't start test node: %v", err)
    64  	}
    65  	if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil {
    66  		t.Fatalf("can't import test blocks: %v", err)
    67  	}
    68  	return n, blocks
    69  }
    70  
    71  func generateTestChain() (*core.Genesis, []*types.Block) {
    72  	db := rawdb.NewMemoryDatabase()
    73  	config := params.AllEthashProtocolChanges
    74  	genesis := &core.Genesis{
    75  		Config:    config,
    76  		Alloc:     core.GenesisAlloc{testAddr: {Balance: testBalance}},
    77  		ExtraData: []byte("test genesis"),
    78  		Timestamp: 9000,
    79  	}
    80  	generate := func(i int, g *core.BlockGen) {
    81  		g.OffsetTime(5)
    82  		g.SetExtra([]byte("test"))
    83  	}
    84  	gblock := genesis.ToBlock(db)
    85  	engine := ethash.NewFaker()
    86  	blocks, _ := core.GenerateChain(config, gblock, engine, db, 1, generate)
    87  	blocks = append([]*types.Block{gblock}, blocks...)
    88  	return genesis, blocks
    89  }
    90  
    91  func TestGethClient(t *testing.T) {
    92  	t.Skip("bor due to burn contract")
    93  
    94  	backend, _ := newTestBackend(t)
    95  	client, err := backend.Attach()
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  	defer backend.Close()
   100  	defer client.Close()
   101  
   102  	tests := []struct {
   103  		name string
   104  		test func(t *testing.T)
   105  	}{
   106  		{
   107  			"TestAccessList",
   108  			func(t *testing.T) { testAccessList(t, client) },
   109  		},
   110  		{
   111  			"TestGetProof",
   112  			func(t *testing.T) { testGetProof(t, client) },
   113  		}, {
   114  			"TestGCStats",
   115  			func(t *testing.T) { testGCStats(t, client) },
   116  		}, {
   117  			"TestMemStats",
   118  			func(t *testing.T) { testMemStats(t, client) },
   119  		}, {
   120  			"TestGetNodeInfo",
   121  			func(t *testing.T) { testGetNodeInfo(t, client) },
   122  		}, {
   123  			"TestSetHead",
   124  			func(t *testing.T) { testSetHead(t, client) },
   125  		}, {
   126  			"TestSubscribePendingTxs",
   127  			func(t *testing.T) { testSubscribePendingTransactions(t, client) },
   128  		}, {
   129  			"TestCallContract",
   130  			func(t *testing.T) { testCallContract(t, client) },
   131  		},
   132  	}
   133  	t.Parallel()
   134  	for _, tt := range tests {
   135  		t.Run(tt.name, tt.test)
   136  	}
   137  }
   138  
   139  func testAccessList(t *testing.T, client *rpc.Client) {
   140  	ec := New(client)
   141  	// Test transfer
   142  	msg := ethereum.CallMsg{
   143  		From:     testAddr,
   144  		To:       &common.Address{},
   145  		Gas:      21000,
   146  		GasPrice: big.NewInt(765625000),
   147  		Value:    big.NewInt(1),
   148  	}
   149  	al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
   150  	if err != nil {
   151  		t.Fatalf("unexpected error: %v", err)
   152  	}
   153  	if vmErr != "" {
   154  		t.Fatalf("unexpected vm error: %v", vmErr)
   155  	}
   156  	if gas != 21000 {
   157  		t.Fatalf("unexpected gas used: %v", gas)
   158  	}
   159  	if len(*al) != 0 {
   160  		t.Fatalf("unexpected length of accesslist: %v", len(*al))
   161  	}
   162  	// Test reverting transaction
   163  	msg = ethereum.CallMsg{
   164  		From:     testAddr,
   165  		To:       nil,
   166  		Gas:      100000,
   167  		GasPrice: big.NewInt(1000000000),
   168  		Value:    big.NewInt(1),
   169  		Data:     common.FromHex("0x608060806080608155fd"),
   170  	}
   171  	al, gas, vmErr, err = ec.CreateAccessList(context.Background(), msg)
   172  	if err != nil {
   173  		t.Fatalf("unexpected error: %v", err)
   174  	}
   175  	if vmErr == "" {
   176  		t.Fatalf("wanted vmErr, got none")
   177  	}
   178  	if gas == 21000 {
   179  		t.Fatalf("unexpected gas used: %v", gas)
   180  	}
   181  	if len(*al) != 1 || al.StorageKeys() != 1 {
   182  		t.Fatalf("unexpected length of accesslist: %v", len(*al))
   183  	}
   184  	// address changes between calls, so we can't test for it.
   185  	if (*al)[0].Address == common.HexToAddress("0x0") {
   186  		t.Fatalf("unexpected address: %v", (*al)[0].Address)
   187  	}
   188  	if (*al)[0].StorageKeys[0] != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000081") {
   189  		t.Fatalf("unexpected storage key: %v", (*al)[0].StorageKeys[0])
   190  	}
   191  }
   192  
   193  func testGetProof(t *testing.T, client *rpc.Client) {
   194  	ec := New(client)
   195  	ethcl := ethclient.NewClient(client)
   196  	result, err := ec.GetProof(context.Background(), testAddr, []string{}, nil)
   197  	if err != nil {
   198  		t.Fatal(err)
   199  	}
   200  	if !bytes.Equal(result.Address[:], testAddr[:]) {
   201  		t.Fatalf("unexpected address, want: %v got: %v", testAddr, result.Address)
   202  	}
   203  	// test nonce
   204  	nonce, _ := ethcl.NonceAt(context.Background(), result.Address, nil)
   205  	if result.Nonce != nonce {
   206  		t.Fatalf("invalid nonce, want: %v got: %v", nonce, result.Nonce)
   207  	}
   208  	// test balance
   209  	balance, _ := ethcl.BalanceAt(context.Background(), result.Address, nil)
   210  	if result.Balance.Cmp(balance) != 0 {
   211  		t.Fatalf("invalid balance, want: %v got: %v", balance, result.Balance)
   212  	}
   213  }
   214  
   215  func testGCStats(t *testing.T, client *rpc.Client) {
   216  	ec := New(client)
   217  	_, err := ec.GCStats(context.Background())
   218  	if err != nil {
   219  		t.Fatal(err)
   220  	}
   221  }
   222  
   223  func testMemStats(t *testing.T, client *rpc.Client) {
   224  	ec := New(client)
   225  	stats, err := ec.MemStats(context.Background())
   226  	if err != nil {
   227  		t.Fatal(err)
   228  	}
   229  	if stats.Alloc == 0 {
   230  		t.Fatal("Invalid mem stats retrieved")
   231  	}
   232  }
   233  
   234  func testGetNodeInfo(t *testing.T, client *rpc.Client) {
   235  	ec := New(client)
   236  	info, err := ec.GetNodeInfo(context.Background())
   237  	if err != nil {
   238  		t.Fatal(err)
   239  	}
   240  
   241  	if info.Name == "" {
   242  		t.Fatal("Invalid node info retrieved")
   243  	}
   244  }
   245  
   246  func testSetHead(t *testing.T, client *rpc.Client) {
   247  	ec := New(client)
   248  	err := ec.SetHead(context.Background(), big.NewInt(0))
   249  	if err != nil {
   250  		t.Fatal(err)
   251  	}
   252  }
   253  
   254  func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) {
   255  	ec := New(client)
   256  	ethcl := ethclient.NewClient(client)
   257  	// Subscribe to Transactions
   258  	ch := make(chan common.Hash)
   259  	ec.SubscribePendingTransactions(context.Background(), ch)
   260  	// Send a transaction
   261  	chainID, err := ethcl.ChainID(context.Background())
   262  	if err != nil {
   263  		t.Fatal(err)
   264  	}
   265  	// Create transaction
   266  	tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
   267  	signer := types.LatestSignerForChainID(chainID)
   268  	signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  	signedTx, err := tx.WithSignature(signer, signature)
   273  	if err != nil {
   274  		t.Fatal(err)
   275  	}
   276  	// Send transaction
   277  	err = ethcl.SendTransaction(context.Background(), signedTx)
   278  	if err != nil {
   279  		t.Fatal(err)
   280  	}
   281  	// Check that the transaction was send over the channel
   282  	hash := <-ch
   283  	if hash != signedTx.Hash() {
   284  		t.Fatalf("Invalid tx hash received, got %v, want %v", hash, signedTx.Hash())
   285  	}
   286  }
   287  
   288  func testCallContract(t *testing.T, client *rpc.Client) {
   289  	ec := New(client)
   290  	msg := ethereum.CallMsg{
   291  		From:     testAddr,
   292  		To:       &common.Address{},
   293  		Gas:      21000,
   294  		GasPrice: big.NewInt(1000000000),
   295  		Value:    big.NewInt(1),
   296  	}
   297  	// CallContract without override
   298  	if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), nil); err != nil {
   299  		t.Fatalf("unexpected error: %v", err)
   300  	}
   301  	// CallContract with override
   302  	override := OverrideAccount{
   303  		Nonce: 1,
   304  	}
   305  	mapAcc := make(map[common.Address]OverrideAccount)
   306  	mapAcc[testAddr] = override
   307  	if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), &mapAcc); err != nil {
   308  		t.Fatalf("unexpected error: %v", err)
   309  	}
   310  }