2020-10-12 14:17:34 +00:00
package commands
2020-10-14 15:59:42 +00:00
import (
2021-05-04 05:51:28 +00:00
"bytes"
2020-10-14 15:59:42 +00:00
"context"
"fmt"
2021-07-01 04:29:32 +00:00
"math/big"
2020-10-12 14:17:34 +00:00
2021-07-01 21:31:14 +00:00
"github.com/ledgerwatch/erigon-lib/gointerfaces"
"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
"github.com/ledgerwatch/erigon-lib/gointerfaces/types"
2021-05-20 18:25:53 +00:00
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/common/hexutil"
"github.com/ledgerwatch/erigon/core/rawdb"
types2 "github.com/ledgerwatch/erigon/core/types"
2021-09-15 07:22:57 +00:00
"github.com/ledgerwatch/erigon/rlp"
2021-05-20 18:25:53 +00:00
"github.com/ledgerwatch/erigon/rpc"
2020-10-14 15:59:42 +00:00
)
2020-10-24 17:03:52 +00:00
// GetTransactionByHash implements eth_getTransactionByHash. Returns information about a transaction given the transaction's hash.
2020-10-14 15:59:42 +00:00
func ( api * APIImpl ) GetTransactionByHash ( ctx context . Context , hash common . Hash ) ( * RPCTransaction , error ) {
2021-04-03 06:26:00 +00:00
tx , err := api . db . BeginRo ( ctx )
2020-10-14 15:59:42 +00:00
if err != nil {
return nil , err
}
defer tx . Rollback ( )
// https://infura.io/docs/ethereum/json-rpc/eth-getTransactionByHash
2021-07-11 05:25:21 +00:00
txn , blockHash , blockNumber , txIndex , err := rawdb . ReadTransaction ( tx , hash )
if err != nil {
return nil , err
}
2021-07-01 04:29:32 +00:00
// Add GasPrice for the DynamicFeeTransaction
var baseFee * big . Int
chainConfig , err := api . chainConfig ( tx )
if err != nil {
return nil , err
}
if chainConfig . IsLondon ( blockNumber ) && blockHash != ( common . Hash { } ) {
2021-09-29 06:51:51 +00:00
block , err := api . blockByHashWithSenders ( tx , blockHash )
2021-07-01 04:29:32 +00:00
if err != nil {
return nil , err
}
baseFee = block . BaseFee ( )
}
2021-05-04 21:58:13 +00:00
if txn != nil {
2021-07-01 04:29:32 +00:00
return newRPCTransaction ( txn , blockHash , blockNumber , txIndex , baseFee ) , nil
2021-05-04 05:51:28 +00:00
}
2021-07-22 14:21:55 +00:00
curHeader := rawdb . ReadCurrentHeader ( tx )
2021-10-20 00:28:14 +00:00
if curHeader == nil {
return nil , nil
}
2021-07-22 14:21:55 +00:00
2021-05-04 05:51:28 +00:00
// No finalized transaction, try to retrieve it from the pool
reply , err := api . txPool . Transactions ( ctx , & txpool . TransactionsRequest { Hashes : [ ] * types . H256 { gointerfaces . ConvertHashToH256 ( hash ) } } )
if err != nil {
return nil , err
}
2021-05-04 21:58:13 +00:00
if len ( reply . RlpTxs [ 0 ] ) > 0 {
2021-09-15 07:22:57 +00:00
s := rlp . NewStream ( bytes . NewReader ( reply . RlpTxs [ 0 ] ) , uint64 ( len ( reply . RlpTxs [ 0 ] ) ) )
txn , err = types2 . DecodeTransaction ( s )
2021-05-04 05:51:28 +00:00
if err != nil {
return nil , err
}
2021-07-22 14:21:55 +00:00
return newRPCPendingTransaction ( txn , curHeader , chainConfig ) , nil
2021-05-04 05:51:28 +00:00
}
// Transaction unknown, return as such
return nil , nil
}
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
func ( api * APIImpl ) GetRawTransactionByHash ( ctx context . Context , hash common . Hash ) ( hexutil . Bytes , error ) {
tx , err := api . db . BeginRo ( ctx )
if err != nil {
return nil , err
}
defer tx . Rollback ( )
// https://infura.io/docs/ethereum/json-rpc/eth-getTransactionByHash
2021-07-11 05:25:21 +00:00
txn , _ , _ , _ , err := rawdb . ReadTransaction ( tx , hash )
if err != nil {
return nil , err
}
2021-05-04 21:58:13 +00:00
if txn != nil {
2021-05-04 05:51:28 +00:00
var buf bytes . Buffer
err = txn . MarshalBinary ( & buf )
return buf . Bytes ( ) , err
}
// No finalized transaction, try to retrieve it from the pool
reply , err := api . txPool . Transactions ( ctx , & txpool . TransactionsRequest { Hashes : [ ] * types . H256 { gointerfaces . ConvertHashToH256 ( hash ) } } )
if err != nil {
return nil , err
}
2021-05-04 21:58:13 +00:00
if len ( reply . RlpTxs [ 0 ] ) > 0 {
2021-05-04 05:51:28 +00:00
return reply . RlpTxs [ 0 ] , nil
}
return nil , nil
2020-10-14 15:59:42 +00:00
}
2020-10-24 17:03:52 +00:00
// GetTransactionByBlockHashAndIndex implements eth_getTransactionByBlockHashAndIndex. Returns information about a transaction given the block's hash and a transaction index.
2020-10-14 15:59:42 +00:00
func ( api * APIImpl ) GetTransactionByBlockHashAndIndex ( ctx context . Context , blockHash common . Hash , txIndex hexutil . Uint64 ) ( * RPCTransaction , error ) {
2021-04-03 06:26:00 +00:00
tx , err := api . db . BeginRo ( ctx )
2020-10-14 15:59:42 +00:00
if err != nil {
return nil , err
}
defer tx . Rollback ( )
// https://infura.io/docs/ethereum/json-rpc/eth-getTransactionByBlockHashAndIndex
2021-09-29 06:51:51 +00:00
block , err := api . blockByHashWithSenders ( tx , blockHash )
2020-10-24 06:57:09 +00:00
if err != nil {
return nil , err
}
2020-10-14 15:59:42 +00:00
if block == nil {
2021-05-26 10:35:39 +00:00
return nil , nil // not error, see https://github.com/ledgerwatch/erigon/issues/1645
2020-10-14 15:59:42 +00:00
}
txs := block . Transactions ( )
if uint64 ( txIndex ) >= uint64 ( len ( txs ) ) {
return nil , fmt . Errorf ( "txIndex (%d) out of range (nTxs: %d)" , uint64 ( txIndex ) , uint64 ( len ( txs ) ) )
}
2021-07-01 04:29:32 +00:00
return newRPCTransaction ( txs [ txIndex ] , block . Hash ( ) , block . NumberU64 ( ) , uint64 ( txIndex ) , block . BaseFee ( ) ) , nil
2020-10-14 15:59:42 +00:00
}
2021-05-04 05:51:28 +00:00
// GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index.
func ( api * APIImpl ) GetRawTransactionByBlockHashAndIndex ( ctx context . Context , blockHash common . Hash , index hexutil . Uint ) ( hexutil . Bytes , error ) {
tx , err := api . db . BeginRo ( ctx )
if err != nil {
return nil , err
}
defer tx . Rollback ( )
// https://infura.io/docs/ethereum/json-rpc/eth-getRawTransactionByBlockHashAndIndex
2021-09-29 06:51:51 +00:00
block , err := api . blockByHashWithSenders ( tx , blockHash )
2021-05-04 05:51:28 +00:00
if err != nil {
return nil , err
}
if block == nil {
2021-05-26 10:35:39 +00:00
return nil , nil // not error, see https://github.com/ledgerwatch/erigon/issues/1645
2021-05-04 05:51:28 +00:00
}
return newRPCRawTransactionFromBlockIndex ( block , uint64 ( index ) )
}
2020-10-24 17:03:52 +00:00
// GetTransactionByBlockNumberAndIndex implements eth_getTransactionByBlockNumberAndIndex. Returns information about a transaction given a block number and transaction index.
2020-10-14 15:59:42 +00:00
func ( api * APIImpl ) GetTransactionByBlockNumberAndIndex ( ctx context . Context , blockNr rpc . BlockNumber , txIndex hexutil . Uint ) ( * RPCTransaction , error ) {
2021-04-03 06:26:00 +00:00
tx , err := api . db . BeginRo ( ctx )
2020-10-14 15:59:42 +00:00
if err != nil {
return nil , err
}
defer tx . Rollback ( )
// https://infura.io/docs/ethereum/json-rpc/eth-getTransactionByBlockNumberAndIndex
blockNum , err := getBlockNumber ( blockNr , tx )
if err != nil {
return nil , err
}
2021-09-29 06:51:51 +00:00
block , err := api . blockByNumberWithSenders ( tx , blockNum )
2020-10-24 06:57:09 +00:00
if err != nil {
return nil , err
}
2020-10-14 15:59:42 +00:00
if block == nil {
2021-05-26 10:35:39 +00:00
return nil , nil // not error, see https://github.com/ledgerwatch/erigon/issues/1645
2020-10-14 15:59:42 +00:00
}
txs := block . Transactions ( )
if uint64 ( txIndex ) >= uint64 ( len ( txs ) ) {
return nil , fmt . Errorf ( "txIndex (%d) out of range (nTxs: %d)" , uint64 ( txIndex ) , uint64 ( len ( txs ) ) )
}
2021-07-01 04:29:32 +00:00
return newRPCTransaction ( txs [ txIndex ] , block . Hash ( ) , block . NumberU64 ( ) , uint64 ( txIndex ) , block . BaseFee ( ) ) , nil
2020-10-14 15:59:42 +00:00
}
2021-05-04 05:51:28 +00:00
// GetRawTransactionByBlockNumberAndIndex returns the bytes of the transaction for the given block number and index.
func ( api * APIImpl ) GetRawTransactionByBlockNumberAndIndex ( ctx context . Context , blockNr rpc . BlockNumber , index hexutil . Uint ) ( hexutil . Bytes , error ) {
tx , err := api . db . BeginRo ( ctx )
if err != nil {
return nil , err
}
defer tx . Rollback ( )
// https://infura.io/docs/ethereum/json-rpc/eth-getRawTransactionByBlockNumberAndIndex
2021-09-29 06:51:51 +00:00
block , err := api . blockByRPCNumber ( blockNr , tx )
2021-05-04 05:51:28 +00:00
if err != nil {
return nil , err
}
if block == nil {
2021-05-26 10:35:39 +00:00
return nil , nil // not error, see https://github.com/ledgerwatch/erigon/issues/1645
2021-05-04 05:51:28 +00:00
}
return newRPCRawTransactionFromBlockIndex ( block , uint64 ( index ) )
}