github.com/daethereum/go-dae@v2.2.3+incompatible/ethclient/ethclient.go (about) 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 17 // Package ethclient provides a client for the Ethereum RPC API. 18 package ethclient 19 20 import ( 21 "context" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "math/big" 26 27 "github.com/daethereum/go-dae" 28 "github.com/daethereum/go-dae/common" 29 "github.com/daethereum/go-dae/common/hexutil" 30 "github.com/daethereum/go-dae/core/types" 31 "github.com/daethereum/go-dae/rpc" 32 ) 33 34 // Client defines typed wrappers for the Ethereum RPC API. 35 type Client struct { 36 c *rpc.Client 37 } 38 39 // Dial connects a client to the given URL. 40 func Dial(rawurl string) (*Client, error) { 41 return DialContext(context.Background(), rawurl) 42 } 43 44 func DialContext(ctx context.Context, rawurl string) (*Client, error) { 45 c, err := rpc.DialContext(ctx, rawurl) 46 if err != nil { 47 return nil, err 48 } 49 return NewClient(c), nil 50 } 51 52 // NewClient creates a client that uses the given RPC client. 53 func NewClient(c *rpc.Client) *Client { 54 return &Client{c} 55 } 56 57 func (ec *Client) Close() { 58 ec.c.Close() 59 } 60 61 // Blockchain Access 62 63 // ChainID retrieves the current chain ID for transaction replay protection. 64 func (ec *Client) ChainID(ctx context.Context) (*big.Int, error) { 65 var result hexutil.Big 66 err := ec.c.CallContext(ctx, &result, "eth_chainId") 67 if err != nil { 68 return nil, err 69 } 70 return (*big.Int)(&result), err 71 } 72 73 // BlockByHash returns the given full block. 74 // 75 // Note that loading full blocks requires two requests. Use HeaderByHash 76 // if you don't need all transactions or uncle headers. 77 func (ec *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 78 return ec.getBlock(ctx, "eth_getBlockByHash", hash, true) 79 } 80 81 // BlockByNumber returns a block from the current canonical chain. If number is nil, the 82 // latest known block is returned. 83 // 84 // Note that loading full blocks requires two requests. Use HeaderByNumber 85 // if you don't need all transactions or uncle headers. 86 func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { 87 return ec.getBlock(ctx, "eth_getBlockByNumber", toBlockNumArg(number), true) 88 } 89 90 // BlockNumber returns the most recent block number 91 func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) { 92 var result hexutil.Uint64 93 err := ec.c.CallContext(ctx, &result, "eth_blockNumber") 94 return uint64(result), err 95 } 96 97 // PeerCount returns the number of p2p peers as reported by the net_peerCount method. 98 func (ec *Client) PeerCount(ctx context.Context) (uint64, error) { 99 var result hexutil.Uint64 100 err := ec.c.CallContext(ctx, &result, "net_peerCount") 101 return uint64(result), err 102 } 103 104 type rpcBlock struct { 105 Hash common.Hash `json:"hash"` 106 Transactions []rpcTransaction `json:"transactions"` 107 UncleHashes []common.Hash `json:"uncles"` 108 } 109 110 func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) { 111 var raw json.RawMessage 112 err := ec.c.CallContext(ctx, &raw, method, args...) 113 if err != nil { 114 return nil, err 115 } else if len(raw) == 0 { 116 return nil, ethereum.NotFound 117 } 118 // Decode header and transactions. 119 var head *types.Header 120 var body rpcBlock 121 if err := json.Unmarshal(raw, &head); err != nil { 122 return nil, err 123 } 124 if err := json.Unmarshal(raw, &body); err != nil { 125 return nil, err 126 } 127 // Quick-verify transaction and uncle lists. This mostly helps with debugging the server. 128 if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 { 129 return nil, fmt.Errorf("server returned non-empty uncle list but block header indicates no uncles") 130 } 131 if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 { 132 return nil, fmt.Errorf("server returned empty uncle list but block header indicates uncles") 133 } 134 if head.TxHash == types.EmptyRootHash && len(body.Transactions) > 0 { 135 return nil, fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions") 136 } 137 if head.TxHash != types.EmptyRootHash && len(body.Transactions) == 0 { 138 return nil, fmt.Errorf("server returned empty transaction list but block header indicates transactions") 139 } 140 // Load uncles because they are not included in the block response. 141 var uncles []*types.Header 142 if len(body.UncleHashes) > 0 { 143 uncles = make([]*types.Header, len(body.UncleHashes)) 144 reqs := make([]rpc.BatchElem, len(body.UncleHashes)) 145 for i := range reqs { 146 reqs[i] = rpc.BatchElem{ 147 Method: "eth_getUncleByBlockHashAndIndex", 148 Args: []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))}, 149 Result: &uncles[i], 150 } 151 } 152 if err := ec.c.BatchCallContext(ctx, reqs); err != nil { 153 return nil, err 154 } 155 for i := range reqs { 156 if reqs[i].Error != nil { 157 return nil, reqs[i].Error 158 } 159 if uncles[i] == nil { 160 return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:]) 161 } 162 } 163 } 164 // Fill the sender cache of transactions in the block. 165 txs := make([]*types.Transaction, len(body.Transactions)) 166 for i, tx := range body.Transactions { 167 if tx.From != nil { 168 setSenderFromServer(tx.tx, *tx.From, body.Hash) 169 } 170 txs[i] = tx.tx 171 } 172 return types.NewBlockWithHeader(head).WithBody(txs, uncles), nil 173 } 174 175 // HeaderByHash returns the block header with the given hash. 176 func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 177 var head *types.Header 178 err := ec.c.CallContext(ctx, &head, "eth_getBlockByHash", hash, false) 179 if err == nil && head == nil { 180 err = ethereum.NotFound 181 } 182 return head, err 183 } 184 185 // HeaderByNumber returns a block header from the current canonical chain. If number is 186 // nil, the latest known header is returned. 187 func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { 188 var head *types.Header 189 err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false) 190 if err == nil && head == nil { 191 err = ethereum.NotFound 192 } 193 return head, err 194 } 195 196 type rpcTransaction struct { 197 tx *types.Transaction 198 txExtraInfo 199 } 200 201 type txExtraInfo struct { 202 BlockNumber *string `json:"blockNumber,omitempty"` 203 BlockHash *common.Hash `json:"blockHash,omitempty"` 204 From *common.Address `json:"from,omitempty"` 205 } 206 207 func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error { 208 if err := json.Unmarshal(msg, &tx.tx); err != nil { 209 return err 210 } 211 return json.Unmarshal(msg, &tx.txExtraInfo) 212 } 213 214 // TransactionByHash returns the transaction with the given hash. 215 func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { 216 var json *rpcTransaction 217 err = ec.c.CallContext(ctx, &json, "eth_getTransactionByHash", hash) 218 if err != nil { 219 return nil, false, err 220 } else if json == nil { 221 return nil, false, ethereum.NotFound 222 } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { 223 return nil, false, fmt.Errorf("server returned transaction without signature") 224 } 225 if json.From != nil && json.BlockHash != nil { 226 setSenderFromServer(json.tx, *json.From, *json.BlockHash) 227 } 228 return json.tx, json.BlockNumber == nil, nil 229 } 230 231 // TransactionSender returns the sender address of the given transaction. The transaction 232 // must be known to the remote node and included in the blockchain at the given block and 233 // index. The sender is the one derived by the protocol at the time of inclusion. 234 // 235 // There is a fast-path for transactions retrieved by TransactionByHash and 236 // TransactionInBlock. Getting their sender address can be done without an RPC interaction. 237 func (ec *Client) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) { 238 // Try to load the address from the cache. 239 sender, err := types.Sender(&senderFromServer{blockhash: block}, tx) 240 if err == nil { 241 return sender, nil 242 } 243 244 // It was not found in cache, ask the server. 245 var meta struct { 246 Hash common.Hash 247 From common.Address 248 } 249 if err = ec.c.CallContext(ctx, &meta, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)); err != nil { 250 return common.Address{}, err 251 } 252 if meta.Hash == (common.Hash{}) || meta.Hash != tx.Hash() { 253 return common.Address{}, errors.New("wrong inclusion block/index") 254 } 255 return meta.From, nil 256 } 257 258 // TransactionCount returns the total number of transactions in the given block. 259 func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { 260 var num hexutil.Uint 261 err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByHash", blockHash) 262 return uint(num), err 263 } 264 265 // TransactionInBlock returns a single transaction at index in the given block. 266 func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { 267 var json *rpcTransaction 268 err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index)) 269 if err != nil { 270 return nil, err 271 } 272 if json == nil { 273 return nil, ethereum.NotFound 274 } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { 275 return nil, fmt.Errorf("server returned transaction without signature") 276 } 277 if json.From != nil && json.BlockHash != nil { 278 setSenderFromServer(json.tx, *json.From, *json.BlockHash) 279 } 280 return json.tx, err 281 } 282 283 // TransactionReceipt returns the receipt of a transaction by transaction hash. 284 // Note that the receipt is not available for pending transactions. 285 func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { 286 var r *types.Receipt 287 err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash) 288 if err == nil { 289 if r == nil { 290 return nil, ethereum.NotFound 291 } 292 } 293 return r, err 294 } 295 296 // SyncProgress retrieves the current progress of the sync algorithm. If there's 297 // no sync currently running, it returns nil. 298 func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) { 299 var raw json.RawMessage 300 if err := ec.c.CallContext(ctx, &raw, "eth_syncing"); err != nil { 301 return nil, err 302 } 303 // Handle the possible response types 304 var syncing bool 305 if err := json.Unmarshal(raw, &syncing); err == nil { 306 return nil, nil // Not syncing (always false) 307 } 308 var p *rpcProgress 309 if err := json.Unmarshal(raw, &p); err != nil { 310 return nil, err 311 } 312 return p.toSyncProgress(), nil 313 } 314 315 // SubscribeNewHead subscribes to notifications about the current blockchain head 316 // on the given channel. 317 func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { 318 return ec.c.EthSubscribe(ctx, ch, "newHeads") 319 } 320 321 // State Access 322 323 // NetworkID returns the network ID (also known as the chain ID) for this chain. 324 func (ec *Client) NetworkID(ctx context.Context) (*big.Int, error) { 325 version := new(big.Int) 326 var ver string 327 if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil { 328 return nil, err 329 } 330 if _, ok := version.SetString(ver, 10); !ok { 331 return nil, fmt.Errorf("invalid net_version result %q", ver) 332 } 333 return version, nil 334 } 335 336 // BalanceAt returns the wei balance of the given account. 337 // The block number can be nil, in which case the balance is taken from the latest known block. 338 func (ec *Client) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { 339 var result hexutil.Big 340 err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, toBlockNumArg(blockNumber)) 341 return (*big.Int)(&result), err 342 } 343 344 // StorageAt returns the value of key in the contract storage of the given account. 345 // The block number can be nil, in which case the value is taken from the latest known block. 346 func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { 347 var result hexutil.Bytes 348 err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, toBlockNumArg(blockNumber)) 349 return result, err 350 } 351 352 // CodeAt returns the contract code of the given account. 353 // The block number can be nil, in which case the code is taken from the latest known block. 354 func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { 355 var result hexutil.Bytes 356 err := ec.c.CallContext(ctx, &result, "eth_getCode", account, toBlockNumArg(blockNumber)) 357 return result, err 358 } 359 360 // NonceAt returns the account nonce of the given account. 361 // The block number can be nil, in which case the nonce is taken from the latest known block. 362 func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { 363 var result hexutil.Uint64 364 err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, toBlockNumArg(blockNumber)) 365 return uint64(result), err 366 } 367 368 // Filters 369 370 // FilterLogs executes a filter query. 371 func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { 372 var result []types.Log 373 arg, err := toFilterArg(q) 374 if err != nil { 375 return nil, err 376 } 377 err = ec.c.CallContext(ctx, &result, "eth_getLogs", arg) 378 return result, err 379 } 380 381 // SubscribeFilterLogs subscribes to the results of a streaming filter query. 382 func (ec *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { 383 arg, err := toFilterArg(q) 384 if err != nil { 385 return nil, err 386 } 387 return ec.c.EthSubscribe(ctx, ch, "logs", arg) 388 } 389 390 func toFilterArg(q ethereum.FilterQuery) (interface{}, error) { 391 arg := map[string]interface{}{ 392 "address": q.Addresses, 393 "topics": q.Topics, 394 } 395 if q.BlockHash != nil { 396 arg["blockHash"] = *q.BlockHash 397 if q.FromBlock != nil || q.ToBlock != nil { 398 return nil, fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock") 399 } 400 } else { 401 if q.FromBlock == nil { 402 arg["fromBlock"] = "0x0" 403 } else { 404 arg["fromBlock"] = toBlockNumArg(q.FromBlock) 405 } 406 arg["toBlock"] = toBlockNumArg(q.ToBlock) 407 } 408 return arg, nil 409 } 410 411 // Pending State 412 413 // PendingBalanceAt returns the wei balance of the given account in the pending state. 414 func (ec *Client) PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) { 415 var result hexutil.Big 416 err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, "pending") 417 return (*big.Int)(&result), err 418 } 419 420 // PendingStorageAt returns the value of key in the contract storage of the given account in the pending state. 421 func (ec *Client) PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) { 422 var result hexutil.Bytes 423 err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, "pending") 424 return result, err 425 } 426 427 // PendingCodeAt returns the contract code of the given account in the pending state. 428 func (ec *Client) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { 429 var result hexutil.Bytes 430 err := ec.c.CallContext(ctx, &result, "eth_getCode", account, "pending") 431 return result, err 432 } 433 434 // PendingNonceAt returns the account nonce of the given account in the pending state. 435 // This is the nonce that should be used for the next transaction. 436 func (ec *Client) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { 437 var result hexutil.Uint64 438 err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, "pending") 439 return uint64(result), err 440 } 441 442 // PendingTransactionCount returns the total number of transactions in the pending state. 443 func (ec *Client) PendingTransactionCount(ctx context.Context) (uint, error) { 444 var num hexutil.Uint 445 err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByNumber", "pending") 446 return uint(num), err 447 } 448 449 // Contract Calling 450 451 // CallContract executes a message call transaction, which is directly executed in the VM 452 // of the node, but never mined into the blockchain. 453 // 454 // blockNumber selects the block height at which the call runs. It can be nil, in which 455 // case the code is taken from the latest known block. Note that state from very old 456 // blocks might not be available. 457 func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { 458 var hex hexutil.Bytes 459 err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), toBlockNumArg(blockNumber)) 460 if err != nil { 461 return nil, err 462 } 463 return hex, nil 464 } 465 466 // CallContractAtHash is almost the same as CallContract except that it selects 467 // the block by block hash instead of block height. 468 func (ec *Client) CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) { 469 var hex hexutil.Bytes 470 err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false)) 471 if err != nil { 472 return nil, err 473 } 474 return hex, nil 475 } 476 477 // PendingCallContract executes a message call transaction using the EVM. 478 // The state seen by the contract call is the pending state. 479 func (ec *Client) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { 480 var hex hexutil.Bytes 481 err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), "pending") 482 if err != nil { 483 return nil, err 484 } 485 return hex, nil 486 } 487 488 // SuggestGasPrice retrieves the currently suggested gas price to allow a timely 489 // execution of a transaction. 490 func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 491 var hex hexutil.Big 492 if err := ec.c.CallContext(ctx, &hex, "eth_gasPrice"); err != nil { 493 return nil, err 494 } 495 return (*big.Int)(&hex), nil 496 } 497 498 // SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to 499 // allow a timely execution of a transaction. 500 func (ec *Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 501 var hex hexutil.Big 502 if err := ec.c.CallContext(ctx, &hex, "eth_maxPriorityFeePerGas"); err != nil { 503 return nil, err 504 } 505 return (*big.Int)(&hex), nil 506 } 507 508 // EstimateGas tries to estimate the gas needed to execute a specific transaction based on 509 // the current pending state of the backend blockchain. There is no guarantee that this is 510 // the true gas limit requirement as other transactions may be added or removed by miners, 511 // but it should provide a basis for setting a reasonable default. 512 func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) { 513 var hex hexutil.Uint64 514 err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg)) 515 if err != nil { 516 return 0, err 517 } 518 return uint64(hex), nil 519 } 520 521 // SendTransaction injects a signed transaction into the pending pool for execution. 522 // 523 // If the transaction was a contract creation use the TransactionReceipt method to get the 524 // contract address after the transaction has been mined. 525 func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error { 526 data, err := tx.MarshalBinary() 527 if err != nil { 528 return err 529 } 530 return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data)) 531 } 532 533 func toBlockNumArg(number *big.Int) string { 534 if number == nil { 535 return "latest" 536 } 537 pending := big.NewInt(-1) 538 if number.Cmp(pending) == 0 { 539 return "pending" 540 } 541 return hexutil.EncodeBig(number) 542 } 543 544 func toCallArg(msg ethereum.CallMsg) interface{} { 545 arg := map[string]interface{}{ 546 "from": msg.From, 547 "to": msg.To, 548 } 549 if len(msg.Data) > 0 { 550 arg["data"] = hexutil.Bytes(msg.Data) 551 } 552 if msg.Value != nil { 553 arg["value"] = (*hexutil.Big)(msg.Value) 554 } 555 if msg.Gas != 0 { 556 arg["gas"] = hexutil.Uint64(msg.Gas) 557 } 558 if msg.GasPrice != nil { 559 arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) 560 } 561 return arg 562 } 563 564 // rpcProgress is a copy of SyncProgress with hex-encoded fields. 565 type rpcProgress struct { 566 StartingBlock hexutil.Uint64 567 CurrentBlock hexutil.Uint64 568 HighestBlock hexutil.Uint64 569 570 PulledStates hexutil.Uint64 571 KnownStates hexutil.Uint64 572 573 SyncedAccounts hexutil.Uint64 574 SyncedAccountBytes hexutil.Uint64 575 SyncedBytecodes hexutil.Uint64 576 SyncedBytecodeBytes hexutil.Uint64 577 SyncedStorage hexutil.Uint64 578 SyncedStorageBytes hexutil.Uint64 579 HealedTrienodes hexutil.Uint64 580 HealedTrienodeBytes hexutil.Uint64 581 HealedBytecodes hexutil.Uint64 582 HealedBytecodeBytes hexutil.Uint64 583 HealingTrienodes hexutil.Uint64 584 HealingBytecode hexutil.Uint64 585 } 586 587 func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress { 588 if p == nil { 589 return nil 590 } 591 return ðereum.SyncProgress{ 592 StartingBlock: uint64(p.StartingBlock), 593 CurrentBlock: uint64(p.CurrentBlock), 594 HighestBlock: uint64(p.HighestBlock), 595 PulledStates: uint64(p.PulledStates), 596 KnownStates: uint64(p.KnownStates), 597 SyncedAccounts: uint64(p.SyncedAccounts), 598 SyncedAccountBytes: uint64(p.SyncedAccountBytes), 599 SyncedBytecodes: uint64(p.SyncedBytecodes), 600 SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes), 601 SyncedStorage: uint64(p.SyncedStorage), 602 SyncedStorageBytes: uint64(p.SyncedStorageBytes), 603 HealedTrienodes: uint64(p.HealedTrienodes), 604 HealedTrienodeBytes: uint64(p.HealedTrienodeBytes), 605 HealedBytecodes: uint64(p.HealedBytecodes), 606 HealedBytecodeBytes: uint64(p.HealedBytecodeBytes), 607 HealingTrienodes: uint64(p.HealingTrienodes), 608 HealingBytecode: uint64(p.HealingBytecode), 609 } 610 }