2020-08-01 07:39:04 +00:00
|
|
|
package commands
|
|
|
|
|
|
|
|
import (
|
2021-05-04 05:51:28 +00:00
|
|
|
"bytes"
|
2020-08-01 07:39:04 +00:00
|
|
|
"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
|
|
|
|
2021-09-29 06:51:51 +00:00
|
|
|
lru "github.com/hashicorp/golang-lru"
|
2021-07-01 21:31:14 +00:00
|
|
|
"github.com/holiman/uint256"
|
2021-10-12 05:04:04 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
|
2021-07-29 11:53:13 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/kv"
|
2021-09-29 01:36:25 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/kv/kvcache"
|
2022-08-12 09:13:14 +00:00
|
|
|
libstate "github.com/ledgerwatch/erigon-lib/state"
|
2022-08-25 05:24:01 +00:00
|
|
|
"github.com/ledgerwatch/erigon/cmd/state/exec22"
|
2021-05-20 18:25:53 +00:00
|
|
|
"github.com/ledgerwatch/erigon/common"
|
|
|
|
"github.com/ledgerwatch/erigon/common/hexutil"
|
|
|
|
"github.com/ledgerwatch/erigon/common/math"
|
2021-10-12 05:04:04 +00:00
|
|
|
"github.com/ledgerwatch/erigon/consensus/misc"
|
2021-05-20 18:25:53 +00:00
|
|
|
"github.com/ledgerwatch/erigon/core/rawdb"
|
|
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
|
|
ethFilters "github.com/ledgerwatch/erigon/eth/filters"
|
|
|
|
"github.com/ledgerwatch/erigon/internal/ethapi"
|
|
|
|
"github.com/ledgerwatch/erigon/params"
|
|
|
|
"github.com/ledgerwatch/erigon/rpc"
|
2022-06-10 15:18:43 +00:00
|
|
|
"github.com/ledgerwatch/erigon/turbo/rpchelper"
|
2022-05-26 03:31:06 +00:00
|
|
|
"github.com/ledgerwatch/erigon/turbo/services"
|
2022-08-12 09:13:14 +00:00
|
|
|
"github.com/ledgerwatch/log/v3"
|
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)
|
2021-05-04 05:51:28 +00:00
|
|
|
GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (hexutil.Bytes, error)
|
|
|
|
GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (hexutil.Bytes, error)
|
|
|
|
GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, 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)
|
2022-08-30 02:49:05 +00:00
|
|
|
GetLogs(ctx context.Context, crit ethFilters.FilterCriteria) (types.Logs, error)
|
2021-04-18 05:05:54 +00:00
|
|
|
GetBlockReceipts(ctx context.Context, number rpc.BlockNumber) ([]map[string]interface{}, 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)
|
2022-06-24 08:11:38 +00:00
|
|
|
NewPendingTransactionFilter(_ context.Context) (string, error)
|
|
|
|
NewBlockFilter(_ context.Context) (string, error)
|
|
|
|
NewFilter(_ context.Context, crit ethFilters.FilterCriteria) (string, error)
|
2022-05-25 09:08:06 +00:00
|
|
|
UninstallFilter(_ context.Context, index string) (bool, error)
|
|
|
|
GetFilterChanges(_ context.Context, index string) ([]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)
|
2022-03-01 15:40:24 +00:00
|
|
|
Call(ctx context.Context, args ethapi.CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *ethapi.StateOverrides) (hexutil.Bytes, error)
|
2022-03-30 01:04:51 +00:00
|
|
|
EstimateGas(ctx context.Context, argsOrNil *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)
|
2022-02-14 18:39:45 +00:00
|
|
|
CreateAccessList(ctx context.Context, args ethapi.CallArgs, blockNrOrHash *rpc.BlockNumberOrHash, optimizeGas *bool) (*accessListResult, 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-08-01 07:39:04 +00:00
|
|
|
}
|
|
|
|
|
2021-01-02 19:28:22 +00:00
|
|
|
type BaseAPI struct {
|
2021-09-29 06:51:51 +00:00
|
|
|
stateCache kvcache.Cache // thread-safe
|
|
|
|
blocksLRU *lru.Cache // thread-safe
|
2022-06-10 15:18:43 +00:00
|
|
|
filters *rpchelper.Filters
|
2021-09-02 08:47:48 +00:00
|
|
|
_chainConfig *params.ChainConfig
|
|
|
|
_genesis *types.Block
|
|
|
|
_genesisLock sync.RWMutex
|
2021-10-06 09:09:47 +00:00
|
|
|
|
2022-08-12 09:13:14 +00:00
|
|
|
_historyV2 *bool
|
|
|
|
_historyV2Lock sync.RWMutex
|
|
|
|
|
2022-06-01 02:57:12 +00:00
|
|
|
_blockReader services.FullBlockReader
|
2022-05-26 03:31:06 +00:00
|
|
|
_txnReader services.TxnReader
|
2022-08-19 02:35:43 +00:00
|
|
|
_agg *libstate.Aggregator22
|
2022-08-25 05:24:01 +00:00
|
|
|
_txNums *exec22.TxNums
|
2021-01-02 19:28:22 +00:00
|
|
|
}
|
|
|
|
|
2022-08-25 05:24:01 +00:00
|
|
|
func NewBaseApi(f *rpchelper.Filters, stateCache kvcache.Cache, blockReader services.FullBlockReader, agg *libstate.Aggregator22, txNums *exec22.TxNums, singleNodeMode bool) *BaseAPI {
|
2021-10-12 05:04:04 +00:00
|
|
|
blocksLRUSize := 128 // ~32Mb
|
2021-09-29 06:51:51 +00:00
|
|
|
if !singleNodeMode {
|
2021-10-12 05:04:04 +00:00
|
|
|
blocksLRUSize = 512
|
|
|
|
}
|
|
|
|
blocksLRU, err := lru.New(blocksLRUSize)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
2021-09-29 06:51:51 +00:00
|
|
|
}
|
2021-10-12 05:04:04 +00:00
|
|
|
|
2022-08-12 09:13:14 +00:00
|
|
|
return &BaseAPI{filters: f, stateCache: stateCache, blocksLRU: blocksLRU, _blockReader: blockReader, _txnReader: blockReader, _agg: agg, _txNums: txNums}
|
2021-05-17 12:15:19 +00:00
|
|
|
}
|
|
|
|
|
2021-07-28 02:47:38 +00:00
|
|
|
func (api *BaseAPI) chainConfig(tx kv.Tx) (*params.ChainConfig, error) {
|
2021-03-30 09:53:54 +00:00
|
|
|
cfg, _, err := api.chainConfigWithGenesis(tx)
|
2021-01-02 19:28:22 +00:00
|
|
|
return cfg, err
|
|
|
|
}
|
|
|
|
|
2021-07-01 04:29:32 +00:00
|
|
|
// nolint:unused
|
2021-07-28 02:47:38 +00:00
|
|
|
func (api *BaseAPI) genesis(tx kv.Tx) (*types.Block, error) {
|
2021-03-30 09:53:54 +00:00
|
|
|
_, genesis, err := api.chainConfigWithGenesis(tx)
|
2021-01-02 19:28:22 +00:00
|
|
|
return genesis, err
|
|
|
|
}
|
|
|
|
|
2022-01-07 13:52:38 +00:00
|
|
|
func (api *BaseAPI) txnLookup(ctx context.Context, tx kv.Tx, txnHash common.Hash) (uint64, bool, error) {
|
|
|
|
return api._txnReader.TxnLookup(ctx, tx, txnHash)
|
|
|
|
}
|
|
|
|
|
2021-09-29 06:51:51 +00:00
|
|
|
func (api *BaseAPI) blockByNumberWithSenders(tx kv.Tx, number uint64) (*types.Block, error) {
|
|
|
|
hash, hashErr := rawdb.ReadCanonicalHash(tx, number)
|
|
|
|
if hashErr != nil {
|
|
|
|
return nil, hashErr
|
|
|
|
}
|
|
|
|
return api.blockWithSenders(tx, hash, number)
|
|
|
|
}
|
|
|
|
func (api *BaseAPI) blockByHashWithSenders(tx kv.Tx, hash common.Hash) (*types.Block, error) {
|
|
|
|
if api.blocksLRU != nil {
|
|
|
|
if it, ok := api.blocksLRU.Get(hash); ok && it != nil {
|
|
|
|
return it.(*types.Block), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
number := rawdb.ReadHeaderNumber(tx, hash)
|
|
|
|
if number == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return api.blockWithSenders(tx, hash, *number)
|
|
|
|
}
|
|
|
|
func (api *BaseAPI) blockWithSenders(tx kv.Tx, hash common.Hash, number uint64) (*types.Block, error) {
|
|
|
|
if api.blocksLRU != nil {
|
|
|
|
if it, ok := api.blocksLRU.Get(hash); ok && it != nil {
|
|
|
|
return it.(*types.Block), nil
|
|
|
|
}
|
|
|
|
}
|
2021-11-14 04:08:52 +00:00
|
|
|
block, _, err := api._blockReader.BlockWithSenders(context.Background(), tx, hash, number)
|
2021-09-29 06:51:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-11-10 03:31:13 +00:00
|
|
|
if block == nil { // don't save nil's to cache
|
|
|
|
return nil, nil
|
|
|
|
}
|
2021-11-14 04:08:52 +00:00
|
|
|
// don't save empty blocks to cache, because in Erigon
|
|
|
|
// if block become non-canonical - we remove it's transactions, but block can become canonical in future
|
|
|
|
if block.Transactions().Len() == 0 {
|
|
|
|
return block, nil
|
|
|
|
}
|
2021-09-29 06:51:51 +00:00
|
|
|
if api.blocksLRU != nil {
|
2022-01-07 13:52:38 +00:00
|
|
|
// calc fields before put to cache
|
|
|
|
for _, txn := range block.Transactions() {
|
|
|
|
txn.Hash()
|
|
|
|
}
|
|
|
|
block.Hash()
|
2021-09-29 06:51:51 +00:00
|
|
|
api.blocksLRU.Add(hash, block)
|
|
|
|
}
|
|
|
|
return block, nil
|
|
|
|
}
|
|
|
|
|
2022-08-12 09:13:14 +00:00
|
|
|
func (api *BaseAPI) historyV2(tx kv.Tx) bool {
|
|
|
|
api._historyV2Lock.RLock()
|
|
|
|
historyV2 := api._historyV2
|
|
|
|
api._historyV2Lock.RUnlock()
|
|
|
|
|
|
|
|
if historyV2 != nil {
|
|
|
|
return *historyV2
|
|
|
|
}
|
2022-08-12 14:45:09 +00:00
|
|
|
enabled, err := rawdb.HistoryV2.Enabled(tx)
|
2022-08-12 09:13:14 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Warn("HisoryV2Enabled: read", "err", err)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
api._historyV2Lock.Lock()
|
|
|
|
api._historyV2 = &enabled
|
|
|
|
api._historyV2Lock.Unlock()
|
|
|
|
return enabled
|
|
|
|
}
|
|
|
|
|
2021-07-28 02:47:38 +00:00
|
|
|
func (api *BaseAPI) chainConfigWithGenesis(tx kv.Tx) (*params.ChainConfig, *types.Block, error) {
|
2021-09-02 08:47:48 +00:00
|
|
|
api._genesisLock.RLock()
|
|
|
|
cc, genesisBlock := api._chainConfig, api._genesis
|
|
|
|
api._genesisLock.RUnlock()
|
2021-01-02 19:28:22 +00:00
|
|
|
|
2021-09-02 08:47:48 +00:00
|
|
|
if cc != nil {
|
|
|
|
return cc, genesisBlock, nil
|
|
|
|
}
|
2021-05-01 07:42:23 +00:00
|
|
|
genesisBlock, err := rawdb.ReadBlockByNumber(tx, 0)
|
2021-01-02 19:28:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
2021-09-02 08:47:48 +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 {
|
2021-09-02 08:47:48 +00:00
|
|
|
api._genesisLock.Lock()
|
|
|
|
api._genesis = genesisBlock
|
|
|
|
api._chainConfig = cc
|
|
|
|
api._genesisLock.Unlock()
|
2021-01-02 19:28:22 +00:00
|
|
|
}
|
|
|
|
return cc, genesisBlock, nil
|
|
|
|
}
|
|
|
|
|
2021-05-17 12:15:19 +00:00
|
|
|
func (api *BaseAPI) pendingBlock() *types.Block {
|
|
|
|
return api.filters.LastPendingBlock()
|
|
|
|
}
|
|
|
|
|
2021-09-29 06:51:51 +00:00
|
|
|
func (api *BaseAPI) blockByRPCNumber(number rpc.BlockNumber, tx kv.Tx) (*types.Block, error) {
|
2022-06-14 13:29:49 +00:00
|
|
|
n, _, _, err := rpchelper.GetBlockNumber(rpc.BlockNumberOrHashWithNumber(number), tx, api.filters)
|
2021-05-17 12:15:19 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2021-09-29 06:51:51 +00:00
|
|
|
block, err := api.blockByNumberWithSenders(tx, n)
|
2021-05-17 12:15:19 +00:00
|
|
|
return block, err
|
|
|
|
}
|
|
|
|
|
2022-07-05 08:49:39 +00:00
|
|
|
func (api *BaseAPI) headerByRPCNumber(number rpc.BlockNumber, tx kv.Tx) (*types.Header, error) {
|
|
|
|
n, h, _, err := rpchelper.GetBlockNumber(rpc.BlockNumberOrHashWithNumber(number), tx, api.filters)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return api._blockReader.Header(context.Background(), tx, h, n)
|
|
|
|
}
|
|
|
|
|
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
|
2022-06-10 15:18:43 +00:00
|
|
|
ethBackend rpchelper.ApiBackend
|
2021-05-04 01:37:17 +00:00
|
|
|
txPool txpool.TxpoolClient
|
2021-05-17 12:15:19 +00:00
|
|
|
mining txpool.MiningClient
|
2021-07-28 02:47:38 +00:00
|
|
|
db kv.RoDB
|
2021-03-29 03:58:45 +00:00
|
|
|
GasCap uint64
|
2020-08-01 07:39:04 +00:00
|
|
|
}
|
|
|
|
|
2020-10-12 08:39:33 +00:00
|
|
|
// NewEthAPI returns APIImpl instance
|
2022-06-10 15:18:43 +00:00
|
|
|
func NewEthAPI(base *BaseAPI, db kv.RoDB, eth rpchelper.ApiBackend, txPool txpool.TxpoolClient, mining txpool.MiningClient, gascap uint64) *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-05-17 12:15:19 +00:00
|
|
|
BaseAPI: base,
|
2020-10-03 08:07:49 +00:00
|
|
|
db: db,
|
|
|
|
ethBackend: eth,
|
2021-05-04 01:37:17 +00:00
|
|
|
txPool: txPool,
|
2021-05-17 12:15:19 +00:00
|
|
|
mining: mining,
|
2020-10-03 08:07:49 +00:00
|
|
|
GasCap: gascap,
|
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 {
|
2021-04-22 17:11:37 +00:00
|
|
|
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,omitempty"`
|
2021-06-27 21:14:01 +00:00
|
|
|
Tip *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"`
|
|
|
|
FeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"`
|
2021-04-22 17:11:37 +00:00
|
|
|
Hash common.Hash `json:"hash"`
|
|
|
|
Input hexutil.Bytes `json:"input"`
|
|
|
|
Nonce hexutil.Uint64 `json:"nonce"`
|
|
|
|
To *common.Address `json:"to"`
|
|
|
|
TransactionIndex *hexutil.Uint64 `json:"transactionIndex"`
|
|
|
|
Value *hexutil.Big `json:"value"`
|
|
|
|
Type hexutil.Uint64 `json:"type"`
|
|
|
|
Accesses *types.AccessList `json:"accessList,omitempty"`
|
|
|
|
ChainID *hexutil.Big `json:"chainId,omitempty"`
|
|
|
|
V *hexutil.Big `json:"v"`
|
|
|
|
R *hexutil.Big `json:"r"`
|
|
|
|
S *hexutil.Big `json:"s"`
|
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).
|
2021-07-01 04:29:32 +00:00
|
|
|
func newRPCTransaction(tx types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64, baseFee *big.Int) *RPCTransaction {
|
2021-04-22 17:11:37 +00:00
|
|
|
// Determine the signer. For replay-protected transactions, use the most permissive
|
|
|
|
// signer, because we assume that signers are backwards-compatible with old
|
|
|
|
// transactions. For non-protected transactions, the homestead signer signer is used
|
|
|
|
// because the return value of ChainId is zero for those transactions.
|
2021-05-04 21:58:13 +00:00
|
|
|
var chainId *big.Int
|
2020-09-08 19:39:31 +00:00
|
|
|
result := &RPCTransaction{
|
2021-04-22 17:11:37 +00:00
|
|
|
Type: hexutil.Uint64(tx.Type()),
|
|
|
|
Gas: hexutil.Uint64(tx.GetGas()),
|
|
|
|
Hash: tx.Hash(),
|
|
|
|
Input: hexutil.Bytes(tx.GetData()),
|
|
|
|
Nonce: hexutil.Uint64(tx.GetNonce()),
|
|
|
|
To: tx.GetTo(),
|
|
|
|
Value: (*hexutil.Big)(tx.GetValue().ToBig()),
|
|
|
|
}
|
|
|
|
switch t := tx.(type) {
|
|
|
|
case *types.LegacyTx:
|
2021-05-04 21:58:13 +00:00
|
|
|
chainId = types.DeriveChainId(&t.V).ToBig()
|
2021-04-22 17:11:37 +00:00
|
|
|
result.GasPrice = (*hexutil.Big)(t.GasPrice.ToBig())
|
|
|
|
result.V = (*hexutil.Big)(t.V.ToBig())
|
|
|
|
result.R = (*hexutil.Big)(t.R.ToBig())
|
|
|
|
result.S = (*hexutil.Big)(t.S.ToBig())
|
|
|
|
case *types.AccessListTx:
|
2021-05-04 21:58:13 +00:00
|
|
|
chainId = t.ChainID.ToBig()
|
|
|
|
result.ChainID = (*hexutil.Big)(chainId)
|
2021-04-22 17:11:37 +00:00
|
|
|
result.GasPrice = (*hexutil.Big)(t.GasPrice.ToBig())
|
|
|
|
result.V = (*hexutil.Big)(t.V.ToBig())
|
|
|
|
result.R = (*hexutil.Big)(t.R.ToBig())
|
|
|
|
result.S = (*hexutil.Big)(t.S.ToBig())
|
|
|
|
result.Accesses = &t.AccessList
|
|
|
|
case *types.DynamicFeeTransaction:
|
2021-05-04 21:58:13 +00:00
|
|
|
chainId = t.ChainID.ToBig()
|
|
|
|
result.ChainID = (*hexutil.Big)(chainId)
|
2021-04-22 17:11:37 +00:00
|
|
|
result.Tip = (*hexutil.Big)(t.Tip.ToBig())
|
|
|
|
result.FeeCap = (*hexutil.Big)(t.FeeCap.ToBig())
|
|
|
|
result.V = (*hexutil.Big)(t.V.ToBig())
|
|
|
|
result.R = (*hexutil.Big)(t.R.ToBig())
|
|
|
|
result.S = (*hexutil.Big)(t.S.ToBig())
|
|
|
|
result.Accesses = &t.AccessList
|
2021-07-01 04:29:32 +00:00
|
|
|
baseFee, overflow := uint256.FromBig(baseFee)
|
|
|
|
if baseFee != nil && !overflow && blockHash != (common.Hash{}) {
|
|
|
|
// price = min(tip + baseFee, gasFeeCap)
|
|
|
|
price := math.Min256(new(uint256.Int).Add(tx.GetTip(), baseFee), tx.GetFeeCap())
|
|
|
|
result.GasPrice = (*hexutil.Big)(price.ToBig())
|
|
|
|
} else {
|
|
|
|
result.GasPrice = nil
|
|
|
|
}
|
2020-09-08 19:39:31 +00:00
|
|
|
}
|
2021-05-04 21:58:13 +00:00
|
|
|
signer := types.LatestSignerForChainID(chainId)
|
2021-04-22 17:11:37 +00:00
|
|
|
result.From, _ = tx.Sender(*signer)
|
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
|
|
|
|
}
|
2021-05-04 05:51:28 +00:00
|
|
|
|
2022-07-09 03:15:22 +00:00
|
|
|
// newRPCBorTransaction returns a Bor transaction that will serialize to the RPC
|
|
|
|
// representation, with the given location metadata set (if available).
|
|
|
|
func newRPCBorTransaction(opaqueTx types.Transaction, txHash common.Hash, blockHash common.Hash, blockNumber uint64, index uint64, baseFee *big.Int) *RPCTransaction {
|
|
|
|
tx := opaqueTx.(*types.LegacyTx)
|
|
|
|
result := &RPCTransaction{
|
|
|
|
Type: hexutil.Uint64(tx.Type()),
|
|
|
|
ChainID: (*hexutil.Big)(new(big.Int)),
|
|
|
|
GasPrice: (*hexutil.Big)(tx.GasPrice.ToBig()),
|
|
|
|
Gas: hexutil.Uint64(tx.GetGas()),
|
|
|
|
Hash: txHash,
|
|
|
|
Input: hexutil.Bytes(tx.GetData()),
|
|
|
|
Nonce: hexutil.Uint64(tx.GetNonce()),
|
|
|
|
From: common.Address{},
|
|
|
|
To: tx.GetTo(),
|
|
|
|
Value: (*hexutil.Big)(tx.GetValue().ToBig()),
|
|
|
|
}
|
|
|
|
if blockHash != (common.Hash{}) {
|
|
|
|
result.BlockHash = &blockHash
|
|
|
|
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
|
|
|
|
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-05-04 05:51:28 +00:00
|
|
|
// newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
|
2021-07-22 14:21:55 +00:00
|
|
|
func newRPCPendingTransaction(tx types.Transaction, current *types.Header, config *params.ChainConfig) *RPCTransaction {
|
|
|
|
var baseFee *big.Int
|
|
|
|
if current != nil {
|
|
|
|
baseFee = misc.CalcBaseFee(config, current)
|
|
|
|
}
|
|
|
|
return newRPCTransaction(tx, common.Hash{}, 0, 0, baseFee)
|
2021-05-04 05:51:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index.
|
|
|
|
func newRPCRawTransactionFromBlockIndex(b *types.Block, index uint64) (hexutil.Bytes, error) {
|
|
|
|
txs := b.Transactions()
|
|
|
|
if index >= uint64(len(txs)) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
|
|
err := txs[index].MarshalBinary(&buf)
|
|
|
|
return buf.Bytes(), err
|
|
|
|
}
|