From b4c66584a694ca48fda713ee9775b07229e51fa5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Isabel=20Sch=C3=B6ps=20Thiel?=
<155141998+IST-Github@users.noreply.github.com>
Date: Mon, 1 Jan 2024 00:42:39 +0100
Subject: [PATCH] Delete ethclient directory
---
ethclient/ethclient.go | 716 -----------------------
ethclient/ethclient_test.go | 745 ------------------------
ethclient/gethclient/gethclient.go | 335 -----------
ethclient/gethclient/gethclient_test.go | 570 ------------------
ethclient/signer.go | 62 --
5 files changed, 2428 deletions(-)
delete mode 100644 ethclient/ethclient.go
delete mode 100644 ethclient/ethclient_test.go
delete mode 100644 ethclient/gethclient/gethclient.go
delete mode 100644 ethclient/gethclient/gethclient_test.go
delete mode 100644 ethclient/signer.go
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go
deleted file mode 100644
index e8a201f71b..0000000000
--- a/ethclient/ethclient.go
+++ /dev/null
@@ -1,716 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-// Package ethclient provides a client for the Ethereum RPC API.
-package ethclient
-
-import (
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "math/big"
-
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/rpc"
-)
-
-// Client defines typed wrappers for the Ethereum RPC API.
-type Client struct {
- c *rpc.Client
-}
-
-// Dial connects a client to the given URL.
-func Dial(rawurl string) (*Client, error) {
- return DialContext(context.Background(), rawurl)
-}
-
-// DialContext connects a client to the given URL with context.
-func DialContext(ctx context.Context, rawurl string) (*Client, error) {
- c, err := rpc.DialContext(ctx, rawurl)
- if err != nil {
- return nil, err
- }
- return NewClient(c), nil
-}
-
-// NewClient creates a client that uses the given RPC client.
-func NewClient(c *rpc.Client) *Client {
- return &Client{c}
-}
-
-// Close closes the underlying RPC connection.
-func (ec *Client) Close() {
- ec.c.Close()
-}
-
-// Client gets the underlying RPC client.
-func (ec *Client) Client() *rpc.Client {
- return ec.c
-}
-
-// Blockchain Access
-
-// ChainID retrieves the current chain ID for transaction replay protection.
-func (ec *Client) ChainID(ctx context.Context) (*big.Int, error) {
- var result hexutil.Big
- err := ec.c.CallContext(ctx, &result, "eth_chainId")
- if err != nil {
- return nil, err
- }
- return (*big.Int)(&result), err
-}
-
-// BlockByHash returns the given full block.
-//
-// Note that loading full blocks requires two requests. Use HeaderByHash
-// if you don't need all transactions or uncle headers.
-func (ec *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
- return ec.getBlock(ctx, "eth_getBlockByHash", hash, true)
-}
-
-// BlockByNumber returns a block from the current canonical chain. If number is nil, the
-// latest known block is returned.
-//
-// Note that loading full blocks requires two requests. Use HeaderByNumber
-// if you don't need all transactions or uncle headers.
-func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
- return ec.getBlock(ctx, "eth_getBlockByNumber", toBlockNumArg(number), true)
-}
-
-// BlockNumber returns the most recent block number
-func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) {
- var result hexutil.Uint64
- err := ec.c.CallContext(ctx, &result, "eth_blockNumber")
- return uint64(result), err
-}
-
-// PeerCount returns the number of p2p peers as reported by the net_peerCount method.
-func (ec *Client) PeerCount(ctx context.Context) (uint64, error) {
- var result hexutil.Uint64
- err := ec.c.CallContext(ctx, &result, "net_peerCount")
- return uint64(result), err
-}
-
-// BlockReceipts returns the receipts of a given block number or hash.
-func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) {
- var r []*types.Receipt
- err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String())
- if err == nil && r == nil {
- return nil, ethereum.NotFound
- }
- return r, err
-}
-
-type rpcBlock struct {
- Hash common.Hash `json:"hash"`
- Transactions []rpcTransaction `json:"transactions"`
- UncleHashes []common.Hash `json:"uncles"`
- Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
-}
-
-func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) {
- var raw json.RawMessage
- err := ec.c.CallContext(ctx, &raw, method, args...)
- if err != nil {
- return nil, err
- }
-
- // Decode header and transactions.
- var head *types.Header
- if err := json.Unmarshal(raw, &head); err != nil {
- return nil, err
- }
- // When the block is not found, the API returns JSON null.
- if head == nil {
- return nil, ethereum.NotFound
- }
-
- var body rpcBlock
- if err := json.Unmarshal(raw, &body); err != nil {
- return nil, err
- }
- // Quick-verify transaction and uncle lists. This mostly helps with debugging the server.
- if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 {
- return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles")
- }
- if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 {
- return nil, errors.New("server returned empty uncle list but block header indicates uncles")
- }
- if head.TxHash == types.EmptyTxsHash && len(body.Transactions) > 0 {
- return nil, errors.New("server returned non-empty transaction list but block header indicates no transactions")
- }
- if head.TxHash != types.EmptyTxsHash && len(body.Transactions) == 0 {
- return nil, errors.New("server returned empty transaction list but block header indicates transactions")
- }
- // Load uncles because they are not included in the block response.
- var uncles []*types.Header
- if len(body.UncleHashes) > 0 {
- uncles = make([]*types.Header, len(body.UncleHashes))
- reqs := make([]rpc.BatchElem, len(body.UncleHashes))
- for i := range reqs {
- reqs[i] = rpc.BatchElem{
- Method: "eth_getUncleByBlockHashAndIndex",
- Args: []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))},
- Result: &uncles[i],
- }
- }
- if err := ec.c.BatchCallContext(ctx, reqs); err != nil {
- return nil, err
- }
- for i := range reqs {
- if reqs[i].Error != nil {
- return nil, reqs[i].Error
- }
- if uncles[i] == nil {
- return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:])
- }
- }
- }
- // Fill the sender cache of transactions in the block.
- txs := make([]*types.Transaction, len(body.Transactions))
- for i, tx := range body.Transactions {
- if tx.From != nil {
- setSenderFromServer(tx.tx, *tx.From, body.Hash)
- }
- txs[i] = tx.tx
- }
- return types.NewBlockWithHeader(head).WithBody(txs, uncles).WithWithdrawals(body.Withdrawals), nil
-}
-
-// HeaderByHash returns the block header with the given hash.
-func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
- var head *types.Header
- err := ec.c.CallContext(ctx, &head, "eth_getBlockByHash", hash, false)
- if err == nil && head == nil {
- err = ethereum.NotFound
- }
- return head, err
-}
-
-// HeaderByNumber returns a block header from the current canonical chain. If number is
-// nil, the latest known header is returned.
-func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
- var head *types.Header
- err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false)
- if err == nil && head == nil {
- err = ethereum.NotFound
- }
- return head, err
-}
-
-type rpcTransaction struct {
- tx *types.Transaction
- txExtraInfo
-}
-
-type txExtraInfo struct {
- BlockNumber *string `json:"blockNumber,omitempty"`
- BlockHash *common.Hash `json:"blockHash,omitempty"`
- From *common.Address `json:"from,omitempty"`
-}
-
-func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error {
- if err := json.Unmarshal(msg, &tx.tx); err != nil {
- return err
- }
- return json.Unmarshal(msg, &tx.txExtraInfo)
-}
-
-// TransactionByHash returns the transaction with the given hash.
-func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) {
- var json *rpcTransaction
- err = ec.c.CallContext(ctx, &json, "eth_getTransactionByHash", hash)
- if err != nil {
- return nil, false, err
- } else if json == nil {
- return nil, false, ethereum.NotFound
- } else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
- return nil, false, errors.New("server returned transaction without signature")
- }
- if json.From != nil && json.BlockHash != nil {
- setSenderFromServer(json.tx, *json.From, *json.BlockHash)
- }
- return json.tx, json.BlockNumber == nil, nil
-}
-
-// TransactionSender returns the sender address of the given transaction. The transaction
-// must be known to the remote node and included in the blockchain at the given block and
-// index. The sender is the one derived by the protocol at the time of inclusion.
-//
-// There is a fast-path for transactions retrieved by TransactionByHash and
-// TransactionInBlock. Getting their sender address can be done without an RPC interaction.
-func (ec *Client) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) {
- // Try to load the address from the cache.
- sender, err := types.Sender(&senderFromServer{blockhash: block}, tx)
- if err == nil {
- return sender, nil
- }
-
- // It was not found in cache, ask the server.
- var meta struct {
- Hash common.Hash
- From common.Address
- }
- if err = ec.c.CallContext(ctx, &meta, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)); err != nil {
- return common.Address{}, err
- }
- if meta.Hash == (common.Hash{}) || meta.Hash != tx.Hash() {
- return common.Address{}, errors.New("wrong inclusion block/index")
- }
- return meta.From, nil
-}
-
-// TransactionCount returns the total number of transactions in the given block.
-func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) {
- var num hexutil.Uint
- err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByHash", blockHash)
- return uint(num), err
-}
-
-// TransactionInBlock returns a single transaction at index in the given block.
-func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
- var json *rpcTransaction
- err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index))
- if err != nil {
- return nil, err
- }
- if json == nil {
- return nil, ethereum.NotFound
- } else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
- return nil, errors.New("server returned transaction without signature")
- }
- if json.From != nil && json.BlockHash != nil {
- setSenderFromServer(json.tx, *json.From, *json.BlockHash)
- }
- return json.tx, err
-}
-
-// TransactionReceipt returns the receipt of a transaction by transaction hash.
-// Note that the receipt is not available for pending transactions.
-func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
- var r *types.Receipt
- err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash)
- if err == nil {
- if r == nil {
- return nil, ethereum.NotFound
- }
- }
- return r, err
-}
-
-// SyncProgress retrieves the current progress of the sync algorithm. If there's
-// no sync currently running, it returns nil.
-func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) {
- var raw json.RawMessage
- if err := ec.c.CallContext(ctx, &raw, "eth_syncing"); err != nil {
- return nil, err
- }
- // Handle the possible response types
- var syncing bool
- if err := json.Unmarshal(raw, &syncing); err == nil {
- return nil, nil // Not syncing (always false)
- }
- var p *rpcProgress
- if err := json.Unmarshal(raw, &p); err != nil {
- return nil, err
- }
- return p.toSyncProgress(), nil
-}
-
-// SubscribeNewHead subscribes to notifications about the current blockchain head
-// on the given channel.
-func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
- sub, err := ec.c.EthSubscribe(ctx, ch, "newHeads")
- if err != nil {
- // Defensively prefer returning nil interface explicitly on error-path, instead
- // of letting default golang behavior wrap it with non-nil interface that stores
- // nil concrete type value.
- return nil, err
- }
- return sub, nil
-}
-
-// State Access
-
-// NetworkID returns the network ID for this client.
-func (ec *Client) NetworkID(ctx context.Context) (*big.Int, error) {
- version := new(big.Int)
- var ver string
- if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil {
- return nil, err
- }
- if _, ok := version.SetString(ver, 10); !ok {
- return nil, fmt.Errorf("invalid net_version result %q", ver)
- }
- return version, nil
-}
-
-// BalanceAt returns the wei balance of the given account.
-// The block number can be nil, in which case the balance is taken from the latest known block.
-func (ec *Client) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) {
- var result hexutil.Big
- err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, toBlockNumArg(blockNumber))
- return (*big.Int)(&result), err
-}
-
-// BalanceAtHash returns the wei balance of the given account.
-func (ec *Client) BalanceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (*big.Int, error) {
- var result hexutil.Big
- err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
- return (*big.Int)(&result), err
-}
-
-// StorageAt returns the value of key in the contract storage of the given account.
-// The block number can be nil, in which case the value is taken from the latest known block.
-func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
- var result hexutil.Bytes
- err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, toBlockNumArg(blockNumber))
- return result, err
-}
-
-// StorageAtHash returns the value of key in the contract storage of the given account.
-func (ec *Client) StorageAtHash(ctx context.Context, account common.Address, key common.Hash, blockHash common.Hash) ([]byte, error) {
- var result hexutil.Bytes
- err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, rpc.BlockNumberOrHashWithHash(blockHash, false))
- return result, err
-}
-
-// CodeAt returns the contract code of the given account.
-// The block number can be nil, in which case the code is taken from the latest known block.
-func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) {
- var result hexutil.Bytes
- err := ec.c.CallContext(ctx, &result, "eth_getCode", account, toBlockNumArg(blockNumber))
- return result, err
-}
-
-// CodeAtHash returns the contract code of the given account.
-func (ec *Client) CodeAtHash(ctx context.Context, account common.Address, blockHash common.Hash) ([]byte, error) {
- var result hexutil.Bytes
- err := ec.c.CallContext(ctx, &result, "eth_getCode", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
- return result, err
-}
-
-// NonceAt returns the account nonce of the given account.
-// The block number can be nil, in which case the nonce is taken from the latest known block.
-func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) {
- var result hexutil.Uint64
- err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, toBlockNumArg(blockNumber))
- return uint64(result), err
-}
-
-// NonceAtHash returns the account nonce of the given account.
-func (ec *Client) NonceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (uint64, error) {
- var result hexutil.Uint64
- err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, rpc.BlockNumberOrHashWithHash(blockHash, false))
- return uint64(result), err
-}
-
-// Filters
-
-// FilterLogs executes a filter query.
-func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) {
- var result []types.Log
- arg, err := toFilterArg(q)
- if err != nil {
- return nil, err
- }
- err = ec.c.CallContext(ctx, &result, "eth_getLogs", arg)
- return result, err
-}
-
-// SubscribeFilterLogs subscribes to the results of a streaming filter query.
-func (ec *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
- arg, err := toFilterArg(q)
- if err != nil {
- return nil, err
- }
- sub, err := ec.c.EthSubscribe(ctx, ch, "logs", arg)
- if err != nil {
- // Defensively prefer returning nil interface explicitly on error-path, instead
- // of letting default golang behavior wrap it with non-nil interface that stores
- // nil concrete type value.
- return nil, err
- }
- return sub, nil
-}
-
-func toFilterArg(q ethereum.FilterQuery) (interface{}, error) {
- arg := map[string]interface{}{
- "address": q.Addresses,
- "topics": q.Topics,
- }
- if q.BlockHash != nil {
- arg["blockHash"] = *q.BlockHash
- if q.FromBlock != nil || q.ToBlock != nil {
- return nil, errors.New("cannot specify both BlockHash and FromBlock/ToBlock")
- }
- } else {
- if q.FromBlock == nil {
- arg["fromBlock"] = "0x0"
- } else {
- arg["fromBlock"] = toBlockNumArg(q.FromBlock)
- }
- arg["toBlock"] = toBlockNumArg(q.ToBlock)
- }
- return arg, nil
-}
-
-// Pending State
-
-// PendingBalanceAt returns the wei balance of the given account in the pending state.
-func (ec *Client) PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) {
- var result hexutil.Big
- err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, "pending")
- return (*big.Int)(&result), err
-}
-
-// PendingStorageAt returns the value of key in the contract storage of the given account in the pending state.
-func (ec *Client) PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) {
- var result hexutil.Bytes
- err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, "pending")
- return result, err
-}
-
-// PendingCodeAt returns the contract code of the given account in the pending state.
-func (ec *Client) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) {
- var result hexutil.Bytes
- err := ec.c.CallContext(ctx, &result, "eth_getCode", account, "pending")
- return result, err
-}
-
-// PendingNonceAt returns the account nonce of the given account in the pending state.
-// This is the nonce that should be used for the next transaction.
-func (ec *Client) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
- var result hexutil.Uint64
- err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, "pending")
- return uint64(result), err
-}
-
-// PendingTransactionCount returns the total number of transactions in the pending state.
-func (ec *Client) PendingTransactionCount(ctx context.Context) (uint, error) {
- var num hexutil.Uint
- err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByNumber", "pending")
- return uint(num), err
-}
-
-// Contract Calling
-
-// CallContract executes a message call transaction, which is directly executed in the VM
-// of the node, but never mined into the blockchain.
-//
-// blockNumber selects the block height at which the call runs. It can be nil, in which
-// case the code is taken from the latest known block. Note that state from very old
-// blocks might not be available.
-func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
- var hex hexutil.Bytes
- err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), toBlockNumArg(blockNumber))
- if err != nil {
- return nil, err
- }
- return hex, nil
-}
-
-// CallContractAtHash is almost the same as CallContract except that it selects
-// the block by block hash instead of block height.
-func (ec *Client) CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) {
- var hex hexutil.Bytes
- err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false))
- if err != nil {
- return nil, err
- }
- return hex, nil
-}
-
-// PendingCallContract executes a message call transaction using the EVM.
-// The state seen by the contract call is the pending state.
-func (ec *Client) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) {
- var hex hexutil.Bytes
- err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), "pending")
- if err != nil {
- return nil, err
- }
- return hex, nil
-}
-
-// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
-// execution of a transaction.
-func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
- var hex hexutil.Big
- if err := ec.c.CallContext(ctx, &hex, "eth_gasPrice"); err != nil {
- return nil, err
- }
- return (*big.Int)(&hex), nil
-}
-
-// SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to
-// allow a timely execution of a transaction.
-func (ec *Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
- var hex hexutil.Big
- if err := ec.c.CallContext(ctx, &hex, "eth_maxPriorityFeePerGas"); err != nil {
- return nil, err
- }
- return (*big.Int)(&hex), nil
-}
-
-type feeHistoryResultMarshaling struct {
- OldestBlock *hexutil.Big `json:"oldestBlock"`
- Reward [][]*hexutil.Big `json:"reward,omitempty"`
- BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"`
- GasUsedRatio []float64 `json:"gasUsedRatio"`
-}
-
-// FeeHistory retrieves the fee market history.
-func (ec *Client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*ethereum.FeeHistory, error) {
- var res feeHistoryResultMarshaling
- if err := ec.c.CallContext(ctx, &res, "eth_feeHistory", hexutil.Uint(blockCount), toBlockNumArg(lastBlock), rewardPercentiles); err != nil {
- return nil, err
- }
- reward := make([][]*big.Int, len(res.Reward))
- for i, r := range res.Reward {
- reward[i] = make([]*big.Int, len(r))
- for j, r := range r {
- reward[i][j] = (*big.Int)(r)
- }
- }
- baseFee := make([]*big.Int, len(res.BaseFee))
- for i, b := range res.BaseFee {
- baseFee[i] = (*big.Int)(b)
- }
- return ðereum.FeeHistory{
- OldestBlock: (*big.Int)(res.OldestBlock),
- Reward: reward,
- BaseFee: baseFee,
- GasUsedRatio: res.GasUsedRatio,
- }, nil
-}
-
-// EstimateGas tries to estimate the gas needed to execute a specific transaction based on
-// the current pending state of the backend blockchain. There is no guarantee that this is
-// the true gas limit requirement as other transactions may be added or removed by miners,
-// but it should provide a basis for setting a reasonable default.
-func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) {
- var hex hexutil.Uint64
- err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg))
- if err != nil {
- return 0, err
- }
- return uint64(hex), nil
-}
-
-// SendTransaction injects a signed transaction into the pending pool for execution.
-//
-// If the transaction was a contract creation use the TransactionReceipt method to get the
-// contract address after the transaction has been mined.
-func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error {
- data, err := tx.MarshalBinary()
- if err != nil {
- return err
- }
- return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data))
-}
-
-func toBlockNumArg(number *big.Int) string {
- if number == nil {
- return "latest"
- }
- if number.Sign() >= 0 {
- return hexutil.EncodeBig(number)
- }
- // It's negative.
- if number.IsInt64() {
- return rpc.BlockNumber(number.Int64()).String()
- }
- // It's negative and large, which is invalid.
- return fmt.Sprintf("", number)
-}
-
-func toCallArg(msg ethereum.CallMsg) interface{} {
- arg := map[string]interface{}{
- "from": msg.From,
- "to": msg.To,
- }
- if len(msg.Data) > 0 {
- arg["input"] = hexutil.Bytes(msg.Data)
- }
- if msg.Value != nil {
- arg["value"] = (*hexutil.Big)(msg.Value)
- }
- if msg.Gas != 0 {
- arg["gas"] = hexutil.Uint64(msg.Gas)
- }
- if msg.GasPrice != nil {
- arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
- }
- if msg.GasFeeCap != nil {
- arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap)
- }
- if msg.GasTipCap != nil {
- arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap)
- }
- return arg
-}
-
-// rpcProgress is a copy of SyncProgress with hex-encoded fields.
-type rpcProgress struct {
- StartingBlock hexutil.Uint64
- CurrentBlock hexutil.Uint64
- HighestBlock hexutil.Uint64
-
- PulledStates hexutil.Uint64
- KnownStates hexutil.Uint64
-
- SyncedAccounts hexutil.Uint64
- SyncedAccountBytes hexutil.Uint64
- SyncedBytecodes hexutil.Uint64
- SyncedBytecodeBytes hexutil.Uint64
- SyncedStorage hexutil.Uint64
- SyncedStorageBytes hexutil.Uint64
- HealedTrienodes hexutil.Uint64
- HealedTrienodeBytes hexutil.Uint64
- HealedBytecodes hexutil.Uint64
- HealedBytecodeBytes hexutil.Uint64
- HealingTrienodes hexutil.Uint64
- HealingBytecode hexutil.Uint64
-}
-
-func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress {
- if p == nil {
- return nil
- }
- return ðereum.SyncProgress{
- StartingBlock: uint64(p.StartingBlock),
- CurrentBlock: uint64(p.CurrentBlock),
- HighestBlock: uint64(p.HighestBlock),
- PulledStates: uint64(p.PulledStates),
- KnownStates: uint64(p.KnownStates),
- SyncedAccounts: uint64(p.SyncedAccounts),
- SyncedAccountBytes: uint64(p.SyncedAccountBytes),
- SyncedBytecodes: uint64(p.SyncedBytecodes),
- SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes),
- SyncedStorage: uint64(p.SyncedStorage),
- SyncedStorageBytes: uint64(p.SyncedStorageBytes),
- HealedTrienodes: uint64(p.HealedTrienodes),
- HealedTrienodeBytes: uint64(p.HealedTrienodeBytes),
- HealedBytecodes: uint64(p.HealedBytecodes),
- HealedBytecodeBytes: uint64(p.HealedBytecodeBytes),
- HealingTrienodes: uint64(p.HealingTrienodes),
- HealingBytecode: uint64(p.HealingBytecode),
- }
-}
diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go
deleted file mode 100644
index 0f87ad5f5c..0000000000
--- a/ethclient/ethclient_test.go
+++ /dev/null
@@ -1,745 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package ethclient
-
-import (
- "bytes"
- "context"
- "errors"
- "math/big"
- "reflect"
- "testing"
- "time"
-
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/consensus/ethash"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/eth/ethconfig"
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/rpc"
-)
-
-// Verify that Client implements the ethereum interfaces.
-var (
- _ = ethereum.ChainReader(&Client{})
- _ = ethereum.TransactionReader(&Client{})
- _ = ethereum.ChainStateReader(&Client{})
- _ = ethereum.ChainSyncReader(&Client{})
- _ = ethereum.ContractCaller(&Client{})
- _ = ethereum.GasEstimator(&Client{})
- _ = ethereum.GasPricer(&Client{})
- _ = ethereum.LogFilterer(&Client{})
- _ = ethereum.PendingStateReader(&Client{})
- // _ = ethereum.PendingStateEventer(&Client{})
- _ = ethereum.PendingContractCaller(&Client{})
-)
-
-func TestToFilterArg(t *testing.T) {
- blockHashErr := errors.New("cannot specify both BlockHash and FromBlock/ToBlock")
- addresses := []common.Address{
- common.HexToAddress("0xD36722ADeC3EdCB29c8e7b5a47f352D701393462"),
- }
- blockHash := common.HexToHash(
- "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb",
- )
-
- for _, testCase := range []struct {
- name string
- input ethereum.FilterQuery
- output interface{}
- err error
- }{
- {
- "without BlockHash",
- ethereum.FilterQuery{
- Addresses: addresses,
- FromBlock: big.NewInt(1),
- ToBlock: big.NewInt(2),
- Topics: [][]common.Hash{},
- },
- map[string]interface{}{
- "address": addresses,
- "fromBlock": "0x1",
- "toBlock": "0x2",
- "topics": [][]common.Hash{},
- },
- nil,
- },
- {
- "with nil fromBlock and nil toBlock",
- ethereum.FilterQuery{
- Addresses: addresses,
- Topics: [][]common.Hash{},
- },
- map[string]interface{}{
- "address": addresses,
- "fromBlock": "0x0",
- "toBlock": "latest",
- "topics": [][]common.Hash{},
- },
- nil,
- },
- {
- "with negative fromBlock and negative toBlock",
- ethereum.FilterQuery{
- Addresses: addresses,
- FromBlock: big.NewInt(-1),
- ToBlock: big.NewInt(-1),
- Topics: [][]common.Hash{},
- },
- map[string]interface{}{
- "address": addresses,
- "fromBlock": "pending",
- "toBlock": "pending",
- "topics": [][]common.Hash{},
- },
- nil,
- },
- {
- "with blockhash",
- ethereum.FilterQuery{
- Addresses: addresses,
- BlockHash: &blockHash,
- Topics: [][]common.Hash{},
- },
- map[string]interface{}{
- "address": addresses,
- "blockHash": blockHash,
- "topics": [][]common.Hash{},
- },
- nil,
- },
- {
- "with blockhash and from block",
- ethereum.FilterQuery{
- Addresses: addresses,
- BlockHash: &blockHash,
- FromBlock: big.NewInt(1),
- Topics: [][]common.Hash{},
- },
- nil,
- blockHashErr,
- },
- {
- "with blockhash and to block",
- ethereum.FilterQuery{
- Addresses: addresses,
- BlockHash: &blockHash,
- ToBlock: big.NewInt(1),
- Topics: [][]common.Hash{},
- },
- nil,
- blockHashErr,
- },
- {
- "with blockhash and both from / to block",
- ethereum.FilterQuery{
- Addresses: addresses,
- BlockHash: &blockHash,
- FromBlock: big.NewInt(1),
- ToBlock: big.NewInt(2),
- Topics: [][]common.Hash{},
- },
- nil,
- blockHashErr,
- },
- } {
- t.Run(testCase.name, func(t *testing.T) {
- output, err := toFilterArg(testCase.input)
- if (testCase.err == nil) != (err == nil) {
- t.Fatalf("expected error %v but got %v", testCase.err, err)
- }
- if testCase.err != nil {
- if testCase.err.Error() != err.Error() {
- t.Fatalf("expected error %v but got %v", testCase.err, err)
- }
- } else if !reflect.DeepEqual(testCase.output, output) {
- t.Fatalf("expected filter arg %v but got %v", testCase.output, output)
- }
- })
- }
-}
-
-var (
- testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
- testBalance = big.NewInt(2e15)
-)
-
-var genesis = &core.Genesis{
- Config: params.AllEthashProtocolChanges,
- Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance}},
- ExtraData: []byte("test genesis"),
- Timestamp: 9000,
- BaseFee: big.NewInt(params.InitialBaseFee),
-}
-
-var testTx1 = types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), &types.LegacyTx{
- Nonce: 0,
- Value: big.NewInt(12),
- GasPrice: big.NewInt(params.InitialBaseFee),
- Gas: params.TxGas,
- To: &common.Address{2},
-})
-
-var testTx2 = types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), &types.LegacyTx{
- Nonce: 1,
- Value: big.NewInt(8),
- GasPrice: big.NewInt(params.InitialBaseFee),
- Gas: params.TxGas,
- To: &common.Address{2},
-})
-
-func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
- // Generate test chain.
- blocks := generateTestChain()
-
- // Create node
- n, err := node.New(&node.Config{})
- if err != nil {
- t.Fatalf("can't create new node: %v", err)
- }
- // Create Ethereum Service
- config := ðconfig.Config{Genesis: genesis}
- ethservice, err := eth.New(n, config)
- if err != nil {
- t.Fatalf("can't create new ethereum service: %v", err)
- }
- // Import the test chain.
- if err := n.Start(); err != nil {
- t.Fatalf("can't start test node: %v", err)
- }
- if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil {
- t.Fatalf("can't import test blocks: %v", err)
- }
- return n, blocks
-}
-
-func generateTestChain() []*types.Block {
- generate := func(i int, g *core.BlockGen) {
- g.OffsetTime(5)
- g.SetExtra([]byte("test"))
- if i == 1 {
- // Test transactions are included in block #2.
- g.AddTx(testTx1)
- g.AddTx(testTx2)
- }
- }
- _, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 2, generate)
- return append([]*types.Block{genesis.ToBlock()}, blocks...)
-}
-
-func TestEthClient(t *testing.T) {
- backend, chain := newTestBackend(t)
- client := backend.Attach()
- defer backend.Close()
- defer client.Close()
-
- tests := map[string]struct {
- test func(t *testing.T)
- }{
- "Header": {
- func(t *testing.T) { testHeader(t, chain, client) },
- },
- "BalanceAt": {
- func(t *testing.T) { testBalanceAt(t, client) },
- },
- "TxInBlockInterrupted": {
- func(t *testing.T) { testTransactionInBlockInterrupted(t, client) },
- },
- "ChainID": {
- func(t *testing.T) { testChainID(t, client) },
- },
- "GetBlock": {
- func(t *testing.T) { testGetBlock(t, client) },
- },
- "StatusFunctions": {
- func(t *testing.T) { testStatusFunctions(t, client) },
- },
- "CallContract": {
- func(t *testing.T) { testCallContract(t, client) },
- },
- "CallContractAtHash": {
- func(t *testing.T) { testCallContractAtHash(t, client) },
- },
- "AtFunctions": {
- func(t *testing.T) { testAtFunctions(t, client) },
- },
- "TransactionSender": {
- func(t *testing.T) { testTransactionSender(t, client) },
- },
- }
-
- t.Parallel()
- for name, tt := range tests {
- t.Run(name, tt.test)
- }
-}
-
-func testHeader(t *testing.T, chain []*types.Block, client *rpc.Client) {
- tests := map[string]struct {
- block *big.Int
- want *types.Header
- wantErr error
- }{
- "genesis": {
- block: big.NewInt(0),
- want: chain[0].Header(),
- },
- "first_block": {
- block: big.NewInt(1),
- want: chain[1].Header(),
- },
- "future_block": {
- block: big.NewInt(1000000000),
- want: nil,
- wantErr: ethereum.NotFound,
- },
- }
- for name, tt := range tests {
- t.Run(name, func(t *testing.T) {
- ec := NewClient(client)
- ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
- defer cancel()
-
- got, err := ec.HeaderByNumber(ctx, tt.block)
- if !errors.Is(err, tt.wantErr) {
- t.Fatalf("HeaderByNumber(%v) error = %q, want %q", tt.block, err, tt.wantErr)
- }
- if got != nil && got.Number != nil && got.Number.Sign() == 0 {
- got.Number = big.NewInt(0) // hack to make DeepEqual work
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Fatalf("HeaderByNumber(%v)\n = %v\nwant %v", tt.block, got, tt.want)
- }
- })
- }
-}
-
-func testBalanceAt(t *testing.T, client *rpc.Client) {
- tests := map[string]struct {
- account common.Address
- block *big.Int
- want *big.Int
- wantErr error
- }{
- "valid_account_genesis": {
- account: testAddr,
- block: big.NewInt(0),
- want: testBalance,
- },
- "valid_account": {
- account: testAddr,
- block: big.NewInt(1),
- want: testBalance,
- },
- "non_existent_account": {
- account: common.Address{1},
- block: big.NewInt(1),
- want: big.NewInt(0),
- },
- "future_block": {
- account: testAddr,
- block: big.NewInt(1000000000),
- want: big.NewInt(0),
- wantErr: errors.New("header not found"),
- },
- }
- for name, tt := range tests {
- t.Run(name, func(t *testing.T) {
- ec := NewClient(client)
- ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
- defer cancel()
-
- got, err := ec.BalanceAt(ctx, tt.account, tt.block)
- if tt.wantErr != nil && (err == nil || err.Error() != tt.wantErr.Error()) {
- t.Fatalf("BalanceAt(%x, %v) error = %q, want %q", tt.account, tt.block, err, tt.wantErr)
- }
- if got.Cmp(tt.want) != 0 {
- t.Fatalf("BalanceAt(%x, %v) = %v, want %v", tt.account, tt.block, got, tt.want)
- }
- })
- }
-}
-
-func testTransactionInBlockInterrupted(t *testing.T, client *rpc.Client) {
- ec := NewClient(client)
-
- // Get current block by number.
- block, err := ec.BlockByNumber(context.Background(), nil)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
-
- // Test tx in block interrupted.
- ctx, cancel := context.WithCancel(context.Background())
- cancel()
- <-ctx.Done() // Ensure the close of the Done channel
- tx, err := ec.TransactionInBlock(ctx, block.Hash(), 0)
- if tx != nil {
- t.Fatal("transaction should be nil")
- }
- if err == nil || err == ethereum.NotFound {
- t.Fatal("error should not be nil/notfound")
- }
-
- // Test tx in block not found.
- if _, err := ec.TransactionInBlock(context.Background(), block.Hash(), 20); err != ethereum.NotFound {
- t.Fatal("error should be ethereum.NotFound")
- }
-}
-
-func testChainID(t *testing.T, client *rpc.Client) {
- ec := NewClient(client)
- id, err := ec.ChainID(context.Background())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if id == nil || id.Cmp(params.AllEthashProtocolChanges.ChainID) != 0 {
- t.Fatalf("ChainID returned wrong number: %+v", id)
- }
-}
-
-func testGetBlock(t *testing.T, client *rpc.Client) {
- ec := NewClient(client)
-
- // Get current block number
- blockNumber, err := ec.BlockNumber(context.Background())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if blockNumber != 2 {
- t.Fatalf("BlockNumber returned wrong number: %d", blockNumber)
- }
- // Get current block by number
- block, err := ec.BlockByNumber(context.Background(), new(big.Int).SetUint64(blockNumber))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if block.NumberU64() != blockNumber {
- t.Fatalf("BlockByNumber returned wrong block: want %d got %d", blockNumber, block.NumberU64())
- }
- // Get current block by hash
- blockH, err := ec.BlockByHash(context.Background(), block.Hash())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if block.Hash() != blockH.Hash() {
- t.Fatalf("BlockByHash returned wrong block: want %v got %v", block.Hash().Hex(), blockH.Hash().Hex())
- }
- // Get header by number
- header, err := ec.HeaderByNumber(context.Background(), new(big.Int).SetUint64(blockNumber))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if block.Header().Hash() != header.Hash() {
- t.Fatalf("HeaderByNumber returned wrong header: want %v got %v", block.Header().Hash().Hex(), header.Hash().Hex())
- }
- // Get header by hash
- headerH, err := ec.HeaderByHash(context.Background(), block.Hash())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if block.Header().Hash() != headerH.Hash() {
- t.Fatalf("HeaderByHash returned wrong header: want %v got %v", block.Header().Hash().Hex(), headerH.Hash().Hex())
- }
-}
-
-func testStatusFunctions(t *testing.T, client *rpc.Client) {
- ec := NewClient(client)
-
- // Sync progress
- progress, err := ec.SyncProgress(context.Background())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if progress != nil {
- t.Fatalf("unexpected progress: %v", progress)
- }
-
- // NetworkID
- networkID, err := ec.NetworkID(context.Background())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if networkID.Cmp(big.NewInt(1337)) != 0 {
- t.Fatalf("unexpected networkID: %v", networkID)
- }
-
- // SuggestGasPrice
- gasPrice, err := ec.SuggestGasPrice(context.Background())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if gasPrice.Cmp(big.NewInt(1000000000)) != 0 {
- t.Fatalf("unexpected gas price: %v", gasPrice)
- }
-
- // SuggestGasTipCap
- gasTipCap, err := ec.SuggestGasTipCap(context.Background())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if gasTipCap.Cmp(big.NewInt(234375000)) != 0 {
- t.Fatalf("unexpected gas tip cap: %v", gasTipCap)
- }
-
- // FeeHistory
- history, err := ec.FeeHistory(context.Background(), 1, big.NewInt(2), []float64{95, 99})
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- want := ðereum.FeeHistory{
- OldestBlock: big.NewInt(2),
- Reward: [][]*big.Int{
- {
- big.NewInt(234375000),
- big.NewInt(234375000),
- },
- },
- BaseFee: []*big.Int{
- big.NewInt(765625000),
- big.NewInt(671627818),
- },
- GasUsedRatio: []float64{0.008912678667376286},
- }
- if !reflect.DeepEqual(history, want) {
- t.Fatalf("FeeHistory result doesn't match expected: (got: %v, want: %v)", history, want)
- }
-}
-
-func testCallContractAtHash(t *testing.T, client *rpc.Client) {
- ec := NewClient(client)
-
- // EstimateGas
- msg := ethereum.CallMsg{
- From: testAddr,
- To: &common.Address{},
- Gas: 21000,
- Value: big.NewInt(1),
- }
- gas, err := ec.EstimateGas(context.Background(), msg)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if gas != 21000 {
- t.Fatalf("unexpected gas price: %v", gas)
- }
- block, err := ec.HeaderByNumber(context.Background(), big.NewInt(1))
- if err != nil {
- t.Fatalf("BlockByNumber error: %v", err)
- }
- // CallContract
- if _, err := ec.CallContractAtHash(context.Background(), msg, block.Hash()); err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
-}
-
-func testCallContract(t *testing.T, client *rpc.Client) {
- ec := NewClient(client)
-
- // EstimateGas
- msg := ethereum.CallMsg{
- From: testAddr,
- To: &common.Address{},
- Gas: 21000,
- Value: big.NewInt(1),
- }
- gas, err := ec.EstimateGas(context.Background(), msg)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if gas != 21000 {
- t.Fatalf("unexpected gas price: %v", gas)
- }
- // CallContract
- if _, err := ec.CallContract(context.Background(), msg, big.NewInt(1)); err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- // PendingCallContract
- if _, err := ec.PendingCallContract(context.Background(), msg); err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
-}
-
-func testAtFunctions(t *testing.T, client *rpc.Client) {
- ec := NewClient(client)
-
- block, err := ec.HeaderByNumber(context.Background(), big.NewInt(1))
- if err != nil {
- t.Fatalf("BlockByNumber error: %v", err)
- }
-
- // send a transaction for some interesting pending status
- sendTransaction(ec)
- time.Sleep(100 * time.Millisecond)
-
- // Check pending transaction count
- pending, err := ec.PendingTransactionCount(context.Background())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if pending != 1 {
- t.Fatalf("unexpected pending, wanted 1 got: %v", pending)
- }
- // Query balance
- balance, err := ec.BalanceAt(context.Background(), testAddr, nil)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- hashBalance, err := ec.BalanceAtHash(context.Background(), testAddr, block.Hash())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if balance.Cmp(hashBalance) == 0 {
- t.Fatalf("unexpected balance at hash: %v %v", balance, hashBalance)
- }
- penBalance, err := ec.PendingBalanceAt(context.Background(), testAddr)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if balance.Cmp(penBalance) == 0 {
- t.Fatalf("unexpected balance: %v %v", balance, penBalance)
- }
- // NonceAt
- nonce, err := ec.NonceAt(context.Background(), testAddr, nil)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- hashNonce, err := ec.NonceAtHash(context.Background(), testAddr, block.Hash())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if hashNonce == nonce {
- t.Fatalf("unexpected nonce at hash: %v %v", nonce, hashNonce)
- }
- penNonce, err := ec.PendingNonceAt(context.Background(), testAddr)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if penNonce != nonce+1 {
- t.Fatalf("unexpected nonce: %v %v", nonce, penNonce)
- }
- // StorageAt
- storage, err := ec.StorageAt(context.Background(), testAddr, common.Hash{}, nil)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- hashStorage, err := ec.StorageAtHash(context.Background(), testAddr, common.Hash{}, block.Hash())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !bytes.Equal(storage, hashStorage) {
- t.Fatalf("unexpected storage at hash: %v %v", storage, hashStorage)
- }
- penStorage, err := ec.PendingStorageAt(context.Background(), testAddr, common.Hash{})
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !bytes.Equal(storage, penStorage) {
- t.Fatalf("unexpected storage: %v %v", storage, penStorage)
- }
- // CodeAt
- code, err := ec.CodeAt(context.Background(), testAddr, nil)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- hashCode, err := ec.CodeAtHash(context.Background(), common.Address{}, block.Hash())
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !bytes.Equal(code, hashCode) {
- t.Fatalf("unexpected code at hash: %v %v", code, hashCode)
- }
- penCode, err := ec.PendingCodeAt(context.Background(), testAddr)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !bytes.Equal(code, penCode) {
- t.Fatalf("unexpected code: %v %v", code, penCode)
- }
-}
-
-func testTransactionSender(t *testing.T, client *rpc.Client) {
- ec := NewClient(client)
- ctx := context.Background()
-
- // Retrieve testTx1 via RPC.
- block2, err := ec.HeaderByNumber(ctx, big.NewInt(2))
- if err != nil {
- t.Fatal("can't get block 1:", err)
- }
- tx1, err := ec.TransactionInBlock(ctx, block2.Hash(), 0)
- if err != nil {
- t.Fatal("can't get tx:", err)
- }
- if tx1.Hash() != testTx1.Hash() {
- t.Fatalf("wrong tx hash %v, want %v", tx1.Hash(), testTx1.Hash())
- }
-
- // The sender address is cached in tx1, so no additional RPC should be required in
- // TransactionSender. Ensure the server is not asked by canceling the context here.
- canceledCtx, cancel := context.WithCancel(context.Background())
- cancel()
- <-canceledCtx.Done() // Ensure the close of the Done channel
- sender1, err := ec.TransactionSender(canceledCtx, tx1, block2.Hash(), 0)
- if err != nil {
- t.Fatal(err)
- }
- if sender1 != testAddr {
- t.Fatal("wrong sender:", sender1)
- }
-
- // Now try to get the sender of testTx2, which was not fetched through RPC.
- // TransactionSender should query the server here.
- sender2, err := ec.TransactionSender(ctx, testTx2, block2.Hash(), 1)
- if err != nil {
- t.Fatal(err)
- }
- if sender2 != testAddr {
- t.Fatal("wrong sender:", sender2)
- }
-}
-
-func sendTransaction(ec *Client) error {
- chainID, err := ec.ChainID(context.Background())
- if err != nil {
- return err
- }
- nonce, err := ec.PendingNonceAt(context.Background(), testAddr)
- if err != nil {
- return err
- }
-
- signer := types.LatestSignerForChainID(chainID)
- tx, err := types.SignNewTx(testKey, signer, &types.LegacyTx{
- Nonce: nonce,
- To: &common.Address{2},
- Value: big.NewInt(1),
- Gas: 22000,
- GasPrice: big.NewInt(params.InitialBaseFee),
- })
- if err != nil {
- return err
- }
- return ec.SendTransaction(context.Background(), tx)
-}
diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go
deleted file mode 100644
index e2c0ef3ed0..0000000000
--- a/ethclient/gethclient/gethclient.go
+++ /dev/null
@@ -1,335 +0,0 @@
-// Copyright 2021 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-// Package gethclient provides an RPC client for geth-specific APIs.
-package gethclient
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "math/big"
- "runtime"
- "runtime/debug"
-
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/rpc"
-)
-
-// Client is a wrapper around rpc.Client that implements geth-specific functionality.
-//
-// If you want to use the standardized Ethereum RPC functionality, use ethclient.Client instead.
-type Client struct {
- c *rpc.Client
-}
-
-// New creates a client that uses the given RPC client.
-func New(c *rpc.Client) *Client {
- return &Client{c}
-}
-
-// CreateAccessList tries to create an access list for a specific transaction based on the
-// current pending state of the blockchain.
-func (ec *Client) CreateAccessList(ctx context.Context, msg ethereum.CallMsg) (*types.AccessList, uint64, string, error) {
- type accessListResult struct {
- Accesslist *types.AccessList `json:"accessList"`
- Error string `json:"error,omitempty"`
- GasUsed hexutil.Uint64 `json:"gasUsed"`
- }
- var result accessListResult
- if err := ec.c.CallContext(ctx, &result, "eth_createAccessList", toCallArg(msg)); err != nil {
- return nil, 0, "", err
- }
- return result.Accesslist, uint64(result.GasUsed), result.Error, nil
-}
-
-// AccountResult is the result of a GetProof operation.
-type AccountResult struct {
- Address common.Address `json:"address"`
- AccountProof []string `json:"accountProof"`
- Balance *big.Int `json:"balance"`
- CodeHash common.Hash `json:"codeHash"`
- Nonce uint64 `json:"nonce"`
- StorageHash common.Hash `json:"storageHash"`
- StorageProof []StorageResult `json:"storageProof"`
-}
-
-// StorageResult provides a proof for a key-value pair.
-type StorageResult struct {
- Key string `json:"key"`
- Value *big.Int `json:"value"`
- Proof []string `json:"proof"`
-}
-
-// GetProof returns the account and storage values of the specified account including the Merkle-proof.
-// The block number can be nil, in which case the value is taken from the latest known block.
-func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []string, blockNumber *big.Int) (*AccountResult, error) {
- type storageResult struct {
- Key string `json:"key"`
- Value *hexutil.Big `json:"value"`
- Proof []string `json:"proof"`
- }
-
- type accountResult struct {
- Address common.Address `json:"address"`
- AccountProof []string `json:"accountProof"`
- Balance *hexutil.Big `json:"balance"`
- CodeHash common.Hash `json:"codeHash"`
- Nonce hexutil.Uint64 `json:"nonce"`
- StorageHash common.Hash `json:"storageHash"`
- StorageProof []storageResult `json:"storageProof"`
- }
-
- // Avoid keys being 'null'.
- if keys == nil {
- keys = []string{}
- }
-
- var res accountResult
- err := ec.c.CallContext(ctx, &res, "eth_getProof", account, keys, toBlockNumArg(blockNumber))
- // Turn hexutils back to normal datatypes
- storageResults := make([]StorageResult, 0, len(res.StorageProof))
- for _, st := range res.StorageProof {
- storageResults = append(storageResults, StorageResult{
- Key: st.Key,
- Value: st.Value.ToInt(),
- Proof: st.Proof,
- })
- }
- result := AccountResult{
- Address: res.Address,
- AccountProof: res.AccountProof,
- Balance: res.Balance.ToInt(),
- Nonce: uint64(res.Nonce),
- CodeHash: res.CodeHash,
- StorageHash: res.StorageHash,
- StorageProof: storageResults,
- }
- return &result, err
-}
-
-// CallContract executes a message call transaction, which is directly executed in the VM
-// of the node, but never mined into the blockchain.
-//
-// blockNumber selects the block height at which the call runs. It can be nil, in which
-// case the code is taken from the latest known block. Note that state from very old
-// blocks might not be available.
-//
-// overrides specifies a map of contract states that should be overwritten before executing
-// the message call.
-// Please use ethclient.CallContract instead if you don't need the override functionality.
-func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int, overrides *map[common.Address]OverrideAccount) ([]byte, error) {
- var hex hexutil.Bytes
- err := ec.c.CallContext(
- ctx, &hex, "eth_call", toCallArg(msg),
- toBlockNumArg(blockNumber), overrides,
- )
- return hex, err
-}
-
-// CallContractWithBlockOverrides executes a message call transaction, which is directly executed
-// in the VM of the node, but never mined into the blockchain.
-//
-// blockNumber selects the block height at which the call runs. It can be nil, in which
-// case the code is taken from the latest known block. Note that state from very old
-// blocks might not be available.
-//
-// overrides specifies a map of contract states that should be overwritten before executing
-// the message call.
-//
-// blockOverrides specifies block fields exposed to the EVM that can be overridden for the call.
-//
-// Please use ethclient.CallContract instead if you don't need the override functionality.
-func (ec *Client) CallContractWithBlockOverrides(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int, overrides *map[common.Address]OverrideAccount, blockOverrides BlockOverrides) ([]byte, error) {
- var hex hexutil.Bytes
- err := ec.c.CallContext(
- ctx, &hex, "eth_call", toCallArg(msg),
- toBlockNumArg(blockNumber), overrides, blockOverrides,
- )
- return hex, err
-}
-
-// GCStats retrieves the current garbage collection stats from a geth node.
-func (ec *Client) GCStats(ctx context.Context) (*debug.GCStats, error) {
- var result debug.GCStats
- err := ec.c.CallContext(ctx, &result, "debug_gcStats")
- return &result, err
-}
-
-// MemStats retrieves the current memory stats from a geth node.
-func (ec *Client) MemStats(ctx context.Context) (*runtime.MemStats, error) {
- var result runtime.MemStats
- err := ec.c.CallContext(ctx, &result, "debug_memStats")
- return &result, err
-}
-
-// SetHead sets the current head of the local chain by block number.
-// Note, this is a destructive action and may severely damage your chain.
-// Use with extreme caution.
-func (ec *Client) SetHead(ctx context.Context, number *big.Int) error {
- return ec.c.CallContext(ctx, nil, "debug_setHead", toBlockNumArg(number))
-}
-
-// GetNodeInfo retrieves the node info of a geth node.
-func (ec *Client) GetNodeInfo(ctx context.Context) (*p2p.NodeInfo, error) {
- var result p2p.NodeInfo
- err := ec.c.CallContext(ctx, &result, "admin_nodeInfo")
- return &result, err
-}
-
-// SubscribeFullPendingTransactions subscribes to new pending transactions.
-func (ec *Client) SubscribeFullPendingTransactions(ctx context.Context, ch chan<- *types.Transaction) (*rpc.ClientSubscription, error) {
- return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions", true)
-}
-
-// SubscribePendingTransactions subscribes to new pending transaction hashes.
-func (ec *Client) SubscribePendingTransactions(ctx context.Context, ch chan<- common.Hash) (*rpc.ClientSubscription, error) {
- return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions")
-}
-
-func toBlockNumArg(number *big.Int) string {
- if number == nil {
- return "latest"
- }
- if number.Sign() >= 0 {
- return hexutil.EncodeBig(number)
- }
- // It's negative.
- if number.IsInt64() {
- return rpc.BlockNumber(number.Int64()).String()
- }
- // It's negative and large, which is invalid.
- return fmt.Sprintf("", number)
-}
-
-func toCallArg(msg ethereum.CallMsg) interface{} {
- arg := map[string]interface{}{
- "from": msg.From,
- "to": msg.To,
- }
- if len(msg.Data) > 0 {
- arg["input"] = hexutil.Bytes(msg.Data)
- }
- if msg.Value != nil {
- arg["value"] = (*hexutil.Big)(msg.Value)
- }
- if msg.Gas != 0 {
- arg["gas"] = hexutil.Uint64(msg.Gas)
- }
- if msg.GasPrice != nil {
- arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
- }
- return arg
-}
-
-// OverrideAccount specifies the state of an account to be overridden.
-type OverrideAccount struct {
- // Nonce sets nonce of the account. Note: the nonce override will only
- // be applied when it is set to a non-zero value.
- Nonce uint64
-
- // Code sets the contract code. The override will be applied
- // when the code is non-nil, i.e. setting empty code is possible
- // using an empty slice.
- Code []byte
-
- // Balance sets the account balance.
- Balance *big.Int
-
- // State sets the complete storage. The override will be applied
- // when the given map is non-nil. Using an empty map wipes the
- // entire contract storage during the call.
- State map[common.Hash]common.Hash
-
- // StateDiff allows overriding individual storage slots.
- StateDiff map[common.Hash]common.Hash
-}
-
-func (a OverrideAccount) MarshalJSON() ([]byte, error) {
- type acc struct {
- Nonce hexutil.Uint64 `json:"nonce,omitempty"`
- Code string `json:"code,omitempty"`
- Balance *hexutil.Big `json:"balance,omitempty"`
- State interface{} `json:"state,omitempty"`
- StateDiff map[common.Hash]common.Hash `json:"stateDiff,omitempty"`
- }
-
- output := acc{
- Nonce: hexutil.Uint64(a.Nonce),
- Balance: (*hexutil.Big)(a.Balance),
- StateDiff: a.StateDiff,
- }
- if a.Code != nil {
- output.Code = hexutil.Encode(a.Code)
- }
- if a.State != nil {
- output.State = a.State
- }
- return json.Marshal(output)
-}
-
-// BlockOverrides specifies the set of header fields to override.
-type BlockOverrides struct {
- // Number overrides the block number.
- Number *big.Int
- // Difficulty overrides the block difficulty.
- Difficulty *big.Int
- // Time overrides the block timestamp. Time is applied only when
- // it is non-zero.
- Time uint64
- // GasLimit overrides the block gas limit. GasLimit is applied only when
- // it is non-zero.
- GasLimit uint64
- // Coinbase overrides the block coinbase. Coinbase is applied only when
- // it is different from the zero address.
- Coinbase common.Address
- // Random overrides the block extra data which feeds into the RANDOM opcode.
- // Random is applied only when it is a non-zero hash.
- Random common.Hash
- // BaseFee overrides the block base fee.
- BaseFee *big.Int
-}
-
-func (o BlockOverrides) MarshalJSON() ([]byte, error) {
- type override struct {
- Number *hexutil.Big `json:"number,omitempty"`
- Difficulty *hexutil.Big `json:"difficulty,omitempty"`
- Time hexutil.Uint64 `json:"time,omitempty"`
- GasLimit hexutil.Uint64 `json:"gasLimit,omitempty"`
- Coinbase *common.Address `json:"coinbase,omitempty"`
- Random *common.Hash `json:"random,omitempty"`
- BaseFee *hexutil.Big `json:"baseFee,omitempty"`
- }
-
- output := override{
- Number: (*hexutil.Big)(o.Number),
- Difficulty: (*hexutil.Big)(o.Difficulty),
- Time: hexutil.Uint64(o.Time),
- GasLimit: hexutil.Uint64(o.GasLimit),
- BaseFee: (*hexutil.Big)(o.BaseFee),
- }
- if o.Coinbase != (common.Address{}) {
- output.Coinbase = &o.Coinbase
- }
- if o.Random != (common.Hash{}) {
- output.Random = &o.Random
- }
- return json.Marshal(output)
-}
diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go
deleted file mode 100644
index fdd94a7d73..0000000000
--- a/ethclient/gethclient/gethclient_test.go
+++ /dev/null
@@ -1,570 +0,0 @@
-// Copyright 2021 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package gethclient
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "math/big"
- "testing"
-
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/consensus/ethash"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/eth/ethconfig"
- "github.com/ethereum/go-ethereum/eth/filters"
- "github.com/ethereum/go-ethereum/ethclient"
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/rpc"
-)
-
-var (
- testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
- testContract = common.HexToAddress("0xbeef")
- testEmpty = common.HexToAddress("0xeeee")
- testSlot = common.HexToHash("0xdeadbeef")
- testValue = crypto.Keccak256Hash(testSlot[:])
- testBalance = big.NewInt(2e15)
-)
-
-func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
- // Generate test chain.
- genesis, blocks := generateTestChain()
- // Create node
- n, err := node.New(&node.Config{})
- if err != nil {
- t.Fatalf("can't create new node: %v", err)
- }
- // Create Ethereum Service
- config := ðconfig.Config{Genesis: genesis}
- ethservice, err := eth.New(n, config)
- if err != nil {
- t.Fatalf("can't create new ethereum service: %v", err)
- }
- filterSystem := filters.NewFilterSystem(ethservice.APIBackend, filters.Config{})
- n.RegisterAPIs([]rpc.API{{
- Namespace: "eth",
- Service: filters.NewFilterAPI(filterSystem, false),
- }})
-
- // Import the test chain.
- if err := n.Start(); err != nil {
- t.Fatalf("can't start test node: %v", err)
- }
- if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil {
- t.Fatalf("can't import test blocks: %v", err)
- }
- return n, blocks
-}
-
-func generateTestChain() (*core.Genesis, []*types.Block) {
- genesis := &core.Genesis{
- Config: params.AllEthashProtocolChanges,
- Alloc: core.GenesisAlloc{
- testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}},
- testContract: {Nonce: 1, Code: []byte{0x13, 0x37}},
- testEmpty: {Balance: big.NewInt(1)},
- },
- ExtraData: []byte("test genesis"),
- Timestamp: 9000,
- }
- generate := func(i int, g *core.BlockGen) {
- g.OffsetTime(5)
- g.SetExtra([]byte("test"))
- }
- _, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 1, generate)
- blocks = append([]*types.Block{genesis.ToBlock()}, blocks...)
- return genesis, blocks
-}
-
-func TestGethClient(t *testing.T) {
- backend, _ := newTestBackend(t)
- client := backend.Attach()
- defer backend.Close()
- defer client.Close()
-
- tests := []struct {
- name string
- test func(t *testing.T)
- }{
- {
- "TestGetProof1",
- func(t *testing.T) { testGetProof(t, client, testAddr) },
- }, {
- "TestGetProof2",
- func(t *testing.T) { testGetProof(t, client, testContract) },
- }, {
- "TestGetProofEmpty",
- func(t *testing.T) { testGetProof(t, client, testEmpty) },
- }, {
- "TestGetProofNonExistent",
- func(t *testing.T) { testGetProofNonExistent(t, client) },
- }, {
- "TestGetProofCanonicalizeKeys",
- func(t *testing.T) { testGetProofCanonicalizeKeys(t, client) },
- }, {
- "TestGCStats",
- func(t *testing.T) { testGCStats(t, client) },
- }, {
- "TestMemStats",
- func(t *testing.T) { testMemStats(t, client) },
- }, {
- "TestGetNodeInfo",
- func(t *testing.T) { testGetNodeInfo(t, client) },
- }, {
- "TestSubscribePendingTxHashes",
- func(t *testing.T) { testSubscribePendingTransactions(t, client) },
- }, {
- "TestSubscribePendingTxs",
- func(t *testing.T) { testSubscribeFullPendingTransactions(t, client) },
- }, {
- "TestCallContract",
- func(t *testing.T) { testCallContract(t, client) },
- }, {
- "TestCallContractWithBlockOverrides",
- func(t *testing.T) { testCallContractWithBlockOverrides(t, client) },
- },
- // The testaccesslist is a bit time-sensitive: the newTestBackend imports
- // one block. The `testAcessList` fails if the miner has not yet created a
- // new pending-block after the import event.
- // Hence: this test should be last, execute the tests serially.
- {
- "TestAccessList",
- func(t *testing.T) { testAccessList(t, client) },
- }, {
- "TestSetHead",
- func(t *testing.T) { testSetHead(t, client) },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, tt.test)
- }
-}
-
-func testAccessList(t *testing.T, client *rpc.Client) {
- ec := New(client)
- // Test transfer
- msg := ethereum.CallMsg{
- From: testAddr,
- To: &common.Address{},
- Gas: 21000,
- GasPrice: big.NewInt(765625000),
- Value: big.NewInt(1),
- }
- al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if vmErr != "" {
- t.Fatalf("unexpected vm error: %v", vmErr)
- }
- if gas != 21000 {
- t.Fatalf("unexpected gas used: %v", gas)
- }
- if len(*al) != 0 {
- t.Fatalf("unexpected length of accesslist: %v", len(*al))
- }
- // Test reverting transaction
- msg = ethereum.CallMsg{
- From: testAddr,
- To: nil,
- Gas: 100000,
- GasPrice: big.NewInt(1000000000),
- Value: big.NewInt(1),
- Data: common.FromHex("0x608060806080608155fd"),
- }
- al, gas, vmErr, err = ec.CreateAccessList(context.Background(), msg)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if vmErr == "" {
- t.Fatalf("wanted vmErr, got none")
- }
- if gas == 21000 {
- t.Fatalf("unexpected gas used: %v", gas)
- }
- if len(*al) != 1 || al.StorageKeys() != 1 {
- t.Fatalf("unexpected length of accesslist: %v", len(*al))
- }
- // address changes between calls, so we can't test for it.
- if (*al)[0].Address == common.HexToAddress("0x0") {
- t.Fatalf("unexpected address: %v", (*al)[0].Address)
- }
- if (*al)[0].StorageKeys[0] != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000081") {
- t.Fatalf("unexpected storage key: %v", (*al)[0].StorageKeys[0])
- }
-}
-
-func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) {
- ec := New(client)
- ethcl := ethclient.NewClient(client)
- result, err := ec.GetProof(context.Background(), addr, []string{testSlot.String()}, nil)
- if err != nil {
- t.Fatal(err)
- }
- if result.Address != addr {
- t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr)
- }
- // test nonce
- if nonce, _ := ethcl.NonceAt(context.Background(), addr, nil); result.Nonce != nonce {
- t.Fatalf("invalid nonce, want: %v got: %v", nonce, result.Nonce)
- }
- // test balance
- if balance, _ := ethcl.BalanceAt(context.Background(), addr, nil); result.Balance.Cmp(balance) != 0 {
- t.Fatalf("invalid balance, want: %v got: %v", balance, result.Balance)
- }
- // test storage
- if len(result.StorageProof) != 1 {
- t.Fatalf("invalid storage proof, want 1 proof, got %v proof(s)", len(result.StorageProof))
- }
- for _, proof := range result.StorageProof {
- if proof.Key != testSlot.String() {
- t.Fatalf("invalid storage proof key, want: %q, got: %q", testSlot.String(), proof.Key)
- }
- slotValue, _ := ethcl.StorageAt(context.Background(), addr, common.HexToHash(proof.Key), nil)
- if have, want := common.BigToHash(proof.Value), common.BytesToHash(slotValue); have != want {
- t.Fatalf("addr %x, invalid storage proof value: have: %v, want: %v", addr, have, want)
- }
- }
- // test code
- code, _ := ethcl.CodeAt(context.Background(), addr, nil)
- if have, want := result.CodeHash, crypto.Keccak256Hash(code); have != want {
- t.Fatalf("codehash wrong, have %v want %v ", have, want)
- }
-}
-
-func testGetProofCanonicalizeKeys(t *testing.T, client *rpc.Client) {
- ec := New(client)
-
- // Tests with non-canon input for storage keys.
- // Here we check that the storage key is canonicalized.
- result, err := ec.GetProof(context.Background(), testAddr, []string{"0x0dEadbeef"}, nil)
- if err != nil {
- t.Fatal(err)
- }
- if result.StorageProof[0].Key != "0xdeadbeef" {
- t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key)
- }
- if result, err = ec.GetProof(context.Background(), testAddr, []string{"0x000deadbeef"}, nil); err != nil {
- t.Fatal(err)
- }
- if result.StorageProof[0].Key != "0xdeadbeef" {
- t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key)
- }
-
- // If the requested storage key is 32 bytes long, it will be returned as is.
- hashSizedKey := "0x00000000000000000000000000000000000000000000000000000000deadbeef"
- result, err = ec.GetProof(context.Background(), testAddr, []string{hashSizedKey}, nil)
- if err != nil {
- t.Fatal(err)
- }
- if result.StorageProof[0].Key != hashSizedKey {
- t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key)
- }
-}
-
-func testGetProofNonExistent(t *testing.T, client *rpc.Client) {
- addr := common.HexToAddress("0x0001")
- ec := New(client)
- result, err := ec.GetProof(context.Background(), addr, nil, nil)
- if err != nil {
- t.Fatal(err)
- }
- if result.Address != addr {
- t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr)
- }
- // test nonce
- if result.Nonce != 0 {
- t.Fatalf("invalid nonce, want: %v got: %v", 0, result.Nonce)
- }
- // test balance
- if result.Balance.Cmp(big.NewInt(0)) != 0 {
- t.Fatalf("invalid balance, want: %v got: %v", 0, result.Balance)
- }
- // test storage
- if have := len(result.StorageProof); have != 0 {
- t.Fatalf("invalid storage proof, want 0 proof, got %v proof(s)", have)
- }
- // test codeHash
- if have, want := result.CodeHash, (common.Hash{}); have != want {
- t.Fatalf("codehash wrong, have %v want %v ", have, want)
- }
- // test codeHash
- if have, want := result.StorageHash, (common.Hash{}); have != want {
- t.Fatalf("storagehash wrong, have %v want %v ", have, want)
- }
-}
-
-func testGCStats(t *testing.T, client *rpc.Client) {
- ec := New(client)
- _, err := ec.GCStats(context.Background())
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func testMemStats(t *testing.T, client *rpc.Client) {
- ec := New(client)
- stats, err := ec.MemStats(context.Background())
- if err != nil {
- t.Fatal(err)
- }
- if stats.Alloc == 0 {
- t.Fatal("Invalid mem stats retrieved")
- }
-}
-
-func testGetNodeInfo(t *testing.T, client *rpc.Client) {
- ec := New(client)
- info, err := ec.GetNodeInfo(context.Background())
- if err != nil {
- t.Fatal(err)
- }
-
- if info.Name == "" {
- t.Fatal("Invalid node info retrieved")
- }
-}
-
-func testSetHead(t *testing.T, client *rpc.Client) {
- ec := New(client)
- err := ec.SetHead(context.Background(), big.NewInt(0))
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) {
- ec := New(client)
- ethcl := ethclient.NewClient(client)
- // Subscribe to Transactions
- ch := make(chan common.Hash)
- ec.SubscribePendingTransactions(context.Background(), ch)
- // Send a transaction
- chainID, err := ethcl.ChainID(context.Background())
- if err != nil {
- t.Fatal(err)
- }
- // Create transaction
- tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
- signer := types.LatestSignerForChainID(chainID)
- signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
- if err != nil {
- t.Fatal(err)
- }
- signedTx, err := tx.WithSignature(signer, signature)
- if err != nil {
- t.Fatal(err)
- }
- // Send transaction
- err = ethcl.SendTransaction(context.Background(), signedTx)
- if err != nil {
- t.Fatal(err)
- }
- // Check that the transaction was sent over the channel
- hash := <-ch
- if hash != signedTx.Hash() {
- t.Fatalf("Invalid tx hash received, got %v, want %v", hash, signedTx.Hash())
- }
-}
-
-func testSubscribeFullPendingTransactions(t *testing.T, client *rpc.Client) {
- ec := New(client)
- ethcl := ethclient.NewClient(client)
- // Subscribe to Transactions
- ch := make(chan *types.Transaction)
- ec.SubscribeFullPendingTransactions(context.Background(), ch)
- // Send a transaction
- chainID, err := ethcl.ChainID(context.Background())
- if err != nil {
- t.Fatal(err)
- }
- // Create transaction
- tx := types.NewTransaction(1, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
- signer := types.LatestSignerForChainID(chainID)
- signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
- if err != nil {
- t.Fatal(err)
- }
- signedTx, err := tx.WithSignature(signer, signature)
- if err != nil {
- t.Fatal(err)
- }
- // Send transaction
- err = ethcl.SendTransaction(context.Background(), signedTx)
- if err != nil {
- t.Fatal(err)
- }
- // Check that the transaction was sent over the channel
- tx = <-ch
- if tx.Hash() != signedTx.Hash() {
- t.Fatalf("Invalid tx hash received, got %v, want %v", tx.Hash(), signedTx.Hash())
- }
-}
-
-func testCallContract(t *testing.T, client *rpc.Client) {
- ec := New(client)
- msg := ethereum.CallMsg{
- From: testAddr,
- To: &common.Address{},
- Gas: 21000,
- GasPrice: big.NewInt(1000000000),
- Value: big.NewInt(1),
- }
- // CallContract without override
- if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), nil); err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- // CallContract with override
- override := OverrideAccount{
- Nonce: 1,
- }
- mapAcc := make(map[common.Address]OverrideAccount)
- mapAcc[testAddr] = override
- if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), &mapAcc); err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
-}
-
-func TestOverrideAccountMarshal(t *testing.T) {
- om := map[common.Address]OverrideAccount{
- {0x11}: {
- // Zero-valued nonce is not overridden, but simply dropped by the encoder.
- Nonce: 0,
- },
- {0xaa}: {
- Nonce: 5,
- },
- {0xbb}: {
- Code: []byte{1},
- },
- {0xcc}: {
- // 'code', 'balance', 'state' should be set when input is
- // a non-nil but empty value.
- Code: []byte{},
- Balance: big.NewInt(0),
- State: map[common.Hash]common.Hash{},
- // For 'stateDiff' the behavior is different, empty map
- // is ignored because it makes no difference.
- StateDiff: map[common.Hash]common.Hash{},
- },
- }
-
- marshalled, err := json.MarshalIndent(&om, "", " ")
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
-
- expected := `{
- "0x1100000000000000000000000000000000000000": {},
- "0xaa00000000000000000000000000000000000000": {
- "nonce": "0x5"
- },
- "0xbb00000000000000000000000000000000000000": {
- "code": "0x01"
- },
- "0xcc00000000000000000000000000000000000000": {
- "code": "0x",
- "balance": "0x0",
- "state": {}
- }
-}`
-
- if string(marshalled) != expected {
- t.Error("wrong output:", string(marshalled))
- t.Error("want:", expected)
- }
-}
-
-func TestBlockOverridesMarshal(t *testing.T) {
- for i, tt := range []struct {
- bo BlockOverrides
- want string
- }{
- {
- bo: BlockOverrides{},
- want: `{}`,
- },
- {
- bo: BlockOverrides{
- Coinbase: common.HexToAddress("0x1111111111111111111111111111111111111111"),
- },
- want: `{"coinbase":"0x1111111111111111111111111111111111111111"}`,
- },
- {
- bo: BlockOverrides{
- Number: big.NewInt(1),
- Difficulty: big.NewInt(2),
- Time: 3,
- GasLimit: 4,
- BaseFee: big.NewInt(5),
- },
- want: `{"number":"0x1","difficulty":"0x2","time":"0x3","gasLimit":"0x4","baseFee":"0x5"}`,
- },
- } {
- marshalled, err := json.Marshal(&tt.bo)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if string(marshalled) != tt.want {
- t.Errorf("Testcase #%d failed. expected\n%s\ngot\n%s", i, tt.want, string(marshalled))
- }
- }
-}
-
-func testCallContractWithBlockOverrides(t *testing.T, client *rpc.Client) {
- ec := New(client)
- msg := ethereum.CallMsg{
- From: testAddr,
- To: &common.Address{},
- Gas: 50000,
- GasPrice: big.NewInt(1000000000),
- Value: big.NewInt(1),
- }
- override := OverrideAccount{
- // Returns coinbase address.
- Code: common.FromHex("0x41806000526014600cf3"),
- }
- mapAcc := make(map[common.Address]OverrideAccount)
- mapAcc[common.Address{}] = override
- res, err := ec.CallContract(context.Background(), msg, big.NewInt(0), &mapAcc)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !bytes.Equal(res, common.FromHex("0x0000000000000000000000000000000000000000")) {
- t.Fatalf("unexpected result: %x", res)
- }
-
- // Now test with block overrides
- bo := BlockOverrides{
- Coinbase: common.HexToAddress("0x1111111111111111111111111111111111111111"),
- }
- res, err = ec.CallContractWithBlockOverrides(context.Background(), msg, big.NewInt(0), &mapAcc, bo)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !bytes.Equal(res, common.FromHex("0x1111111111111111111111111111111111111111")) {
- t.Fatalf("unexpected result: %x", res)
- }
-}
diff --git a/ethclient/signer.go b/ethclient/signer.go
deleted file mode 100644
index f827d4eb56..0000000000
--- a/ethclient/signer.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package ethclient
-
-import (
- "errors"
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
-)
-
-// senderFromServer is a types.Signer that remembers the sender address returned by the RPC
-// server. It is stored in the transaction's sender address cache to avoid an additional
-// request in TransactionSender.
-type senderFromServer struct {
- addr common.Address
- blockhash common.Hash
-}
-
-var errNotCached = errors.New("sender not cached")
-
-func setSenderFromServer(tx *types.Transaction, addr common.Address, block common.Hash) {
- // Use types.Sender for side-effect to store our signer into the cache.
- types.Sender(&senderFromServer{addr, block}, tx)
-}
-
-func (s *senderFromServer) Equal(other types.Signer) bool {
- os, ok := other.(*senderFromServer)
- return ok && os.blockhash == s.blockhash
-}
-
-func (s *senderFromServer) Sender(tx *types.Transaction) (common.Address, error) {
- if s.addr == (common.Address{}) {
- return common.Address{}, errNotCached
- }
- return s.addr, nil
-}
-
-func (s *senderFromServer) ChainID() *big.Int {
- panic("can't sign with senderFromServer")
-}
-func (s *senderFromServer) Hash(tx *types.Transaction) common.Hash {
- panic("can't sign with senderFromServer")
-}
-func (s *senderFromServer) SignatureValues(tx *types.Transaction, sig []byte) (R, S, V *big.Int, err error) {
- panic("can't sign with senderFromServer")
-}