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