gethclient.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. // Package gethclient provides an RPC client for geth-specific APIs.
  17. package gethclient
  18. import (
  19. "context"
  20. "math/big"
  21. "runtime"
  22. "runtime/debug"
  23. "github.com/ethereum/go-ethereum"
  24. "github.com/ethereum/go-ethereum/common"
  25. "github.com/ethereum/go-ethereum/common/hexutil"
  26. "github.com/ethereum/go-ethereum/core/types"
  27. "github.com/ethereum/go-ethereum/p2p"
  28. "github.com/ethereum/go-ethereum/rpc"
  29. )
  30. // Client is a wrapper around rpc.Client that implements geth-specific functionality.
  31. //
  32. // If you want to use the standardized Ethereum RPC functionality, use ethclient.Client instead.
  33. type Client struct {
  34. c *rpc.Client
  35. }
  36. // New creates a client that uses the given RPC client.
  37. func New(c *rpc.Client) *Client {
  38. return &Client{c}
  39. }
  40. // CreateAccessList tries to create an access list for a specific transaction based on the
  41. // current pending state of the blockchain.
  42. func (ec *Client) CreateAccessList(ctx context.Context, msg ethereum.CallMsg) (*types.AccessList, uint64, string, error) {
  43. type accessListResult struct {
  44. Accesslist *types.AccessList `json:"accessList"`
  45. Error string `json:"error,omitempty"`
  46. GasUsed hexutil.Uint64 `json:"gasUsed"`
  47. }
  48. var result accessListResult
  49. if err := ec.c.CallContext(ctx, &result, "eth_createAccessList", toCallArg(msg)); err != nil {
  50. return nil, 0, "", err
  51. }
  52. return result.Accesslist, uint64(result.GasUsed), result.Error, nil
  53. }
  54. // AccountResult is the result of a GetProof operation.
  55. type AccountResult struct {
  56. Address common.Address `json:"address"`
  57. AccountProof []string `json:"accountProof"`
  58. Balance *big.Int `json:"balance"`
  59. CodeHash common.Hash `json:"codeHash"`
  60. Nonce uint64 `json:"nonce"`
  61. StorageHash common.Hash `json:"storageHash"`
  62. StorageProof []StorageResult `json:"storageProof"`
  63. }
  64. // StorageResult provides a proof for a key-value pair.
  65. type StorageResult struct {
  66. Key string `json:"key"`
  67. Value *big.Int `json:"value"`
  68. Proof []string `json:"proof"`
  69. }
  70. // GetProof returns the account and storage values of the specified account including the Merkle-proof.
  71. // The block number can be nil, in which case the value is taken from the latest known block.
  72. func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []string, blockNumber *big.Int) (*AccountResult, error) {
  73. type storageResult struct {
  74. Key string `json:"key"`
  75. Value *hexutil.Big `json:"value"`
  76. Proof []string `json:"proof"`
  77. }
  78. type accountResult struct {
  79. Address common.Address `json:"address"`
  80. AccountProof []string `json:"accountProof"`
  81. Balance *hexutil.Big `json:"balance"`
  82. CodeHash common.Hash `json:"codeHash"`
  83. Nonce hexutil.Uint64 `json:"nonce"`
  84. StorageHash common.Hash `json:"storageHash"`
  85. StorageProof []storageResult `json:"storageProof"`
  86. }
  87. var res accountResult
  88. err := ec.c.CallContext(ctx, &res, "eth_getProof", account, keys, toBlockNumArg(blockNumber))
  89. // Turn hexutils back to normal datatypes
  90. storageResults := make([]StorageResult, 0, len(res.StorageProof))
  91. for _, st := range res.StorageProof {
  92. storageResults = append(storageResults, StorageResult{
  93. Key: st.Key,
  94. Value: st.Value.ToInt(),
  95. Proof: st.Proof,
  96. })
  97. }
  98. result := AccountResult{
  99. Address: res.Address,
  100. AccountProof: res.AccountProof,
  101. Balance: res.Balance.ToInt(),
  102. Nonce: uint64(res.Nonce),
  103. CodeHash: res.CodeHash,
  104. StorageHash: res.StorageHash,
  105. StorageProof: storageResults,
  106. }
  107. return &result, err
  108. }
  109. // OverrideAccount specifies the state of an account to be overridden.
  110. type OverrideAccount struct {
  111. Nonce uint64 `json:"nonce"`
  112. Code []byte `json:"code"`
  113. Balance *big.Int `json:"balance"`
  114. State map[common.Hash]common.Hash `json:"state"`
  115. StateDiff map[common.Hash]common.Hash `json:"stateDiff"`
  116. }
  117. // CallContract executes a message call transaction, which is directly executed in the VM
  118. // of the node, but never mined into the blockchain.
  119. //
  120. // blockNumber selects the block height at which the call runs. It can be nil, in which
  121. // case the code is taken from the latest known block. Note that state from very old
  122. // blocks might not be available.
  123. //
  124. // overrides specifies a map of contract states that should be overwritten before executing
  125. // the message call.
  126. // Please use ethclient.CallContract instead if you don't need the override functionality.
  127. func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int, overrides *map[common.Address]OverrideAccount) ([]byte, error) {
  128. var hex hexutil.Bytes
  129. err := ec.c.CallContext(
  130. ctx, &hex, "eth_call", toCallArg(msg),
  131. toBlockNumArg(blockNumber), toOverrideMap(overrides),
  132. )
  133. return hex, err
  134. }
  135. // GCStats retrieves the current garbage collection stats from a geth node.
  136. func (ec *Client) GCStats(ctx context.Context) (*debug.GCStats, error) {
  137. var result debug.GCStats
  138. err := ec.c.CallContext(ctx, &result, "debug_gcStats")
  139. return &result, err
  140. }
  141. // MemStats retrieves the current memory stats from a geth node.
  142. func (ec *Client) MemStats(ctx context.Context) (*runtime.MemStats, error) {
  143. var result runtime.MemStats
  144. err := ec.c.CallContext(ctx, &result, "debug_memStats")
  145. return &result, err
  146. }
  147. // SetHead sets the current head of the local chain by block number.
  148. // Note, this is a destructive action and may severely damage your chain.
  149. // Use with extreme caution.
  150. func (ec *Client) SetHead(ctx context.Context, number *big.Int) error {
  151. return ec.c.CallContext(ctx, nil, "debug_setHead", toBlockNumArg(number))
  152. }
  153. // GetNodeInfo retrieves the node info of a geth node.
  154. func (ec *Client) GetNodeInfo(ctx context.Context) (*p2p.NodeInfo, error) {
  155. var result p2p.NodeInfo
  156. err := ec.c.CallContext(ctx, &result, "admin_nodeInfo")
  157. return &result, err
  158. }
  159. // SubscribePendingTransactions subscribes to new pending transactions.
  160. func (ec *Client) SubscribePendingTransactions(ctx context.Context, ch chan<- common.Hash) (*rpc.ClientSubscription, error) {
  161. return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions")
  162. }
  163. func toBlockNumArg(number *big.Int) string {
  164. if number == nil {
  165. return "latest"
  166. }
  167. pending := big.NewInt(-1)
  168. if number.Cmp(pending) == 0 {
  169. return "pending"
  170. }
  171. return hexutil.EncodeBig(number)
  172. }
  173. func toCallArg(msg ethereum.CallMsg) interface{} {
  174. arg := map[string]interface{}{
  175. "from": msg.From,
  176. "to": msg.To,
  177. }
  178. if len(msg.Data) > 0 {
  179. arg["data"] = hexutil.Bytes(msg.Data)
  180. }
  181. if msg.Value != nil {
  182. arg["value"] = (*hexutil.Big)(msg.Value)
  183. }
  184. if msg.Gas != 0 {
  185. arg["gas"] = hexutil.Uint64(msg.Gas)
  186. }
  187. if msg.GasPrice != nil {
  188. arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
  189. }
  190. return arg
  191. }
  192. func toOverrideMap(overrides *map[common.Address]OverrideAccount) interface{} {
  193. if overrides == nil {
  194. return nil
  195. }
  196. type overrideAccount struct {
  197. Nonce hexutil.Uint64 `json:"nonce"`
  198. Code hexutil.Bytes `json:"code"`
  199. Balance *hexutil.Big `json:"balance"`
  200. State map[common.Hash]common.Hash `json:"state"`
  201. StateDiff map[common.Hash]common.Hash `json:"stateDiff"`
  202. }
  203. result := make(map[common.Address]overrideAccount)
  204. for addr, override := range *overrides {
  205. result[addr] = overrideAccount{
  206. Nonce: hexutil.Uint64(override.Nonce),
  207. Code: override.Code,
  208. Balance: (*hexutil.Big)(override.Balance),
  209. State: override.State,
  210. StateDiff: override.StateDiff,
  211. }
  212. }
  213. return &result
  214. }