github.com/dominant-strategies/go-quai@v0.28.2/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/dominant-strategies/go-quai/common" 33 "github.com/dominant-strategies/go-quai/common/hexutil" 34 "github.com/dominant-strategies/go-quai/consensus" 35 "github.com/dominant-strategies/go-quai/consensus/blake3pow" 36 "github.com/dominant-strategies/go-quai/core" 37 "github.com/dominant-strategies/go-quai/core/rawdb" 38 "github.com/dominant-strategies/go-quai/core/state" 39 "github.com/dominant-strategies/go-quai/core/types" 40 "github.com/dominant-strategies/go-quai/core/vm" 41 "github.com/dominant-strategies/go-quai/crypto" 42 "github.com/dominant-strategies/go-quai/ethdb" 43 "github.com/dominant-strategies/go-quai/internal/quaiapi" 44 "github.com/dominant-strategies/go-quai/params" 45 "github.com/dominant-strategies/go-quai/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: blake3pow.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) 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) ChainConfig() *params.ChainConfig { 130 return b.chainConfig 131 } 132 133 func (b *testBackend) Engine() consensus.Engine { 134 return b.engine 135 } 136 137 func (b *testBackend) ChainDb() ethdb.Database { 138 return b.chaindb 139 } 140 141 func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, error) { 142 statedb, err := b.chain.StateAt(block.Root()) 143 if err != nil { 144 return nil, errStateNotFound 145 } 146 return statedb, nil 147 } 148 149 func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) { 150 parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1) 151 if parent == nil { 152 return nil, vm.BlockContext{}, nil, errBlockNotFound 153 } 154 statedb, err := b.chain.StateAt(parent.Root()) 155 if err != nil { 156 return nil, vm.BlockContext{}, nil, errStateNotFound 157 } 158 if txIndex == 0 && len(block.Transactions()) == 0 { 159 return nil, vm.BlockContext{}, statedb, nil 160 } 161 // Recompute transactions up to the target index. 162 signer := types.MakeSigner(b.chainConfig, block.Number()) 163 for idx, tx := range block.Transactions() { 164 msg, _ := tx.AsMessage(signer, block.BaseFee()) 165 txContext := core.NewEVMTxContext(msg) 166 context := core.NewEVMBlockContext(block.Header(), b.chain, nil) 167 if idx == txIndex { 168 return msg, context, statedb, nil 169 } 170 vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{}) 171 if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { 172 return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) 173 } 174 statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) 175 } 176 return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) 177 } 178 179 func TestTraceCall(t *testing.T) { 180 t.Parallel() 181 182 // Initialize test accounts 183 accounts := newAccounts(3) 184 genesis := &core.Genesis{Alloc: core.GenesisAlloc{ 185 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 186 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 187 accounts[2].addr: {Balance: big.NewInt(params.Ether)}, 188 }} 189 genBlocks := 10 190 signer := types.HomesteadSigner{} 191 api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { 192 // Transfer from account[0] to account[1] 193 // value: 1000 wei 194 // fee: 0 wei 195 tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key) 196 b.AddTx(tx) 197 })) 198 199 var testSuite = []struct { 200 blockNumber rpc.BlockNumber 201 call quaiapi.TransactionArgs 202 config *TraceCallConfig 203 expectErr error 204 expect interface{} 205 }{ 206 // Standard JSON trace upon the genesis, plain transfer. 207 { 208 blockNumber: rpc.BlockNumber(0), 209 call: quaiapi.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: &quaiapi.ExecutionResult{ 217 Gas: params.TxGas, 218 Failed: false, 219 ReturnValue: "", 220 StructLogs: []quaiapi.StructLogRes{}, 221 }, 222 }, 223 // Standard JSON trace upon the head, plain transfer. 224 { 225 blockNumber: rpc.BlockNumber(genBlocks), 226 call: quaiapi.TransactionArgs{ 227 From: &accounts[0].addr, 228 To: &accounts[1].addr, 229 Value: (*hexutil.Big)(big.NewInt(1000)), 230 }, 231 config: nil, 232 expectErr: nil, 233 expect: &quaiapi.ExecutionResult{ 234 Gas: params.TxGas, 235 Failed: false, 236 ReturnValue: "", 237 StructLogs: []quaiapi.StructLogRes{}, 238 }, 239 }, 240 // Standard JSON trace upon the non-existent block, error expects 241 { 242 blockNumber: rpc.BlockNumber(genBlocks + 1), 243 call: quaiapi.TransactionArgs{ 244 From: &accounts[0].addr, 245 To: &accounts[1].addr, 246 Value: (*hexutil.Big)(big.NewInt(1000)), 247 }, 248 config: nil, 249 expectErr: fmt.Errorf("block #%d not found", genBlocks+1), 250 expect: nil, 251 }, 252 // Standard JSON trace upon the latest block 253 { 254 blockNumber: rpc.LatestBlockNumber, 255 call: quaiapi.TransactionArgs{ 256 From: &accounts[0].addr, 257 To: &accounts[1].addr, 258 Value: (*hexutil.Big)(big.NewInt(1000)), 259 }, 260 config: nil, 261 expectErr: nil, 262 expect: &quaiapi.ExecutionResult{ 263 Gas: params.TxGas, 264 Failed: false, 265 ReturnValue: "", 266 StructLogs: []quaiapi.StructLogRes{}, 267 }, 268 }, 269 // Standard JSON trace upon the pending block 270 { 271 blockNumber: rpc.PendingBlockNumber, 272 call: quaiapi.TransactionArgs{ 273 From: &accounts[0].addr, 274 To: &accounts[1].addr, 275 Value: (*hexutil.Big)(big.NewInt(1000)), 276 }, 277 config: nil, 278 expectErr: nil, 279 expect: &quaiapi.ExecutionResult{ 280 Gas: params.TxGas, 281 Failed: false, 282 ReturnValue: "", 283 StructLogs: []quaiapi.StructLogRes{}, 284 }, 285 }, 286 } 287 for _, testspec := range testSuite { 288 result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config) 289 if testspec.expectErr != nil { 290 if err == nil { 291 t.Errorf("Expect error %v, get nothing", testspec.expectErr) 292 continue 293 } 294 if !reflect.DeepEqual(err, testspec.expectErr) { 295 t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err) 296 } 297 } else { 298 if err != nil { 299 t.Errorf("Expect no error, get %v", err) 300 continue 301 } 302 if !reflect.DeepEqual(result, testspec.expect) { 303 t.Errorf("Result mismatch, want %v, get %v", testspec.expect, result) 304 } 305 } 306 } 307 } 308 309 func TestOverriddenTraceCall(t *testing.T) { 310 t.Parallel() 311 312 // Initialize test accounts 313 accounts := newAccounts(3) 314 genesis := &core.Genesis{Alloc: core.GenesisAlloc{ 315 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 316 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 317 accounts[2].addr: {Balance: big.NewInt(params.Ether)}, 318 }} 319 genBlocks := 10 320 signer := types.HomesteadSigner{} 321 api := NewAPI(newTestBackend(t, genBlocks, 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 })) 328 randomAccounts, tracer := newAccounts(3), "callTracer" 329 330 var testSuite = []struct { 331 blockNumber rpc.BlockNumber 332 call quaiapi.TransactionArgs 333 config *TraceCallConfig 334 expectErr error 335 expect *callTrace 336 }{ 337 // Succcessful call with state overriding 338 { 339 blockNumber: rpc.PendingBlockNumber, 340 call: quaiapi.TransactionArgs{ 341 From: &randomAccounts[0].addr, 342 To: &randomAccounts[1].addr, 343 Value: (*hexutil.Big)(big.NewInt(1000)), 344 }, 345 config: &TraceCallConfig{ 346 Tracer: &tracer, 347 StateOverrides: &quaiapi.StateOverride{ 348 randomAccounts[0].addr: quaiapi.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))}, 349 }, 350 }, 351 expectErr: nil, 352 expect: &callTrace{ 353 Type: "CALL", 354 From: randomAccounts[0].addr, 355 To: randomAccounts[1].addr, 356 Gas: newRPCUint64(24979000), 357 GasUsed: newRPCUint64(0), 358 Value: (*hexutil.Big)(big.NewInt(1000)), 359 }, 360 }, 361 // Invalid call without state overriding 362 { 363 blockNumber: rpc.PendingBlockNumber, 364 call: quaiapi.TransactionArgs{ 365 From: &randomAccounts[0].addr, 366 To: &randomAccounts[1].addr, 367 Value: (*hexutil.Big)(big.NewInt(1000)), 368 }, 369 config: &TraceCallConfig{ 370 Tracer: &tracer, 371 }, 372 expectErr: core.ErrInsufficientFunds, 373 expect: nil, 374 }, 375 // Successful simple contract call 376 // 377 // // SPDX-License-Identifier: GPL-3.0 378 // 379 // pragma solidity >=0.7.0 <0.8.0; 380 // 381 // /** 382 // * @title Storage 383 // * @dev Store & retrieve value in a variable 384 // */ 385 // contract Storage { 386 // uint256 public number; 387 // constructor() { 388 // number = block.number; 389 // } 390 // } 391 { 392 blockNumber: rpc.PendingBlockNumber, 393 call: quaiapi.TransactionArgs{ 394 From: &randomAccounts[0].addr, 395 To: &randomAccounts[2].addr, 396 Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number() 397 }, 398 config: &TraceCallConfig{ 399 Tracer: &tracer, 400 StateOverrides: &quaiapi.StateOverride{ 401 randomAccounts[2].addr: quaiapi.OverrideAccount{ 402 Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")), 403 StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}), 404 }, 405 }, 406 }, 407 expectErr: nil, 408 expect: &callTrace{ 409 Type: "CALL", 410 From: randomAccounts[0].addr, 411 To: randomAccounts[2].addr, 412 Input: hexutil.Bytes(common.Hex2Bytes("8381f58a")), 413 Output: hexutil.Bytes(common.BigToHash(big.NewInt(123)).Bytes()), 414 Gas: newRPCUint64(24978936), 415 GasUsed: newRPCUint64(2283), 416 Value: (*hexutil.Big)(big.NewInt(0)), 417 }, 418 }, 419 } 420 for i, testspec := range testSuite { 421 result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config) 422 if testspec.expectErr != nil { 423 if err == nil { 424 t.Errorf("test %d: want error %v, have nothing", i, testspec.expectErr) 425 continue 426 } 427 if !errors.Is(err, testspec.expectErr) { 428 t.Errorf("test %d: error mismatch, want %v, have %v", i, testspec.expectErr, err) 429 } 430 } else { 431 if err != nil { 432 t.Errorf("test %d: want no error, have %v", i, err) 433 continue 434 } 435 ret := new(callTrace) 436 if err := json.Unmarshal(result.(json.RawMessage), ret); err != nil { 437 t.Fatalf("test %d: failed to unmarshal trace result: %v", i, err) 438 } 439 if !jsonEqual(ret, testspec.expect) { 440 // uncomment this for easier debugging 441 //have, _ := json.MarshalIndent(ret, "", " ") 442 //want, _ := json.MarshalIndent(testspec.expect, "", " ") 443 //t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want)) 444 t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, testspec.expect) 445 } 446 } 447 } 448 } 449 450 func TestTraceTransaction(t *testing.T) { 451 t.Parallel() 452 453 // Initialize test accounts 454 accounts := newAccounts(2) 455 genesis := &core.Genesis{Alloc: core.GenesisAlloc{ 456 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 457 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 458 }} 459 target := common.Hash{} 460 signer := types.HomesteadSigner{} 461 api := NewAPI(newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) { 462 // Transfer from account[0] to account[1] 463 // value: 1000 wei 464 // fee: 0 wei 465 tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key) 466 b.AddTx(tx) 467 target = tx.Hash() 468 })) 469 result, err := api.TraceTransaction(context.Background(), target, nil) 470 if err != nil { 471 t.Errorf("Failed to trace transaction %v", err) 472 } 473 if !reflect.DeepEqual(result, &quaiapi.ExecutionResult{ 474 Gas: params.TxGas, 475 Failed: false, 476 ReturnValue: "", 477 StructLogs: []quaiapi.StructLogRes{}, 478 }) { 479 t.Error("Transaction tracing result is different") 480 } 481 } 482 483 func TestTraceBlock(t *testing.T) { 484 t.Parallel() 485 486 // Initialize test accounts 487 accounts := newAccounts(3) 488 genesis := &core.Genesis{Alloc: core.GenesisAlloc{ 489 accounts[0].addr: {Balance: big.NewInt(params.Ether)}, 490 accounts[1].addr: {Balance: big.NewInt(params.Ether)}, 491 accounts[2].addr: {Balance: big.NewInt(params.Ether)}, 492 }} 493 genBlocks := 10 494 signer := types.HomesteadSigner{} 495 api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { 496 // Transfer from account[0] to account[1] 497 // value: 1000 wei 498 // fee: 0 wei 499 tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key) 500 b.AddTx(tx) 501 })) 502 503 var testSuite = []struct { 504 blockNumber rpc.BlockNumber 505 config *TraceConfig 506 expect interface{} 507 expectErr error 508 }{ 509 // Trace genesis block, expect error 510 { 511 blockNumber: rpc.BlockNumber(0), 512 config: nil, 513 expect: nil, 514 expectErr: errors.New("genesis is not traceable"), 515 }, 516 // Trace head block 517 { 518 blockNumber: rpc.BlockNumber(genBlocks), 519 config: nil, 520 expectErr: nil, 521 expect: []*txTraceResult{ 522 { 523 Result: &quaiapi.ExecutionResult{ 524 Gas: params.TxGas, 525 Failed: false, 526 ReturnValue: "", 527 StructLogs: []quaiapi.StructLogRes{}, 528 }, 529 }, 530 }, 531 }, 532 // Trace non-existent block 533 { 534 blockNumber: rpc.BlockNumber(genBlocks + 1), 535 config: nil, 536 expectErr: fmt.Errorf("block #%d not found", genBlocks+1), 537 expect: nil, 538 }, 539 // Trace latest block 540 { 541 blockNumber: rpc.LatestBlockNumber, 542 config: nil, 543 expectErr: nil, 544 expect: []*txTraceResult{ 545 { 546 Result: &quaiapi.ExecutionResult{ 547 Gas: params.TxGas, 548 Failed: false, 549 ReturnValue: "", 550 StructLogs: []quaiapi.StructLogRes{}, 551 }, 552 }, 553 }, 554 }, 555 // Trace pending block 556 { 557 blockNumber: rpc.PendingBlockNumber, 558 config: nil, 559 expectErr: nil, 560 expect: []*txTraceResult{ 561 { 562 Result: &quaiapi.ExecutionResult{ 563 Gas: params.TxGas, 564 Failed: false, 565 ReturnValue: "", 566 StructLogs: []quaiapi.StructLogRes{}, 567 }, 568 }, 569 }, 570 }, 571 } 572 for _, testspec := range testSuite { 573 result, err := api.TraceBlockByNumber(context.Background(), testspec.blockNumber, testspec.config) 574 if testspec.expectErr != nil { 575 if err == nil { 576 t.Errorf("Expect error %v, get nothing", testspec.expectErr) 577 continue 578 } 579 if !reflect.DeepEqual(err, testspec.expectErr) { 580 t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err) 581 } 582 } else { 583 if err != nil { 584 t.Errorf("Expect no error, get %v", err) 585 continue 586 } 587 if !reflect.DeepEqual(result, testspec.expect) { 588 t.Errorf("Result mismatch, want %v, get %v", testspec.expect, result) 589 } 590 } 591 } 592 } 593 594 type Account struct { 595 key *ecdsa.PrivateKey 596 addr common.Address 597 } 598 599 type Accounts []Account 600 601 func (a Accounts) Len() int { return len(a) } 602 func (a Accounts) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 603 func (a Accounts) Less(i, j int) bool { return bytes.Compare(a[i].addr.Bytes(), a[j].addr.Bytes()) < 0 } 604 605 func newAccounts(n int) (accounts Accounts) { 606 for i := 0; i < n; i++ { 607 key, _ := crypto.GenerateKey() 608 addr := crypto.PubkeyToAddress(key.PublicKey) 609 accounts = append(accounts, Account{key: key, addr: addr}) 610 } 611 sort.Sort(accounts) 612 return accounts 613 } 614 615 func newRPCBalance(balance *big.Int) **hexutil.Big { 616 rpcBalance := (*hexutil.Big)(balance) 617 return &rpcBalance 618 } 619 620 func newRPCUint64(number uint64) *hexutil.Uint64 { 621 rpcUint64 := hexutil.Uint64(number) 622 return &rpcUint64 623 } 624 625 func newRPCBytes(bytes []byte) *hexutil.Bytes { 626 rpcBytes := hexutil.Bytes(bytes) 627 return &rpcBytes 628 } 629 630 func newStates(keys []common.Hash, vals []common.Hash) *map[common.Hash]common.Hash { 631 if len(keys) != len(vals) { 632 panic("invalid input") 633 } 634 m := make(map[common.Hash]common.Hash) 635 for i := 0; i < len(keys); i++ { 636 m[keys[i]] = vals[i] 637 } 638 return &m 639 }