@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@ -58,10 +59,25 @@ func NewPublicEthereumAPI(b Backend) *PublicEthereumAPI {
return & PublicEthereumAPI { b }
}
// GasPrice returns a suggestion for a gas price.
// GasPrice returns a suggestion for a gas price for legacy transactions .
func ( s * PublicEthereumAPI ) GasPrice ( ctx context . Context ) ( * hexutil . Big , error ) {
price , err := s . b . SuggestPrice ( ctx )
return ( * hexutil . Big ) ( price ) , err
tipcap , err := s . b . SuggestGasTipCap ( ctx )
if err != nil {
return nil , err
}
if head := s . b . CurrentHeader ( ) ; head . BaseFee != nil {
tipcap . Add ( tipcap , head . BaseFee )
}
return ( * hexutil . Big ) ( tipcap ) , err
}
// MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic transactions.
func ( s * PublicEthereumAPI ) MaxPriorityFeePerGas ( ctx context . Context ) ( * hexutil . Big , error ) {
tipcap , err := s . b . SuggestGasTipCap ( ctx )
if err != nil {
return nil , err
}
return ( * hexutil . Big ) ( tipcap ) , err
}
// Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not
@ -105,12 +121,12 @@ func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string]*RPCTransac
"queued" : make ( map [ string ] map [ string ] * RPCTransaction ) ,
}
pending , queue := s . b . TxPoolContent ( )
curHeader := s . b . CurrentHeader ( )
// Flatten the pending transactions
for account , txs := range pending {
dump := make ( map [ string ] * RPCTransaction )
for _ , tx := range txs {
dump [ fmt . Sprintf ( "%d" , tx . Nonce ( ) ) ] = newRPCPendingTransaction ( tx )
dump [ fmt . Sprintf ( "%d" , tx . Nonce ( ) ) ] = newRPCPendingTransaction ( tx , curHeader , s . b . ChainConfig ( ) )
}
content [ "pending" ] [ account . Hex ( ) ] = dump
}
@ -118,7 +134,7 @@ func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string]*RPCTransac
for account , txs := range queue {
dump := make ( map [ string ] * RPCTransaction )
for _ , tx := range txs {
dump [ fmt . Sprintf ( "%d" , tx . Nonce ( ) ) ] = newRPCPendingTransaction ( tx )
dump [ fmt . Sprintf ( "%d" , tx . Nonce ( ) ) ] = newRPCPendingTransaction ( tx , curHeader , s . b . ChainConfig ( ) )
}
content [ "queued" ] [ account . Hex ( ) ] = dump
}
@ -829,7 +845,10 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
defer cancel ( )
// Get a new instance of the EVM.
msg := args . ToMessage ( globalGasCap )
msg , err := args . ToMessage ( globalGasCap , header . BaseFee )
if err != nil {
return nil , err
}
evm , vmError , err := b . GetEVM ( ctx , msg , state , header , nil )
if err != nil {
return nil , err
@ -1088,7 +1107,7 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes {
// RPCMarshalHeader converts the given header to the RPC output .
func RPCMarshalHeader ( head * types . Header ) map [ string ] interface { } {
return map [ string ] interface { } {
result := map [ string ] interface { } {
"number" : ( * hexutil . Big ) ( head . Number ) ,
"hash" : head . Hash ( ) ,
"parentHash" : head . ParentHash ,
@ -1107,6 +1126,12 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
"transactionsRoot" : head . TxHash ,
"receiptsRoot" : head . ReceiptHash ,
}
if head . BaseFee != nil {
result [ "baseFeePerGas" ] = ( * hexutil . Big ) ( head . BaseFee )
}
return result
}
// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
@ -1173,6 +1198,8 @@ type RPCTransaction struct {
From common . Address ` json:"from" `
Gas hexutil . Uint64 ` json:"gas" `
GasPrice * hexutil . Big ` json:"gasPrice" `
FeeCap * hexutil . Big ` json:"maxFeePerGas,omitempty" `
Tip * hexutil . Big ` json:"maxPriorityFeePerGas,omitempty" `
Hash common . Hash ` json:"hash" `
Input hexutil . Bytes ` json:"input" `
Nonce hexutil . Uint64 ` json:"nonce" `
@ -1189,7 +1216,7 @@ type RPCTransaction struct {
// 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 {
func newRPCTransaction ( tx * types . Transaction , blockHash common . Hash , blockNumber uint64 , index uint64 , baseFee * big . Int ) * 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
@ -1200,7 +1227,6 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
} else {
signer = types . HomesteadSigner { }
}
from , _ := types . Sender ( signer , tx )
v , r , s := tx . RawSignatureValues ( )
result := & RPCTransaction {
@ -1222,17 +1248,36 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
result . BlockNumber = ( * hexutil . Big ) ( new ( big . Int ) . SetUint64 ( blockNumber ) )
result . TransactionIndex = ( * hexutil . Uint64 ) ( & index )
}
if tx . Type ( ) != types . LegacyTxType {
switch tx . Type ( ) {
case types . AccessListTxType :
al := tx . AccessList ( )
result . Accesses = & al
result . ChainID = ( * hexutil . Big ) ( tx . ChainId ( ) )
case types . DynamicFeeTxType :
al := tx . AccessList ( )
result . Accesses = & al
result . ChainID = ( * hexutil . Big ) ( tx . ChainId ( ) )
result . FeeCap = ( * hexutil . Big ) ( tx . FeeCap ( ) )
result . Tip = ( * hexutil . Big ) ( tx . Tip ( ) )
// if the transaction has been mined, compute the effective gas price
if baseFee != nil && blockHash != ( common . Hash { } ) {
// price = min(tip, feeCap - baseFee) + baseFee
price := math . BigMin ( new ( big . Int ) . Add ( tx . Tip ( ) , baseFee ) , tx . FeeCap ( ) )
result . GasPrice = ( * hexutil . Big ) ( price )
} else {
result . GasPrice = nil
}
}
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 )
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 )
}
// newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
@ -1241,7 +1286,7 @@ func newRPCTransactionFromBlockIndex(b *types.Block, index uint64) *RPCTransacti
if index >= uint64 ( len ( txs ) ) {
return nil
}
return newRPCTransaction ( txs [ index ] , b . Hash ( ) , b . NumberU64 ( ) , index )
return newRPCTransaction ( txs [ index ] , b . Hash ( ) , b . NumberU64 ( ) , index , b . BaseFee ( ) )
}
// newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index.
@ -1450,11 +1495,15 @@ func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, has
return nil , err
}
if tx != nil {
return newRPCTransaction ( tx , blockHash , blockNumber , index ) , nil
header , err := s . b . HeaderByHash ( ctx , blockHash )
if err != nil {
return nil , err
}
return newRPCTransaction ( tx , blockHash , blockNumber , index , header . BaseFee ) , nil
}
// No finalized transaction, try to retrieve it from the pool
if tx := s . b . GetPoolTransaction ( hash ) ; tx != nil {
return newRPCPendingTransaction ( tx ) , nil
return newRPCPendingTransaction ( tx , s . b . CurrentHeader ( ) , s . b . ChainConfig ( ) ) , nil
}
// Transaction unknown, return as such
@ -1705,11 +1754,12 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, err
accounts [ account . Address ] = struct { } { }
}
}
curHeader := s . b . CurrentHeader ( )
transactions := make ( [ ] * RPCTransaction , 0 , len ( pending ) )
for _ , tx := range pending {
from , _ := types . Sender ( s . signer , tx )
if _ , exists := accounts [ from ] ; exists {
transactions = append ( transactions , newRPCPendingTransaction ( tx ) )
transactions = append ( transactions , newRPCPendingTransaction ( tx , curHeader , s . b . ChainConfig ( ) ) )
}
}
return transactions , nil