2016-11-09 01:01:56 +00:00
|
|
|
|
// Copyright 2015 The go-ethereum Authors
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// This file is part of the go-ethereum library.
|
|
|
|
|
//
|
|
|
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
package ethapi
|
|
|
|
|
|
|
|
|
|
import (
|
2017-03-22 17:20:33 +00:00
|
|
|
|
"context"
|
2022-09-16 16:16:32 +00:00
|
|
|
|
"encoding/hex"
|
2017-01-11 12:20:24 +00:00
|
|
|
|
"errors"
|
2015-12-16 03:26:23 +00:00
|
|
|
|
"fmt"
|
|
|
|
|
"math/big"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
2018-04-05 12:13:02 +00:00
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
2015-12-16 03:26:23 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/accounts"
|
2017-01-24 09:49:20 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
2018-01-07 18:38:11 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/scwallet"
|
2015-12-16 03:26:23 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
2016-12-16 10:19:03 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
common: move big integer math to common/math (#3699)
* common: remove CurrencyToString
Move denomination values to params instead.
* common: delete dead code
* common: move big integer operations to common/math
This commit consolidates all big integer operations into common/math and
adds tests and documentation.
There should be no change in semantics for BigPow, BigMin, BigMax, S256,
U256, Exp and their behaviour is now locked in by tests.
The BigD, BytesToBig and Bytes2Big functions don't provide additional
value, all uses are replaced by new(big.Int).SetBytes().
BigToBytes is now called PaddedBigBytes, its minimum output size
parameter is now specified as the number of bytes instead of bits. The
single use of this function is in the EVM's MSTORE instruction.
Big and String2Big are replaced by ParseBig, which is slightly stricter.
It previously accepted leading zeros for hexadecimal inputs but treated
decimal inputs as octal if a leading zero digit was present.
ParseUint64 is used in places where String2Big was used to decode a
uint64.
The new functions MustParseBig and MustParseUint64 are now used in many
places where parsing errors were previously ignored.
* common: delete unused big integer variables
* accounts/abi: replace uses of BytesToBig with use of encoding/binary
* common: remove BytesToBig
* common: remove Bytes2Big
* common: remove BigTrue
* cmd/utils: add BigFlag and use it for error-checked integer flags
While here, remove environment variable processing for DirectoryFlag
because we don't use it.
* core: add missing error checks in genesis block parser
* common: remove String2Big
* cmd/evm: use utils.BigFlag
* common/math: check for 256 bit overflow in ParseBig
This is supposed to prevent silent overflow/truncation of values in the
genesis block JSON. Without this check, a genesis block that set a
balance larger than 256 bits would lead to weird behaviour in the VM.
* cmd/utils: fixup import
2017-02-26 21:21:51 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/common/math"
|
2023-05-02 08:28:43 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/consensus"
|
2023-08-01 09:58:45 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
2015-12-16 03:26:23 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/core"
|
2021-04-21 07:21:22 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/core/state"
|
2015-12-16 03:26:23 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
|
|
|
"github.com/ethereum/go-ethereum/core/vm"
|
|
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
2023-11-27 14:20:09 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/eth/gasestimator"
|
2021-11-25 12:17:09 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
2017-02-22 12:10:07 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/log"
|
2015-12-16 03:26:23 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/p2p"
|
common: move big integer math to common/math (#3699)
* common: remove CurrencyToString
Move denomination values to params instead.
* common: delete dead code
* common: move big integer operations to common/math
This commit consolidates all big integer operations into common/math and
adds tests and documentation.
There should be no change in semantics for BigPow, BigMin, BigMax, S256,
U256, Exp and their behaviour is now locked in by tests.
The BigD, BytesToBig and Bytes2Big functions don't provide additional
value, all uses are replaced by new(big.Int).SetBytes().
BigToBytes is now called PaddedBigBytes, its minimum output size
parameter is now specified as the number of bytes instead of bits. The
single use of this function is in the EVM's MSTORE instruction.
Big and String2Big are replaced by ParseBig, which is slightly stricter.
It previously accepted leading zeros for hexadecimal inputs but treated
decimal inputs as octal if a leading zero digit was present.
ParseUint64 is used in places where String2Big was used to decode a
uint64.
The new functions MustParseBig and MustParseUint64 are now used in many
places where parsing errors were previously ignored.
* common: delete unused big integer variables
* accounts/abi: replace uses of BytesToBig with use of encoding/binary
* common: remove BytesToBig
* common: remove Bytes2Big
* common: remove BigTrue
* cmd/utils: add BigFlag and use it for error-checked integer flags
While here, remove environment variable processing for DirectoryFlag
because we don't use it.
* core: add missing error checks in genesis block parser
* common: remove String2Big
* cmd/evm: use utils.BigFlag
* common/math: check for 256 bit overflow in ParseBig
This is supposed to prevent silent overflow/truncation of values in the
genesis block JSON. Without this check, a genesis block that set a
balance larger than 256 bits would lead to weird behaviour in the VM.
* cmd/utils: fixup import
2017-02-26 21:21:51 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/params"
|
2015-12-16 03:26:23 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/rlp"
|
|
|
|
|
"github.com/ethereum/go-ethereum/rpc"
|
2023-08-31 18:33:18 +00:00
|
|
|
|
"github.com/ethereum/go-ethereum/trie"
|
2024-01-23 13:51:58 +00:00
|
|
|
|
"github.com/holiman/uint256"
|
2018-01-07 18:38:11 +00:00
|
|
|
|
"github.com/tyler-smith/go-bip39"
|
2015-12-16 03:26:23 +00:00
|
|
|
|
)
|
|
|
|
|
|
2023-11-28 20:31:47 +00:00
|
|
|
|
// estimateGasErrorRatio is the amount of overestimation eth_estimateGas is
|
|
|
|
|
// allowed to produce in order to speed up calculations.
|
|
|
|
|
const estimateGasErrorRatio = 0.015
|
|
|
|
|
|
2024-01-17 14:06:14 +00:00
|
|
|
|
var errBlobTxNotSupported = errors.New("signing blob transactions not supported")
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// EthereumAPI provides an API to access Ethereum related information.
|
|
|
|
|
type EthereumAPI struct {
|
2016-06-14 22:36:31 +00:00
|
|
|
|
b Backend
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// NewEthereumAPI creates a new Ethereum protocol API.
|
|
|
|
|
func NewEthereumAPI(b Backend) *EthereumAPI {
|
|
|
|
|
return &EthereumAPI{b}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
// GasPrice returns a suggestion for a gas price for legacy transactions.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *EthereumAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) {
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-18 10:16:34 +00:00
|
|
|
|
// MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *EthereumAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) {
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
tipcap, err := s.b.SuggestGasTipCap(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return (*hexutil.Big)(tipcap), err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-08 06:57:51 +00:00
|
|
|
|
type feeHistoryResult struct {
|
2021-07-27 03:27:28 +00:00
|
|
|
|
OldestBlock *hexutil.Big `json:"oldestBlock"`
|
2021-07-08 06:57:51 +00:00
|
|
|
|
Reward [][]*hexutil.Big `json:"reward,omitempty"`
|
|
|
|
|
BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"`
|
|
|
|
|
GasUsedRatio []float64 `json:"gasUsedRatio"`
|
2021-06-28 14:16:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-29 16:22:04 +00:00
|
|
|
|
// FeeHistory returns the fee market history.
|
2023-02-07 14:44:27 +00:00
|
|
|
|
func (s *EthereumAPI) FeeHistory(ctx context.Context, blockCount math.HexOrDecimal64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) {
|
2023-03-23 20:12:37 +00:00
|
|
|
|
oldest, reward, baseFee, gasUsed, err := s.b.FeeHistory(ctx, uint64(blockCount), lastBlock, rewardPercentiles)
|
2021-06-28 14:16:32 +00:00
|
|
|
|
if err != nil {
|
2021-07-08 06:57:51 +00:00
|
|
|
|
return nil, err
|
2021-06-28 14:16:32 +00:00
|
|
|
|
}
|
2021-07-08 06:57:51 +00:00
|
|
|
|
results := &feeHistoryResult{
|
2021-07-27 03:27:28 +00:00
|
|
|
|
OldestBlock: (*hexutil.Big)(oldest),
|
2021-07-08 06:57:51 +00:00
|
|
|
|
GasUsedRatio: gasUsed,
|
2021-06-28 14:16:32 +00:00
|
|
|
|
}
|
|
|
|
|
if reward != nil {
|
|
|
|
|
results.Reward = make([][]*hexutil.Big, len(reward))
|
2021-07-08 06:57:51 +00:00
|
|
|
|
for i, w := range reward {
|
|
|
|
|
results.Reward[i] = make([]*hexutil.Big, len(w))
|
|
|
|
|
for j, v := range w {
|
|
|
|
|
results.Reward[i][j] = (*hexutil.Big)(v)
|
2021-06-28 14:16:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if baseFee != nil {
|
|
|
|
|
results.BaseFee = make([]*hexutil.Big, len(baseFee))
|
|
|
|
|
for i, v := range baseFee {
|
|
|
|
|
results.BaseFee[i] = (*hexutil.Big)(v)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return results, nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 08:57:07 +00:00
|
|
|
|
// Syncing returns false in case the node is currently not syncing with the network. It can be up-to-date or has not
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// yet received the latest block headers from its pears. In case it is synchronizing:
|
2023-05-02 08:57:07 +00:00
|
|
|
|
// - startingBlock: block number this node started to synchronize from
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// - currentBlock: block number this node is currently importing
|
|
|
|
|
// - highestBlock: block number of the highest block header this node has received from peers
|
|
|
|
|
// - pulledStates: number of state entries processed until now
|
|
|
|
|
// - knownStates: number of known state entries that still need to be pulled
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *EthereumAPI) Syncing() (interface{}, error) {
|
2021-09-10 07:55:48 +00:00
|
|
|
|
progress := s.b.SyncProgress()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
|
|
|
|
|
// Return not syncing if the synchronisation already completed
|
2024-01-22 20:05:18 +00:00
|
|
|
|
if progress.Done() {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
// Otherwise gather the block sync stats
|
|
|
|
|
return map[string]interface{}{
|
2024-01-22 20:05:18 +00:00
|
|
|
|
"startingBlock": hexutil.Uint64(progress.StartingBlock),
|
|
|
|
|
"currentBlock": hexutil.Uint64(progress.CurrentBlock),
|
|
|
|
|
"highestBlock": hexutil.Uint64(progress.HighestBlock),
|
|
|
|
|
"syncedAccounts": hexutil.Uint64(progress.SyncedAccounts),
|
|
|
|
|
"syncedAccountBytes": hexutil.Uint64(progress.SyncedAccountBytes),
|
|
|
|
|
"syncedBytecodes": hexutil.Uint64(progress.SyncedBytecodes),
|
|
|
|
|
"syncedBytecodeBytes": hexutil.Uint64(progress.SyncedBytecodeBytes),
|
|
|
|
|
"syncedStorage": hexutil.Uint64(progress.SyncedStorage),
|
|
|
|
|
"syncedStorageBytes": hexutil.Uint64(progress.SyncedStorageBytes),
|
|
|
|
|
"healedTrienodes": hexutil.Uint64(progress.HealedTrienodes),
|
|
|
|
|
"healedTrienodeBytes": hexutil.Uint64(progress.HealedTrienodeBytes),
|
|
|
|
|
"healedBytecodes": hexutil.Uint64(progress.HealedBytecodes),
|
|
|
|
|
"healedBytecodeBytes": hexutil.Uint64(progress.HealedBytecodeBytes),
|
|
|
|
|
"healingTrienodes": hexutil.Uint64(progress.HealingTrienodes),
|
|
|
|
|
"healingBytecode": hexutil.Uint64(progress.HealingBytecode),
|
|
|
|
|
"txIndexFinishedBlocks": hexutil.Uint64(progress.TxIndexFinishedBlocks),
|
|
|
|
|
"txIndexRemainingBlocks": hexutil.Uint64(progress.TxIndexRemainingBlocks),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 08:57:07 +00:00
|
|
|
|
// TxPoolAPI offers and API for the transaction pool. It only operates on data that is non-confidential.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
type TxPoolAPI struct {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
b Backend
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// NewTxPoolAPI creates a new tx pool service that gives information about the transaction pool.
|
|
|
|
|
func NewTxPoolAPI(b Backend) *TxPoolAPI {
|
|
|
|
|
return &TxPoolAPI{b}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Content returns the transactions contained within the transaction pool.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction {
|
2016-06-27 15:28:34 +00:00
|
|
|
|
content := map[string]map[string]map[string]*RPCTransaction{
|
|
|
|
|
"pending": make(map[string]map[string]*RPCTransaction),
|
|
|
|
|
"queued": make(map[string]map[string]*RPCTransaction),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
pending, queue := s.b.TxPoolContent()
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
curHeader := s.b.CurrentHeader()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// Flatten the pending transactions
|
2016-06-27 15:28:34 +00:00
|
|
|
|
for account, txs := range pending {
|
|
|
|
|
dump := make(map[string]*RPCTransaction)
|
2017-05-29 08:14:56 +00:00
|
|
|
|
for _, tx := range txs {
|
2022-11-14 13:48:01 +00:00
|
|
|
|
dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
content["pending"][account.Hex()] = dump
|
|
|
|
|
}
|
|
|
|
|
// Flatten the queued transactions
|
2016-06-27 15:28:34 +00:00
|
|
|
|
for account, txs := range queue {
|
|
|
|
|
dump := make(map[string]*RPCTransaction)
|
2017-05-29 08:14:56 +00:00
|
|
|
|
for _, tx := range txs {
|
2022-11-14 13:48:01 +00:00
|
|
|
|
dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
content["queued"][account.Hex()] = dump
|
|
|
|
|
}
|
|
|
|
|
return content
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-13 10:40:58 +00:00
|
|
|
|
// ContentFrom returns the transactions contained within the transaction pool.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TxPoolAPI) ContentFrom(addr common.Address) map[string]map[string]*RPCTransaction {
|
2021-07-13 10:40:58 +00:00
|
|
|
|
content := make(map[string]map[string]*RPCTransaction, 2)
|
|
|
|
|
pending, queue := s.b.TxPoolContentFrom(addr)
|
|
|
|
|
curHeader := s.b.CurrentHeader()
|
|
|
|
|
|
|
|
|
|
// Build the pending transactions
|
|
|
|
|
dump := make(map[string]*RPCTransaction, len(pending))
|
|
|
|
|
for _, tx := range pending {
|
2022-11-14 13:48:01 +00:00
|
|
|
|
dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
|
2021-07-13 10:40:58 +00:00
|
|
|
|
}
|
|
|
|
|
content["pending"] = dump
|
|
|
|
|
|
|
|
|
|
// Build the queued transactions
|
|
|
|
|
dump = make(map[string]*RPCTransaction, len(queue))
|
|
|
|
|
for _, tx := range queue {
|
2022-11-14 13:48:01 +00:00
|
|
|
|
dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
|
2021-07-13 10:40:58 +00:00
|
|
|
|
}
|
|
|
|
|
content["queued"] = dump
|
|
|
|
|
|
|
|
|
|
return content
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// Status returns the number of pending and queued transaction in the pool.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TxPoolAPI) Status() map[string]hexutil.Uint {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
pending, queue := s.b.Stats()
|
2016-12-17 14:39:55 +00:00
|
|
|
|
return map[string]hexutil.Uint{
|
|
|
|
|
"pending": hexutil.Uint(pending),
|
|
|
|
|
"queued": hexutil.Uint(queue),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Inspect retrieves the content of the transaction pool and flattens it into an
|
|
|
|
|
// easily inspectable list.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TxPoolAPI) Inspect() map[string]map[string]map[string]string {
|
2016-06-27 15:28:34 +00:00
|
|
|
|
content := map[string]map[string]map[string]string{
|
|
|
|
|
"pending": make(map[string]map[string]string),
|
|
|
|
|
"queued": make(map[string]map[string]string),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
pending, queue := s.b.TxPoolContent()
|
|
|
|
|
|
|
|
|
|
// Define a formatter to flatten a transaction into a string
|
|
|
|
|
var format = func(tx *types.Transaction) string {
|
|
|
|
|
if to := tx.To(); to != nil {
|
2017-11-17 13:07:57 +00:00
|
|
|
|
return fmt.Sprintf("%s: %v wei + %v gas × %v wei", tx.To().Hex(), tx.Value(), tx.Gas(), tx.GasPrice())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2017-11-17 13:07:57 +00:00
|
|
|
|
return fmt.Sprintf("contract creation: %v wei + %v gas × %v wei", tx.Value(), tx.Gas(), tx.GasPrice())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
// Flatten the pending transactions
|
2016-06-27 15:28:34 +00:00
|
|
|
|
for account, txs := range pending {
|
|
|
|
|
dump := make(map[string]string)
|
2017-05-29 08:14:56 +00:00
|
|
|
|
for _, tx := range txs {
|
|
|
|
|
dump[fmt.Sprintf("%d", tx.Nonce())] = format(tx)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
content["pending"][account.Hex()] = dump
|
|
|
|
|
}
|
|
|
|
|
// Flatten the queued transactions
|
2016-06-27 15:28:34 +00:00
|
|
|
|
for account, txs := range queue {
|
|
|
|
|
dump := make(map[string]string)
|
2017-05-29 08:14:56 +00:00
|
|
|
|
for _, tx := range txs {
|
|
|
|
|
dump[fmt.Sprintf("%d", tx.Nonce())] = format(tx)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
content["queued"][account.Hex()] = dump
|
|
|
|
|
}
|
|
|
|
|
return content
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// EthereumAccountAPI provides an API to access accounts managed by this node.
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// It offers only methods that can retrieve accounts.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
type EthereumAccountAPI struct {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
am *accounts.Manager
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// NewEthereumAccountAPI creates a new EthereumAccountAPI.
|
|
|
|
|
func NewEthereumAccountAPI(am *accounts.Manager) *EthereumAccountAPI {
|
|
|
|
|
return &EthereumAccountAPI{am: am}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// Accounts returns the collection of accounts this node manages.
|
|
|
|
|
func (s *EthereumAccountAPI) Accounts() []common.Address {
|
2019-08-08 09:23:40 +00:00
|
|
|
|
return s.am.Accounts()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// PersonalAccountAPI provides an API to access accounts managed by this node.
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// It offers methods to create, (un)lock en list accounts. Some methods accept
|
|
|
|
|
// passwords and are therefore considered private by default.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
type PersonalAccountAPI struct {
|
2017-05-25 15:08:13 +00:00
|
|
|
|
am *accounts.Manager
|
|
|
|
|
nonceLock *AddrLocker
|
|
|
|
|
b Backend
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-20 11:42:48 +00:00
|
|
|
|
// NewPersonalAccountAPI creates a new PersonalAccountAPI.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func NewPersonalAccountAPI(b Backend, nonceLock *AddrLocker) *PersonalAccountAPI {
|
|
|
|
|
return &PersonalAccountAPI{
|
2017-06-01 14:16:12 +00:00
|
|
|
|
am: b.AccountManager(),
|
|
|
|
|
nonceLock: nonceLock,
|
|
|
|
|
b: b,
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-15 09:44:22 +00:00
|
|
|
|
// ListAccounts will return a list of addresses for accounts this node manages.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) ListAccounts() []common.Address {
|
2019-08-08 09:23:40 +00:00
|
|
|
|
return s.am.Accounts()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-02-07 10:47:34 +00:00
|
|
|
|
// rawWallet is a JSON representation of an accounts.Wallet interface, with its
|
|
|
|
|
// data contents extracted into plain fields.
|
|
|
|
|
type rawWallet struct {
|
|
|
|
|
URL string `json:"url"`
|
|
|
|
|
Status string `json:"status"`
|
2017-08-09 09:51:16 +00:00
|
|
|
|
Failure string `json:"failure,omitempty"`
|
|
|
|
|
Accounts []accounts.Account `json:"accounts,omitempty"`
|
2017-02-07 10:47:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ListWallets will return a list of wallets this node manages.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) ListWallets() []rawWallet {
|
2017-04-24 12:00:30 +00:00
|
|
|
|
wallets := make([]rawWallet, 0) // return [] instead of nil if empty
|
2017-02-07 10:47:34 +00:00
|
|
|
|
for _, wallet := range s.am.Wallets() {
|
2017-08-09 09:51:16 +00:00
|
|
|
|
status, failure := wallet.Status()
|
|
|
|
|
|
|
|
|
|
raw := rawWallet{
|
2017-02-08 13:53:02 +00:00
|
|
|
|
URL: wallet.URL().String(),
|
2017-08-09 09:51:16 +00:00
|
|
|
|
Status: status,
|
2017-02-07 10:47:34 +00:00
|
|
|
|
Accounts: wallet.Accounts(),
|
2017-08-09 09:51:16 +00:00
|
|
|
|
}
|
|
|
|
|
if failure != nil {
|
|
|
|
|
raw.Failure = failure.Error()
|
|
|
|
|
}
|
|
|
|
|
wallets = append(wallets, raw)
|
2017-02-07 10:47:34 +00:00
|
|
|
|
}
|
|
|
|
|
return wallets
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-01 15:45:17 +00:00
|
|
|
|
// OpenWallet initiates a hardware wallet opening procedure, establishing a USB
|
|
|
|
|
// connection and attempting to authenticate via the provided passphrase. Note,
|
|
|
|
|
// the method may return an extra challenge requiring a second open (e.g. the
|
|
|
|
|
// Trezor PIN matrix challenge).
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) OpenWallet(url string, passphrase *string) error {
|
2017-08-01 15:45:17 +00:00
|
|
|
|
wallet, err := s.am.Wallet(url)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
pass := ""
|
|
|
|
|
if passphrase != nil {
|
|
|
|
|
pass = *passphrase
|
|
|
|
|
}
|
|
|
|
|
return wallet.Open(pass)
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 08:57:07 +00:00
|
|
|
|
// DeriveAccount requests an HD wallet to derive a new account, optionally pinning
|
2017-02-07 10:47:34 +00:00
|
|
|
|
// it for later reuse.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) {
|
2017-02-07 10:47:34 +00:00
|
|
|
|
wallet, err := s.am.Wallet(url)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return accounts.Account{}, err
|
|
|
|
|
}
|
2017-02-08 18:25:52 +00:00
|
|
|
|
derivPath, err := accounts.ParseDerivationPath(path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return accounts.Account{}, err
|
|
|
|
|
}
|
2017-02-07 10:47:34 +00:00
|
|
|
|
if pin == nil {
|
|
|
|
|
pin = new(bool)
|
|
|
|
|
}
|
2017-02-08 18:25:52 +00:00
|
|
|
|
return wallet.Derive(derivPath, *pin)
|
2017-02-07 10:47:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// NewAccount will create a new account and returns the address for the new account.
|
2023-05-17 08:29:56 +00:00
|
|
|
|
func (s *PersonalAccountAPI) NewAccount(password string) (common.AddressEIP55, error) {
|
2020-07-02 08:00:18 +00:00
|
|
|
|
ks, err := fetchKeystore(s.am)
|
|
|
|
|
if err != nil {
|
2023-05-17 08:29:56 +00:00
|
|
|
|
return common.AddressEIP55{}, err
|
2020-07-02 08:00:18 +00:00
|
|
|
|
}
|
|
|
|
|
acc, err := ks.NewAccount(password)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if err == nil {
|
2023-05-17 08:29:56 +00:00
|
|
|
|
addrEIP55 := common.AddressEIP55(acc.Address)
|
|
|
|
|
log.Info("Your new key was generated", "address", addrEIP55.String())
|
2019-05-07 12:49:51 +00:00
|
|
|
|
log.Warn("Please backup your key file!", "path", acc.URL.Path)
|
|
|
|
|
log.Warn("Please remember your password!")
|
2023-05-17 08:29:56 +00:00
|
|
|
|
return addrEIP55, nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2023-05-17 08:29:56 +00:00
|
|
|
|
return common.AddressEIP55{}, err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-25 08:21:28 +00:00
|
|
|
|
// fetchKeystore retrieves the encrypted keystore from the account manager.
|
2020-07-02 08:00:18 +00:00
|
|
|
|
func fetchKeystore(am *accounts.Manager) (*keystore.KeyStore, error) {
|
|
|
|
|
if ks := am.Backends(keystore.KeyStoreType); len(ks) > 0 {
|
|
|
|
|
return ks[0].(*keystore.KeyStore), nil
|
|
|
|
|
}
|
|
|
|
|
return nil, errors.New("local keystore not used")
|
2017-01-24 09:49:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// ImportRawKey stores the given hex encoded ECDSA key into the key directory,
|
|
|
|
|
// encrypting it with the passphrase.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) ImportRawKey(privkey string, password string) (common.Address, error) {
|
2017-05-23 11:58:03 +00:00
|
|
|
|
key, err := crypto.HexToECDSA(privkey)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return common.Address{}, err
|
|
|
|
|
}
|
2020-07-02 08:00:18 +00:00
|
|
|
|
ks, err := fetchKeystore(s.am)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return common.Address{}, err
|
|
|
|
|
}
|
|
|
|
|
acc, err := ks.ImportECDSA(key, password)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
return acc.Address, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UnlockAccount will unlock the account associated with the given address with
|
|
|
|
|
// the given password for duration seconds. If duration is nil it will use a
|
|
|
|
|
// default of 300 seconds. It returns an indication if the account was unlocked.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, duration *uint64) (bool, error) {
|
2019-04-04 11:03:10 +00:00
|
|
|
|
// When the API is exposed by external RPC(http, ws etc), unless the user
|
|
|
|
|
// explicitly specifies to allow the insecure account unlocking, otherwise
|
|
|
|
|
// it is disabled.
|
|
|
|
|
if s.b.ExtRPCEnabled() && !s.b.AccountManager().Config().InsecureUnlockAllowed {
|
|
|
|
|
return false, errors.New("account unlock with HTTP access is forbidden")
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-11 12:20:24 +00:00
|
|
|
|
const max = uint64(time.Duration(math.MaxInt64) / time.Second)
|
2016-12-17 14:39:55 +00:00
|
|
|
|
var d time.Duration
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if duration == nil {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
d = 300 * time.Second
|
2017-01-11 12:20:24 +00:00
|
|
|
|
} else if *duration > max {
|
|
|
|
|
return false, errors.New("unlock duration too large")
|
2016-12-17 14:39:55 +00:00
|
|
|
|
} else {
|
|
|
|
|
d = time.Duration(*duration) * time.Second
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2020-07-02 08:00:18 +00:00
|
|
|
|
ks, err := fetchKeystore(s.am)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return false, err
|
|
|
|
|
}
|
|
|
|
|
err = ks.TimedUnlock(accounts.Account{Address: addr}, password, d)
|
2018-10-10 09:29:05 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
log.Warn("Failed account unlock attempt", "address", addr, "err", err)
|
|
|
|
|
}
|
2017-01-11 12:20:24 +00:00
|
|
|
|
return err == nil, err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LockAccount will lock the account associated with the given address when it's unlocked.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) LockAccount(addr common.Address) bool {
|
2020-07-02 08:00:18 +00:00
|
|
|
|
if ks, err := fetchKeystore(s.am); err == nil {
|
|
|
|
|
return ks.Lock(addr) == nil
|
|
|
|
|
}
|
|
|
|
|
return false
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-15 09:11:14 +00:00
|
|
|
|
// signTransaction sets defaults and signs the given transaction
|
2018-01-26 17:32:43 +00:00
|
|
|
|
// NOTE: the caller needs to ensure that the nonceLock is held, if applicable,
|
|
|
|
|
// and release it after the transaction has been submitted to the tx pool
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) signTransaction(ctx context.Context, args *TransactionArgs, passwd string) (*types.Transaction, error) {
|
2017-02-07 10:47:34 +00:00
|
|
|
|
// Look up the wallet containing the requested signer
|
2021-05-25 20:30:21 +00:00
|
|
|
|
account := accounts.Account{Address: args.from()}
|
2017-02-07 10:47:34 +00:00
|
|
|
|
wallet, err := s.am.Find(account)
|
|
|
|
|
if err != nil {
|
2018-01-26 17:32:43 +00:00
|
|
|
|
return nil, err
|
2017-05-25 15:08:13 +00:00
|
|
|
|
}
|
|
|
|
|
// Set some sanity defaults and terminate on failure
|
|
|
|
|
if err := args.setDefaults(ctx, s.b); err != nil {
|
2018-01-26 17:32:43 +00:00
|
|
|
|
return nil, err
|
2017-05-25 15:08:13 +00:00
|
|
|
|
}
|
2017-02-07 10:47:34 +00:00
|
|
|
|
// Assemble the transaction and sign with the wallet
|
2016-12-17 14:39:55 +00:00
|
|
|
|
tx := args.toTransaction()
|
2017-01-24 09:49:20 +00:00
|
|
|
|
|
2019-02-07 10:59:17 +00:00
|
|
|
|
return wallet.SignTxWithPassphrase(account, passwd, tx, s.b.ChainConfig().ChainID)
|
2018-01-26 17:32:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SendTransaction will create a transaction from the given arguments and
|
2021-05-25 20:30:21 +00:00
|
|
|
|
// tries to sign it with the key associated with args.From. If the given
|
|
|
|
|
// passwd isn't able to decrypt the key it fails.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) SendTransaction(ctx context.Context, args TransactionArgs, passwd string) (common.Hash, error) {
|
2018-01-26 17:32:43 +00:00
|
|
|
|
if args.Nonce == nil {
|
2022-10-11 07:37:00 +00:00
|
|
|
|
// Hold the mutex around signing to prevent concurrent assignment of
|
2018-01-26 17:32:43 +00:00
|
|
|
|
// the same nonce to multiple accounts.
|
2021-05-25 20:30:21 +00:00
|
|
|
|
s.nonceLock.LockAddr(args.from())
|
|
|
|
|
defer s.nonceLock.UnlockAddr(args.from())
|
2018-01-26 17:32:43 +00:00
|
|
|
|
}
|
2024-01-17 14:06:14 +00:00
|
|
|
|
if args.IsEIP4844() {
|
|
|
|
|
return common.Hash{}, errBlobTxNotSupported
|
|
|
|
|
}
|
2018-10-10 09:29:05 +00:00
|
|
|
|
signed, err := s.signTransaction(ctx, &args, passwd)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if err != nil {
|
2021-05-25 20:30:21 +00:00
|
|
|
|
log.Warn("Failed transaction send attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
2019-01-21 14:38:13 +00:00
|
|
|
|
return SubmitTransaction(ctx, s.b, signed)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-26 17:32:43 +00:00
|
|
|
|
// SignTransaction will create a transaction from the given arguments and
|
2021-02-05 12:51:53 +00:00
|
|
|
|
// tries to sign it with the key associated with args.From. If the given passwd isn't
|
2018-01-26 17:32:43 +00:00
|
|
|
|
// able to decrypt the key it fails. The transaction is returned in RLP-form, not broadcast
|
|
|
|
|
// to other nodes
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) SignTransaction(ctx context.Context, args TransactionArgs, passwd string) (*SignTransactionResult, error) {
|
2018-01-26 17:32:43 +00:00
|
|
|
|
// No need to obtain the noncelock mutex, since we won't be sending this
|
|
|
|
|
// tx into the transaction pool, but right back to the user
|
2021-05-25 20:30:21 +00:00
|
|
|
|
if args.From == nil {
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return nil, errors.New("sender not specified")
|
2021-05-25 20:30:21 +00:00
|
|
|
|
}
|
2018-01-26 17:32:43 +00:00
|
|
|
|
if args.Gas == nil {
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return nil, errors.New("gas not specified")
|
2018-01-26 17:32:43 +00:00
|
|
|
|
}
|
2021-07-13 10:40:01 +00:00
|
|
|
|
if args.GasPrice == nil && (args.MaxFeePerGas == nil || args.MaxPriorityFeePerGas == nil) {
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")
|
2018-01-26 17:32:43 +00:00
|
|
|
|
}
|
2024-01-17 14:06:14 +00:00
|
|
|
|
if args.IsEIP4844() {
|
|
|
|
|
return nil, errBlobTxNotSupported
|
|
|
|
|
}
|
2018-01-26 17:32:43 +00:00
|
|
|
|
if args.Nonce == nil {
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return nil, errors.New("nonce not specified")
|
2018-01-26 17:32:43 +00:00
|
|
|
|
}
|
2021-08-10 13:56:34 +00:00
|
|
|
|
// Before actually signing the transaction, ensure the transaction fee is reasonable.
|
2021-07-13 10:40:01 +00:00
|
|
|
|
tx := args.toTransaction()
|
|
|
|
|
if err := checkTxFee(tx.GasPrice(), tx.Gas(), s.b.RPCTxFeeCap()); err != nil {
|
2020-07-13 10:45:39 +00:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2018-10-10 09:29:05 +00:00
|
|
|
|
signed, err := s.signTransaction(ctx, &args, passwd)
|
2018-01-26 17:32:43 +00:00
|
|
|
|
if err != nil {
|
2021-05-25 20:30:21 +00:00
|
|
|
|
log.Warn("Failed transaction sign attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err)
|
2018-01-26 17:32:43 +00:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2021-02-25 14:26:57 +00:00
|
|
|
|
data, err := signed.MarshalBinary()
|
2018-01-26 17:32:43 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return &SignTransactionResult{data, signed}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-28 19:25:49 +00:00
|
|
|
|
// Sign calculates an Ethereum ECDSA signature for:
|
2022-06-10 08:57:32 +00:00
|
|
|
|
// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))
|
2016-10-28 19:25:49 +00:00
|
|
|
|
//
|
2017-01-05 10:35:23 +00:00
|
|
|
|
// Note, the produced signature conforms to the secp256k1 curve R, S and V values,
|
|
|
|
|
// where the V value will be 27 or 28 for legacy reasons.
|
|
|
|
|
//
|
2016-10-28 19:25:49 +00:00
|
|
|
|
// The key used to calculate the signature is decrypted with the given password.
|
|
|
|
|
//
|
2024-02-13 09:14:18 +00:00
|
|
|
|
// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-sign
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) {
|
2017-02-07 10:47:34 +00:00
|
|
|
|
// Look up the wallet containing the requested signer
|
|
|
|
|
account := accounts.Account{Address: addr}
|
|
|
|
|
|
|
|
|
|
wallet, err := s.b.AccountManager().Find(account)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
// Assemble sign the data with the wallet
|
accounts, eth, clique, signer: support for external signer API (#18079)
* accounts, eth, clique: implement external backend + move sighash calc to backend
* signer: implement account_Version on external API
* accounts/external: enable ipc, add copyright
* accounts, internal, signer: formatting
* node: go fmt
* flags: disallow --dev in combo with --externalsigner
* accounts: remove clique-specific signing method, replace with more generic
* accounts, consensus: formatting + fix error in tests
* signer/core: remove (test-) import cycle
* clique: remove unused import
* accounts: remove CliqueHash and avoid dependency on package crypto
* consensus/clique: unduplicate header encoding
2019-02-05 10:23:57 +00:00
|
|
|
|
signature, err := wallet.SignTextWithPassphrase(account, passwd, data)
|
2017-01-05 10:35:23 +00:00
|
|
|
|
if err != nil {
|
2018-10-10 09:29:05 +00:00
|
|
|
|
log.Warn("Failed data sign attempt", "address", addr, "err", err)
|
2017-01-05 10:35:23 +00:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2019-08-22 13:14:06 +00:00
|
|
|
|
signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
|
2017-01-05 10:35:23 +00:00
|
|
|
|
return signature, nil
|
2016-10-28 19:25:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// EcRecover returns the address for the account that was used to create the signature.
|
|
|
|
|
// Note, this function is compatible with eth_sign and personal_sign. As such it recovers
|
|
|
|
|
// the address of:
|
|
|
|
|
// hash = keccak256("\x19Ethereum Signed Message:\n"${message length}${message})
|
|
|
|
|
// addr = ecrecover(hash, signature)
|
|
|
|
|
//
|
2017-01-05 10:35:23 +00:00
|
|
|
|
// Note, the signature must conform to the secp256k1 curve R, S and V values, where
|
2018-09-25 10:26:35 +00:00
|
|
|
|
// the V value must be 27 or 28 for legacy reasons.
|
2017-01-05 10:35:23 +00:00
|
|
|
|
//
|
2024-02-13 09:14:18 +00:00
|
|
|
|
// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-ecrecover
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
|
2019-08-22 13:14:06 +00:00
|
|
|
|
if len(sig) != crypto.SignatureLength {
|
|
|
|
|
return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength)
|
2016-10-28 19:25:49 +00:00
|
|
|
|
}
|
2019-08-22 13:14:06 +00:00
|
|
|
|
if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 {
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return common.Address{}, errors.New("invalid Ethereum signature (V is not 27 or 28)")
|
2016-10-28 19:25:49 +00:00
|
|
|
|
}
|
2019-08-22 13:14:06 +00:00
|
|
|
|
sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1
|
2017-01-05 10:35:23 +00:00
|
|
|
|
|
accounts, eth, clique, signer: support for external signer API (#18079)
* accounts, eth, clique: implement external backend + move sighash calc to backend
* signer: implement account_Version on external API
* accounts/external: enable ipc, add copyright
* accounts, internal, signer: formatting
* node: go fmt
* flags: disallow --dev in combo with --externalsigner
* accounts: remove clique-specific signing method, replace with more generic
* accounts, consensus: formatting + fix error in tests
* signer/core: remove (test-) import cycle
* clique: remove unused import
* accounts: remove CliqueHash and avoid dependency on package crypto
* consensus/clique: unduplicate header encoding
2019-02-05 10:23:57 +00:00
|
|
|
|
rpk, err := crypto.SigToPub(accounts.TextHash(data), sig)
|
2016-10-28 19:25:49 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return common.Address{}, err
|
|
|
|
|
}
|
2018-06-12 13:26:08 +00:00
|
|
|
|
return crypto.PubkeyToAddress(*rpk), nil
|
2016-10-28 19:25:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-22 13:27:41 +00:00
|
|
|
|
// InitializeWallet initializes a new wallet at the provided URL, by generating and returning a new private key.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) InitializeWallet(ctx context.Context, url string) (string, error) {
|
2018-01-07 18:38:11 +00:00
|
|
|
|
wallet, err := s.am.Wallet(url)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
entropy, err := bip39.NewEntropy(256)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mnemonic, err := bip39.NewMnemonic(entropy)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
seed := bip39.NewSeed(mnemonic, "")
|
|
|
|
|
|
|
|
|
|
switch wallet := wallet.(type) {
|
|
|
|
|
case *scwallet.Wallet:
|
|
|
|
|
return mnemonic, wallet.Initialize(seed)
|
|
|
|
|
default:
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return "", errors.New("specified wallet does not support initialization")
|
2018-01-07 18:38:11 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-22 13:27:41 +00:00
|
|
|
|
// Unpair deletes a pairing between wallet and geth.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *PersonalAccountAPI) Unpair(ctx context.Context, url string, pin string) error {
|
2018-01-07 18:38:11 +00:00
|
|
|
|
wallet, err := s.am.Wallet(url)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch wallet := wallet.(type) {
|
|
|
|
|
case *scwallet.Wallet:
|
|
|
|
|
return wallet.Unpair([]byte(pin))
|
|
|
|
|
default:
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return errors.New("specified wallet does not support pairing")
|
2018-01-07 18:38:11 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// BlockChainAPI provides an API to access Ethereum blockchain data.
|
|
|
|
|
type BlockChainAPI struct {
|
2016-07-27 15:47:46 +00:00
|
|
|
|
b Backend
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// NewBlockChainAPI creates a new Ethereum blockchain API.
|
|
|
|
|
func NewBlockChainAPI(b Backend) *BlockChainAPI {
|
|
|
|
|
return &BlockChainAPI{b}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// ChainId is the EIP-155 replay-protection chain id for the current Ethereum chain config.
|
2022-06-25 19:34:21 +00:00
|
|
|
|
//
|
|
|
|
|
// Note, this method does not conform to EIP-695 because the configured chain ID is always
|
|
|
|
|
// returned, regardless of the current head block. We used to return an error when the chain
|
|
|
|
|
// wasn't synced up to a block where EIP-155 is enabled, but this behavior caused issues
|
|
|
|
|
// in CL clients.
|
2022-06-24 16:03:13 +00:00
|
|
|
|
func (api *BlockChainAPI) ChainId() *hexutil.Big {
|
|
|
|
|
return (*hexutil.Big)(api.b.ChainConfig().ChainID)
|
2019-06-11 11:12:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// BlockNumber returns the block number of the chain head.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) BlockNumber() hexutil.Uint64 {
|
2016-10-14 03:51:29 +00:00
|
|
|
|
header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available
|
2018-06-11 10:15:59 +00:00
|
|
|
|
return hexutil.Uint64(header.Number.Uint64())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetBalance returns the amount of wei for the given address in the state of the
|
|
|
|
|
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
|
|
|
|
|
// block numbers are also allowed.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) {
|
2019-09-26 08:47:31 +00:00
|
|
|
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if state == nil || err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2024-01-23 13:51:58 +00:00
|
|
|
|
b := state.GetBalance(address).ToBig()
|
|
|
|
|
return (*hexutil.Big)(b), state.Error()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-07 20:10:49 +00:00
|
|
|
|
// AccountResult structs for GetProof
|
2018-10-18 19:41:22 +00:00
|
|
|
|
type AccountResult struct {
|
|
|
|
|
Address common.Address `json:"address"`
|
|
|
|
|
AccountProof []string `json:"accountProof"`
|
|
|
|
|
Balance *hexutil.Big `json:"balance"`
|
|
|
|
|
CodeHash common.Hash `json:"codeHash"`
|
|
|
|
|
Nonce hexutil.Uint64 `json:"nonce"`
|
|
|
|
|
StorageHash common.Hash `json:"storageHash"`
|
|
|
|
|
StorageProof []StorageResult `json:"storageProof"`
|
|
|
|
|
}
|
2021-05-25 20:30:21 +00:00
|
|
|
|
|
2018-10-18 19:41:22 +00:00
|
|
|
|
type StorageResult struct {
|
|
|
|
|
Key string `json:"key"`
|
|
|
|
|
Value *hexutil.Big `json:"value"`
|
|
|
|
|
Proof []string `json:"proof"`
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-31 06:52:27 +00:00
|
|
|
|
// proofList implements ethdb.KeyValueWriter and collects the proofs as
|
|
|
|
|
// hex-strings for delivery to rpc-caller.
|
|
|
|
|
type proofList []string
|
|
|
|
|
|
|
|
|
|
func (n *proofList) Put(key []byte, value []byte) error {
|
|
|
|
|
*n = append(*n, hexutil.Encode(value))
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (n *proofList) Delete(key []byte) error {
|
|
|
|
|
panic("not supported")
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-18 19:41:22 +00:00
|
|
|
|
// GetProof returns the Merkle-proof for a given account and optionally some storage keys.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
|
2023-05-31 06:52:27 +00:00
|
|
|
|
var (
|
|
|
|
|
keys = make([]common.Hash, len(storageKeys))
|
2023-06-21 16:11:11 +00:00
|
|
|
|
keyLengths = make([]int, len(storageKeys))
|
2023-05-31 06:52:27 +00:00
|
|
|
|
storageProof = make([]StorageResult, len(storageKeys))
|
|
|
|
|
)
|
2023-06-21 16:11:11 +00:00
|
|
|
|
// Deserialize all keys. This prevents state access on invalid input.
|
2023-05-31 06:52:27 +00:00
|
|
|
|
for i, hexKey := range storageKeys {
|
2023-06-21 16:11:11 +00:00
|
|
|
|
var err error
|
|
|
|
|
keys[i], keyLengths[i], err = decodeHash(hexKey)
|
|
|
|
|
if err != nil {
|
2023-05-31 06:52:27 +00:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-10-17 07:25:16 +00:00
|
|
|
|
statedb, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
|
|
|
|
if statedb == nil || err != nil {
|
2018-10-18 19:41:22 +00:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2023-10-17 07:25:16 +00:00
|
|
|
|
codeHash := statedb.GetCodeHash(address)
|
|
|
|
|
storageRoot := statedb.GetStorageRoot(address)
|
2023-06-21 16:11:11 +00:00
|
|
|
|
|
2023-10-17 07:25:16 +00:00
|
|
|
|
if len(keys) > 0 {
|
|
|
|
|
var storageTrie state.Trie
|
|
|
|
|
if storageRoot != types.EmptyRootHash && storageRoot != (common.Hash{}) {
|
|
|
|
|
id := trie.StorageTrieID(header.Root, crypto.Keccak256Hash(address.Bytes()), storageRoot)
|
|
|
|
|
st, err := trie.NewStateTrie(id, statedb.Database().TrieDB())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
storageTrie = st
|
2022-09-16 16:16:32 +00:00
|
|
|
|
}
|
2023-10-17 07:25:16 +00:00
|
|
|
|
// Create the proofs for the storageKeys.
|
|
|
|
|
for i, key := range keys {
|
|
|
|
|
// Output key encoding is a bit special: if the input was a 32-byte hash, it is
|
|
|
|
|
// returned as such. Otherwise, we apply the QUANTITY encoding mandated by the
|
|
|
|
|
// JSON-RPC spec for getProof. This behavior exists to preserve backwards
|
|
|
|
|
// compatibility with older client versions.
|
|
|
|
|
var outputKey string
|
|
|
|
|
if keyLengths[i] != 32 {
|
|
|
|
|
outputKey = hexutil.EncodeBig(key.Big())
|
|
|
|
|
} else {
|
|
|
|
|
outputKey = hexutil.Encode(key[:])
|
|
|
|
|
}
|
|
|
|
|
if storageTrie == nil {
|
|
|
|
|
storageProof[i] = StorageResult{outputKey, &hexutil.Big{}, []string{}}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
var proof proofList
|
|
|
|
|
if err := storageTrie.Prove(crypto.Keccak256(key.Bytes()), &proof); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
value := (*hexutil.Big)(statedb.GetState(address, key).Big())
|
|
|
|
|
storageProof[i] = StorageResult{outputKey, value, proof}
|
2018-10-18 19:41:22 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-21 16:11:11 +00:00
|
|
|
|
// Create the accountProof.
|
2023-10-17 07:25:16 +00:00
|
|
|
|
tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), statedb.Database().TrieDB())
|
2023-08-31 18:33:18 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
var accountProof proofList
|
|
|
|
|
if err := tr.Prove(crypto.Keccak256(address.Bytes()), &accountProof); err != nil {
|
|
|
|
|
return nil, err
|
2018-10-18 19:41:22 +00:00
|
|
|
|
}
|
2024-01-23 13:51:58 +00:00
|
|
|
|
balance := statedb.GetBalance(address).ToBig()
|
2018-10-18 19:41:22 +00:00
|
|
|
|
return &AccountResult{
|
|
|
|
|
Address: address,
|
2023-08-31 18:33:18 +00:00
|
|
|
|
AccountProof: accountProof,
|
2024-01-23 13:51:58 +00:00
|
|
|
|
Balance: (*hexutil.Big)(balance),
|
2018-10-18 19:41:22 +00:00
|
|
|
|
CodeHash: codeHash,
|
2023-10-17 07:25:16 +00:00
|
|
|
|
Nonce: hexutil.Uint64(statedb.GetNonce(address)),
|
|
|
|
|
StorageHash: storageRoot,
|
2018-10-18 19:41:22 +00:00
|
|
|
|
StorageProof: storageProof,
|
2023-10-17 07:25:16 +00:00
|
|
|
|
}, statedb.Error()
|
2018-10-18 19:41:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-16 16:16:32 +00:00
|
|
|
|
// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
|
2023-05-02 08:57:07 +00:00
|
|
|
|
// be prefixed by 0x and can have a byte length up to 32.
|
2023-06-21 16:11:11 +00:00
|
|
|
|
func decodeHash(s string) (h common.Hash, inputLength int, err error) {
|
2022-09-16 16:16:32 +00:00
|
|
|
|
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
|
|
|
|
|
s = s[2:]
|
|
|
|
|
}
|
2022-09-28 16:55:44 +00:00
|
|
|
|
if (len(s) & 1) > 0 {
|
|
|
|
|
s = "0" + s
|
|
|
|
|
}
|
2022-09-16 16:16:32 +00:00
|
|
|
|
b, err := hex.DecodeString(s)
|
|
|
|
|
if err != nil {
|
2023-06-21 16:11:11 +00:00
|
|
|
|
return common.Hash{}, 0, errors.New("hex string invalid")
|
2022-09-16 16:16:32 +00:00
|
|
|
|
}
|
|
|
|
|
if len(b) > 32 {
|
2023-06-21 16:11:11 +00:00
|
|
|
|
return common.Hash{}, len(b), errors.New("hex string too long, want at most 32 bytes")
|
2022-09-16 16:16:32 +00:00
|
|
|
|
}
|
2023-06-21 16:11:11 +00:00
|
|
|
|
return common.BytesToHash(b), len(b), nil
|
2022-09-16 16:16:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-23 13:52:24 +00:00
|
|
|
|
// GetHeaderByNumber returns the requested canonical block header.
|
2023-05-29 12:52:08 +00:00
|
|
|
|
// - When blockNr is -1 the chain pending header is returned.
|
|
|
|
|
// - When blockNr is -2 the chain latest header is returned.
|
|
|
|
|
// - When blockNr is -3 the chain finalized header is returned.
|
|
|
|
|
// - When blockNr is -4 the chain safe header is returned.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (map[string]interface{}, error) {
|
2019-07-23 13:52:24 +00:00
|
|
|
|
header, err := s.b.HeaderByNumber(ctx, number)
|
|
|
|
|
if header != nil && err == nil {
|
2020-07-13 09:02:54 +00:00
|
|
|
|
response := s.rpcMarshalHeader(ctx, header)
|
2019-07-23 13:52:24 +00:00
|
|
|
|
if number == rpc.PendingBlockNumber {
|
|
|
|
|
// Pending header need to nil out a few fields
|
|
|
|
|
for _, field := range []string{"hash", "nonce", "miner"} {
|
|
|
|
|
response[field] = nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return response, err
|
|
|
|
|
}
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetHeaderByHash returns the requested header by hash.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} {
|
2019-07-25 06:29:53 +00:00
|
|
|
|
header, _ := s.b.HeaderByHash(ctx, hash)
|
2019-07-23 13:52:24 +00:00
|
|
|
|
if header != nil {
|
2020-07-13 09:02:54 +00:00
|
|
|
|
return s.rpcMarshalHeader(ctx, header)
|
2019-07-23 13:52:24 +00:00
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetBlockByNumber returns the requested canonical block.
|
2023-05-29 12:52:08 +00:00
|
|
|
|
// - When blockNr is -1 the chain pending block is returned.
|
|
|
|
|
// - When blockNr is -2 the chain latest block is returned.
|
|
|
|
|
// - When blockNr is -3 the chain finalized block is returned.
|
|
|
|
|
// - When blockNr is -4 the chain safe block is returned.
|
2022-09-10 11:25:40 +00:00
|
|
|
|
// - When fullTx is true all transactions in the block are returned, otherwise
|
|
|
|
|
// only the transaction hash is returned.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
|
2019-07-23 13:52:24 +00:00
|
|
|
|
block, err := s.b.BlockByNumber(ctx, number)
|
|
|
|
|
if block != nil && err == nil {
|
2020-07-13 09:02:54 +00:00
|
|
|
|
response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
|
2019-07-23 13:52:24 +00:00
|
|
|
|
if err == nil && number == rpc.PendingBlockNumber {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// Pending blocks need to nil out a few fields
|
2020-02-07 09:44:32 +00:00
|
|
|
|
for _, field := range []string{"hash", "nonce", "miner"} {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
response[field] = nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return response, err
|
|
|
|
|
}
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
|
|
|
|
|
// detail, otherwise only the transaction hash is returned.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
|
2019-07-25 06:29:53 +00:00
|
|
|
|
block, err := s.b.BlockByHash(ctx, hash)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if block != nil {
|
2020-07-13 09:02:54 +00:00
|
|
|
|
return s.rpcMarshalBlock(ctx, block, true, fullTx)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-24 04:43:51 +00:00
|
|
|
|
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
block, err := s.b.BlockByNumber(ctx, blockNr)
|
|
|
|
|
if block != nil {
|
|
|
|
|
uncles := block.Uncles()
|
2016-12-17 14:39:55 +00:00
|
|
|
|
if index >= hexutil.Uint(len(uncles)) {
|
2017-03-03 09:41:52 +00:00
|
|
|
|
log.Debug("Requested uncle not found", "number", blockNr, "hash", block.Hash(), "index", index)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
2016-12-17 14:39:55 +00:00
|
|
|
|
block = types.NewBlockWithHeader(uncles[index])
|
2020-07-13 09:02:54 +00:00
|
|
|
|
return s.rpcMarshalBlock(ctx, block, false, false)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-24 04:43:51 +00:00
|
|
|
|
// GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) {
|
2019-07-25 06:29:53 +00:00
|
|
|
|
block, err := s.b.BlockByHash(ctx, blockHash)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if block != nil {
|
|
|
|
|
uncles := block.Uncles()
|
2016-12-17 14:39:55 +00:00
|
|
|
|
if index >= hexutil.Uint(len(uncles)) {
|
2017-03-03 09:41:52 +00:00
|
|
|
|
log.Debug("Requested uncle not found", "number", block.Number(), "hash", blockHash, "index", index)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
2016-12-17 14:39:55 +00:00
|
|
|
|
block = types.NewBlockWithHeader(uncles[index])
|
2020-07-13 09:02:54 +00:00
|
|
|
|
return s.rpcMarshalBlock(ctx, block, false, false)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
n := hexutil.Uint(len(block.Uncles()))
|
|
|
|
|
return &n
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetUncleCountByBlockHash returns number of uncles in the block for the given block hash
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
|
2019-07-25 06:29:53 +00:00
|
|
|
|
if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
n := hexutil.Uint(len(block.Uncles()))
|
|
|
|
|
return &n
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetCode returns the code stored at the given address in the state for the given block number.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
2019-09-26 08:47:31 +00:00
|
|
|
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if state == nil || err != nil {
|
2017-06-27 13:57:06 +00:00
|
|
|
|
return nil, err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2017-06-27 13:57:06 +00:00
|
|
|
|
code := state.GetCode(address)
|
|
|
|
|
return code, state.Error()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetStorageAt returns the storage from the state at the given address, key and
|
|
|
|
|
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
|
|
|
|
|
// numbers are also allowed.
|
2022-09-16 16:16:32 +00:00
|
|
|
|
func (s *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, hexKey string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
2019-09-26 08:47:31 +00:00
|
|
|
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if state == nil || err != nil {
|
2017-06-27 13:57:06 +00:00
|
|
|
|
return nil, err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2023-06-21 16:11:11 +00:00
|
|
|
|
key, _, err := decodeHash(hexKey)
|
2022-09-16 16:16:32 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("unable to decode storage key: %s", err)
|
|
|
|
|
}
|
|
|
|
|
res := state.GetState(address, key)
|
2017-06-27 13:57:06 +00:00
|
|
|
|
return res[:], state.Error()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-15 12:35:48 +00:00
|
|
|
|
// GetBlockReceipts returns the block receipts for the given block hash or number or tag.
|
|
|
|
|
func (s *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) {
|
|
|
|
|
block, err := s.b.BlockByNumberOrHash(ctx, blockNrOrHash)
|
|
|
|
|
if block == nil || err != nil {
|
|
|
|
|
// When the block doesn't exist, the RPC method should return JSON null
|
|
|
|
|
// as per specification.
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
receipts, err := s.b.GetReceipts(ctx, block.Hash())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
txs := block.Transactions()
|
|
|
|
|
if len(txs) != len(receipts) {
|
|
|
|
|
return nil, fmt.Errorf("receipts length mismatch: %d vs %d", len(txs), len(receipts))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Derive the sender.
|
|
|
|
|
signer := types.MakeSigner(s.b.ChainConfig(), block.Number(), block.Time())
|
|
|
|
|
|
|
|
|
|
result := make([]map[string]interface{}, len(receipts))
|
|
|
|
|
for i, receipt := range receipts {
|
|
|
|
|
result[i] = marshalReceipt(receipt, block.Hash(), block.NumberU64(), signer, txs[i], i)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-21 07:21:22 +00:00
|
|
|
|
// OverrideAccount indicates the overriding fields of account during the execution
|
|
|
|
|
// of a message call.
|
2019-08-08 13:44:11 +00:00
|
|
|
|
// Note, state and stateDiff can't be specified at the same time. If state is
|
|
|
|
|
// set, message execution will only use the data in the given state. Otherwise
|
|
|
|
|
// if statDiff is set, all diff will be applied first and then execute the call
|
|
|
|
|
// message.
|
2021-04-21 07:21:22 +00:00
|
|
|
|
type OverrideAccount struct {
|
2019-08-08 13:44:11 +00:00
|
|
|
|
Nonce *hexutil.Uint64 `json:"nonce"`
|
|
|
|
|
Code *hexutil.Bytes `json:"code"`
|
|
|
|
|
Balance **hexutil.Big `json:"balance"`
|
|
|
|
|
State *map[common.Hash]common.Hash `json:"state"`
|
|
|
|
|
StateDiff *map[common.Hash]common.Hash `json:"stateDiff"`
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-21 08:18:27 +00:00
|
|
|
|
// StateOverride is the collection of overridden accounts.
|
2021-04-21 07:21:22 +00:00
|
|
|
|
type StateOverride map[common.Address]OverrideAccount
|
2016-09-27 10:13:13 +00:00
|
|
|
|
|
2021-04-21 07:21:22 +00:00
|
|
|
|
// Apply overrides the fields of specified accounts into the given state.
|
|
|
|
|
func (diff *StateOverride) Apply(state *state.StateDB) error {
|
|
|
|
|
if diff == nil {
|
|
|
|
|
return nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2021-04-21 07:21:22 +00:00
|
|
|
|
for addr, account := range *diff {
|
2019-08-08 13:44:11 +00:00
|
|
|
|
// Override account nonce.
|
|
|
|
|
if account.Nonce != nil {
|
|
|
|
|
state.SetNonce(addr, uint64(*account.Nonce))
|
|
|
|
|
}
|
|
|
|
|
// Override account(contract) code.
|
|
|
|
|
if account.Code != nil {
|
|
|
|
|
state.SetCode(addr, *account.Code)
|
|
|
|
|
}
|
|
|
|
|
// Override account balance.
|
|
|
|
|
if account.Balance != nil {
|
2024-01-23 13:51:58 +00:00
|
|
|
|
u256Balance, _ := uint256.FromBig((*big.Int)(*account.Balance))
|
|
|
|
|
state.SetBalance(addr, u256Balance)
|
2019-08-08 13:44:11 +00:00
|
|
|
|
}
|
|
|
|
|
if account.State != nil && account.StateDiff != nil {
|
2021-04-21 07:21:22 +00:00
|
|
|
|
return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex())
|
2019-08-08 13:44:11 +00:00
|
|
|
|
}
|
|
|
|
|
// Replace entire state if caller requires.
|
|
|
|
|
if account.State != nil {
|
|
|
|
|
state.SetStorage(addr, *account.State)
|
|
|
|
|
}
|
|
|
|
|
// Apply state diff into specified accounts.
|
|
|
|
|
if account.StateDiff != nil {
|
|
|
|
|
for key, value := range *account.StateDiff {
|
|
|
|
|
state.SetState(addr, key, value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-10 13:24:30 +00:00
|
|
|
|
// Now finalize the changes. Finalize is normally performed between transactions.
|
|
|
|
|
// By using finalize, the overrides are semantically behaving as
|
|
|
|
|
// if they were created in a transaction just before the tracing occur.
|
|
|
|
|
state.Finalise(false)
|
2021-04-21 07:21:22 +00:00
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-02 09:39:36 +00:00
|
|
|
|
// BlockOverrides is a set of header fields to override.
|
|
|
|
|
type BlockOverrides struct {
|
2023-10-02 09:49:29 +00:00
|
|
|
|
Number *hexutil.Big
|
|
|
|
|
Difficulty *hexutil.Big
|
|
|
|
|
Time *hexutil.Uint64
|
|
|
|
|
GasLimit *hexutil.Uint64
|
|
|
|
|
Coinbase *common.Address
|
|
|
|
|
Random *common.Hash
|
|
|
|
|
BaseFee *hexutil.Big
|
|
|
|
|
BlobBaseFee *hexutil.Big
|
2022-06-02 09:39:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply overrides the given header fields into the given block context.
|
|
|
|
|
func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) {
|
|
|
|
|
if diff == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if diff.Number != nil {
|
|
|
|
|
blockCtx.BlockNumber = diff.Number.ToInt()
|
|
|
|
|
}
|
|
|
|
|
if diff.Difficulty != nil {
|
|
|
|
|
blockCtx.Difficulty = diff.Difficulty.ToInt()
|
|
|
|
|
}
|
|
|
|
|
if diff.Time != nil {
|
2023-01-25 11:12:28 +00:00
|
|
|
|
blockCtx.Time = uint64(*diff.Time)
|
2022-06-02 09:39:36 +00:00
|
|
|
|
}
|
|
|
|
|
if diff.GasLimit != nil {
|
|
|
|
|
blockCtx.GasLimit = uint64(*diff.GasLimit)
|
|
|
|
|
}
|
|
|
|
|
if diff.Coinbase != nil {
|
|
|
|
|
blockCtx.Coinbase = *diff.Coinbase
|
|
|
|
|
}
|
|
|
|
|
if diff.Random != nil {
|
|
|
|
|
blockCtx.Random = diff.Random
|
|
|
|
|
}
|
2022-07-05 12:48:34 +00:00
|
|
|
|
if diff.BaseFee != nil {
|
|
|
|
|
blockCtx.BaseFee = diff.BaseFee.ToInt()
|
|
|
|
|
}
|
2023-10-02 09:49:29 +00:00
|
|
|
|
if diff.BlobBaseFee != nil {
|
|
|
|
|
blockCtx.BlobBaseFee = diff.BlobBaseFee.ToInt()
|
|
|
|
|
}
|
2022-06-02 09:39:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 08:28:43 +00:00
|
|
|
|
// ChainContextBackend provides methods required to implement ChainContext.
|
|
|
|
|
type ChainContextBackend interface {
|
|
|
|
|
Engine() consensus.Engine
|
|
|
|
|
HeaderByNumber(context.Context, rpc.BlockNumber) (*types.Header, error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ChainContext is an implementation of core.ChainContext. It's main use-case
|
|
|
|
|
// is instantiating a vm.BlockContext without having access to the BlockChain object.
|
|
|
|
|
type ChainContext struct {
|
|
|
|
|
b ChainContextBackend
|
|
|
|
|
ctx context.Context
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewChainContext creates a new ChainContext object.
|
|
|
|
|
func NewChainContext(ctx context.Context, backend ChainContextBackend) *ChainContext {
|
|
|
|
|
return &ChainContext{ctx: ctx, b: backend}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (context *ChainContext) Engine() consensus.Engine {
|
|
|
|
|
return context.b.Engine()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (context *ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header {
|
|
|
|
|
// This method is called to get the hash for a block number when executing the BLOCKHASH
|
|
|
|
|
// opcode. Hence no need to search for non-canonical blocks.
|
|
|
|
|
header, err := context.b.HeaderByNumber(context.ctx, rpc.BlockNumber(number))
|
|
|
|
|
if err != nil || header.Hash() != hash {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return header
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 12:40:18 +00:00
|
|
|
|
func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
|
2021-04-21 07:21:22 +00:00
|
|
|
|
if err := overrides.Apply(state); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2017-01-04 19:17:24 +00:00
|
|
|
|
// Setup context so it may be cancelled the call has completed
|
|
|
|
|
// or, in case of unmetered gas, setup a context with a timeout.
|
|
|
|
|
var cancel context.CancelFunc
|
2018-03-02 12:35:02 +00:00
|
|
|
|
if timeout > 0 {
|
|
|
|
|
ctx, cancel = context.WithTimeout(ctx, timeout)
|
2017-01-04 19:17:24 +00:00
|
|
|
|
} else {
|
|
|
|
|
ctx, cancel = context.WithCancel(ctx)
|
2017-02-08 12:39:26 +00:00
|
|
|
|
}
|
2017-01-04 19:17:24 +00:00
|
|
|
|
// Make sure the context is cancelled when the call has completed
|
|
|
|
|
// this makes sure resources are cleaned up.
|
2018-03-02 12:35:02 +00:00
|
|
|
|
defer cancel()
|
2017-01-04 19:17:24 +00:00
|
|
|
|
|
|
|
|
|
// Get a new instance of the EVM.
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
msg, err := args.ToMessage(globalGasCap, header.BaseFee)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2023-05-02 08:28:43 +00:00
|
|
|
|
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
|
|
|
|
|
if blockOverrides != nil {
|
|
|
|
|
blockOverrides.Apply(&blockCtx)
|
|
|
|
|
}
|
2023-11-24 11:26:42 +00:00
|
|
|
|
evm := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx)
|
2023-05-11 12:23:47 +00:00
|
|
|
|
|
2017-01-04 19:17:24 +00:00
|
|
|
|
// Wait for the context to be done and cancel the evm. Even if the
|
|
|
|
|
// EVM has finished, cancelling may be done (repeatedly)
|
|
|
|
|
go func() {
|
2017-08-07 15:14:40 +00:00
|
|
|
|
<-ctx.Done()
|
|
|
|
|
evm.Cancel()
|
2017-01-04 19:17:24 +00:00
|
|
|
|
}()
|
|
|
|
|
|
2021-02-25 14:26:57 +00:00
|
|
|
|
// Execute the message.
|
2017-11-13 11:47:27 +00:00
|
|
|
|
gp := new(core.GasPool).AddGas(math.MaxUint64)
|
2020-04-22 08:25:36 +00:00
|
|
|
|
result, err := core.ApplyMessage(evm, msg, gp)
|
2023-11-24 11:26:42 +00:00
|
|
|
|
if err := state.Error(); err != nil {
|
2020-04-22 08:25:36 +00:00
|
|
|
|
return nil, err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2021-02-25 14:26:57 +00:00
|
|
|
|
|
2019-06-24 08:54:06 +00:00
|
|
|
|
// If the timer caused an abort, return an appropriate error message
|
|
|
|
|
if evm.Cancelled() {
|
2020-04-22 08:25:36 +00:00
|
|
|
|
return nil, fmt.Errorf("execution aborted (timeout = %v)", timeout)
|
2019-06-24 08:54:06 +00:00
|
|
|
|
}
|
2020-07-01 17:54:21 +00:00
|
|
|
|
if err != nil {
|
core, core/types: plain Message struct (#25977)
Here, the core.Message interface turns into a plain struct and
types.Message gets removed.
This is a breaking change to packages core and core/types. While we do
not promise API stability for package core, we do for core/types. An
exception can be made for types.Message, since it doesn't have any
purpose apart from invoking the state transition in package core.
types.Message was also marked deprecated by the same commit it
got added in, 4dca5d4db7 (November 2016).
The core.Message interface was added in December 2014, in commit
db494170dc, for the purpose of 'testing' state transitions. It's the
same change that made transaction struct fields private. Before that,
the state transition used *types.Transaction directly.
Over time, multiple implementations of the interface accrued across
different packages, since constructing a Message is required whenever
one wants to invoke the state transition. These implementations all
looked very similar, a struct with private fields exposing the fields
as accessor methods.
By changing Message into a struct with public fields we can remove all
these useless interface implementations. It will also hopefully
simplify future changes to the type with less updates to apply across
all of go-ethereum when a field is added to Message.
---------
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-03-09 13:19:12 +00:00
|
|
|
|
return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.GasLimit)
|
2020-07-01 17:54:21 +00:00
|
|
|
|
}
|
|
|
|
|
return result, nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-20 12:40:18 +00:00
|
|
|
|
func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
|
|
|
|
|
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
|
|
|
|
|
|
|
|
|
|
state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
|
|
|
|
if state == nil || err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap)
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// Call executes the given transaction on the state for the given block number.
|
2019-08-08 13:44:11 +00:00
|
|
|
|
//
|
|
|
|
|
// Additionally, the caller can specify a batch of contract for fields overriding.
|
|
|
|
|
//
|
|
|
|
|
// Note, this function doesn't make and changes in the state/blockchain and is
|
|
|
|
|
// useful to execute and retrieve values.
|
2023-09-26 12:22:11 +00:00
|
|
|
|
func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) {
|
|
|
|
|
if blockNrOrHash == nil {
|
|
|
|
|
latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
|
|
|
|
blockNrOrHash = &latest
|
|
|
|
|
}
|
|
|
|
|
result, err := DoCall(ctx, s.b, args, *blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap())
|
2020-04-22 08:25:36 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2020-06-08 08:09:49 +00:00
|
|
|
|
// If the result contains a revert reason, try to unpack and return it.
|
|
|
|
|
if len(result.Revert()) > 0 {
|
2023-11-27 14:20:09 +00:00
|
|
|
|
return nil, newRevertError(result.Revert())
|
2020-04-22 08:25:36 +00:00
|
|
|
|
}
|
2020-06-08 08:09:49 +00:00
|
|
|
|
return result.Return(), result.Err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-18 07:03:14 +00:00
|
|
|
|
// DoEstimateGas returns the lowest possible gas limit that allows the transaction to run
|
|
|
|
|
// successfully at block `blockNrOrHash`. It returns error if the transaction would revert, or if
|
|
|
|
|
// there are unexpected failures. The gas limit is capped by both `args.Gas` (if non-nil &
|
|
|
|
|
// non-zero) and `gasCap` (if non-zero).
|
2023-08-07 14:03:57 +00:00
|
|
|
|
func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, gasCap uint64) (hexutil.Uint64, error) {
|
2023-11-27 14:20:09 +00:00
|
|
|
|
// Retrieve the base state and mutate it with any overrides
|
2023-08-18 07:03:14 +00:00
|
|
|
|
state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
|
|
|
|
if state == nil || err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
2023-11-27 14:20:09 +00:00
|
|
|
|
if err = overrides.Apply(state); err != nil {
|
2023-08-18 07:03:14 +00:00
|
|
|
|
return 0, err
|
|
|
|
|
}
|
2023-11-27 14:20:09 +00:00
|
|
|
|
// Construct the gas estimator option from the user input
|
|
|
|
|
opts := &gasestimator.Options{
|
2023-11-28 20:31:47 +00:00
|
|
|
|
Config: b.ChainConfig(),
|
|
|
|
|
Chain: NewChainContext(ctx, b),
|
|
|
|
|
Header: header,
|
|
|
|
|
State: state,
|
|
|
|
|
ErrorRatio: estimateGasErrorRatio,
|
2019-04-08 11:49:52 +00:00
|
|
|
|
}
|
2023-11-27 14:20:09 +00:00
|
|
|
|
// Run the gas estimation andwrap any revertals into a custom return
|
|
|
|
|
call, err := args.ToMessage(gasCap, header.BaseFee)
|
2023-08-07 14:03:57 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
2023-11-27 14:20:09 +00:00
|
|
|
|
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
|
|
|
|
|
if err != nil {
|
|
|
|
|
if len(revert) > 0 {
|
|
|
|
|
return 0, newRevertError(revert)
|
2017-11-14 16:26:31 +00:00
|
|
|
|
}
|
2023-11-27 14:20:09 +00:00
|
|
|
|
return 0, err
|
2017-11-14 16:26:31 +00:00
|
|
|
|
}
|
2023-11-27 14:20:09 +00:00
|
|
|
|
return hexutil.Uint64(estimate), nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-18 07:03:14 +00:00
|
|
|
|
// EstimateGas returns the lowest possible gas limit that allows the transaction to run
|
|
|
|
|
// successfully at block `blockNrOrHash`, or the latest block if `blockNrOrHash` is unspecified. It
|
|
|
|
|
// returns error if the transaction would revert or if there are unexpected failures. The returned
|
|
|
|
|
// value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap
|
|
|
|
|
// configuration (if non-zero).
|
2024-01-17 14:06:14 +00:00
|
|
|
|
// Note: Required blob gas is not computed in this method.
|
2023-08-07 14:03:57 +00:00
|
|
|
|
func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Uint64, error) {
|
2023-05-11 12:23:05 +00:00
|
|
|
|
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
2020-09-23 08:29:48 +00:00
|
|
|
|
if blockNrOrHash != nil {
|
|
|
|
|
bNrOrHash = *blockNrOrHash
|
|
|
|
|
}
|
2023-08-07 14:03:57 +00:00
|
|
|
|
return DoEstimateGas(ctx, s.b, args, bNrOrHash, overrides, s.b.RPCGasCap())
|
2019-01-21 14:38:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-23 13:52:24 +00:00
|
|
|
|
// RPCMarshalHeader converts the given header to the RPC output .
|
2021-08-26 06:35:37 +00:00
|
|
|
|
func RPCMarshalHeader(head *types.Header) map[string]interface{} {
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
result := map[string]interface{}{
|
2016-12-17 14:39:55 +00:00
|
|
|
|
"number": (*hexutil.Big)(head.Number),
|
2019-07-23 13:52:24 +00:00
|
|
|
|
"hash": head.Hash(),
|
2016-08-03 23:40:50 +00:00
|
|
|
|
"parentHash": head.ParentHash,
|
|
|
|
|
"nonce": head.Nonce,
|
|
|
|
|
"mixHash": head.MixDigest,
|
|
|
|
|
"sha3Uncles": head.UncleHash,
|
|
|
|
|
"logsBloom": head.Bloom,
|
|
|
|
|
"stateRoot": head.Root,
|
2021-08-26 06:35:37 +00:00
|
|
|
|
"miner": head.Coinbase,
|
2016-12-17 14:39:55 +00:00
|
|
|
|
"difficulty": (*hexutil.Big)(head.Difficulty),
|
2016-12-12 11:25:59 +00:00
|
|
|
|
"extraData": hexutil.Bytes(head.Extra),
|
2017-11-13 11:47:27 +00:00
|
|
|
|
"gasLimit": hexutil.Uint64(head.GasLimit),
|
|
|
|
|
"gasUsed": hexutil.Uint64(head.GasUsed),
|
2019-04-02 20:28:48 +00:00
|
|
|
|
"timestamp": hexutil.Uint64(head.Time),
|
2016-08-03 23:40:50 +00:00
|
|
|
|
"transactionsRoot": head.TxHash,
|
2016-10-06 22:38:00 +00:00
|
|
|
|
"receiptsRoot": head.ReceiptHash,
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
if head.BaseFee != nil {
|
|
|
|
|
result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee)
|
|
|
|
|
}
|
2023-01-25 14:32:25 +00:00
|
|
|
|
if head.WithdrawalsHash != nil {
|
|
|
|
|
result["withdrawalsRoot"] = head.WithdrawalsHash
|
|
|
|
|
}
|
2023-08-18 12:22:35 +00:00
|
|
|
|
if head.BlobGasUsed != nil {
|
|
|
|
|
result["blobGasUsed"] = hexutil.Uint64(*head.BlobGasUsed)
|
|
|
|
|
}
|
|
|
|
|
if head.ExcessBlobGas != nil {
|
|
|
|
|
result["excessBlobGas"] = hexutil.Uint64(*head.ExcessBlobGas)
|
|
|
|
|
}
|
2023-08-26 02:52:12 +00:00
|
|
|
|
if head.ParentBeaconRoot != nil {
|
|
|
|
|
result["parentBeaconBlockRoot"] = head.ParentBeaconRoot
|
|
|
|
|
}
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
return result
|
2019-07-23 13:52:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
|
|
|
|
|
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
|
|
|
|
|
// transaction hashes.
|
2023-06-13 07:02:11 +00:00
|
|
|
|
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *params.ChainConfig) map[string]interface{} {
|
2021-08-26 06:35:37 +00:00
|
|
|
|
fields := RPCMarshalHeader(block.Header())
|
2019-07-25 06:25:16 +00:00
|
|
|
|
fields["size"] = hexutil.Uint64(block.Size())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
|
|
|
|
|
if inclTx {
|
2023-05-16 08:40:47 +00:00
|
|
|
|
formatTx := func(idx int, tx *types.Transaction) interface{} {
|
|
|
|
|
return tx.Hash()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
if fullTx {
|
2023-05-16 08:40:47 +00:00
|
|
|
|
formatTx = func(idx int, tx *types.Transaction) interface{} {
|
|
|
|
|
return newRPCTransactionFromBlockIndex(block, uint64(idx), config)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-07-23 13:52:24 +00:00
|
|
|
|
txs := block.Transactions()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
transactions := make([]interface{}, len(txs))
|
2018-06-11 08:03:40 +00:00
|
|
|
|
for i, tx := range txs {
|
2023-05-16 08:40:47 +00:00
|
|
|
|
transactions[i] = formatTx(i, tx)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
fields["transactions"] = transactions
|
|
|
|
|
}
|
2019-07-23 13:52:24 +00:00
|
|
|
|
uncles := block.Uncles()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
uncleHashes := make([]common.Hash, len(uncles))
|
|
|
|
|
for i, uncle := range uncles {
|
|
|
|
|
uncleHashes[i] = uncle.Hash()
|
|
|
|
|
}
|
|
|
|
|
fields["uncles"] = uncleHashes
|
2023-01-31 08:34:03 +00:00
|
|
|
|
if block.Header().WithdrawalsHash != nil {
|
|
|
|
|
fields["withdrawals"] = block.Withdrawals()
|
|
|
|
|
}
|
2023-06-13 07:02:11 +00:00
|
|
|
|
return fields
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-23 13:52:24 +00:00
|
|
|
|
// rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// a `BlockchainAPI`.
|
|
|
|
|
func (s *BlockChainAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} {
|
2021-08-26 06:35:37 +00:00
|
|
|
|
fields := RPCMarshalHeader(header)
|
2020-07-13 09:02:54 +00:00
|
|
|
|
fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, header.Hash()))
|
2019-07-23 13:52:24 +00:00
|
|
|
|
return fields
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// a `BlockchainAPI`.
|
|
|
|
|
func (s *BlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
2023-06-13 07:02:11 +00:00
|
|
|
|
fields := RPCMarshalBlock(b, inclTx, fullTx, s.b.ChainConfig())
|
2020-01-06 11:25:38 +00:00
|
|
|
|
if inclTx {
|
2020-07-13 09:02:54 +00:00
|
|
|
|
fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, b.Hash()))
|
2020-01-06 11:25:38 +00:00
|
|
|
|
}
|
2023-06-13 07:02:11 +00:00
|
|
|
|
return fields, nil
|
2018-06-11 08:03:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
|
|
|
|
|
type RPCTransaction struct {
|
2023-08-18 12:22:35 +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"`
|
|
|
|
|
GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"`
|
|
|
|
|
GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"`
|
|
|
|
|
MaxFeePerBlobGas *hexutil.Big `json:"maxFeePerBlobGas,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"`
|
|
|
|
|
BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
|
|
|
|
|
V *hexutil.Big `json:"v"`
|
|
|
|
|
R *hexutil.Big `json:"r"`
|
|
|
|
|
S *hexutil.Big `json:"s"`
|
|
|
|
|
YParity *hexutil.Uint64 `json:"yParity,omitempty"`
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 16:39:53 +00:00
|
|
|
|
// newRPCTransaction returns a transaction that will serialize to the RPC
|
|
|
|
|
// representation, with the given location metadata set (if available).
|
2023-04-21 09:52:02 +00:00
|
|
|
|
func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, blockTime uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction {
|
|
|
|
|
signer := types.MakeSigner(config, new(big.Int).SetUint64(blockNumber), blockTime)
|
2016-11-02 12:44:13 +00:00
|
|
|
|
from, _ := types.Sender(signer, tx)
|
2016-12-17 14:39:55 +00:00
|
|
|
|
v, r, s := tx.RawSignatureValues()
|
2017-07-14 16:39:53 +00:00
|
|
|
|
result := &RPCTransaction{
|
2021-02-25 14:26:57 +00:00
|
|
|
|
Type: hexutil.Uint64(tx.Type()),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
From: from,
|
2017-11-13 11:47:27 +00:00
|
|
|
|
Gas: hexutil.Uint64(tx.Gas()),
|
2016-12-17 14:39:55 +00:00
|
|
|
|
GasPrice: (*hexutil.Big)(tx.GasPrice()),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
Hash: tx.Hash(),
|
2016-12-12 11:25:59 +00:00
|
|
|
|
Input: hexutil.Bytes(tx.Data()),
|
2016-12-17 14:39:55 +00:00
|
|
|
|
Nonce: hexutil.Uint64(tx.Nonce()),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
To: tx.To(),
|
2016-12-17 14:39:55 +00:00
|
|
|
|
Value: (*hexutil.Big)(tx.Value()),
|
|
|
|
|
V: (*hexutil.Big)(v),
|
|
|
|
|
R: (*hexutil.Big)(r),
|
|
|
|
|
S: (*hexutil.Big)(s),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2017-07-14 16:39:53 +00:00
|
|
|
|
if blockHash != (common.Hash{}) {
|
2019-07-30 13:39:48 +00:00
|
|
|
|
result.BlockHash = &blockHash
|
2017-07-14 16:39:53 +00:00
|
|
|
|
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
|
2019-07-30 13:39:48 +00:00
|
|
|
|
result.TransactionIndex = (*hexutil.Uint64)(&index)
|
2017-07-14 16:39:53 +00:00
|
|
|
|
}
|
2023-08-04 22:54:55 +00:00
|
|
|
|
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
switch tx.Type() {
|
2022-06-29 09:58:59 +00:00
|
|
|
|
case types.LegacyTxType:
|
|
|
|
|
// if a legacy transaction has an EIP-155 chain id, include it explicitly
|
2022-07-07 19:50:28 +00:00
|
|
|
|
if id := tx.ChainId(); id.Sign() != 0 {
|
2022-06-29 09:58:59 +00:00
|
|
|
|
result.ChainID = (*hexutil.Big)(id)
|
|
|
|
|
}
|
2023-08-04 22:54:55 +00:00
|
|
|
|
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
case types.AccessListTxType:
|
|
|
|
|
al := tx.AccessList()
|
2023-08-04 22:54:55 +00:00
|
|
|
|
yparity := hexutil.Uint64(v.Sign())
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
result.Accesses = &al
|
|
|
|
|
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
2023-08-04 22:54:55 +00:00
|
|
|
|
result.YParity = &yparity
|
|
|
|
|
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
case types.DynamicFeeTxType:
|
2021-02-25 14:26:57 +00:00
|
|
|
|
al := tx.AccessList()
|
2023-08-04 22:54:55 +00:00
|
|
|
|
yparity := hexutil.Uint64(v.Sign())
|
2021-02-25 14:26:57 +00:00
|
|
|
|
result.Accesses = &al
|
|
|
|
|
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
2023-08-04 22:54:55 +00:00
|
|
|
|
result.YParity = &yparity
|
2021-06-08 10:05:41 +00:00
|
|
|
|
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
|
|
|
|
|
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
// if the transaction has been mined, compute the effective gas price
|
|
|
|
|
if baseFee != nil && blockHash != (common.Hash{}) {
|
2023-08-04 23:08:53 +00:00
|
|
|
|
// price = min(gasTipCap + baseFee, gasFeeCap)
|
2023-08-18 12:22:35 +00:00
|
|
|
|
result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
|
|
|
|
|
} else {
|
|
|
|
|
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case types.BlobTxType:
|
|
|
|
|
al := tx.AccessList()
|
|
|
|
|
yparity := hexutil.Uint64(v.Sign())
|
|
|
|
|
result.Accesses = &al
|
|
|
|
|
result.ChainID = (*hexutil.Big)(tx.ChainId())
|
|
|
|
|
result.YParity = &yparity
|
|
|
|
|
result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap())
|
|
|
|
|
result.GasTipCap = (*hexutil.Big)(tx.GasTipCap())
|
|
|
|
|
// if the transaction has been mined, compute the effective gas price
|
|
|
|
|
if baseFee != nil && blockHash != (common.Hash{}) {
|
|
|
|
|
result.GasPrice = (*hexutil.Big)(effectiveGasPrice(tx, baseFee))
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
} else {
|
2021-08-10 13:39:06 +00:00
|
|
|
|
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
}
|
2023-08-18 12:22:35 +00:00
|
|
|
|
result.MaxFeePerBlobGas = (*hexutil.Big)(tx.BlobGasFeeCap())
|
|
|
|
|
result.BlobVersionedHashes = tx.BlobHashes()
|
2021-02-25 14:26:57 +00:00
|
|
|
|
}
|
2017-07-14 16:39:53 +00:00
|
|
|
|
return result
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-18 12:22:35 +00:00
|
|
|
|
// effectiveGasPrice computes the transaction gas fee, based on the given basefee value.
|
|
|
|
|
//
|
|
|
|
|
// price = min(gasTipCap + baseFee, gasFeeCap)
|
|
|
|
|
func effectiveGasPrice(tx *types.Transaction, baseFee *big.Int) *big.Int {
|
|
|
|
|
fee := tx.GasTipCap()
|
|
|
|
|
fee = fee.Add(fee, baseFee)
|
2023-09-17 14:00:04 +00:00
|
|
|
|
if tx.GasFeeCapIntCmp(fee) < 0 {
|
|
|
|
|
return tx.GasFeeCap()
|
2023-08-18 12:22:35 +00:00
|
|
|
|
}
|
|
|
|
|
return fee
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-14 13:48:01 +00:00
|
|
|
|
// NewRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
|
|
|
|
|
func NewRPCPendingTransaction(tx *types.Transaction, current *types.Header, config *params.ChainConfig) *RPCTransaction {
|
2023-04-21 09:52:02 +00:00
|
|
|
|
var (
|
|
|
|
|
baseFee *big.Int
|
|
|
|
|
blockNumber = uint64(0)
|
|
|
|
|
blockTime = uint64(0)
|
|
|
|
|
)
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
if current != nil {
|
2023-08-01 09:58:45 +00:00
|
|
|
|
baseFee = eip1559.CalcBaseFee(config, current)
|
2021-10-18 18:53:08 +00:00
|
|
|
|
blockNumber = current.Number.Uint64()
|
2023-04-21 09:52:02 +00:00
|
|
|
|
blockTime = current.Time
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
}
|
2023-04-21 09:52:02 +00:00
|
|
|
|
return newRPCTransaction(tx, common.Hash{}, blockNumber, blockTime, 0, baseFee, config)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 16:39:53 +00:00
|
|
|
|
// newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
|
2021-10-07 13:51:14 +00:00
|
|
|
|
func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, config *params.ChainConfig) *RPCTransaction {
|
2017-07-14 16:39:53 +00:00
|
|
|
|
txs := b.Transactions()
|
|
|
|
|
if index >= uint64(len(txs)) {
|
|
|
|
|
return nil
|
2016-10-06 22:38:00 +00:00
|
|
|
|
}
|
2023-04-21 09:52:02 +00:00
|
|
|
|
return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time(), index, b.BaseFee(), config)
|
2017-07-14 16:39:53 +00:00
|
|
|
|
}
|
2016-10-06 22:38:00 +00:00
|
|
|
|
|
2017-07-14 16:39:53 +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 {
|
|
|
|
|
txs := b.Transactions()
|
|
|
|
|
if index >= uint64(len(txs)) {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2021-02-25 14:26:57 +00:00
|
|
|
|
blob, _ := txs[index].MarshalBinary()
|
2017-07-14 16:39:53 +00:00
|
|
|
|
return blob
|
2016-10-06 22:38:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-07 14:54:31 +00:00
|
|
|
|
// accessListResult returns an optional accesslist
|
2023-05-02 08:57:07 +00:00
|
|
|
|
// It's the result of the `debug_createAccessList` RPC call.
|
2021-04-07 14:54:31 +00:00
|
|
|
|
// It contains an error if the transaction itself failed.
|
|
|
|
|
type accessListResult struct {
|
|
|
|
|
Accesslist *types.AccessList `json:"accessList"`
|
|
|
|
|
Error string `json:"error,omitempty"`
|
|
|
|
|
GasUsed hexutil.Uint64 `json:"gasUsed"`
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-02 08:57:07 +00:00
|
|
|
|
// CreateAccessList creates an EIP-2930 type AccessList for the given transaction.
|
2021-04-07 14:54:31 +00:00
|
|
|
|
// Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *BlockChainAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) {
|
2024-01-12 18:59:36 +00:00
|
|
|
|
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
2021-04-07 14:54:31 +00:00
|
|
|
|
if blockNrOrHash != nil {
|
|
|
|
|
bNrOrHash = *blockNrOrHash
|
|
|
|
|
}
|
|
|
|
|
acl, gasUsed, vmerr, err := AccessList(ctx, s.b, bNrOrHash, args)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
result := &accessListResult{Accesslist: &acl, GasUsed: hexutil.Uint64(gasUsed)}
|
|
|
|
|
if vmerr != nil {
|
|
|
|
|
result.Error = vmerr.Error()
|
|
|
|
|
}
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AccessList creates an access list for the given transaction.
|
|
|
|
|
// If the accesslist creation fails an error is returned.
|
|
|
|
|
// If the transaction itself fails, an vmErr is returned.
|
2021-05-25 20:30:21 +00:00
|
|
|
|
func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrHash, args TransactionArgs) (acl types.AccessList, gasUsed uint64, vmErr error, err error) {
|
2021-04-07 14:54:31 +00:00
|
|
|
|
// Retrieve the execution context
|
|
|
|
|
db, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
|
|
|
|
if db == nil || err != nil {
|
|
|
|
|
return nil, 0, nil, err
|
|
|
|
|
}
|
2022-08-03 16:18:45 +00:00
|
|
|
|
// If the gas amount is not set, default to RPC gas cap.
|
|
|
|
|
if args.Gas == nil {
|
|
|
|
|
tmp := hexutil.Uint64(b.RPCGasCap())
|
|
|
|
|
args.Gas = &tmp
|
|
|
|
|
}
|
2021-04-07 14:54:31 +00:00
|
|
|
|
|
|
|
|
|
// Ensure any missing fields are filled, extract the recipient and input data
|
|
|
|
|
if err := args.setDefaults(ctx, b); err != nil {
|
|
|
|
|
return nil, 0, nil, err
|
|
|
|
|
}
|
|
|
|
|
var to common.Address
|
|
|
|
|
if args.To != nil {
|
|
|
|
|
to = *args.To
|
|
|
|
|
} else {
|
2021-05-25 20:30:21 +00:00
|
|
|
|
to = crypto.CreateAddress(args.from(), uint64(*args.Nonce))
|
2021-04-07 14:54:31 +00:00
|
|
|
|
}
|
2022-01-10 07:44:21 +00:00
|
|
|
|
isPostMerge := header.Difficulty.Cmp(common.Big0) == 0
|
2021-04-07 14:54:31 +00:00
|
|
|
|
// Retrieve the precompiles since they don't need to be added to the access list
|
2023-01-25 11:12:28 +00:00
|
|
|
|
precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time))
|
2021-04-07 14:54:31 +00:00
|
|
|
|
|
|
|
|
|
// Create an initial tracer
|
2021-11-25 12:17:09 +00:00
|
|
|
|
prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles)
|
2021-04-07 14:54:31 +00:00
|
|
|
|
if args.AccessList != nil {
|
2021-11-25 12:17:09 +00:00
|
|
|
|
prevTracer = logger.NewAccessListTracer(*args.AccessList, args.from(), to, precompiles)
|
2021-04-07 14:54:31 +00:00
|
|
|
|
}
|
|
|
|
|
for {
|
|
|
|
|
// Retrieve the current access list to expand
|
|
|
|
|
accessList := prevTracer.AccessList()
|
|
|
|
|
log.Trace("Creating access list", "input", accessList)
|
|
|
|
|
|
|
|
|
|
// Copy the original db so we don't modify it
|
|
|
|
|
statedb := db.Copy()
|
2021-07-28 12:21:35 +00:00
|
|
|
|
// Set the accesslist to the last al
|
|
|
|
|
args.AccessList = &accessList
|
|
|
|
|
msg, err := args.ToMessage(b.RPCGasCap(), header.BaseFee)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, 0, nil, err
|
|
|
|
|
}
|
2021-04-07 14:54:31 +00:00
|
|
|
|
|
|
|
|
|
// Apply the transaction with the access list tracer
|
2021-11-25 12:17:09 +00:00
|
|
|
|
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
2023-04-04 13:50:13 +00:00
|
|
|
|
config := vm.Config{Tracer: tracer, NoBaseFee: true}
|
2023-11-24 11:26:42 +00:00
|
|
|
|
vmenv := b.GetEVM(ctx, msg, statedb, header, &config, nil)
|
core, core/types: plain Message struct (#25977)
Here, the core.Message interface turns into a plain struct and
types.Message gets removed.
This is a breaking change to packages core and core/types. While we do
not promise API stability for package core, we do for core/types. An
exception can be made for types.Message, since it doesn't have any
purpose apart from invoking the state transition in package core.
types.Message was also marked deprecated by the same commit it
got added in, 4dca5d4db7 (November 2016).
The core.Message interface was added in December 2014, in commit
db494170dc, for the purpose of 'testing' state transitions. It's the
same change that made transaction struct fields private. Before that,
the state transition used *types.Transaction directly.
Over time, multiple implementations of the interface accrued across
different packages, since constructing a Message is required whenever
one wants to invoke the state transition. These implementations all
looked very similar, a struct with private fields exposing the fields
as accessor methods.
By changing Message into a struct with public fields we can remove all
these useless interface implementations. It will also hopefully
simplify future changes to the type with less updates to apply across
all of go-ethereum when a field is added to Message.
---------
Co-authored-by: Felix Lange <fjl@twurst.com>
2023-03-09 13:19:12 +00:00
|
|
|
|
res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
2021-04-07 14:54:31 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.toTransaction().Hash(), err)
|
|
|
|
|
}
|
|
|
|
|
if tracer.Equal(prevTracer) {
|
|
|
|
|
return accessList, res.UsedGas, res.Err, nil
|
|
|
|
|
}
|
|
|
|
|
prevTracer = tracer
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// TransactionAPI exposes methods for reading and creating transaction data.
|
|
|
|
|
type TransactionAPI struct {
|
2017-05-25 15:08:13 +00:00
|
|
|
|
b Backend
|
|
|
|
|
nonceLock *AddrLocker
|
2021-02-25 14:26:57 +00:00
|
|
|
|
signer types.Signer
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// NewTransactionAPI creates a new RPC service with methods for interacting with transactions.
|
|
|
|
|
func NewTransactionAPI(b Backend, nonceLock *AddrLocker) *TransactionAPI {
|
2021-02-25 14:26:57 +00:00
|
|
|
|
// The signer used by the API should always be the 'latest' known one because we expect
|
|
|
|
|
// signers to be backwards-compatible with old transactions.
|
|
|
|
|
signer := types.LatestSigner(b.ChainConfig())
|
2022-06-21 09:05:43 +00:00
|
|
|
|
return &TransactionAPI{b, nonceLock, signer}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
n := hexutil.Uint(len(block.Transactions()))
|
|
|
|
|
return &n
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
|
2019-07-25 06:29:53 +00:00
|
|
|
|
if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
n := hexutil.Uint(len(block.Transactions()))
|
|
|
|
|
return &n
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
|
2021-10-07 13:51:14 +00:00
|
|
|
|
return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2017-07-14 16:39:53 +00:00
|
|
|
|
return nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction {
|
2019-07-25 06:29:53 +00:00
|
|
|
|
if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
|
2021-10-07 13:51:14 +00:00
|
|
|
|
return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2017-07-14 16:39:53 +00:00
|
|
|
|
return nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-06 22:38:00 +00:00
|
|
|
|
// GetRawTransactionByBlockNumberAndIndex returns the bytes of the transaction for the given block number and index.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) hexutil.Bytes {
|
2016-10-06 22:38:00 +00:00
|
|
|
|
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
|
2017-07-14 16:39:53 +00:00
|
|
|
|
return newRPCRawTransactionFromBlockIndex(block, uint64(index))
|
2016-10-06 22:38:00 +00:00
|
|
|
|
}
|
2017-07-14 16:39:53 +00:00
|
|
|
|
return nil
|
2016-10-06 22:38:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) hexutil.Bytes {
|
2019-07-25 06:29:53 +00:00
|
|
|
|
if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
|
2017-07-14 16:39:53 +00:00
|
|
|
|
return newRPCRawTransactionFromBlockIndex(block, uint64(index))
|
2016-10-06 22:38:00 +00:00
|
|
|
|
}
|
2017-07-14 16:39:53 +00:00
|
|
|
|
return nil
|
2016-10-06 22:38:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// GetTransactionCount returns the number of transactions the given address has sent for the given block number
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) {
|
2019-01-07 08:47:11 +00:00
|
|
|
|
// Ask transaction pool for the nonce which includes pending transactions
|
2019-09-26 08:47:31 +00:00
|
|
|
|
if blockNr, ok := blockNrOrHash.Number(); ok && blockNr == rpc.PendingBlockNumber {
|
2019-01-07 08:47:11 +00:00
|
|
|
|
nonce, err := s.b.GetPoolNonce(ctx, address)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return (*hexutil.Uint64)(&nonce), nil
|
|
|
|
|
}
|
|
|
|
|
// Resolve block number and use its state to ask for the nonce
|
2019-09-26 08:47:31 +00:00
|
|
|
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if state == nil || err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2017-06-27 13:57:06 +00:00
|
|
|
|
nonce := state.GetNonce(address)
|
|
|
|
|
return (*hexutil.Uint64)(&nonce), state.Error()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetTransactionByHash returns the transaction for the given hash
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
|
2017-07-14 16:39:53 +00:00
|
|
|
|
// Try to return an already finalized transaction
|
2024-01-22 20:05:18 +00:00
|
|
|
|
found, tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
|
|
|
|
|
if !found {
|
|
|
|
|
// No finalized transaction, try to retrieve it from the pool
|
|
|
|
|
if tx := s.b.GetPoolTransaction(hash); tx != nil {
|
|
|
|
|
return NewRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig()), nil
|
|
|
|
|
}
|
|
|
|
|
if err == nil {
|
|
|
|
|
return nil, nil
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
}
|
2024-01-22 20:05:18 +00:00
|
|
|
|
return nil, NewTxIndexingError()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2024-01-22 20:05:18 +00:00
|
|
|
|
header, err := s.b.HeaderByHash(ctx, blockHash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2024-01-22 20:05:18 +00:00
|
|
|
|
return newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, s.b.ChainConfig()), nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-06 22:38:00 +00:00
|
|
|
|
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
2017-07-14 16:39:53 +00:00
|
|
|
|
// Retrieve a finalized transaction, or a pooled otherwise
|
2024-01-22 20:05:18 +00:00
|
|
|
|
found, tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
|
|
|
|
|
if !found {
|
|
|
|
|
if tx = s.b.GetPoolTransaction(hash); tx != nil {
|
|
|
|
|
return tx.MarshalBinary()
|
|
|
|
|
}
|
|
|
|
|
if err == nil {
|
2017-07-14 16:39:53 +00:00
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
2024-01-22 20:05:18 +00:00
|
|
|
|
return nil, NewTxIndexingError()
|
2016-10-06 22:38:00 +00:00
|
|
|
|
}
|
2021-02-25 14:26:57 +00:00
|
|
|
|
return tx.MarshalBinary()
|
2016-10-06 22:38:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
|
2024-01-22 20:05:18 +00:00
|
|
|
|
found, tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, NewTxIndexingError() // transaction is not fully indexed
|
|
|
|
|
}
|
|
|
|
|
if !found {
|
|
|
|
|
return nil, nil // transaction is not existent or reachable
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2023-04-21 09:52:02 +00:00
|
|
|
|
header, err := s.b.HeaderByHash(ctx, blockHash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2018-02-22 10:48:14 +00:00
|
|
|
|
receipts, err := s.b.GetReceipts(ctx, blockHash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2023-03-16 22:53:39 +00:00
|
|
|
|
if uint64(len(receipts)) <= index {
|
2018-02-28 10:40:15 +00:00
|
|
|
|
return nil, nil
|
2017-12-14 12:24:34 +00:00
|
|
|
|
}
|
2018-02-22 10:48:14 +00:00
|
|
|
|
receipt := receipts[index]
|
2015-12-16 03:26:23 +00:00
|
|
|
|
|
2021-02-25 14:26:57 +00:00
|
|
|
|
// Derive the sender.
|
2023-04-21 09:52:02 +00:00
|
|
|
|
signer := types.MakeSigner(s.b.ChainConfig(), header.Number, header.Time)
|
2023-08-15 12:35:48 +00:00
|
|
|
|
return marshalReceipt(receipt, blockHash, blockNumber, signer, tx, int(index)), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// marshalReceipt marshals a transaction receipt into a JSON object.
|
|
|
|
|
func marshalReceipt(receipt *types.Receipt, blockHash common.Hash, blockNumber uint64, signer types.Signer, tx *types.Transaction, txIndex int) map[string]interface{} {
|
2016-11-02 12:44:13 +00:00
|
|
|
|
from, _ := types.Sender(signer, tx)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
|
|
|
|
|
fields := map[string]interface{}{
|
2017-07-14 16:39:53 +00:00
|
|
|
|
"blockHash": blockHash,
|
|
|
|
|
"blockNumber": hexutil.Uint64(blockNumber),
|
2023-08-15 12:35:48 +00:00
|
|
|
|
"transactionHash": tx.Hash(),
|
|
|
|
|
"transactionIndex": hexutil.Uint64(txIndex),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
"from": from,
|
|
|
|
|
"to": tx.To(),
|
2017-11-13 11:47:27 +00:00
|
|
|
|
"gasUsed": hexutil.Uint64(receipt.GasUsed),
|
|
|
|
|
"cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
"contractAddress": nil,
|
|
|
|
|
"logs": receipt.Logs,
|
2016-08-03 23:40:50 +00:00
|
|
|
|
"logsBloom": receipt.Bloom,
|
2021-02-25 14:26:57 +00:00
|
|
|
|
"type": hexutil.Uint(tx.Type()),
|
2023-03-06 16:19:41 +00:00
|
|
|
|
"effectiveGasPrice": (*hexutil.Big)(receipt.EffectiveGasPrice),
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2023-03-06 16:19:41 +00:00
|
|
|
|
|
2017-08-26 07:30:56 +00:00
|
|
|
|
// Assign receipt status or post state.
|
|
|
|
|
if len(receipt.PostState) > 0 {
|
|
|
|
|
fields["root"] = hexutil.Bytes(receipt.PostState)
|
|
|
|
|
} else {
|
2017-10-02 08:42:08 +00:00
|
|
|
|
fields["status"] = hexutil.Uint(receipt.Status)
|
2017-08-26 07:30:56 +00:00
|
|
|
|
}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if receipt.Logs == nil {
|
2022-02-15 09:44:22 +00:00
|
|
|
|
fields["logs"] = []*types.Log{}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2023-03-06 16:19:41 +00:00
|
|
|
|
|
2023-08-18 12:22:35 +00:00
|
|
|
|
if tx.Type() == types.BlobTxType {
|
|
|
|
|
fields["blobGasUsed"] = hexutil.Uint64(receipt.BlobGasUsed)
|
|
|
|
|
fields["blobGasPrice"] = (*hexutil.Big)(receipt.BlobGasPrice)
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
|
2016-08-03 23:40:50 +00:00
|
|
|
|
if receipt.ContractAddress != (common.Address{}) {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
fields["contractAddress"] = receipt.ContractAddress
|
|
|
|
|
}
|
2023-08-15 12:35:48 +00:00
|
|
|
|
return fields
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sign is a helper function that signs a transaction with the private key of the given address.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
2017-02-07 10:47:34 +00:00
|
|
|
|
// Look up the wallet containing the requested signer
|
|
|
|
|
account := accounts.Account{Address: addr}
|
|
|
|
|
|
|
|
|
|
wallet, err := s.b.AccountManager().Find(account)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
// Request the wallet to sign the transaction
|
2019-02-07 10:59:17 +00:00
|
|
|
|
return wallet.SignTx(account, tx, s.b.ChainConfig().ChainID)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-21 14:38:13 +00:00
|
|
|
|
// SubmitTransaction is a helper function that submits tx to txPool and logs a message.
|
|
|
|
|
func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
|
2020-06-17 07:46:31 +00:00
|
|
|
|
// If the transaction fee cap is already specified, ensure the
|
|
|
|
|
// fee of the given transaction is _reasonable_.
|
2020-07-13 10:45:39 +00:00
|
|
|
|
if err := checkTxFee(tx.GasPrice(), tx.Gas(), b.RPCTxFeeCap()); err != nil {
|
|
|
|
|
return common.Hash{}, err
|
2020-06-17 07:46:31 +00:00
|
|
|
|
}
|
2021-02-23 12:09:19 +00:00
|
|
|
|
if !b.UnprotectedAllowed() && !tx.Protected() {
|
|
|
|
|
// Ensure only eip155 signed transactions are submitted if EIP155Required is set.
|
|
|
|
|
return common.Hash{}, errors.New("only replay-protected (EIP-155) transactions allowed over RPC")
|
|
|
|
|
}
|
2017-01-24 09:49:20 +00:00
|
|
|
|
if err := b.SendTx(ctx, tx); err != nil {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
2021-01-26 11:13:55 +00:00
|
|
|
|
// Print a log with full tx details for manual investigations and interventions
|
2023-04-21 09:52:02 +00:00
|
|
|
|
head := b.CurrentBlock()
|
|
|
|
|
signer := types.MakeSigner(b.ChainConfig(), head.Number, head.Time)
|
2021-01-26 11:13:55 +00:00
|
|
|
|
from, err := types.Sender(signer, tx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-24 09:49:20 +00:00
|
|
|
|
if tx.To() == nil {
|
|
|
|
|
addr := crypto.CreateAddress(from, tx.Nonce())
|
2021-01-26 11:13:55 +00:00
|
|
|
|
log.Info("Submitted contract creation", "hash", tx.Hash().Hex(), "from", from, "nonce", tx.Nonce(), "contract", addr.Hex(), "value", tx.Value())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
} else {
|
2021-01-26 11:13:55 +00:00
|
|
|
|
log.Info("Submitted transaction", "hash", tx.Hash().Hex(), "from", from, "nonce", tx.Nonce(), "recipient", tx.To(), "value", tx.Value())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2017-01-24 09:49:20 +00:00
|
|
|
|
return tx.Hash(), nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SendTransaction creates a transaction for the given argument, sign it and submit it to the
|
|
|
|
|
// transaction pool.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) SendTransaction(ctx context.Context, args TransactionArgs) (common.Hash, error) {
|
2017-02-07 10:47:34 +00:00
|
|
|
|
// Look up the wallet containing the requested signer
|
2021-05-25 20:30:21 +00:00
|
|
|
|
account := accounts.Account{Address: args.from()}
|
2017-02-07 10:47:34 +00:00
|
|
|
|
|
|
|
|
|
wallet, err := s.b.AccountManager().Find(account)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
2017-05-25 15:08:13 +00:00
|
|
|
|
|
|
|
|
|
if args.Nonce == nil {
|
2022-10-11 07:37:00 +00:00
|
|
|
|
// Hold the mutex around signing to prevent concurrent assignment of
|
2017-05-25 15:08:13 +00:00
|
|
|
|
// the same nonce to multiple accounts.
|
2021-05-25 20:30:21 +00:00
|
|
|
|
s.nonceLock.LockAddr(args.from())
|
|
|
|
|
defer s.nonceLock.UnlockAddr(args.from())
|
2017-05-25 15:08:13 +00:00
|
|
|
|
}
|
2024-01-17 14:06:14 +00:00
|
|
|
|
if args.IsEIP4844() {
|
|
|
|
|
return common.Hash{}, errBlobTxNotSupported
|
|
|
|
|
}
|
2017-05-25 15:08:13 +00:00
|
|
|
|
|
|
|
|
|
// Set some sanity defaults and terminate on failure
|
|
|
|
|
if err := args.setDefaults(ctx, s.b); err != nil {
|
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
2017-02-07 10:47:34 +00:00
|
|
|
|
// Assemble the transaction and sign with the wallet
|
2016-12-17 14:39:55 +00:00
|
|
|
|
tx := args.toTransaction()
|
2017-01-24 09:49:20 +00:00
|
|
|
|
|
2019-02-07 10:59:17 +00:00
|
|
|
|
signed, err := wallet.SignTx(account, tx, s.b.ChainConfig().ChainID)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
2019-01-21 14:38:13 +00:00
|
|
|
|
return SubmitTransaction(ctx, s.b, signed)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-13 10:40:01 +00:00
|
|
|
|
// FillTransaction fills the defaults (nonce, gas, gasPrice or 1559 fields)
|
|
|
|
|
// on a given unsigned transaction, and returns it to the caller for further
|
|
|
|
|
// processing (signing + broadcast).
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) FillTransaction(ctx context.Context, args TransactionArgs) (*SignTransactionResult, error) {
|
2024-02-08 18:53:32 +00:00
|
|
|
|
args.blobSidecarAllowed = true
|
|
|
|
|
|
2019-08-08 08:22:10 +00:00
|
|
|
|
// Set some sanity defaults and terminate on failure
|
|
|
|
|
if err := args.setDefaults(ctx, s.b); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
// Assemble the transaction and obtain rlp
|
|
|
|
|
tx := args.toTransaction()
|
2021-02-25 14:26:57 +00:00
|
|
|
|
data, err := tx.MarshalBinary()
|
2019-08-08 08:22:10 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return &SignTransactionResult{data, tx}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// SendRawTransaction will add the signed transaction to the transaction pool.
|
|
|
|
|
// The sender is responsible for signing the transaction and using the correct nonce.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) (common.Hash, error) {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
tx := new(types.Transaction)
|
2021-02-25 14:26:57 +00:00
|
|
|
|
if err := tx.UnmarshalBinary(input); err != nil {
|
2017-09-25 08:38:42 +00:00
|
|
|
|
return common.Hash{}, err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2019-01-21 14:38:13 +00:00
|
|
|
|
return SubmitTransaction(ctx, s.b, tx)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-28 19:25:49 +00:00
|
|
|
|
// Sign calculates an ECDSA signature for:
|
2022-06-10 08:57:32 +00:00
|
|
|
|
// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message).
|
2016-10-28 19:25:49 +00:00
|
|
|
|
//
|
2017-01-05 10:35:23 +00:00
|
|
|
|
// Note, the produced signature conforms to the secp256k1 curve R, S and V values,
|
|
|
|
|
// where the V value will be 27 or 28 for legacy reasons.
|
|
|
|
|
//
|
2016-10-28 19:25:49 +00:00
|
|
|
|
// The account associated with addr must be unlocked.
|
|
|
|
|
//
|
|
|
|
|
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) Sign(addr common.Address, data hexutil.Bytes) (hexutil.Bytes, error) {
|
2017-02-07 10:47:34 +00:00
|
|
|
|
// Look up the wallet containing the requested signer
|
|
|
|
|
account := accounts.Account{Address: addr}
|
|
|
|
|
|
|
|
|
|
wallet, err := s.b.AccountManager().Find(account)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
// Sign the requested hash with the wallet
|
accounts, eth, clique, signer: support for external signer API (#18079)
* accounts, eth, clique: implement external backend + move sighash calc to backend
* signer: implement account_Version on external API
* accounts/external: enable ipc, add copyright
* accounts, internal, signer: formatting
* node: go fmt
* flags: disallow --dev in combo with --externalsigner
* accounts: remove clique-specific signing method, replace with more generic
* accounts, consensus: formatting + fix error in tests
* signer/core: remove (test-) import cycle
* clique: remove unused import
* accounts: remove CliqueHash and avoid dependency on package crypto
* consensus/clique: unduplicate header encoding
2019-02-05 10:23:57 +00:00
|
|
|
|
signature, err := wallet.SignText(account, data)
|
2017-01-05 10:35:23 +00:00
|
|
|
|
if err == nil {
|
2016-12-08 12:42:31 +00:00
|
|
|
|
signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
|
2017-01-05 10:35:23 +00:00
|
|
|
|
}
|
|
|
|
|
return signature, err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SignTransactionResult represents a RLP encoded signed transaction.
|
|
|
|
|
type SignTransactionResult struct {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
Raw hexutil.Bytes `json:"raw"`
|
|
|
|
|
Tx *types.Transaction `json:"tx"`
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SignTransaction will sign the given transaction with the from account.
|
|
|
|
|
// The node needs to have the private key of the account corresponding with
|
|
|
|
|
// the given from address and it needs to be unlocked.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) SignTransaction(ctx context.Context, args TransactionArgs) (*SignTransactionResult, error) {
|
2018-01-26 17:32:43 +00:00
|
|
|
|
if args.Gas == nil {
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return nil, errors.New("gas not specified")
|
2018-01-26 17:32:43 +00:00
|
|
|
|
}
|
2021-07-13 10:40:01 +00:00
|
|
|
|
if args.GasPrice == nil && (args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil) {
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")
|
2018-01-26 17:32:43 +00:00
|
|
|
|
}
|
2024-01-17 14:06:14 +00:00
|
|
|
|
if args.IsEIP4844() {
|
|
|
|
|
return nil, errBlobTxNotSupported
|
|
|
|
|
}
|
2017-05-19 13:03:56 +00:00
|
|
|
|
if args.Nonce == nil {
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return nil, errors.New("nonce not specified")
|
2017-05-19 13:03:56 +00:00
|
|
|
|
}
|
2016-12-17 14:39:55 +00:00
|
|
|
|
if err := args.setDefaults(ctx, s.b); err != nil {
|
|
|
|
|
return nil, err
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2020-07-13 10:45:39 +00:00
|
|
|
|
// Before actually sign the transaction, ensure the transaction fee is reasonable.
|
2021-07-13 10:40:01 +00:00
|
|
|
|
tx := args.toTransaction()
|
|
|
|
|
if err := checkTxFee(tx.GasPrice(), tx.Gas(), s.b.RPCTxFeeCap()); err != nil {
|
2020-07-13 10:45:39 +00:00
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2021-07-13 10:40:01 +00:00
|
|
|
|
signed, err := s.sign(args.from(), tx)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2021-07-13 10:40:01 +00:00
|
|
|
|
data, err := signed.MarshalBinary()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2021-07-13 10:40:01 +00:00
|
|
|
|
return &SignTransactionResult{data, signed}, nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-12 10:40:16 +00:00
|
|
|
|
// PendingTransactions returns the transactions that are in the transaction pool
|
|
|
|
|
// and have a from address that is one of the accounts this node manages.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) PendingTransactions() ([]*RPCTransaction, error) {
|
2016-12-10 22:54:58 +00:00
|
|
|
|
pending, err := s.b.GetPoolTransactions()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2018-06-12 10:40:16 +00:00
|
|
|
|
accounts := make(map[common.Address]struct{})
|
|
|
|
|
for _, wallet := range s.b.AccountManager().Wallets() {
|
|
|
|
|
for _, account := range wallet.Accounts() {
|
|
|
|
|
accounts[account.Address] = struct{}{}
|
|
|
|
|
}
|
|
|
|
|
}
|
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>
2021-06-02 13:13:10 +00:00
|
|
|
|
curHeader := s.b.CurrentHeader()
|
2015-12-16 03:26:23 +00:00
|
|
|
|
transactions := make([]*RPCTransaction, 0, len(pending))
|
|
|
|
|
for _, tx := range pending {
|
2021-02-25 14:26:57 +00:00
|
|
|
|
from, _ := types.Sender(s.signer, tx)
|
2018-06-12 10:40:16 +00:00
|
|
|
|
if _, exists := accounts[from]; exists {
|
2022-11-14 13:48:01 +00:00
|
|
|
|
transactions = append(transactions, NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig()))
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-12-10 22:54:58 +00:00
|
|
|
|
return transactions, nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-17 14:39:55 +00:00
|
|
|
|
// Resend accepts an existing transaction and a new gas price and limit. It will remove
|
|
|
|
|
// the given transaction from the pool and reinsert it with the new gas price and limit.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
if sendArgs.Nonce == nil {
|
2023-05-25 06:54:28 +00:00
|
|
|
|
return common.Hash{}, errors.New("missing transaction nonce in transaction spec")
|
2016-12-17 14:39:55 +00:00
|
|
|
|
}
|
|
|
|
|
if err := sendArgs.setDefaults(ctx, s.b); err != nil {
|
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
|
|
|
|
matchTx := sendArgs.toTransaction()
|
2020-07-13 10:45:39 +00:00
|
|
|
|
|
|
|
|
|
// Before replacing the old transaction, ensure the _new_ transaction fee is reasonable.
|
|
|
|
|
var price = matchTx.GasPrice()
|
|
|
|
|
if gasPrice != nil {
|
|
|
|
|
price = gasPrice.ToInt()
|
|
|
|
|
}
|
|
|
|
|
var gas = matchTx.Gas()
|
|
|
|
|
if gasLimit != nil {
|
|
|
|
|
gas = uint64(*gasLimit)
|
|
|
|
|
}
|
|
|
|
|
if err := checkTxFee(price, gas, s.b.RPCTxFeeCap()); err != nil {
|
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
|
|
|
|
// Iterate the pending list for replacement
|
2016-12-10 22:54:58 +00:00
|
|
|
|
pending, err := s.b.GetPoolTransactions()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
for _, p := range pending {
|
2021-02-25 14:26:57 +00:00
|
|
|
|
wantSigHash := s.signer.Hash(matchTx)
|
|
|
|
|
pFrom, err := types.Sender(s.signer, p)
|
2021-05-25 20:30:21 +00:00
|
|
|
|
if err == nil && pFrom == sendArgs.from() && s.signer.Hash(p) == wantSigHash {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
// Match. Re-sign and send the transaction.
|
2018-03-08 10:29:42 +00:00
|
|
|
|
if gasPrice != nil && (*big.Int)(gasPrice).Sign() != 0 {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
sendArgs.GasPrice = gasPrice
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2018-03-08 10:29:42 +00:00
|
|
|
|
if gasLimit != nil && *gasLimit != 0 {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
sendArgs.Gas = gasLimit
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2021-05-25 20:30:21 +00:00
|
|
|
|
signedTx, err := s.sign(sendArgs.from(), sendArgs.toTransaction())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
|
|
|
|
if err = s.b.SendTx(ctx, signedTx); err != nil {
|
|
|
|
|
return common.Hash{}, err
|
|
|
|
|
}
|
|
|
|
|
return signedTx.Hash(), nil
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-29 10:40:02 +00:00
|
|
|
|
return common.Hash{}, fmt.Errorf("transaction %#x not found", matchTx.Hash())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// DebugAPI is the collection of Ethereum APIs exposed over the debugging
|
|
|
|
|
// namespace.
|
|
|
|
|
type DebugAPI struct {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
b Backend
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// NewDebugAPI creates a new instance of DebugAPI.
|
|
|
|
|
func NewDebugAPI(b Backend) *DebugAPI {
|
|
|
|
|
return &DebugAPI{b: b}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-25 08:41:37 +00:00
|
|
|
|
// GetRawHeader retrieves the RLP encoding for a single header.
|
|
|
|
|
func (api *DebugAPI) GetRawHeader(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
|
|
|
|
var hash common.Hash
|
|
|
|
|
if h, ok := blockNrOrHash.Hash(); ok {
|
|
|
|
|
hash = h
|
|
|
|
|
} else {
|
|
|
|
|
block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
hash = block.Hash()
|
|
|
|
|
}
|
|
|
|
|
header, _ := api.b.HeaderByHash(ctx, hash)
|
2021-10-01 08:45:47 +00:00
|
|
|
|
if header == nil {
|
2022-08-25 08:41:37 +00:00
|
|
|
|
return nil, fmt.Errorf("header #%d not found", hash)
|
2021-10-01 08:45:47 +00:00
|
|
|
|
}
|
2021-10-03 13:47:21 +00:00
|
|
|
|
return rlp.EncodeToBytes(header)
|
2021-10-01 08:45:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-25 08:41:37 +00:00
|
|
|
|
// GetRawBlock retrieves the RLP encoded for a single block.
|
|
|
|
|
func (api *DebugAPI) GetRawBlock(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
|
|
|
|
var hash common.Hash
|
|
|
|
|
if h, ok := blockNrOrHash.Hash(); ok {
|
|
|
|
|
hash = h
|
|
|
|
|
} else {
|
|
|
|
|
block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
hash = block.Hash()
|
|
|
|
|
}
|
|
|
|
|
block, _ := api.b.BlockByHash(ctx, hash)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
if block == nil {
|
2022-08-25 08:41:37 +00:00
|
|
|
|
return nil, fmt.Errorf("block #%d not found", hash)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
2021-10-03 13:47:21 +00:00
|
|
|
|
return rlp.EncodeToBytes(block)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-25 08:41:37 +00:00
|
|
|
|
// GetRawReceipts retrieves the binary-encoded receipts of a single block.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (api *DebugAPI) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]hexutil.Bytes, error) {
|
2022-05-14 20:33:41 +00:00
|
|
|
|
var hash common.Hash
|
|
|
|
|
if h, ok := blockNrOrHash.Hash(); ok {
|
|
|
|
|
hash = h
|
|
|
|
|
} else {
|
|
|
|
|
block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
hash = block.Hash()
|
|
|
|
|
}
|
|
|
|
|
receipts, err := api.b.GetReceipts(ctx, hash)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
result := make([]hexutil.Bytes, len(receipts))
|
|
|
|
|
for i, receipt := range receipts {
|
|
|
|
|
b, err := receipt.MarshalBinary()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
result[i] = b
|
|
|
|
|
}
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-25 08:41:37 +00:00
|
|
|
|
// GetRawTransaction returns the bytes of the transaction for the given hash.
|
|
|
|
|
func (s *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
|
|
|
|
// Retrieve a finalized transaction, or a pooled otherwise
|
2024-01-22 20:05:18 +00:00
|
|
|
|
found, tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
|
|
|
|
|
if !found {
|
|
|
|
|
if tx = s.b.GetPoolTransaction(hash); tx != nil {
|
|
|
|
|
return tx.MarshalBinary()
|
|
|
|
|
}
|
|
|
|
|
if err == nil {
|
2022-08-25 08:41:37 +00:00
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
2024-01-22 20:05:18 +00:00
|
|
|
|
return nil, NewTxIndexingError()
|
2022-08-25 08:41:37 +00:00
|
|
|
|
}
|
|
|
|
|
return tx.MarshalBinary()
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// PrintBlock retrieves a block and returns its pretty printed form.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (api *DebugAPI) PrintBlock(ctx context.Context, number uint64) (string, error) {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number))
|
|
|
|
|
if block == nil {
|
|
|
|
|
return "", fmt.Errorf("block #%d not found", number)
|
|
|
|
|
}
|
2018-04-05 12:13:02 +00:00
|
|
|
|
return spew.Sdump(block), nil
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-18 13:15:09 +00:00
|
|
|
|
// ChaindbProperty returns leveldb properties of the key-value database.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (api *DebugAPI) ChaindbProperty(property string) (string, error) {
|
2019-07-18 13:15:09 +00:00
|
|
|
|
return api.b.ChainDb().Stat(property)
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-18 13:15:09 +00:00
|
|
|
|
// ChaindbCompact flattens the entire key-value database into a single level,
|
|
|
|
|
// removing all unused slots and merging all keys.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (api *DebugAPI) ChaindbCompact() error {
|
2023-09-28 09:04:45 +00:00
|
|
|
|
cstart := time.Now()
|
|
|
|
|
for b := 0; b <= 255; b++ {
|
|
|
|
|
var (
|
|
|
|
|
start = []byte{byte(b)}
|
|
|
|
|
end = []byte{byte(b + 1)}
|
|
|
|
|
)
|
|
|
|
|
if b == 255 {
|
|
|
|
|
end = nil
|
|
|
|
|
}
|
|
|
|
|
log.Info("Compacting database", "range", fmt.Sprintf("%#X-%#X", start, end), "elapsed", common.PrettyDuration(time.Since(cstart)))
|
|
|
|
|
if err := api.b.ChainDb().Compact(start, end); err != nil {
|
2017-03-03 09:41:52 +00:00
|
|
|
|
log.Error("Database compaction failed", "err", err)
|
2016-10-20 12:36:48 +00:00
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 03:26:23 +00:00
|
|
|
|
// SetHead rewinds the head of the blockchain to a previous block.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (api *DebugAPI) SetHead(number hexutil.Uint64) {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
api.b.SetHead(uint64(number))
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// NetAPI offers network related RPC methods
|
|
|
|
|
type NetAPI struct {
|
2020-12-23 12:43:22 +00:00
|
|
|
|
net *p2p.Server
|
|
|
|
|
networkVersion uint64
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 09:05:43 +00:00
|
|
|
|
// NewNetAPI creates a new net API instance.
|
|
|
|
|
func NewNetAPI(net *p2p.Server, networkVersion uint64) *NetAPI {
|
|
|
|
|
return &NetAPI{net, networkVersion}
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Listening returns an indication if the node is listening for network connections.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *NetAPI) Listening() bool {
|
2015-12-16 03:26:23 +00:00
|
|
|
|
return true // always listening
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PeerCount returns the number of connected peers
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *NetAPI) PeerCount() hexutil.Uint {
|
2016-12-17 14:39:55 +00:00
|
|
|
|
return hexutil.Uint(s.net.PeerCount())
|
2015-12-16 03:26:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-23 12:43:22 +00:00
|
|
|
|
// Version returns the current ethereum protocol version.
|
2022-06-21 09:05:43 +00:00
|
|
|
|
func (s *NetAPI) Version() string {
|
2020-12-23 12:43:22 +00:00
|
|
|
|
return fmt.Sprintf("%d", s.networkVersion)
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 10:45:39 +00:00
|
|
|
|
// checkTxFee is an internal function used to check whether the fee of
|
|
|
|
|
// the given transaction is _reasonable_(under the cap).
|
|
|
|
|
func checkTxFee(gasPrice *big.Int, gas uint64, cap float64) error {
|
|
|
|
|
// Short circuit if there is no cap for transaction fee at all.
|
|
|
|
|
if cap == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
feeEth := new(big.Float).Quo(new(big.Float).SetInt(new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(gas))), new(big.Float).SetInt(big.NewInt(params.Ether)))
|
|
|
|
|
feeFloat, _ := feeEth.Float64()
|
|
|
|
|
if feeFloat > cap {
|
|
|
|
|
return fmt.Errorf("tx fee (%.2f ether) exceeds the configured cap (%.2f ether)", feeFloat, cap)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|