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