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