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