2020-08-01 07:39:04 +00:00
|
|
|
package commands
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-09-08 19:39:31 +00:00
|
|
|
"math/big"
|
2021-01-02 19:28:22 +00:00
|
|
|
"sync"
|
2020-08-22 20:13:38 +00:00
|
|
|
|
2020-11-17 19:13:41 +00:00
|
|
|
rpcfilters "github.com/ledgerwatch/turbo-geth/cmd/rpcdaemon/filters"
|
2020-08-01 07:39:04 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/common"
|
|
|
|
"github.com/ledgerwatch/turbo-geth/common/hexutil"
|
2021-03-31 04:03:52 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/common/math"
|
2020-08-01 07:39:04 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/core"
|
2021-01-02 19:28:22 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/core/rawdb"
|
2020-08-01 07:39:04 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/core/types"
|
2020-11-17 19:13:41 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/eth/filters"
|
2020-08-01 07:39:04 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/ethdb"
|
|
|
|
"github.com/ledgerwatch/turbo-geth/internal/ethapi"
|
2021-01-02 19:28:22 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/params"
|
2020-08-01 07:39:04 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/rpc"
|
2021-03-30 07:09:00 +00:00
|
|
|
"github.com/ledgerwatch/turbo-geth/turbo/rpchelper"
|
2020-08-01 07:39:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// EthAPI is a collection of functions that are exposed in the
|
|
|
|
type EthAPI interface {
|
2020-10-12 08:39:33 +00:00
|
|
|
// Block related (proposed file: ./eth_blocks.go)
|
2020-08-01 07:39:04 +00:00
|
|
|
GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error)
|
2020-11-06 07:59:50 +00:00
|
|
|
GetBlockByHash(ctx context.Context, hash rpc.BlockNumberOrHash, fullTx bool) (map[string]interface{}, error)
|
2020-08-29 21:28:09 +00:00
|
|
|
GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*hexutil.Uint, error)
|
|
|
|
GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) (*hexutil.Uint, error)
|
2020-10-12 08:39:33 +00:00
|
|
|
|
2020-10-14 15:59:42 +00:00
|
|
|
// Transaction related (see ./eth_txs.go)
|
2020-09-08 19:39:31 +00:00
|
|
|
GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error)
|
|
|
|
GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, txIndex hexutil.Uint64) (*RPCTransaction, error)
|
|
|
|
GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, txIndex hexutil.Uint) (*RPCTransaction, error)
|
2020-10-14 15:59:42 +00:00
|
|
|
|
|
|
|
// Receipt related (see ./eth_receipts.go)
|
2020-10-12 08:39:33 +00:00
|
|
|
GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error)
|
2020-10-14 15:59:42 +00:00
|
|
|
GetLogs(ctx context.Context, crit filters.FilterCriteria) ([]*types.Log, error)
|
2020-10-12 08:39:33 +00:00
|
|
|
|
2020-10-14 15:59:42 +00:00
|
|
|
// Uncle related (see ./eth_uncles.go)
|
2020-09-14 06:59:07 +00:00
|
|
|
GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error)
|
|
|
|
GetUncleByBlockHashAndIndex(ctx context.Context, hash common.Hash, index hexutil.Uint) (map[string]interface{}, error)
|
2020-10-24 17:03:52 +00:00
|
|
|
GetUncleCountByBlockNumber(ctx context.Context, number rpc.BlockNumber) (*hexutil.Uint, error)
|
2020-10-10 12:24:56 +00:00
|
|
|
GetUncleCountByBlockHash(ctx context.Context, hash common.Hash) (*hexutil.Uint, error)
|
2020-10-12 08:39:33 +00:00
|
|
|
|
2020-10-14 15:59:42 +00:00
|
|
|
// Filter related (see ./eth_filters.go)
|
2020-11-09 08:52:18 +00:00
|
|
|
NewPendingTransactionFilter(_ context.Context) (hexutil.Uint64, error)
|
|
|
|
NewBlockFilter(_ context.Context) (hexutil.Uint64, error)
|
|
|
|
NewFilter(_ context.Context, filter interface{}) (hexutil.Uint64, error)
|
|
|
|
UninstallFilter(_ context.Context, index hexutil.Uint64) (bool, error)
|
|
|
|
GetFilterChanges(_ context.Context, index hexutil.Uint64) ([]interface{}, error)
|
2020-10-12 08:39:33 +00:00
|
|
|
|
2020-10-14 15:59:42 +00:00
|
|
|
// Account related (see ./eth_accounts.go)
|
2020-10-24 17:03:52 +00:00
|
|
|
Accounts(ctx context.Context) ([]common.Address, error)
|
2020-10-12 08:39:33 +00:00
|
|
|
GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error)
|
|
|
|
GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error)
|
|
|
|
GetStorageAt(ctx context.Context, address common.Address, index string, blockNrOrHash rpc.BlockNumberOrHash) (string, error)
|
|
|
|
GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error)
|
|
|
|
|
2020-10-14 15:59:42 +00:00
|
|
|
// System related (see ./eth_system.go)
|
2020-10-12 08:39:33 +00:00
|
|
|
BlockNumber(ctx context.Context) (hexutil.Uint64, error)
|
|
|
|
Syncing(ctx context.Context) (interface{}, error)
|
2020-10-24 17:03:52 +00:00
|
|
|
ChainId(ctx context.Context) (hexutil.Uint64, error) /* called eth_protocolVersion elsewhere */
|
|
|
|
ProtocolVersion(_ context.Context) (hexutil.Uint, error)
|
2020-10-20 21:16:28 +00:00
|
|
|
GasPrice(_ context.Context) (*hexutil.Big, error)
|
2020-10-12 08:39:33 +00:00
|
|
|
|
2020-10-14 15:59:42 +00:00
|
|
|
// Sending related (see ./eth_call.go)
|
2020-10-12 08:39:33 +00:00
|
|
|
Call(ctx context.Context, args ethapi.CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *map[common.Address]ethapi.Account) (hexutil.Bytes, error)
|
2021-03-31 04:32:52 +00:00
|
|
|
EstimateGas(ctx context.Context, args ethapi.CallArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error)
|
2020-10-12 08:39:33 +00:00
|
|
|
SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error)
|
2020-11-09 08:52:18 +00:00
|
|
|
SendTransaction(_ context.Context, txObject interface{}) (common.Hash, error)
|
2020-10-24 17:03:52 +00:00
|
|
|
Sign(ctx context.Context, _ common.Address, _ hexutil.Bytes) (hexutil.Bytes, error)
|
2020-11-09 08:52:18 +00:00
|
|
|
SignTransaction(_ context.Context, txObject interface{}) (common.Hash, error)
|
|
|
|
GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNr rpc.BlockNumber) (*interface{}, error)
|
2020-10-12 08:39:33 +00:00
|
|
|
|
2020-10-14 15:59:42 +00:00
|
|
|
// Mining related (see ./eth_mining.go)
|
2021-03-23 09:00:07 +00:00
|
|
|
Coinbase(ctx context.Context) (common.Address, error)
|
|
|
|
Hashrate(ctx context.Context) (uint64, error)
|
|
|
|
Mining(ctx context.Context) (bool, error)
|
|
|
|
GetWork(ctx context.Context) ([4]string, error)
|
|
|
|
SubmitWork(ctx context.Context, nonce types.BlockNonce, powHash, digest common.Hash) (bool, error)
|
|
|
|
SubmitHashrate(ctx context.Context, hashRate hexutil.Uint64, id common.Hash) (bool, error)
|
2020-10-12 08:39:33 +00:00
|
|
|
|
|
|
|
// Deprecated commands in eth_ (proposed file: ./eth_deprecated.go)
|
2020-10-24 17:03:52 +00:00
|
|
|
GetCompilers(_ context.Context) ([]string, error)
|
|
|
|
CompileLLL(_ context.Context, _ string) (hexutil.Bytes, error)
|
|
|
|
CompileSolidity(ctx context.Context, _ string) (hexutil.Bytes, error)
|
|
|
|
CompileSerpent(ctx context.Context, _ string) (hexutil.Bytes, error)
|
2020-08-01 07:39:04 +00:00
|
|
|
}
|
|
|
|
|
2021-01-02 19:28:22 +00:00
|
|
|
type BaseAPI struct {
|
|
|
|
_chainConfig *params.ChainConfig
|
|
|
|
_genesis *types.Block
|
|
|
|
_genesisSetOnce sync.Once
|
|
|
|
}
|
|
|
|
|
2021-03-30 09:53:54 +00:00
|
|
|
func (api *BaseAPI) chainConfig(tx ethdb.Tx) (*params.ChainConfig, error) {
|
|
|
|
cfg, _, err := api.chainConfigWithGenesis(tx)
|
2021-01-02 19:28:22 +00:00
|
|
|
return cfg, err
|
|
|
|
}
|
|
|
|
|
|
|
|
//nolint:unused
|
2021-03-30 09:53:54 +00:00
|
|
|
func (api *BaseAPI) genesis(tx ethdb.Tx) (*types.Block, error) {
|
|
|
|
_, genesis, err := api.chainConfigWithGenesis(tx)
|
2021-01-02 19:28:22 +00:00
|
|
|
return genesis, err
|
|
|
|
}
|
|
|
|
|
2021-03-30 09:53:54 +00:00
|
|
|
func (api *BaseAPI) chainConfigWithGenesis(tx ethdb.Tx) (*params.ChainConfig, *types.Block, error) {
|
2021-01-02 19:28:22 +00:00
|
|
|
if api._chainConfig != nil {
|
|
|
|
return api._chainConfig, api._genesis, nil
|
|
|
|
}
|
|
|
|
|
2021-03-30 09:53:54 +00:00
|
|
|
genesisBlock, err := rawdb.ReadBlockByNumber(ethdb.NewRoTxDb(tx), 0)
|
2021-01-02 19:28:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
2021-04-08 11:03:45 +00:00
|
|
|
cc, err := rawdb.ReadChainConfig(tx, genesisBlock.Hash())
|
2021-01-02 19:28:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
if cc != nil && genesisBlock != nil {
|
|
|
|
api._genesisSetOnce.Do(func() {
|
|
|
|
api._genesis = genesisBlock
|
|
|
|
api._chainConfig = cc
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return cc, genesisBlock, nil
|
|
|
|
}
|
|
|
|
|
2020-08-01 07:39:04 +00:00
|
|
|
// APIImpl is implementation of the EthAPI interface based on remote Db access
|
|
|
|
type APIImpl struct {
|
2021-01-02 19:28:22 +00:00
|
|
|
*BaseAPI
|
2021-03-29 03:58:45 +00:00
|
|
|
ethBackend core.ApiBackend
|
2021-03-30 09:53:54 +00:00
|
|
|
db ethdb.RoKV
|
2021-03-29 03:58:45 +00:00
|
|
|
GasCap uint64
|
|
|
|
filters *rpcfilters.Filters
|
2021-03-30 07:09:00 +00:00
|
|
|
pending *rpchelper.Pending
|
2020-08-01 07:39:04 +00:00
|
|
|
}
|
|
|
|
|
2020-10-12 08:39:33 +00:00
|
|
|
// NewEthAPI returns APIImpl instance
|
2021-03-30 09:53:54 +00:00
|
|
|
func NewEthAPI(db ethdb.RoKV, eth core.ApiBackend, gascap uint64, filters *rpcfilters.Filters, pending *rpchelper.Pending) *APIImpl {
|
2021-03-31 04:03:52 +00:00
|
|
|
if gascap == 0 {
|
|
|
|
gascap = uint64(math.MaxUint64 / 2)
|
|
|
|
}
|
|
|
|
|
2020-08-01 07:39:04 +00:00
|
|
|
return &APIImpl{
|
2021-01-02 19:28:22 +00:00
|
|
|
BaseAPI: &BaseAPI{},
|
2020-10-03 08:07:49 +00:00
|
|
|
db: db,
|
|
|
|
ethBackend: eth,
|
|
|
|
GasCap: gascap,
|
2020-11-17 19:13:41 +00:00
|
|
|
filters: filters,
|
2021-03-30 07:09:00 +00:00
|
|
|
pending: pending,
|
2020-08-01 07:39:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-08 19:39:31 +00:00
|
|
|
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
|
|
|
|
type RPCTransaction struct {
|
|
|
|
BlockHash *common.Hash `json:"blockHash"`
|
|
|
|
BlockNumber *hexutil.Big `json:"blockNumber"`
|
|
|
|
From common.Address `json:"from"`
|
|
|
|
Gas hexutil.Uint64 `json:"gas"`
|
|
|
|
GasPrice *hexutil.Big `json:"gasPrice"`
|
|
|
|
Hash common.Hash `json:"hash"`
|
|
|
|
Input hexutil.Bytes `json:"input"`
|
|
|
|
Nonce hexutil.Uint64 `json:"nonce"`
|
2020-09-15 16:44:28 +00:00
|
|
|
R *hexutil.Big `json:"r"`
|
|
|
|
S *hexutil.Big `json:"s"`
|
2020-09-08 19:39:31 +00:00
|
|
|
To *common.Address `json:"to"`
|
|
|
|
TransactionIndex *hexutil.Uint64 `json:"transactionIndex"`
|
|
|
|
V *hexutil.Big `json:"v"`
|
2020-09-15 16:44:28 +00:00
|
|
|
Value *hexutil.Big `json:"value"`
|
2020-09-08 19:39:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// newRPCTransaction returns a transaction that will serialize to the RPC
|
|
|
|
// representation, with the given location metadata set (if available).
|
|
|
|
func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64) *RPCTransaction {
|
|
|
|
var signer types.Signer = types.FrontierSigner{}
|
|
|
|
if tx.Protected() {
|
2021-03-14 18:52:15 +00:00
|
|
|
signer = types.NewEIP155Signer(tx.ChainId().ToBig())
|
2020-09-08 19:39:31 +00:00
|
|
|
}
|
|
|
|
from, _ := types.Sender(signer, tx)
|
|
|
|
v, r, s := tx.RawSignatureValues()
|
2020-09-03 20:41:06 +00:00
|
|
|
|
2020-09-08 19:39:31 +00:00
|
|
|
result := &RPCTransaction{
|
|
|
|
From: from,
|
|
|
|
Gas: hexutil.Uint64(tx.Gas()),
|
|
|
|
GasPrice: (*hexutil.Big)(tx.GasPrice().ToBig()),
|
|
|
|
Hash: tx.Hash(),
|
|
|
|
Input: hexutil.Bytes(tx.Data()),
|
|
|
|
Nonce: hexutil.Uint64(tx.Nonce()),
|
|
|
|
R: (*hexutil.Big)(r.ToBig()),
|
|
|
|
S: (*hexutil.Big)(s.ToBig()),
|
2020-09-15 16:44:28 +00:00
|
|
|
To: tx.To(),
|
|
|
|
V: (*hexutil.Big)(v.ToBig()),
|
|
|
|
Value: (*hexutil.Big)(tx.Value().ToBig()),
|
2020-09-08 19:39:31 +00:00
|
|
|
}
|
|
|
|
if blockHash != (common.Hash{}) {
|
|
|
|
result.BlockHash = &blockHash
|
|
|
|
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
|
|
|
|
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|