github.1485827954.workers.dev/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 := ðconfig.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 }