good morning!!!!

Skip to content
Snippets Groups Projects
eth_api.go 11.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • Alex Sharov's avatar
    Alex Sharov committed
    package commands
    
    import (
    
    	"bytes"
    
    Alex Sharov's avatar
    Alex Sharov committed
    	"context"
    
    Alex Sharov's avatar
    Alex Sharov committed
    	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters"
    
    	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/services"
    
    Alex Sharov's avatar
    Alex Sharov committed
    	"github.com/ledgerwatch/erigon/common"
    	"github.com/ledgerwatch/erigon/common/hexutil"
    	"github.com/ledgerwatch/erigon/common/math"
    	"github.com/ledgerwatch/erigon/core/rawdb"
    	"github.com/ledgerwatch/erigon/core/types"
    	ethFilters "github.com/ledgerwatch/erigon/eth/filters"
    	"github.com/ledgerwatch/erigon/ethdb"
    	"github.com/ledgerwatch/erigon/gointerfaces/txpool"
    	"github.com/ledgerwatch/erigon/internal/ethapi"
    	"github.com/ledgerwatch/erigon/params"
    	"github.com/ledgerwatch/erigon/rpc"
    
    Alex Sharov's avatar
    Alex Sharov committed
    )
    
    // EthAPI is a collection of functions that are exposed in the
    type EthAPI interface {
    
    	// Block related (proposed file: ./eth_blocks.go)
    
    Alex Sharov's avatar
    Alex Sharov committed
    	GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error)
    
    Igor Mandrigin's avatar
    Igor Mandrigin committed
    	GetBlockByHash(ctx context.Context, hash rpc.BlockNumberOrHash, fullTx bool) (map[string]interface{}, error)
    
    ledgerwatch's avatar
    ledgerwatch committed
    	GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*hexutil.Uint, error)
    	GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) (*hexutil.Uint, error)
    
    	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)
    
    	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)
    
    	GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error)
    
    	GetLogs(ctx context.Context, crit ethFilters.FilterCriteria) ([]*types.Log, error)
    
    	GetBlockReceipts(ctx context.Context, number rpc.BlockNumber) ([]map[string]interface{}, error)
    
    	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)
    
    	GetUncleCountByBlockNumber(ctx context.Context, number rpc.BlockNumber) (*hexutil.Uint, error)
    
    	GetUncleCountByBlockHash(ctx context.Context, hash common.Hash) (*hexutil.Uint, error)
    
    	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)
    
    	Accounts(ctx context.Context) ([]common.Address, error)
    
    	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)
    
    
    	BlockNumber(ctx context.Context) (hexutil.Uint64, error)
    	Syncing(ctx context.Context) (interface{}, error)
    
    	ChainId(ctx context.Context) (hexutil.Uint64, error) /* called eth_protocolVersion elsewhere */
    	ProtocolVersion(_ context.Context) (hexutil.Uint, error)
    
    	GasPrice(_ context.Context) (*hexutil.Big, error)
    
    	Call(ctx context.Context, args ethapi.CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *map[common.Address]ethapi.Account) (hexutil.Bytes, error)
    
    	EstimateGas(ctx context.Context, args ethapi.CallArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error)
    
    	SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error)
    
    	SendTransaction(_ context.Context, txObject interface{}) (common.Hash, error)
    
    	Sign(ctx context.Context, _ common.Address, _ hexutil.Bytes) (hexutil.Bytes, error)
    
    	SignTransaction(_ context.Context, txObject interface{}) (common.Hash, error)
    	GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNr rpc.BlockNumber) (*interface{}, error)
    
    Alex Sharov's avatar
    Alex Sharov committed
    	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)
    
    
    	// Deprecated commands in eth_ (proposed file: ./eth_deprecated.go)
    
    	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)
    
    	filters         *filters.Filters
    
    	_chainConfig    *params.ChainConfig
    	_genesis        *types.Block
    	_genesisSetOnce sync.Once
    }
    
    
    func NewBaseApi(f *filters.Filters) *BaseAPI {
    	return &BaseAPI{filters: f}
    }
    
    
    func (api *BaseAPI) chainConfig(tx ethdb.Tx) (*params.ChainConfig, error) {
    	cfg, _, err := api.chainConfigWithGenesis(tx)
    
    func (api *BaseAPI) genesis(tx ethdb.Tx) (*types.Block, error) {
    	_, genesis, err := api.chainConfigWithGenesis(tx)
    
    func (api *BaseAPI) chainConfigWithGenesis(tx ethdb.Tx) (*params.ChainConfig, *types.Block, error) {
    
    	if api._chainConfig != nil {
    		return api._chainConfig, api._genesis, nil
    	}
    
    
    	genesisBlock, err := rawdb.ReadBlockByNumber(tx, 0)
    
    Alex Sharov's avatar
    Alex Sharov committed
    	cc, err := rawdb.ReadChainConfig(tx, genesisBlock.Hash())
    
    	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
    }
    
    
    func (api *BaseAPI) pendingBlock() *types.Block {
    	return api.filters.LastPendingBlock()
    }
    
    func (api *BaseAPI) getBlockByNumber(number rpc.BlockNumber, tx ethdb.Tx) (*types.Block, error) {
    	if number == rpc.PendingBlockNumber {
    		return api.pendingBlock(), nil
    	}
    
    	n, err := getBlockNumber(number, tx)
    	if err != nil {
    		return nil, err
    	}
    
    	block, _, err := rawdb.ReadBlockByNumberWithSenders(tx, n)
    	return block, err
    }
    
    
    Alex Sharov's avatar
    Alex Sharov committed
    // APIImpl is implementation of the EthAPI interface based on remote Db access
    type APIImpl struct {
    
    	ethBackend services.ApiBackend
    
    	mining     txpool.MiningClient
    
    // NewEthAPI returns APIImpl instance
    
    func NewEthAPI(base *BaseAPI, db ethdb.RoKV, eth services.ApiBackend, txPool txpool.TxpoolClient, mining txpool.MiningClient, gascap uint64) *APIImpl {
    
    	if gascap == 0 {
    		gascap = uint64(math.MaxUint64 / 2)
    	}
    
    
    Alex Sharov's avatar
    Alex Sharov committed
    	return &APIImpl{
    
    		BaseAPI:    base,
    
    		mining:     mining,
    
    // 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,omitempty"`
    	Tip              *hexutil.Big      `json:"tip,omitempty"`
    	FeeCap           *hexutil.Big      `json:"feeCap,omitempty"`
    	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"`
    
    }
    
    // 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 {
    	// 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.
    
    		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:
    
    		chainId = types.DeriveChainId(&t.V).ToBig()
    
    		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:
    
    		chainId = t.ChainID.ToBig()
    		result.ChainID = (*hexutil.Big)(chainId)
    
    		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:
    
    		chainId = t.ChainID.ToBig()
    		result.ChainID = (*hexutil.Big)(chainId)
    
    		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
    
    	signer := types.LatestSignerForChainID(chainId)
    
    	result.From, _ = tx.Sender(*signer)
    
    	if blockHash != (common.Hash{}) {
    		result.BlockHash = &blockHash
    		result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
    		result.TransactionIndex = (*hexutil.Uint64)(&index)
    	}
    	return result
    }
    
    
    // newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
    func newRPCPendingTransaction(tx types.Transaction) *RPCTransaction {
    	return newRPCTransaction(tx, common.Hash{}, 0, 0)
    }
    
    // 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
    }