github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/eth/tracers/api_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 tracers 18 19 import ( 20 "bytes" 21 "context" 22 "crypto/ecdsa" 23 "encoding/json" 24 "errors" 25 "fmt" 26 "math/big" 27 "reflect" 28 "sort" 29 "testing" 30 "time" 31 32 "github.com/ethereum/go-ethereum/common" 33 "github.com/ethereum/go-ethereum/common/hexutil" 34 "github.com/ethereum/go-ethereum/consensus" 35 "github.com/ethereum/go-ethereum/consensus/ethash" 36 "github.com/ethereum/go-ethereum/core" 37 "github.com/ethereum/go-ethereum/core/rawdb" 38 "github.com/ethereum/go-ethereum/core/state" 39 "github.com/ethereum/go-ethereum/core/types" 40 "github.com/ethereum/go-ethereum/core/vm" 41 "github.com/ethereum/go-ethereum/crypto" 42 "github.com/ethereum/go-ethereum/ethdb" 43 "github.com/ethereum/go-ethereum/internal/ethapi" 44 "github.com/ethereum/go-ethereum/params" 45 "github.com/ethereum/go-ethereum/rpc" 46 ) 47 48 var ( 49 errStateNotFound = errors.New("state not found") 50 errBlockNotFound = errors.New("block not found") 51 errTransactionNotFound = errors.New("transaction not found") 52 ) 53 54 type testBackend struct { 55 chainConfig *params.ChainConfig 56 engine consensus.Engine 57 chaindb ethdb.Database 58 chain *core.BlockChain 59 } 60 61 func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend { 62 backend := &testBackend{ 63 chainConfig: params.TestChainConfig, 64 engine: ethash.NewFaker(), 65 chaindb: rawdb.NewMemoryDatabase(), 66 } 67 // Generate blocks for testing 68 gspec.Config = backend.chainConfig 69 var ( 70 gendb = rawdb.NewMemoryDatabase() 71 genesis = gspec.MustCommit(gendb) 72 ) 73 blocks, _ := core.GenerateChain(backend.chainConfig, genesis, backend.engine, gendb, n, generator) 74 75 // Import the canonical chain 76 gspec.MustCommit(backend.chaindb) 77 cacheConfig := &core.CacheConfig{ 78 TrieCleanLimit: 256, 79 TrieDirtyLimit: 256, 80 TrieTimeLimit: 5 * time.Minute, 81 SnapshotLimit: 0, 82 TrieDirtyDisabled: true, // Archive mode 83 } 84 chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, backend.chainConfig, backend.engine, vm.Config{}, nil, nil, nil) 85 if err != nil { 86 t.Fatalf("failed to create tester chain: %v", err) 87 } 88 if n, err := chain.InsertChain(blocks); err != nil { 89 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 90 } 91 backend.chain = chain 92 return backend 93 } 94 95 func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 96 return b.chain.GetHeaderByHash(hash), nil 97 } 98 99 func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { 100 if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber { 101 return b.chain.CurrentHeader(), nil 102 } 103 return b.chain.GetHeaderByNumber(uint64(number)), nil 104 } 105 106 func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 107 return b.chain.GetBlockByHash(hash), nil 108 } 109 110 func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { 111 if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber { 112 return b.chain.CurrentBlock(), nil 113 } 114 return b.chain.GetBlockByNumber(uint64(number)), nil 115 } 116 117 func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { 118 tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash) 119 if tx == nil { 120 return nil, common.Hash{}, 0, 0, errTransactionNotFound 121 } 122 return tx, hash, blockNumber, index, nil 123 } 124 125 func (b *testBackend) RPCGasCap() uint64 { 126 return 25000000 127 } 128 129 func (b *testBackend) RPCRpcReturnDataLimit() uint64 { 130 return 100000 131 } 132 133 func (b *testBackend) ChainConfig() *params.ChainConfig { 134 return b.chainConfig 135 } 136 137 func (b *testBackend) Engine() consensus.Engine { 138 return b.engine 139 } 140 141 func (b *testBackend) ChainDb() ethdb.Database { 142 return b.chaindb 143 } 144 145 func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (*state.StateDB, error) { 146 statedb, err := b.chain.StateAt(block.Root()) 147 if err != nil { 148 return nil, errStateNotFound 149 } 150 return statedb, nil 151 } 152 153 func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) { 154 parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1) 155 if parent == nil { 156 return nil, vm.BlockContext{}, nil, errBlockNotFound 157 } 158 statedb, err := b.chain.StateAt(parent.Root()) 159 if err != nil { 160 return nil, vm.BlockContext{}, nil, errStateNotFound 161 } 162 if txIndex == 0 && len(block.Transactions()) == 0 { 163 return nil, vm.BlockContext{}, statedb, nil 164 } 165 // Recompute transactions up to the target index. 166 signer := types.MakeSigner(b.chainConfig, block.Number()) 167 for idx, tx := range block.Transactions() { 168 msg, _ := tx.AsMessage(signer, block.BaseFee()) 169 txContext := core.NewEVMTxContext(msg) 170 blockContext := core.NewEVMBlockContext(block.Header(), b.chain, nil) 171 if idx == txIndex { 172 return msg, blockContext, statedb, nil 173 } 174 175 vmenv := vm.NewEVM(blockContext, txContext, statedb, b.chainConfig, vm.Config{}) 176 // nolint : contextcheck 177 if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()), context.Background()); err != nil { 178 return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) 179 } 180 181 statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) 182 } 183 return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) 184 } 185 186 func (b *testBackend) GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { 187 tx, blockHash, blockNumber, index := rawdb.ReadBorTransactionWithBlockHash(b.ChainDb(), txHash, blockHash) 188 return tx, blockHash, blockNumber, index, nil 189 } 190 191 func TestTraceCall(t *testing.T) { 192 t.Parallel() 193 194 // Initialize test accounts 195 accounts := newAccounts(3) 196 genesis := &core.Genesis{Alloc: core.GenesisAlloc{ 197 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 198 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 199 accounts[2].addr: {Balance: big.NewInt(params.Ether)}, 200 }} 201 genBlocks := 10 202 signer := types.HomesteadSigner{} 203 api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { 204 // Transfer from account[0] to account[1] 205 // value: 1000 wei 206 // fee: 0 wei 207 tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key) 208 b.AddTx(tx) 209 })) 210 211 var testSuite = []struct { 212 blockNumber rpc.BlockNumber 213 call ethapi.TransactionArgs 214 config *TraceCallConfig 215 expectErr error 216 expect interface{} 217 }{ 218 // Standard JSON trace upon the genesis, plain transfer. 219 { 220 blockNumber: rpc.BlockNumber(0), 221 call: ethapi.TransactionArgs{ 222 From: &accounts[0].addr, 223 To: &accounts[1].addr, 224 Value: (*hexutil.Big)(big.NewInt(1000)), 225 }, 226 config: nil, 227 expectErr: nil, 228 expect: ðapi.ExecutionResult{ 229 Gas: params.TxGas, 230 Failed: false, 231 ReturnValue: "", 232 StructLogs: []ethapi.StructLogRes{}, 233 }, 234 }, 235 // Standard JSON trace upon the head, plain transfer. 236 { 237 blockNumber: rpc.BlockNumber(genBlocks), 238 call: ethapi.TransactionArgs{ 239 From: &accounts[0].addr, 240 To: &accounts[1].addr, 241 Value: (*hexutil.Big)(big.NewInt(1000)), 242 }, 243 config: nil, 244 expectErr: nil, 245 expect: ðapi.ExecutionResult{ 246 Gas: params.TxGas, 247 Failed: false, 248 ReturnValue: "", 249 StructLogs: []ethapi.StructLogRes{}, 250 }, 251 }, 252 // Standard JSON trace upon the non-existent block, error expects 253 { 254 blockNumber: rpc.BlockNumber(genBlocks + 1), 255 call: ethapi.TransactionArgs{ 256 From: &accounts[0].addr, 257 To: &accounts[1].addr, 258 Value: (*hexutil.Big)(big.NewInt(1000)), 259 }, 260 config: nil, 261 expectErr: fmt.Errorf("block #%d not found", genBlocks+1), 262 expect: nil, 263 }, 264 // Standard JSON trace upon the latest block 265 { 266 blockNumber: rpc.LatestBlockNumber, 267 call: ethapi.TransactionArgs{ 268 From: &accounts[0].addr, 269 To: &accounts[1].addr, 270 Value: (*hexutil.Big)(big.NewInt(1000)), 271 }, 272 config: nil, 273 expectErr: nil, 274 expect: ðapi.ExecutionResult{ 275 Gas: params.TxGas, 276 Failed: false, 277 ReturnValue: "", 278 StructLogs: []ethapi.StructLogRes{}, 279 }, 280 }, 281 // Standard JSON trace upon the pending block 282 { 283 blockNumber: rpc.PendingBlockNumber, 284 call: ethapi.TransactionArgs{ 285 From: &accounts[0].addr, 286 To: &accounts[1].addr, 287 Value: (*hexutil.Big)(big.NewInt(1000)), 288 }, 289 config: nil, 290 expectErr: nil, 291 expect: ðapi.ExecutionResult{ 292 Gas: params.TxGas, 293 Failed: false, 294 ReturnValue: "", 295 StructLogs: []ethapi.StructLogRes{}, 296 }, 297 }, 298 } 299 for _, testspec := range testSuite { 300 result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config) 301 if testspec.expectErr != nil { 302 if err == nil { 303 t.Errorf("Expect error %v, get nothing", testspec.expectErr) 304 continue 305 } 306 if !reflect.DeepEqual(err, testspec.expectErr) { 307 t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err) 308 } 309 } else { 310 if err != nil { 311 t.Errorf("Expect no error, get %v", err) 312 continue 313 } 314 if !reflect.DeepEqual(result, testspec.expect) { 315 t.Errorf("Result mismatch, want %v, get %v", testspec.expect, result) 316 } 317 } 318 } 319 } 320 321 func TestTraceTransaction(t *testing.T) { 322 t.Parallel() 323 324 // Initialize test accounts 325 accounts := newAccounts(2) 326 genesis := &core.Genesis{Alloc: core.GenesisAlloc{ 327 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 328 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 329 }} 330 target := common.Hash{} 331 signer := types.HomesteadSigner{} 332 api := NewAPI(newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) { 333 // Transfer from account[0] to account[1] 334 // value: 1000 wei 335 // fee: 0 wei 336 tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key) 337 b.AddTx(tx) 338 target = tx.Hash() 339 })) 340 result, err := api.TraceTransaction(context.Background(), target, nil) 341 if err != nil { 342 t.Errorf("Failed to trace transaction %v", err) 343 } 344 if !reflect.DeepEqual(result, ðapi.ExecutionResult{ 345 Gas: params.TxGas, 346 Failed: false, 347 ReturnValue: "", 348 StructLogs: []ethapi.StructLogRes{}, 349 }) { 350 t.Error("Transaction tracing result is different") 351 } 352 } 353 354 func TestTraceBlock(t *testing.T) { 355 t.Parallel() 356 357 // Initialize test accounts 358 accounts := newAccounts(3) 359 genesis := &core.Genesis{Alloc: core.GenesisAlloc{ 360 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 361 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 362 accounts[2].addr: {Balance: big.NewInt(params.Ether)}, 363 }} 364 genBlocks := 10 365 signer := types.HomesteadSigner{} 366 api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { 367 // Transfer from account[0] to account[1] 368 // value: 1000 wei 369 // fee: 0 wei 370 tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key) 371 b.AddTx(tx) 372 })) 373 374 var testSuite = []struct { 375 blockNumber rpc.BlockNumber 376 config *TraceConfig 377 want string 378 expectErr error 379 }{ 380 // Trace genesis block, expect error 381 { 382 blockNumber: rpc.BlockNumber(0), 383 expectErr: errors.New("genesis is not traceable"), 384 }, 385 // Trace head block 386 { 387 blockNumber: rpc.BlockNumber(genBlocks), 388 want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, 389 }, 390 // Trace non-existent block 391 { 392 blockNumber: rpc.BlockNumber(genBlocks + 1), 393 expectErr: fmt.Errorf("block #%d not found", genBlocks+1), 394 }, 395 // Trace latest block 396 { 397 blockNumber: rpc.LatestBlockNumber, 398 want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, 399 }, 400 // Trace pending block 401 { 402 blockNumber: rpc.PendingBlockNumber, 403 want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, 404 }, 405 } 406 for i, tc := range testSuite { 407 result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config) 408 if tc.expectErr != nil { 409 if err == nil { 410 t.Errorf("test %d, want error %v", i, tc.expectErr) 411 continue 412 } 413 if !reflect.DeepEqual(err, tc.expectErr) { 414 t.Errorf("test %d: error mismatch, want %v, get %v", i, tc.expectErr, err) 415 } 416 continue 417 } 418 if err != nil { 419 t.Errorf("test %d, want no error, have %v", i, err) 420 continue 421 } 422 have, _ := json.Marshal(result) 423 want := tc.want 424 if string(have) != want { 425 t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(have), want) 426 } 427 } 428 } 429 430 func TestIOdump(t *testing.T) { 431 t.Parallel() 432 433 // Initialize test accounts 434 accounts := newAccounts(5) 435 genesis := &core.Genesis{Alloc: core.GenesisAlloc{ 436 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 437 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 438 accounts[2].addr: {Balance: big.NewInt(params.Ether)}, 439 accounts[3].addr: {Balance: big.NewInt(params.Ether)}, 440 accounts[4].addr: {Balance: big.NewInt(params.Ether)}, 441 }} 442 genBlocks := 1 443 signer := types.HomesteadSigner{} 444 api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { 445 // Transfer from account[0] to account[1], account[1] to account[2], account[2] to account[3], account[3] to account[4], account[4] to account[0] 446 // value: 1000 wei 447 // fee: 0 wei 448 449 for j := 0; j < 5; j++ { 450 tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[(j+1)%5].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[j].key) 451 b.AddTx(tx) 452 } 453 })) 454 455 allowIOTracing = true 456 457 ioflag := new(bool) 458 459 *ioflag = true 460 461 var testSuite = []struct { 462 blockNumber rpc.BlockNumber 463 config *TraceConfig 464 want string 465 expectErr error 466 }{ 467 // Trace head block 468 { 469 config: &TraceConfig{ 470 IOFlag: ioflag, 471 }, 472 blockNumber: rpc.BlockNumber(genBlocks), 473 want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}},{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}},{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}},{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}},{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, 474 }, 475 } 476 477 for i, tc := range testSuite { 478 result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config) 479 if tc.expectErr != nil { 480 if err == nil { 481 t.Errorf("test %d, want error %v", i, tc.expectErr) 482 continue 483 } 484 485 if !reflect.DeepEqual(err, tc.expectErr) { 486 t.Errorf("test %d: error mismatch, want %v, get %v", i, tc.expectErr, err) 487 } 488 489 continue 490 } 491 492 if err != nil { 493 t.Errorf("test %d, want no error, have %v", i, err) 494 continue 495 } 496 497 have, err := json.Marshal(result) 498 if err != nil { 499 t.Errorf("Error in Marshal: %v", err) 500 } 501 502 want := tc.want 503 if string(have) != want { 504 t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(have), want) 505 } 506 } 507 } 508 509 func TestTracingWithOverrides(t *testing.T) { 510 t.Parallel() 511 // Initialize test accounts 512 accounts := newAccounts(3) 513 genesis := &core.Genesis{Alloc: core.GenesisAlloc{ 514 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 515 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 516 accounts[2].addr: {Balance: big.NewInt(params.Ether)}, 517 }} 518 genBlocks := 10 519 signer := types.HomesteadSigner{} 520 api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { 521 // Transfer from account[0] to account[1] 522 // value: 1000 wei 523 // fee: 0 wei 524 tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key) 525 b.AddTx(tx) 526 })) 527 randomAccounts := newAccounts(3) 528 type res struct { 529 Gas int 530 Failed bool 531 returnValue string 532 } 533 var testSuite = []struct { 534 blockNumber rpc.BlockNumber 535 call ethapi.TransactionArgs 536 config *TraceCallConfig 537 expectErr error 538 want string 539 }{ 540 // Call which can only succeed if state is state overridden 541 { 542 blockNumber: rpc.PendingBlockNumber, 543 call: ethapi.TransactionArgs{ 544 From: &randomAccounts[0].addr, 545 To: &randomAccounts[1].addr, 546 Value: (*hexutil.Big)(big.NewInt(1000)), 547 }, 548 config: &TraceCallConfig{ 549 StateOverrides: ðapi.StateOverride{ 550 randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))}, 551 }, 552 }, 553 want: `{"gas":21000,"failed":false,"returnValue":""}`, 554 }, 555 // Invalid call without state overriding 556 { 557 blockNumber: rpc.PendingBlockNumber, 558 call: ethapi.TransactionArgs{ 559 From: &randomAccounts[0].addr, 560 To: &randomAccounts[1].addr, 561 Value: (*hexutil.Big)(big.NewInt(1000)), 562 }, 563 config: &TraceCallConfig{}, 564 expectErr: core.ErrInsufficientFunds, 565 }, 566 // Successful simple contract call 567 // 568 // // SPDX-License-Identifier: GPL-3.0 569 // 570 // pragma solidity >=0.7.0 <0.8.0; 571 // 572 // /** 573 // * @title Storage 574 // * @dev Store & retrieve value in a variable 575 // */ 576 // contract Storage { 577 // uint256 public number; 578 // constructor() { 579 // number = block.number; 580 // } 581 // } 582 { 583 blockNumber: rpc.PendingBlockNumber, 584 call: ethapi.TransactionArgs{ 585 From: &randomAccounts[0].addr, 586 To: &randomAccounts[2].addr, 587 Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number() 588 }, 589 config: &TraceCallConfig{ 590 //Tracer: &tracer, 591 StateOverrides: ðapi.StateOverride{ 592 randomAccounts[2].addr: ethapi.OverrideAccount{ 593 Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")), 594 StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}), 595 }, 596 }, 597 }, 598 want: `{"gas":23347,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000007b"}`, 599 }, 600 } 601 for i, tc := range testSuite { 602 result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config) 603 if tc.expectErr != nil { 604 if err == nil { 605 t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr) 606 continue 607 } 608 if !errors.Is(err, tc.expectErr) { 609 t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err) 610 } 611 continue 612 } 613 if err != nil { 614 t.Errorf("test %d: want no error, have %v", i, err) 615 continue 616 } 617 // Turn result into res-struct 618 var ( 619 have res 620 want res 621 ) 622 resBytes, _ := json.Marshal(result) 623 json.Unmarshal(resBytes, &have) 624 json.Unmarshal([]byte(tc.want), &want) 625 if !reflect.DeepEqual(have, want) { 626 t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(resBytes), want) 627 } 628 } 629 } 630 631 type Account struct { 632 key *ecdsa.PrivateKey 633 addr common.Address 634 } 635 636 type Accounts []Account 637 638 func (a Accounts) Len() int { return len(a) } 639 func (a Accounts) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 640 func (a Accounts) Less(i, j int) bool { return bytes.Compare(a[i].addr.Bytes(), a[j].addr.Bytes()) < 0 } 641 642 func newAccounts(n int) (accounts Accounts) { 643 for i := 0; i < n; i++ { 644 key, _ := crypto.GenerateKey() 645 addr := crypto.PubkeyToAddress(key.PublicKey) 646 accounts = append(accounts, Account{key: key, addr: addr}) 647 } 648 sort.Sort(accounts) 649 return accounts 650 } 651 652 func newRPCBalance(balance *big.Int) **hexutil.Big { 653 rpcBalance := (*hexutil.Big)(balance) 654 return &rpcBalance 655 } 656 657 func newRPCBytes(bytes []byte) *hexutil.Bytes { 658 rpcBytes := hexutil.Bytes(bytes) 659 return &rpcBytes 660 } 661 662 func newStates(keys []common.Hash, vals []common.Hash) *map[common.Hash]common.Hash { 663 if len(keys) != len(vals) { 664 panic("invalid input") 665 } 666 m := make(map[common.Hash]common.Hash) 667 for i := 0; i < len(keys); i++ { 668 m[keys[i]] = vals[i] 669 } 670 return &m 671 }