From 726e4607f8914f930cf8ddb433ba5ba514ce2bc2 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Wed, 5 Jun 2019 13:37:30 +0800 Subject: [PATCH] eth, interal, les: add getHeaderBy* APIs --- eth/api_backend.go | 4 ++++ internal/ethapi/api.go | 48 +++++++++++++++++++++++++++++++------- internal/ethapi/backend.go | 1 + les/api_backend.go | 4 ++++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/eth/api_backend.go b/eth/api_backend.go index ee5b51cf5a..233377c818 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -107,6 +107,10 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc. return stateDb, header, err } +func (b *EthAPIBackend) GetHeader(ctx context.Context, blockHash common.Hash) *types.Header { + return b.eth.blockchain.GetHeaderByHash(blockHash) +} + func (b *EthAPIBackend) GetBlock(ctx context.Context, hash common.Hash) (*types.Block, error) { return b.eth.blockchain.GetBlockByHash(hash), nil } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 04df794ec9..127a777e71 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -616,6 +616,33 @@ func (s *PublicBlockChainAPI) GetProof(ctx context.Context, address common.Addre }, state.Error() } +// GetHeaderByNumber returns the requested canonical block header. +// * When blockNr is -1 the chain head is returned. +// * When blockNr is -2 the pending chain head is returned. +func (s *PublicBlockChainAPI) GetHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (map[string]interface{}, error) { + header, err := s.b.HeaderByNumber(ctx, blockNr) + if header != nil && err == nil { + response := rpcMarshalHeader(header) + if blockNr == rpc.PendingBlockNumber { + // Pending blocks 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 (s *PublicBlockChainAPI) GetHeaderByHash(ctx context.Context, blockHash common.Hash) map[string]interface{} { + header := s.b.GetHeader(ctx, blockHash) + 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 *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { @@ -933,14 +960,11 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes { return formatted } -// 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) { - head := b.Header() // copies the header once - fields := map[string]interface{}{ +// rpcMarshalHeader converts the given header to the RPC output . +func rpcMarshalHeader(head *types.Header) map[string]interface{} { + ret := map[string]interface{}{ "number": (*hexutil.Big)(head.Number), - "hash": b.Hash(), + "hash": head.Hash(), "parentHash": head.ParentHash, "nonce": head.Nonce, "mixHash": head.MixDigest, @@ -950,13 +974,21 @@ func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]inter "miner": head.Coinbase, "difficulty": (*hexutil.Big)(head.Difficulty), "extraData": hexutil.Bytes(head.Extra), - "size": hexutil.Uint64(b.Size()), + "size": hexutil.Uint64(head.Size()), "gasLimit": hexutil.Uint64(head.GasLimit), "gasUsed": hexutil.Uint64(head.GasUsed), "timestamp": hexutil.Uint64(head.Time), "transactionsRoot": head.TxHash, "receiptsRoot": head.ReceiptHash, } + return ret +} + +// 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()) if inclTx { formatTx := func(tx *types.Transaction) (interface{}, error) { diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 28ec698972..b19a1b538a 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -54,6 +54,7 @@ type Backend interface { HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) + GetHeader(ctx context.Context, blockHash common.Hash) *types.Header GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) GetTd(blockHash common.Hash) *big.Int diff --git a/les/api_backend.go b/les/api_backend.go index 6de15e7bd2..fb0475ff21 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -88,6 +88,10 @@ func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc. return light.NewState(ctx, header, b.eth.odr), header, nil } +func (b *LesApiBackend) GetHeader(ctx context.Context, blockHash common.Hash) *types.Header { + return b.eth.blockchain.GetHeaderByHash(blockHash) +} + func (b *LesApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) { return b.eth.blockchain.GetBlockByHash(ctx, blockHash) }