core, eth, internal, les: RPC methods and fields for EIP 1559 (#22964)
* internal/ethapi: add baseFee to RPCMarshalHeader * internal/ethapi: add FeeCap, Tip and correct GasPrice to EIP-1559 RPCTransaction results * core,eth,les,internal: add support for tip estimation in gas price oracle * internal/ethapi,eth/gasprice: don't suggest tip larger than fee cap * core/types,internal: use correct eip1559 terminology for json marshalling * eth, internal/ethapi: fix rebase problems * internal/ethapi: fix rpc name of basefee * internal/ethapi: address review concerns * core, eth, internal, les: simplify gasprice oracle (#25) * core, eth, internal, les: simplify gasprice oracle * eth/gasprice: fix typo * internal/ethapi: minor tweak in tx args * internal/ethapi: calculate basefee for pending block * internal/ethapi: fix panic * internal/ethapi, eth/tracers: simplify txargs ToMessage * internal/ethapi: remove unused param * core, eth, internal: fix regressions wrt effective gas price in the evm * eth/gasprice: drop weird debug println * internal/jsre/deps: hack in 1559 gas conversions into embedded web3 * internal/jsre/deps: hack basFee to decimal conversion * internal/ethapi: init feecap and tipcap for legacy txs too * eth, graphql, internal, les: fix gas price suggestion on all combos * internal/jsre/deps: handle decimal tipcap and feecap * eth, internal: minor review fixes * graphql, internal: export max fee cap RPC endpoint * internal/ethapi: fix crash in transaction_args * internal/ethapi: minor refactor to make the code safer Co-authored-by: Ryan Schneider <ryanleeschneider@gmail.com> Co-authored-by: lightclient@protonmail.com <lightclient@protonmail.com> Co-authored-by: gary rong <garyrong0905@gmail.com> Co-authored-by: Péter Szilágyi <peterke@gmail.com>
This commit is contained in:
committed by
GitHub
parent
2dee31930c
commit
5cff9754d7
@ -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
|
||||
|
Reference in New Issue
Block a user