github.com/aidoskuneen/adk-node@v0.0.0-20220315131952-2e32567cb7f4/ethclient/gethclient/gethclient_test.go (about)

     1  // Copyright 2021 The adkgo Authors
     2  // This file is part of the adkgo library (adapted for adkgo from go--ethereum v1.10.8).
     3  //
     4  // the adkgo 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 adkgo 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 adkgo 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/aidoskuneen/adk-node"
    26  	"github.com/aidoskuneen/adk-node/common"
    27  	"github.com/aidoskuneen/adk-node/consensus/ethash"
    28  	"github.com/aidoskuneen/adk-node/core"
    29  	"github.com/aidoskuneen/adk-node/core/rawdb"
    30  	"github.com/aidoskuneen/adk-node/core/types"
    31  	"github.com/aidoskuneen/adk-node/crypto"
    32  	"github.com/aidoskuneen/adk-node/eth"
    33  	"github.com/aidoskuneen/adk-node/eth/ethconfig"
    34  	"github.com/aidoskuneen/adk-node/ethclient"
    35  	"github.com/aidoskuneen/adk-node/node"
    36  	"github.com/aidoskuneen/adk-node/params"
    37  	"github.com/aidoskuneen/adk-node/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  	backend, _ := newTestBackend(t)
    93  	client, err := backend.Attach()
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  	defer backend.Close()
    98  	defer client.Close()
    99  
   100  	tests := map[string]struct {
   101  		test func(t *testing.T)
   102  	}{
   103  		"TestAccessList": {
   104  			func(t *testing.T) { testAccessList(t, client) },
   105  		},
   106  		"TestGetProof": {
   107  			func(t *testing.T) { testGetProof(t, client) },
   108  		},
   109  		"TestGCStats": {
   110  			func(t *testing.T) { testGCStats(t, client) },
   111  		},
   112  		"TestMemStats": {
   113  			func(t *testing.T) { testMemStats(t, client) },
   114  		},
   115  		"TestGetNodeInfo": {
   116  			func(t *testing.T) { testGetNodeInfo(t, client) },
   117  		},
   118  		"TestSetHead": {
   119  			func(t *testing.T) { testSetHead(t, client) },
   120  		},
   121  		"TestSubscribePendingTxs": {
   122  			func(t *testing.T) { testSubscribePendingTransactions(t, client) },
   123  		},
   124  		"TestCallContract": {
   125  			func(t *testing.T) { testCallContract(t, client) },
   126  		},
   127  	}
   128  	t.Parallel()
   129  	for name, tt := range tests {
   130  		t.Run(name, tt.test)
   131  	}
   132  }
   133  
   134  func testAccessList(t *testing.T, client *rpc.Client) {
   135  	ec := New(client)
   136  	// Test transfer
   137  	msg := ethereum.CallMsg{
   138  		From:     testAddr,
   139  		To:       &common.Address{},
   140  		Gas:      21000,
   141  		GasPrice: big.NewInt(765625000),
   142  		Value:    big.NewInt(1),
   143  	}
   144  	al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
   145  	if err != nil {
   146  		t.Fatalf("unexpected error: %v", err)
   147  	}
   148  	if vmErr != "" {
   149  		t.Fatalf("unexpected vm error: %v", vmErr)
   150  	}
   151  	if gas != 21000 {
   152  		t.Fatalf("unexpected gas used: %v", gas)
   153  	}
   154  	if len(*al) != 0 {
   155  		t.Fatalf("unexpected length of accesslist: %v", len(*al))
   156  	}
   157  	// Test reverting transaction
   158  	msg = ethereum.CallMsg{
   159  		From:     testAddr,
   160  		To:       nil,
   161  		Gas:      100000,
   162  		GasPrice: big.NewInt(1000000000),
   163  		Value:    big.NewInt(1),
   164  		Data:     common.FromHex("0x608060806080608155fd"),
   165  	}
   166  	al, gas, vmErr, err = ec.CreateAccessList(context.Background(), msg)
   167  	if err != nil {
   168  		t.Fatalf("unexpected error: %v", err)
   169  	}
   170  	if vmErr == "" {
   171  		t.Fatalf("wanted vmErr, got none")
   172  	}
   173  	if gas == 21000 {
   174  		t.Fatalf("unexpected gas used: %v", gas)
   175  	}
   176  	if len(*al) != 1 || al.StorageKeys() != 1 {
   177  		t.Fatalf("unexpected length of accesslist: %v", len(*al))
   178  	}
   179  	// address changes between calls, so we can't test for it.
   180  	if (*al)[0].Address == common.HexToAddress("0x0") {
   181  		t.Fatalf("unexpected address: %v", (*al)[0].Address)
   182  	}
   183  	if (*al)[0].StorageKeys[0] != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000081") {
   184  		t.Fatalf("unexpected storage key: %v", (*al)[0].StorageKeys[0])
   185  	}
   186  }
   187  
   188  func testGetProof(t *testing.T, client *rpc.Client) {
   189  	ec := New(client)
   190  	ethcl := ethclient.NewClient(client)
   191  	result, err := ec.GetProof(context.Background(), testAddr, []string{}, nil)
   192  	if err != nil {
   193  		t.Fatal(err)
   194  	}
   195  	if !bytes.Equal(result.Address[:], testAddr[:]) {
   196  		t.Fatalf("unexpected address, want: %v got: %v", testAddr, result.Address)
   197  	}
   198  	// test nonce
   199  	nonce, _ := ethcl.NonceAt(context.Background(), result.Address, nil)
   200  	if result.Nonce != nonce {
   201  		t.Fatalf("invalid nonce, want: %v got: %v", nonce, result.Nonce)
   202  	}
   203  	// test balance
   204  	balance, _ := ethcl.BalanceAt(context.Background(), result.Address, nil)
   205  	if result.Balance.Cmp(balance) != 0 {
   206  		t.Fatalf("invalid balance, want: %v got: %v", balance, result.Balance)
   207  	}
   208  }
   209  
   210  func testGCStats(t *testing.T, client *rpc.Client) {
   211  	ec := New(client)
   212  	_, err := ec.GCStats(context.Background())
   213  	if err != nil {
   214  		t.Fatal(err)
   215  	}
   216  }
   217  
   218  func testMemStats(t *testing.T, client *rpc.Client) {
   219  	ec := New(client)
   220  	stats, err := ec.MemStats(context.Background())
   221  	if err != nil {
   222  		t.Fatal(err)
   223  	}
   224  	if stats.Alloc == 0 {
   225  		t.Fatal("Invalid mem stats retrieved")
   226  	}
   227  }
   228  
   229  func testGetNodeInfo(t *testing.T, client *rpc.Client) {
   230  	ec := New(client)
   231  	info, err := ec.GetNodeInfo(context.Background())
   232  	if err != nil {
   233  		t.Fatal(err)
   234  	}
   235  
   236  	if info.Name == "" {
   237  		t.Fatal("Invalid node info retrieved")
   238  	}
   239  }
   240  
   241  func testSetHead(t *testing.T, client *rpc.Client) {
   242  	ec := New(client)
   243  	err := ec.SetHead(context.Background(), big.NewInt(0))
   244  	if err != nil {
   245  		t.Fatal(err)
   246  	}
   247  }
   248  
   249  func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) {
   250  	ec := New(client)
   251  	ethcl := ethclient.NewClient(client)
   252  	// Subscribe to Transactions
   253  	ch := make(chan common.Hash)
   254  	ec.SubscribePendingTransactions(context.Background(), ch)
   255  	// Send a transaction
   256  	chainID, err := ethcl.ChainID(context.Background())
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  	// Create transaction
   261  	tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
   262  	signer := types.LatestSignerForChainID(chainID)
   263  	signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  	signedTx, err := tx.WithSignature(signer, signature)
   268  	if err != nil {
   269  		t.Fatal(err)
   270  	}
   271  	// Send transaction
   272  	err = ethcl.SendTransaction(context.Background(), signedTx)
   273  	if err != nil {
   274  		t.Fatal(err)
   275  	}
   276  	// Check that the transaction was send over the channel
   277  	hash := <-ch
   278  	if hash != signedTx.Hash() {
   279  		t.Fatalf("Invalid tx hash received, got %v, want %v", hash, signedTx.Hash())
   280  	}
   281  }
   282  
   283  func testCallContract(t *testing.T, client *rpc.Client) {
   284  	ec := New(client)
   285  	msg := ethereum.CallMsg{
   286  		From:     testAddr,
   287  		To:       &common.Address{},
   288  		Gas:      21000,
   289  		GasPrice: big.NewInt(1000000000),
   290  		Value:    big.NewInt(1),
   291  	}
   292  	// CallContract without override
   293  	if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), nil); err != nil {
   294  		t.Fatalf("unexpected error: %v", err)
   295  	}
   296  	// CallContract with override
   297  	override := OverrideAccount{
   298  		Nonce: 1,
   299  	}
   300  	mapAcc := make(map[common.Address]OverrideAccount)
   301  	mapAcc[testAddr] = override
   302  	if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), &mapAcc); err != nil {
   303  		t.Fatalf("unexpected error: %v", err)
   304  	}
   305  }