ethclient_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. // Copyright 2016 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. package ethclient
  17. import (
  18. "bytes"
  19. "context"
  20. "errors"
  21. "fmt"
  22. "math/big"
  23. "reflect"
  24. "testing"
  25. "time"
  26. "github.com/ethereum/go-ethereum"
  27. "github.com/ethereum/go-ethereum/accounts/abi/bind"
  28. "github.com/ethereum/go-ethereum/common"
  29. "github.com/ethereum/go-ethereum/consensus/ethash"
  30. "github.com/ethereum/go-ethereum/core"
  31. "github.com/ethereum/go-ethereum/core/rawdb"
  32. "github.com/ethereum/go-ethereum/core/types"
  33. "github.com/ethereum/go-ethereum/crypto"
  34. "github.com/ethereum/go-ethereum/eth"
  35. "github.com/ethereum/go-ethereum/eth/ethconfig"
  36. "github.com/ethereum/go-ethereum/node"
  37. "github.com/ethereum/go-ethereum/params"
  38. "github.com/ethereum/go-ethereum/rpc"
  39. "github.com/stretchr/testify/assert"
  40. )
  41. // Verify that Client implements the ethereum interfaces.
  42. var (
  43. _ = ethereum.ChainReader(&Client{})
  44. _ = ethereum.TransactionReader(&Client{})
  45. _ = ethereum.ChainStateReader(&Client{})
  46. _ = ethereum.ChainSyncReader(&Client{})
  47. _ = ethereum.ContractCaller(&Client{})
  48. _ = ethereum.GasEstimator(&Client{})
  49. _ = ethereum.GasPricer(&Client{})
  50. _ = ethereum.LogFilterer(&Client{})
  51. _ = ethereum.PendingStateReader(&Client{})
  52. // _ = ethereum.PendingStateEventer(&Client{})
  53. _ = ethereum.PendingContractCaller(&Client{})
  54. )
  55. func TestToFilterArg(t *testing.T) {
  56. blockHashErr := fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock")
  57. addresses := []common.Address{
  58. common.HexToAddress("0xD36722ADeC3EdCB29c8e7b5a47f352D701393462"),
  59. }
  60. blockHash := common.HexToHash(
  61. "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb",
  62. )
  63. for _, testCase := range []struct {
  64. name string
  65. input ethereum.FilterQuery
  66. output interface{}
  67. err error
  68. }{
  69. {
  70. "without BlockHash",
  71. ethereum.FilterQuery{
  72. Addresses: addresses,
  73. FromBlock: big.NewInt(1),
  74. ToBlock: big.NewInt(2),
  75. Topics: [][]common.Hash{},
  76. },
  77. map[string]interface{}{
  78. "address": addresses,
  79. "fromBlock": "0x1",
  80. "toBlock": "0x2",
  81. "topics": [][]common.Hash{},
  82. },
  83. nil,
  84. },
  85. {
  86. "with nil fromBlock and nil toBlock",
  87. ethereum.FilterQuery{
  88. Addresses: addresses,
  89. Topics: [][]common.Hash{},
  90. },
  91. map[string]interface{}{
  92. "address": addresses,
  93. "fromBlock": "0x0",
  94. "toBlock": "latest",
  95. "topics": [][]common.Hash{},
  96. },
  97. nil,
  98. },
  99. {
  100. "with negative fromBlock and negative toBlock",
  101. ethereum.FilterQuery{
  102. Addresses: addresses,
  103. FromBlock: big.NewInt(-1),
  104. ToBlock: big.NewInt(-1),
  105. Topics: [][]common.Hash{},
  106. },
  107. map[string]interface{}{
  108. "address": addresses,
  109. "fromBlock": "pending",
  110. "toBlock": "pending",
  111. "topics": [][]common.Hash{},
  112. },
  113. nil,
  114. },
  115. {
  116. "with blockhash",
  117. ethereum.FilterQuery{
  118. Addresses: addresses,
  119. BlockHash: &blockHash,
  120. Topics: [][]common.Hash{},
  121. },
  122. map[string]interface{}{
  123. "address": addresses,
  124. "blockHash": blockHash,
  125. "topics": [][]common.Hash{},
  126. },
  127. nil,
  128. },
  129. {
  130. "with blockhash and from block",
  131. ethereum.FilterQuery{
  132. Addresses: addresses,
  133. BlockHash: &blockHash,
  134. FromBlock: big.NewInt(1),
  135. Topics: [][]common.Hash{},
  136. },
  137. nil,
  138. blockHashErr,
  139. },
  140. {
  141. "with blockhash and to block",
  142. ethereum.FilterQuery{
  143. Addresses: addresses,
  144. BlockHash: &blockHash,
  145. ToBlock: big.NewInt(1),
  146. Topics: [][]common.Hash{},
  147. },
  148. nil,
  149. blockHashErr,
  150. },
  151. {
  152. "with blockhash and both from / to block",
  153. ethereum.FilterQuery{
  154. Addresses: addresses,
  155. BlockHash: &blockHash,
  156. FromBlock: big.NewInt(1),
  157. ToBlock: big.NewInt(2),
  158. Topics: [][]common.Hash{},
  159. },
  160. nil,
  161. blockHashErr,
  162. },
  163. } {
  164. t.Run(testCase.name, func(t *testing.T) {
  165. output, err := toFilterArg(testCase.input)
  166. if (testCase.err == nil) != (err == nil) {
  167. t.Fatalf("expected error %v but got %v", testCase.err, err)
  168. }
  169. if testCase.err != nil {
  170. if testCase.err.Error() != err.Error() {
  171. t.Fatalf("expected error %v but got %v", testCase.err, err)
  172. }
  173. } else if !reflect.DeepEqual(testCase.output, output) {
  174. t.Fatalf("expected filter arg %v but got %v", testCase.output, output)
  175. }
  176. })
  177. }
  178. }
  179. var (
  180. testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  181. testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
  182. testBalance = big.NewInt(2e10)
  183. )
  184. func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
  185. // Generate test chain.
  186. genesis, blocks := generateTestChain()
  187. // Create node
  188. n, err := node.New(&node.Config{})
  189. if err != nil {
  190. t.Fatalf("can't create new node: %v", err)
  191. }
  192. // Create Ethereum Service
  193. config := &ethconfig.Config{Genesis: genesis}
  194. config.Ethash.PowMode = ethash.ModeFake
  195. ethservice, err := eth.New(n, config)
  196. if err != nil {
  197. t.Fatalf("can't create new ethereum service: %v", err)
  198. }
  199. // Import the test chain.
  200. if err := n.Start(); err != nil {
  201. t.Fatalf("can't start test node: %v", err)
  202. }
  203. if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil {
  204. t.Fatalf("can't import test blocks: %v", err)
  205. }
  206. return n, blocks
  207. }
  208. func generateTestChain() (*core.Genesis, []*types.Block) {
  209. db := rawdb.NewMemoryDatabase()
  210. config := params.AllEthashProtocolChanges
  211. genesis := &core.Genesis{
  212. Config: config,
  213. Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance}},
  214. ExtraData: []byte("test genesis"),
  215. Timestamp: 9000,
  216. }
  217. generate := func(i int, g *core.BlockGen) {
  218. g.OffsetTime(5)
  219. g.SetExtra([]byte("test"))
  220. }
  221. gblock := genesis.ToBlock(db)
  222. engine := ethash.NewFaker()
  223. blocks, _ := core.GenerateChain(config, gblock, engine, db, 1, generate)
  224. blocks = append([]*types.Block{gblock}, blocks...)
  225. return genesis, blocks
  226. }
  227. func TestEthClient(t *testing.T) {
  228. backend, chain := newTestBackend(t)
  229. client, _ := backend.Attach()
  230. defer backend.Close()
  231. defer client.Close()
  232. tests := map[string]struct {
  233. test func(t *testing.T)
  234. }{
  235. "TestHeader": {
  236. func(t *testing.T) { testHeader(t, chain, client) },
  237. },
  238. "TestBalanceAt": {
  239. func(t *testing.T) { testBalanceAt(t, client) },
  240. },
  241. "TestTxInBlockInterrupted": {
  242. func(t *testing.T) { testTransactionInBlockInterrupted(t, client) },
  243. },
  244. "TestChainID": {
  245. func(t *testing.T) { testChainID(t, client) },
  246. },
  247. "TestGetBlock": {
  248. func(t *testing.T) { testGetBlock(t, client) },
  249. },
  250. "TestStatusFunctions": {
  251. func(t *testing.T) { testStatusFunctions(t, client) },
  252. },
  253. "TestCallContract": {
  254. func(t *testing.T) { testCallContract(t, client) },
  255. },
  256. "TestAtFunctions": {
  257. func(t *testing.T) { testAtFunctions(t, client) },
  258. },
  259. }
  260. t.Parallel()
  261. for name, tt := range tests {
  262. t.Run(name, tt.test)
  263. }
  264. }
  265. func testHeader(t *testing.T, chain []*types.Block, client *rpc.Client) {
  266. tests := map[string]struct {
  267. block *big.Int
  268. want *types.Header
  269. wantErr error
  270. }{
  271. "genesis": {
  272. block: big.NewInt(0),
  273. want: chain[0].Header(),
  274. },
  275. "first_block": {
  276. block: big.NewInt(1),
  277. want: chain[1].Header(),
  278. },
  279. "future_block": {
  280. block: big.NewInt(1000000000),
  281. want: nil,
  282. wantErr: ethereum.NotFound,
  283. },
  284. }
  285. for name, tt := range tests {
  286. t.Run(name, func(t *testing.T) {
  287. ec := NewClient(client)
  288. ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
  289. defer cancel()
  290. got, err := ec.HeaderByNumber(ctx, tt.block)
  291. if !errors.Is(err, tt.wantErr) {
  292. t.Fatalf("HeaderByNumber(%v) error = %q, want %q", tt.block, err, tt.wantErr)
  293. }
  294. if got != nil && got.Number != nil && got.Number.Sign() == 0 {
  295. got.Number = big.NewInt(0) // hack to make DeepEqual work
  296. }
  297. if !reflect.DeepEqual(got, tt.want) {
  298. t.Fatalf("HeaderByNumber(%v)\n = %v\nwant %v", tt.block, got, tt.want)
  299. }
  300. })
  301. }
  302. }
  303. func testBalanceAt(t *testing.T, client *rpc.Client) {
  304. tests := map[string]struct {
  305. account common.Address
  306. block *big.Int
  307. want *big.Int
  308. wantErr error
  309. }{
  310. "valid_account": {
  311. account: testAddr,
  312. block: big.NewInt(1),
  313. want: testBalance,
  314. },
  315. "non_existent_account": {
  316. account: common.Address{1},
  317. block: big.NewInt(1),
  318. want: big.NewInt(0),
  319. },
  320. "future_block": {
  321. account: testAddr,
  322. block: big.NewInt(1000000000),
  323. want: big.NewInt(0),
  324. wantErr: errors.New("header not found"),
  325. },
  326. }
  327. for name, tt := range tests {
  328. t.Run(name, func(t *testing.T) {
  329. ec := NewClient(client)
  330. ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
  331. defer cancel()
  332. got, err := ec.BalanceAt(ctx, tt.account, tt.block)
  333. if tt.wantErr != nil && (err == nil || err.Error() != tt.wantErr.Error()) {
  334. t.Fatalf("BalanceAt(%x, %v) error = %q, want %q", tt.account, tt.block, err, tt.wantErr)
  335. }
  336. if got.Cmp(tt.want) != 0 {
  337. t.Fatalf("BalanceAt(%x, %v) = %v, want %v", tt.account, tt.block, got, tt.want)
  338. }
  339. })
  340. }
  341. }
  342. func testTransactionInBlockInterrupted(t *testing.T, client *rpc.Client) {
  343. ec := NewClient(client)
  344. // Get current block by number
  345. block, err := ec.BlockByNumber(context.Background(), nil)
  346. if err != nil {
  347. t.Fatalf("unexpected error: %v", err)
  348. }
  349. // Test tx in block interupted
  350. ctx, cancel := context.WithCancel(context.Background())
  351. cancel()
  352. tx, err := ec.TransactionInBlock(ctx, block.Hash(), 1)
  353. if tx != nil {
  354. t.Fatal("transaction should be nil")
  355. }
  356. if err == nil || err == ethereum.NotFound {
  357. t.Fatal("error should not be nil/notfound")
  358. }
  359. // Test tx in block not found
  360. if _, err := ec.TransactionInBlock(context.Background(), block.Hash(), 1); err != ethereum.NotFound {
  361. t.Fatal("error should be ethereum.NotFound")
  362. }
  363. }
  364. func testChainID(t *testing.T, client *rpc.Client) {
  365. ec := NewClient(client)
  366. id, err := ec.ChainID(context.Background())
  367. if err != nil {
  368. t.Fatalf("unexpected error: %v", err)
  369. }
  370. if id == nil || id.Cmp(params.AllEthashProtocolChanges.ChainID) != 0 {
  371. t.Fatalf("ChainID returned wrong number: %+v", id)
  372. }
  373. }
  374. func testGetBlock(t *testing.T, client *rpc.Client) {
  375. ec := NewClient(client)
  376. // Get current block number
  377. blockNumber, err := ec.BlockNumber(context.Background())
  378. if err != nil {
  379. t.Fatalf("unexpected error: %v", err)
  380. }
  381. if blockNumber != 1 {
  382. t.Fatalf("BlockNumber returned wrong number: %d", blockNumber)
  383. }
  384. // Get current block by number
  385. block, err := ec.BlockByNumber(context.Background(), new(big.Int).SetUint64(blockNumber))
  386. if err != nil {
  387. t.Fatalf("unexpected error: %v", err)
  388. }
  389. if block.NumberU64() != blockNumber {
  390. t.Fatalf("BlockByNumber returned wrong block: want %d got %d", blockNumber, block.NumberU64())
  391. }
  392. // Get current block by hash
  393. blockH, err := ec.BlockByHash(context.Background(), block.Hash())
  394. if err != nil {
  395. t.Fatalf("unexpected error: %v", err)
  396. }
  397. if block.Hash() != blockH.Hash() {
  398. t.Fatalf("BlockByHash returned wrong block: want %v got %v", block.Hash().Hex(), blockH.Hash().Hex())
  399. }
  400. // Get header by number
  401. header, err := ec.HeaderByNumber(context.Background(), new(big.Int).SetUint64(blockNumber))
  402. if err != nil {
  403. t.Fatalf("unexpected error: %v", err)
  404. }
  405. if block.Header().Hash() != header.Hash() {
  406. t.Fatalf("HeaderByNumber returned wrong header: want %v got %v", block.Header().Hash().Hex(), header.Hash().Hex())
  407. }
  408. // Get header by hash
  409. headerH, err := ec.HeaderByHash(context.Background(), block.Hash())
  410. if err != nil {
  411. t.Fatalf("unexpected error: %v", err)
  412. }
  413. if block.Header().Hash() != headerH.Hash() {
  414. t.Fatalf("HeaderByHash returned wrong header: want %v got %v", block.Header().Hash().Hex(), headerH.Hash().Hex())
  415. }
  416. }
  417. func testStatusFunctions(t *testing.T, client *rpc.Client) {
  418. ec := NewClient(client)
  419. // Sync progress
  420. progress, err := ec.SyncProgress(context.Background())
  421. if err != nil {
  422. t.Fatalf("unexpected error: %v", err)
  423. }
  424. if progress != nil {
  425. t.Fatalf("unexpected progress: %v", progress)
  426. }
  427. // NetworkID
  428. networkID, err := ec.NetworkID(context.Background())
  429. if err != nil {
  430. t.Fatalf("unexpected error: %v", err)
  431. }
  432. if networkID.Cmp(big.NewInt(0)) != 0 {
  433. t.Fatalf("unexpected networkID: %v", networkID)
  434. }
  435. // SuggestGasPrice (should suggest 1 Gwei)
  436. gasPrice, err := ec.SuggestGasPrice(context.Background())
  437. if err != nil {
  438. t.Fatalf("unexpected error: %v", err)
  439. }
  440. if gasPrice.Cmp(big.NewInt(1000000000)) != 0 {
  441. t.Fatalf("unexpected gas price: %v", gasPrice)
  442. }
  443. }
  444. func testCallContract(t *testing.T, client *rpc.Client) {
  445. ec := NewClient(client)
  446. // EstimateGas
  447. msg := ethereum.CallMsg{
  448. From: testAddr,
  449. To: &common.Address{},
  450. Gas: 21000,
  451. GasPrice: big.NewInt(1),
  452. Value: big.NewInt(1),
  453. }
  454. gas, err := ec.EstimateGas(context.Background(), msg)
  455. if err != nil {
  456. t.Fatalf("unexpected error: %v", err)
  457. }
  458. if gas != 21000 {
  459. t.Fatalf("unexpected gas price: %v", gas)
  460. }
  461. // CallContract
  462. if _, err := ec.CallContract(context.Background(), msg, big.NewInt(1)); err != nil {
  463. t.Fatalf("unexpected error: %v", err)
  464. }
  465. // PendingCallCOntract
  466. if _, err := ec.PendingCallContract(context.Background(), msg); err != nil {
  467. t.Fatalf("unexpected error: %v", err)
  468. }
  469. }
  470. func testAtFunctions(t *testing.T, client *rpc.Client) {
  471. ec := NewClient(client)
  472. // send a transaction for some interesting pending status
  473. sendTransaction(ec)
  474. time.Sleep(100 * time.Millisecond)
  475. // Check pending transaction count
  476. pending, err := ec.PendingTransactionCount(context.Background())
  477. if err != nil {
  478. t.Fatalf("unexpected error: %v", err)
  479. }
  480. if pending != 1 {
  481. t.Fatalf("unexpected pending, wanted 1 got: %v", pending)
  482. }
  483. // Query balance
  484. balance, err := ec.BalanceAt(context.Background(), testAddr, nil)
  485. if err != nil {
  486. t.Fatalf("unexpected error: %v", err)
  487. }
  488. penBalance, err := ec.PendingBalanceAt(context.Background(), testAddr)
  489. if err != nil {
  490. t.Fatalf("unexpected error: %v", err)
  491. }
  492. if balance.Cmp(penBalance) == 0 {
  493. t.Fatalf("unexpected balance: %v %v", balance, penBalance)
  494. }
  495. // NonceAt
  496. nonce, err := ec.NonceAt(context.Background(), testAddr, nil)
  497. if err != nil {
  498. t.Fatalf("unexpected error: %v", err)
  499. }
  500. penNonce, err := ec.PendingNonceAt(context.Background(), testAddr)
  501. if err != nil {
  502. t.Fatalf("unexpected error: %v", err)
  503. }
  504. if penNonce != nonce+1 {
  505. t.Fatalf("unexpected nonce: %v %v", nonce, penNonce)
  506. }
  507. // StorageAt
  508. storage, err := ec.StorageAt(context.Background(), testAddr, common.Hash{}, nil)
  509. if err != nil {
  510. t.Fatalf("unexpected error: %v", err)
  511. }
  512. penStorage, err := ec.PendingStorageAt(context.Background(), testAddr, common.Hash{})
  513. if err != nil {
  514. t.Fatalf("unexpected error: %v", err)
  515. }
  516. if !bytes.Equal(storage, penStorage) {
  517. t.Fatalf("unexpected storage: %v %v", storage, penStorage)
  518. }
  519. // CodeAt
  520. code, err := ec.CodeAt(context.Background(), testAddr, nil)
  521. if err != nil {
  522. t.Fatalf("unexpected error: %v", err)
  523. }
  524. penCode, err := ec.PendingCodeAt(context.Background(), testAddr)
  525. if err != nil {
  526. t.Fatalf("unexpected error: %v", err)
  527. }
  528. if !bytes.Equal(code, penCode) {
  529. t.Fatalf("unexpected code: %v %v", code, penCode)
  530. }
  531. }
  532. func sendTransaction(ec *Client) error {
  533. // Retrieve chainID
  534. chainID, err := ec.ChainID(context.Background())
  535. if err != nil {
  536. return err
  537. }
  538. // Create transaction
  539. tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
  540. signer := types.LatestSignerForChainID(chainID)
  541. signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
  542. if err != nil {
  543. return err
  544. }
  545. signedTx, err := tx.WithSignature(signer, signature)
  546. if err != nil {
  547. return err
  548. }
  549. // Send transaction
  550. return ec.SendTransaction(context.Background(), signedTx, bind.PrivateTxArgs{PrivateFor: nil})
  551. }
  552. // Quorum
  553. func TestClient_PreparePrivateTransaction_whenTypical(t *testing.T) {
  554. testObject := NewClient(nil)
  555. _, err := testObject.PreparePrivateTransaction([]byte("arbitrary payload"), "arbitrary private from")
  556. assert.Error(t, err)
  557. }
  558. func TestClient_PreparePrivateTransaction_whenClientIsConfigured(t *testing.T) {
  559. expectedData := []byte("arbitrary payload")
  560. expectedDataEPH := common.BytesToEncryptedPayloadHash(expectedData)
  561. testObject := NewClient(nil)
  562. testObject.pc = &privateTransactionManagerStubClient{expectedData}
  563. actualData, err := testObject.PreparePrivateTransaction([]byte("arbitrary payload"), "arbitrary private from")
  564. assert.NoError(t, err)
  565. assert.Equal(t, expectedDataEPH, actualData)
  566. }
  567. type privateTransactionManagerStubClient struct {
  568. expectedData []byte
  569. }
  570. func (s *privateTransactionManagerStubClient) StoreRaw(data []byte, from string) (common.EncryptedPayloadHash, error) {
  571. return common.BytesToEncryptedPayloadHash(data), nil
  572. }