mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 02:40:45 +00:00
internal/ethapi: support block number or hash on state-related methods (#19491)
* Support for EIP-1898.
This commit is contained in:
parent
2fcd6f47bb
commit
4616d59935
7 changed files with 202 additions and 20 deletions
|
|
@ -2459,6 +2459,11 @@ func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
|
||||||
return bc.hc.HasHeader(hash, number)
|
return bc.hc.HasHeader(hash, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCanonicalHash returns the canonical hash for a given block number
|
||||||
|
func (bc *BlockChain) GetCanonicalHash(number uint64) common.Hash {
|
||||||
|
return bc.hc.GetCanonicalHash(number)
|
||||||
|
}
|
||||||
|
|
||||||
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
|
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
|
||||||
// hash, fetching towards the genesis block.
|
// hash, fetching towards the genesis block.
|
||||||
func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
|
func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
"github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -382,6 +382,11 @@ func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
|
||||||
return hc.GetHeader(hash, number)
|
return hc.GetHeader(hash, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hc *HeaderChain) GetCanonicalHash(number uint64) common.Hash {
|
||||||
|
// TODO: return rawdb.ReadCanonicalHash(hc.chainDb, number)
|
||||||
|
return GetCanonicalHash(hc.chainDb, number)
|
||||||
|
}
|
||||||
|
|
||||||
// CurrentHeader retrieves the current head header of the canonical chain. The
|
// CurrentHeader retrieves the current head header of the canonical chain. The
|
||||||
// header is retrieved from the HeaderChain's internal cache.
|
// header is retrieved from the HeaderChain's internal cache.
|
||||||
func (hc *HeaderChain) CurrentHeader() *types.Header {
|
func (hc *HeaderChain) CurrentHeader() *types.Header {
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,27 @@ func (b *EthApiBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNum
|
||||||
return b.eth.blockchain.GetHeaderByNumber(uint64(blockNr)), nil
|
return b.eth.blockchain.GetHeaderByNumber(uint64(blockNr)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *EthApiBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
|
||||||
|
if blockNr, ok := blockNrOrHash.Number(); ok {
|
||||||
|
return b.HeaderByNumber(ctx, blockNr)
|
||||||
|
}
|
||||||
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
|
header := b.eth.blockchain.GetHeaderByHash(hash)
|
||||||
|
if header == nil {
|
||||||
|
return nil, errors.New("header for hash not found")
|
||||||
|
}
|
||||||
|
if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
|
||||||
|
return nil, errors.New("hash is not currently canonical")
|
||||||
|
}
|
||||||
|
return header, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid arguments; neither block nor hash specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *EthApiBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
||||||
|
return b.eth.blockchain.GetHeaderByHash(hash), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *EthApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
|
func (b *EthApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
|
||||||
// Pending block is only known by the miner
|
// Pending block is only known by the miner
|
||||||
if blockNr == rpc.PendingBlockNumber {
|
if blockNr == rpc.PendingBlockNumber {
|
||||||
|
|
@ -130,6 +151,31 @@ func (b *EthApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumb
|
||||||
return b.eth.blockchain.GetBlockByNumber(uint64(blockNr)), nil
|
return b.eth.blockchain.GetBlockByNumber(uint64(blockNr)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *EthApiBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
|
||||||
|
return b.eth.blockchain.GetBlockByHash(hash), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *EthApiBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
|
||||||
|
if blockNr, ok := blockNrOrHash.Number(); ok {
|
||||||
|
return b.BlockByNumber(ctx, blockNr)
|
||||||
|
}
|
||||||
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
|
header := b.eth.blockchain.GetHeaderByHash(hash)
|
||||||
|
if header == nil {
|
||||||
|
return nil, errors.New("header for hash not found")
|
||||||
|
}
|
||||||
|
if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
|
||||||
|
return nil, errors.New("hash is not currently canonical")
|
||||||
|
}
|
||||||
|
block := b.eth.blockchain.GetBlock(hash, header.Number.Uint64())
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("header found, but block body is missing")
|
||||||
|
}
|
||||||
|
return block, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid arguments; neither block nor hash specified")
|
||||||
|
}
|
||||||
|
|
||||||
func (b *EthApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
|
func (b *EthApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
|
||||||
// Pending state is only known by the miner
|
// Pending state is only known by the miner
|
||||||
if blockNr == rpc.PendingBlockNumber {
|
if blockNr == rpc.PendingBlockNumber {
|
||||||
|
|
@ -144,6 +190,30 @@ func (b *EthApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.
|
||||||
return stateDb, header, err
|
return stateDb, header, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *EthApiBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
|
||||||
|
if blockNr, ok := blockNrOrHash.Number(); ok {
|
||||||
|
return b.StateAndHeaderByNumber(ctx, blockNr)
|
||||||
|
}
|
||||||
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
|
header, err := b.HeaderByHash(ctx, hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if header == nil {
|
||||||
|
return nil, nil, errors.New("header for hash not found")
|
||||||
|
}
|
||||||
|
if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
|
||||||
|
return nil, nil, errors.New("hash is not currently canonical")
|
||||||
|
}
|
||||||
|
stateDb, err := b.eth.BlockChain().StateAt(header.Root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return stateDb, header, nil
|
||||||
|
}
|
||||||
|
return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
|
||||||
|
}
|
||||||
|
|
||||||
func (b *EthApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) {
|
func (b *EthApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) {
|
||||||
return b.eth.blockchain.GetBlockByHash(blockHash), nil
|
return b.eth.blockchain.GetBlockByHash(blockHash), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -525,8 +525,8 @@ func (s *PublicBlockChainAPI) GetRewardByHash(hash common.Hash) map[string]map[s
|
||||||
// GetBalance returns the amount of wei for the given address in the state of the
|
// 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
|
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
|
||||||
// block numbers are also allowed.
|
// block numbers are also allowed.
|
||||||
func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Big, error) {
|
func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) {
|
||||||
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
if state == nil || err != nil {
|
if state == nil || err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -614,8 +614,8 @@ func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, bloc
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCode returns the code stored at the given address in the state for the given block number.
|
// GetCode returns the code stored at the given address in the state for the given block number.
|
||||||
func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
|
func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
||||||
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
if state == nil || err != nil {
|
if state == nil || err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -624,8 +624,8 @@ func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Addres
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccountInfo returns the information at the given address in the state for the given block number.
|
// GetAccountInfo returns the information at the given address in the state for the given block number.
|
||||||
func (s *PublicBlockChainAPI) GetAccountInfo(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (map[string]interface{}, error) {
|
func (s *PublicBlockChainAPI) GetAccountInfo(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (map[string]interface{}, error) {
|
||||||
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
if state == nil || err != nil {
|
if state == nil || err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -644,8 +644,8 @@ func (s *PublicBlockChainAPI) GetAccountInfo(ctx context.Context, address common
|
||||||
// GetStorageAt returns the storage from the state at the given address, key and
|
// GetStorageAt returns the storage from the state at the given address, key and
|
||||||
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
|
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
|
||||||
// numbers are also allowed.
|
// numbers are also allowed.
|
||||||
func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
|
func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
||||||
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
if state == nil || err != nil {
|
if state == nil || err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1113,10 +1113,10 @@ type CallArgs struct {
|
||||||
Data hexutil.Bytes `json:"data"`
|
Data hexutil.Bytes `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error, error) {
|
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error, error) {
|
||||||
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
|
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
|
||||||
|
|
||||||
statedb, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
statedb, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
if statedb == nil || err != nil {
|
if statedb == nil || err != nil {
|
||||||
return nil, 0, false, err, nil
|
return nil, 0, false, err, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1154,7 +1154,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
|
||||||
// this makes sure resources are cleaned up.
|
// this makes sure resources are cleaned up.
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
block, err := s.b.BlockByNumber(ctx, blockNr)
|
block, err := s.b.BlockByNumberOrHash(ctx, blockNrOrHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, false, err, nil
|
return nil, 0, false, err, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1229,8 +1229,12 @@ func (e *revertError) ErrorData() interface{} {
|
||||||
|
|
||||||
// Call executes the given transaction on the state for the given block number.
|
// Call executes the given transaction on the state for the given block number.
|
||||||
// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
|
// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
|
||||||
func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
|
func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
|
||||||
result, _, failed, err, vmErr := s.doCall(ctx, args, blockNr, vm.Config{}, 5*time.Second)
|
if blockNrOrHash == nil {
|
||||||
|
latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
||||||
|
blockNrOrHash = &latest
|
||||||
|
}
|
||||||
|
result, _, failed, err, vmErr := s.doCall(ctx, args, *blockNrOrHash, vm.Config{}, 5*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1242,9 +1246,13 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr r
|
||||||
return (hexutil.Bytes)(result), vmErr
|
return (hexutil.Bytes)(result), vmErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// EstimateGas returns an estimate of the amount of gas needed to execute the
|
func (s *PublicBlockChainAPI) doEstimateGas(ctx context.Context, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Uint64, error) {
|
||||||
// given transaction against the current pending block.
|
// Retrieve the base state and mutate it with any overrides
|
||||||
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) {
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
|
if state == nil || err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
// Binary search the gas requirement, as it may be higher than the amount used
|
// Binary search the gas requirement, as it may be higher than the amount used
|
||||||
var (
|
var (
|
||||||
lo uint64 = params.TxGas - 1
|
lo uint64 = params.TxGas - 1
|
||||||
|
|
@ -1267,7 +1275,7 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs, bl
|
||||||
executable := func(gas uint64) (bool, []byte, error, error) {
|
executable := func(gas uint64) (bool, []byte, error, error) {
|
||||||
args.Gas = hexutil.Uint64(gas)
|
args.Gas = hexutil.Uint64(gas)
|
||||||
|
|
||||||
res, _, failed, err, vmErr := s.doCall(ctx, args, rpc.LatestBlockNumber, vm.Config{}, 0)
|
res, _, failed, err, vmErr := s.doCall(ctx, args, blockNrOrHash, vm.Config{}, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, vm.ErrOutOfGas) || errors.Is(err, core.ErrIntrinsicGas) {
|
if errors.Is(err, vm.ErrOutOfGas) || errors.Is(err, core.ErrIntrinsicGas) {
|
||||||
return false, nil, nil, nil // Special case, raise gas limit
|
return false, nil, nil, nil // Special case, raise gas limit
|
||||||
|
|
@ -1340,6 +1348,16 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs, bl
|
||||||
return hexutil.Uint64(hi), nil
|
return hexutil.Uint64(hi), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EstimateGas returns an estimate of the amount of gas needed to execute the
|
||||||
|
// given transaction against the current pending block.
|
||||||
|
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) {
|
||||||
|
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
||||||
|
if blockNrOrHash != nil {
|
||||||
|
bNrOrHash = *blockNrOrHash
|
||||||
|
}
|
||||||
|
return s.doEstimateGas(ctx, args, bNrOrHash)
|
||||||
|
}
|
||||||
|
|
||||||
// ExecutionResult groups all structured logs emitted by the EVM
|
// ExecutionResult groups all structured logs emitted by the EVM
|
||||||
// while replaying a transaction in debug mode as well as transaction
|
// while replaying a transaction in debug mode as well as transaction
|
||||||
// execution status, the amount of gas used and the return value
|
// execution status, the amount of gas used and the return value
|
||||||
|
|
@ -1765,8 +1783,17 @@ func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx cont
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransactionCount returns the number of transactions the given address has sent for the given block number
|
// GetTransactionCount returns the number of transactions the given address has sent for the given block number
|
||||||
func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) {
|
func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) {
|
||||||
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
// Ask transaction pool for the nonce which includes pending transactions
|
||||||
|
if blockNr, ok := blockNrOrHash.Number(); ok && blockNr == rpc.PendingBlockNumber {
|
||||||
|
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
|
||||||
|
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
if state == nil || err != nil {
|
if state == nil || err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,13 @@ type Backend interface {
|
||||||
// BlockChain API
|
// BlockChain API
|
||||||
SetHead(number uint64)
|
SetHead(number uint64)
|
||||||
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
|
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
|
||||||
|
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
|
||||||
|
HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error)
|
||||||
BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error)
|
BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error)
|
||||||
|
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
|
||||||
|
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
|
||||||
StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error)
|
StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error)
|
||||||
|
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
|
||||||
GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error)
|
GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error)
|
||||||
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
|
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
|
||||||
GetTd(blockHash common.Hash) *big.Int
|
GetTd(blockHash common.Hash) *big.Int
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,30 @@ func (b *LesApiBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNum
|
||||||
return b.eth.blockchain.GetHeaderByNumberOdr(ctx, uint64(blockNr))
|
return b.eth.blockchain.GetHeaderByNumberOdr(ctx, uint64(blockNr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
|
||||||
|
if blockNr, ok := blockNrOrHash.Number(); ok {
|
||||||
|
return b.HeaderByNumber(ctx, blockNr)
|
||||||
|
}
|
||||||
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
|
header, err := b.HeaderByHash(ctx, hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if header == nil {
|
||||||
|
return nil, errors.New("header for hash not found")
|
||||||
|
}
|
||||||
|
if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
|
||||||
|
return nil, errors.New("hash is not currently canonical")
|
||||||
|
}
|
||||||
|
return header, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid arguments; neither block nor hash specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
|
||||||
|
return b.eth.blockchain.GetHeaderByHash(hash), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
|
func (b *LesApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
|
||||||
header, err := b.HeaderByNumber(ctx, blockNr)
|
header, err := b.HeaderByNumber(ctx, blockNr)
|
||||||
if header == nil || err != nil {
|
if header == nil || err != nil {
|
||||||
|
|
@ -82,6 +106,30 @@ func (b *LesApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumb
|
||||||
return b.GetBlock(ctx, header.Hash())
|
return b.GetBlock(ctx, header.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
|
||||||
|
return b.eth.blockchain.GetBlockByHash(ctx, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
|
||||||
|
if blockNr, ok := blockNrOrHash.Number(); ok {
|
||||||
|
return b.BlockByNumber(ctx, blockNr)
|
||||||
|
}
|
||||||
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
|
block, err := b.BlockByHash(ctx, hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("header found, but block body is missing")
|
||||||
|
}
|
||||||
|
if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(block.NumberU64()) != hash {
|
||||||
|
return nil, errors.New("hash is not currently canonical")
|
||||||
|
}
|
||||||
|
return block, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid arguments; neither block nor hash specified")
|
||||||
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
|
func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
|
||||||
header, err := b.HeaderByNumber(ctx, blockNr)
|
header, err := b.HeaderByNumber(ctx, blockNr)
|
||||||
if header == nil || err != nil {
|
if header == nil || err != nil {
|
||||||
|
|
@ -90,6 +138,23 @@ func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.
|
||||||
return light.NewState(ctx, header, b.eth.odr), header, nil
|
return light.NewState(ctx, header, b.eth.odr), header, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
|
||||||
|
if blockNr, ok := blockNrOrHash.Number(); ok {
|
||||||
|
return b.StateAndHeaderByNumber(ctx, blockNr)
|
||||||
|
}
|
||||||
|
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||||
|
header := b.eth.blockchain.GetHeaderByHash(hash)
|
||||||
|
if header == nil {
|
||||||
|
return nil, nil, errors.New("header for hash not found")
|
||||||
|
}
|
||||||
|
if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
|
||||||
|
return nil, nil, errors.New("hash is not currently canonical")
|
||||||
|
}
|
||||||
|
return light.NewState(ctx, header, b.eth.odr), header, nil
|
||||||
|
}
|
||||||
|
return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
|
||||||
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) {
|
func (b *LesApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) {
|
||||||
return b.eth.blockchain.GetBlockByHash(ctx, blockHash)
|
return b.eth.blockchain.GetBlockByHash(ctx, blockHash)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -420,6 +420,11 @@ func (bc *LightChain) HasHeader(hash common.Hash, number uint64) bool {
|
||||||
return bc.hc.HasHeader(hash, number)
|
return bc.hc.HasHeader(hash, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCanonicalHash returns the canonical hash for a given block number
|
||||||
|
func (bc *LightChain) GetCanonicalHash(number uint64) common.Hash {
|
||||||
|
return bc.hc.GetCanonicalHash(number)
|
||||||
|
}
|
||||||
|
|
||||||
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
|
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
|
||||||
// hash, fetching towards the genesis block.
|
// hash, fetching towards the genesis block.
|
||||||
func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
|
func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue