mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-24 04:27:16 +00:00
initial implementation of eth_GetBlockByNumber, for now I did copy much functions from eth source because we may need max flexibility for benchmarks of rpcdaemon
This commit is contained in:
parent
f7b6b524fe
commit
570d3b79d7
@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
@ -11,8 +12,11 @@ import (
|
||||
|
||||
"github.com/ledgerwatch/turbo-geth/common"
|
||||
"github.com/ledgerwatch/turbo-geth/common/dbutils"
|
||||
"github.com/ledgerwatch/turbo-geth/core/types"
|
||||
"github.com/ledgerwatch/turbo-geth/ethdb/remote"
|
||||
"github.com/ledgerwatch/turbo-geth/internal/ethapi"
|
||||
"github.com/ledgerwatch/turbo-geth/log"
|
||||
"github.com/ledgerwatch/turbo-geth/rlp"
|
||||
"github.com/ledgerwatch/turbo-geth/rpc"
|
||||
)
|
||||
|
||||
@ -29,6 +33,7 @@ func splitAndTrim(input string) []string {
|
||||
// EthAPI is a collection of functions that are exposed in the
|
||||
type EthAPI interface {
|
||||
BlockNumber(ctx context.Context) (uint64, error)
|
||||
GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// APIImpl is implementation of the EthAPI interface based on remote Db access
|
||||
@ -89,6 +94,138 @@ func (api *APIImpl) BlockNumber(ctx context.Context) (uint64, error) {
|
||||
return blockNumber, nil
|
||||
}
|
||||
|
||||
// GetBlockByNumber see https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbynumber
|
||||
// see internal/ethapi.PublicBlockChainAPI.GetBlockByNumber
|
||||
func (api *APIImpl) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
|
||||
if err := api.ensureConnected(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var block *types.Block
|
||||
|
||||
if err := api.db.View(func(tx *remote.Tx) error {
|
||||
block = GetBlockByNumber(tx, uint64(number.Int64()))
|
||||
return nil
|
||||
}); err != nil {
|
||||
api.db.Close()
|
||||
api.db = nil
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("Debug: %#v %#v %#v\n", block.Number(), block.Hash(), block.Size())
|
||||
|
||||
if block != nil {
|
||||
response, err := api.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"} {
|
||||
response[field] = nil
|
||||
}
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// rpcMarshalBlock reimplementation of ethapi.rpcMarshalBlock
|
||||
func (api *APIImpl) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
||||
fields, err := ethapi.RPCMarshalBlock(b, inclTx, fullTx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: implement .GetTd method and uncomment next line
|
||||
//fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(b.Hash()))
|
||||
return fields, err
|
||||
}
|
||||
|
||||
// ReadCanonicalHash reimplementation of rawdb.ReadCanonicalHash
|
||||
func ReadCanonicalHash(tx *remote.Tx, number uint64) common.Hash {
|
||||
bucket := tx.Bucket(dbutils.HeaderPrefix)
|
||||
if bucket == nil {
|
||||
return common.Hash{}
|
||||
//return fmt.Errorf("bucket %s not found", dbutils.HeaderPrefix)
|
||||
}
|
||||
|
||||
data := bucket.Get(dbutils.HeaderHashKey(number))
|
||||
if len(data) == 0 {
|
||||
return common.Hash{}
|
||||
}
|
||||
return common.BytesToHash(data)
|
||||
}
|
||||
|
||||
// GetBlockByNumber reimplementation of chain.GetBlockByNumber
|
||||
func GetBlockByNumber(tx *remote.Tx, number uint64) *types.Block {
|
||||
hash := ReadCanonicalHash(tx, number)
|
||||
if hash == (common.Hash{}) {
|
||||
return nil
|
||||
}
|
||||
return ReadBlock(tx, hash, number)
|
||||
}
|
||||
|
||||
// ReadBlock reimplementation of rawdb.ReadBlock
|
||||
func ReadBlock(tx *remote.Tx, hash common.Hash, number uint64) *types.Block {
|
||||
header := ReadHeader(tx, hash, number)
|
||||
if header == nil {
|
||||
return nil
|
||||
}
|
||||
body := ReadBody(tx, hash, number)
|
||||
if body == nil {
|
||||
return nil
|
||||
}
|
||||
return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
|
||||
}
|
||||
|
||||
// ReadBlock reimplementation of rawdb.ReadBlock
|
||||
func ReadHeaderRLP(tx *remote.Tx, hash common.Hash, number uint64) rlp.RawValue {
|
||||
bucket := tx.Bucket(dbutils.HeaderPrefix)
|
||||
if bucket == nil {
|
||||
//return fmt.Errorf("bucket %s not found", dbutils.HeaderPrefix)
|
||||
log.Error("Bucket not founc", "error", dbutils.HeaderPrefix)
|
||||
return rlp.RawValue{}
|
||||
}
|
||||
return bucket.Get(dbutils.HeaderKey(number, hash))
|
||||
}
|
||||
|
||||
// ReadHeader reimplementation of rawdb.ReadHeader
|
||||
func ReadHeader(tx *remote.Tx, hash common.Hash, number uint64) *types.Header {
|
||||
data := ReadHeaderRLP(tx, hash, number)
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
header := new(types.Header)
|
||||
if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
|
||||
log.Error("Invalid block header RLP", "hash", hash, "err", err)
|
||||
return nil
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
// ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
|
||||
func ReadBodyRLP(tx *remote.Tx, hash common.Hash, number uint64) rlp.RawValue {
|
||||
bucket := tx.Bucket(dbutils.BlockBodyPrefix)
|
||||
if bucket == nil {
|
||||
//return fmt.Errorf("bucket %s not found", dbutils.HeaderPrefix)
|
||||
log.Error("Bucket not founc", "error", dbutils.BlockBodyPrefix)
|
||||
return rlp.RawValue{}
|
||||
}
|
||||
return bucket.Get(dbutils.BlockBodyKey(number, hash))
|
||||
}
|
||||
|
||||
// ReadBody reimplementation of rawdb.ReadBody
|
||||
func ReadBody(tx *remote.Tx, hash common.Hash, number uint64) *types.Body {
|
||||
data := ReadBodyRLP(tx, hash, number)
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
body := new(types.Body)
|
||||
if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
|
||||
log.Error("Invalid block body RLP", "hash", hash, "err", err)
|
||||
return nil
|
||||
}
|
||||
// Post-processing
|
||||
body.SendersToTxs()
|
||||
return body
|
||||
}
|
||||
|
||||
func daemon(cfg Config) {
|
||||
vhosts := splitAndTrim(cfg.rpcVirtualHost)
|
||||
cors := splitAndTrim(cfg.rpcCORSDomain)
|
||||
|
18
cmd/rpcdaemon/test.http
Normal file
18
cmd/rpcdaemon/test.http
Normal file
@ -0,0 +1,18 @@
|
||||
###
|
||||
|
||||
# curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber", "params": ["0x1b4", true], "id":1}' localhost:8545
|
||||
POST localhost:8545
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_getBlockByNumber",
|
||||
"params": [
|
||||
"0x1b4",
|
||||
true
|
||||
],
|
||||
"id": 1
|
||||
}
|
||||
|
||||
###
|
||||
|
Loading…
Reference in New Issue
Block a user