Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 22 additions & 18 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,16 @@ func (b *EthAPIBackend) SetHead(number uint64) {
b.eth.blockchain.SetHead(number)
}

func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
// Pending block is only known by the miner
if blockNr == rpc.PendingBlockNumber {
blockNr = rpc.LatestBlockNumber
if number == rpc.PendingBlockNumber {
number = rpc.LatestBlockNumber
}
// Otherwise resolve and return the block
if blockNr == rpc.LatestBlockNumber {
if number == rpc.LatestBlockNumber {
return b.eth.blockchain.CurrentBlock().Header(), nil
}
if blockNr == rpc.CommittedBlockNumber {
if number == rpc.CommittedBlockNumber {
if b.eth.chainConfig.XDPoS == nil {
return nil, errors.New("PoW does not support confirmed block lookup")
}
Expand All @@ -102,7 +102,7 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNum
return nil, errors.New("PoS V1 does not support confirmed block lookup")
}
}
header := b.eth.blockchain.GetHeaderByNumber(uint64(blockNr))
header := b.eth.blockchain.GetHeaderByNumber(uint64(number))
if header == nil {
return nil, errors.New("header for number not found")
}
Expand Down Expand Up @@ -130,16 +130,16 @@ func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*ty
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, number rpc.BlockNumber) (*types.Block, error) {
// Pending block is only known by the miner
if blockNr == rpc.PendingBlockNumber {
blockNr = rpc.LatestBlockNumber
if number == rpc.PendingBlockNumber {
number = rpc.LatestBlockNumber
}
// Otherwise resolve and return the block
if blockNr == rpc.LatestBlockNumber {
if number == rpc.LatestBlockNumber {
return b.eth.blockchain.CurrentBlock(), nil
}
if blockNr == rpc.CommittedBlockNumber {
if number == rpc.CommittedBlockNumber {
if b.eth.chainConfig.XDPoS == nil {
return nil, errors.New("PoW does not support confirmed block lookup")
}
Expand All @@ -156,7 +156,7 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumb
return nil, errors.New("PoS V1 does not support confirmed block lookup")
}
}
return b.eth.blockchain.GetBlockByNumber(uint64(blockNr)), nil
return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil
}

func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
Expand Down Expand Up @@ -199,13 +199,13 @@ func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts)
return b.eth.miner.PendingBlockAndReceipts()
}

func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
// Pending state is only known by the miner
if blockNr == rpc.PendingBlockNumber {
blockNr = rpc.LatestBlockNumber
if number == rpc.PendingBlockNumber {
number = rpc.LatestBlockNumber
}
// Otherwise resolve the block number and return its state
header, err := b.HeaderByNumber(ctx, blockNr)
header, err := b.HeaderByNumber(ctx, number)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -243,8 +243,12 @@ func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockN
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) {
return b.eth.blockchain.GetBlockByHash(blockHash), nil
func (b *EthAPIBackend) GetHeader(ctx context.Context, hash common.Hash) *types.Header {
return b.eth.blockchain.GetHeaderByHash(hash)
}

func (b *EthAPIBackend) GetBlock(ctx context.Context, hash common.Hash) (*types.Block, error) {
return b.eth.blockchain.GetBlockByHash(hash), nil
}

func (b *EthAPIBackend) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) {
Expand Down
71 changes: 50 additions & 21 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,15 +377,44 @@ func (s *BlockChainAPI) GetTransactionAndReceiptProof(ctx context.Context, hash
return fields, nil
}

// GetHeaderByNumber returns the requested canonical block header.
// - 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.
func (api *BlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (map[string]interface{}, error) {
header, err := api.b.HeaderByNumber(ctx, number)
if header != nil && err == nil {
response := RPCMarshalHeader(header)
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.
func (api *BlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} {
header, _ := api.b.HeaderByHash(ctx, hash)
if header != nil {
return RPCMarshalHeader(header)
}
return nil
}

// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, blockNr)
func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, number)
if block != nil {
response, err := s.rpcOutputBlock(block, true, fullTx)
if err == nil && blockNr == rpc.PendingBlockNumber {
response, err := s.rpcMarshalBlock(block, true, fullTx)
if err == nil && number == rpc.PendingBlockNumber {
// Pending blocks need to nil out a few fields
for _, field := range []string{"hash", "nonce", "miner"} {
for _, field := range []string{"hash", "nonce", "miner", "number"} {
response[field] = nil
}
}
Expand All @@ -396,10 +425,10 @@ func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockN

// 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.
func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.GetBlock(ctx, blockHash)
func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.GetBlock(ctx, hash)
if block != nil {
return s.rpcOutputBlock(block, true, fullTx)
return s.rpcMarshalBlock(block, true, fullTx)
}
return nil, err
}
Expand All @@ -415,7 +444,7 @@ func (s *BlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, block
return nil, nil
}
block = types.NewBlockWithHeader(uncles[index])
return s.rpcOutputBlock(block, false, false)
return s.rpcMarshalBlock(block, false, false)
}
return nil, err
}
Expand All @@ -432,7 +461,7 @@ func (s *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHa
return nil, nil
}
block = types.NewBlockWithHeader(uncles[index])
return s.rpcOutputBlock(block, false, false)
return s.rpcMarshalBlock(block, false, false)
}
return nil, err
}
Expand Down Expand Up @@ -1414,20 +1443,20 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
// 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.
func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
fields := RPCMarshalHeader(b.Header())
fields["size"] = hexutil.Uint64(b.Size())
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
fields := RPCMarshalHeader(block.Header())
fields["size"] = hexutil.Uint64(block.Size())

if inclTx {
formatTx := func(tx *types.Transaction) (interface{}, error) {
return tx.Hash(), nil
}
if fullTx {
formatTx = func(tx *types.Transaction) (interface{}, error) {
return newRPCTransactionFromBlockHash(b, tx.Hash()), nil
return newRPCTransactionFromBlockHash(block, tx.Hash()), nil
}
}
txs := b.Transactions()
txs := block.Transactions()
transactions := make([]interface{}, len(txs))
var err error
for i, tx := range txs {
Expand All @@ -1437,25 +1466,25 @@ func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]inter
}
fields["transactions"] = transactions
}

uncles := b.Uncles()
uncles := block.Uncles()
uncleHashes := make([]common.Hash, len(uncles))
for i, uncle := range uncles {
uncleHashes[i] = uncle.Hash()
}
fields["uncles"] = uncleHashes

return fields, nil
}

// rpcOutputBlock uses the generalized output filler, then adds the total difficulty field, which requires
// rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires
// a `BlockChainAPI`.
func (s *BlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
func (s *BlockChainAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
fields, err := RPCMarshalBlock(b, inclTx, fullTx)
if err != nil {
return nil, err
}
fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(context.Background(), b.Hash()))
if inclTx {
fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(context.Background(), b.Hash()))
}
return fields, err
}

Expand Down
12 changes: 6 additions & 6 deletions internal/ethapi/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,19 @@ type Backend interface {

// BlockChain API
SetHead(number uint64)
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
HeaderByNumber(ctx context.Context, number 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)
CurrentHeader() *types.Header
BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error)
BlockByNumber(ctx context.Context, number 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, number 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, hash common.Hash) (*types.Block, error)
PendingBlockAndReceipts() (*types.Block, types.Receipts)
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
GetTd(ctx context.Context, blockHash common.Hash) *big.Int
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
GetTd(ctx context.Context, hash common.Hash) *big.Int
GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error, error)
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
Expand Down
23 changes: 23 additions & 0 deletions internal/web3ext/web3ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,29 @@ web3._extend({
params: 1,
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
}),
new web3._extend.Method({
name: 'getHeaderByNumber',
call: 'eth_getHeaderByNumber',
params: 1,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
}),
new web3._extend.Method({
name: 'getHeaderByHash',
call: 'eth_getHeaderByHash',
params: 1
}),
new web3._extend.Method({
name: 'getBlockByNumber',
call: 'eth_getBlockByNumber',
params: 2,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter, function (val) { return !!val; }]
}),
new web3._extend.Method({
name: 'getBlockByHash',
call: 'eth_getBlockByHash',
params: 2,
inputFormatter: [null, function (val) { return !!val; }]
}),
new web3._extend.Method({
name: 'getRawTransaction',
call: 'eth_getRawTransactionByHash',
Expand Down