erigon-pulse/cmd/devnet/requests/block.go
Mark Holt 529d359ca6
Bor span testing (#7897)
An update to the devnet to introduce a local heimdall to facilitate
multiple validators without the need for an external process, and hence
validator registration/staking etc.

In this initial release only span generation is supported.  

It has the following changes:

* Introduction of a local grpc heimdall interface
* Allocation of accounts via a devnet account generator ()
* Introduction on 'Services' for the network config

"--chain bor-devnet --bor.localheimdall" will run a 2 validator network
with a local service
"--chain bor-devnet --bor.withoutheimdall" will sun a single validator
with no heimdall service as before

---------

Co-authored-by: Alex Sharp <alexsharp@Alexs-MacBook-Pro-2.local>
2023-07-18 09:47:04 +01:00

164 lines
4.8 KiB
Go

package requests
import (
"bytes"
"fmt"
"math/big"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/common/hexutil"
"github.com/ledgerwatch/erigon/core/types"
)
type EthBlockNumber struct {
CommonResponse
Number hexutil.Uint64 `json:"result"`
}
type EthBlockByNumber struct {
CommonResponse
Result *EthBlockByNumberResult `json:"result"`
}
type EthBlockByNumberResult struct {
Difficulty hexutil.Big `json:"difficulty"`
Miner libcommon.Address `json:"miner"`
Transactions []EthTransaction `json:"transactions"`
TxRoot libcommon.Hash `json:"transactionsRoot"`
Hash libcommon.Hash `json:"hash"`
}
type EthGetTransactionCount struct {
CommonResponse
Result hexutil.Uint64 `json:"result"`
}
type EthSendRawTransaction struct {
CommonResponse
TxnHash libcommon.Hash `json:"result"`
}
func (reqGen *requestGenerator) BlockNumber() (uint64, error) {
var b EthBlockNumber
method, body := reqGen.blockNumber()
res := reqGen.call(method, body, &b)
number := uint64(b.Number)
if res.Err != nil {
return number, fmt.Errorf("error getting current block number: %v", res.Err)
}
return number, nil
}
func (req *requestGenerator) blockNumber() (RPCMethod, string) {
const template = `{"jsonrpc":"2.0","method":%q,"id":%d}`
return Methods.ETHBlockNumber, fmt.Sprintf(template, Methods.ETHBlockNumber, req.reqID)
}
func (reqGen *requestGenerator) GetBlockByNumber(blockNum uint64, withTxs bool) (EthBlockByNumber, error) {
var b EthBlockByNumber
method, body := reqGen.getBlockByNumber(blockNum, withTxs)
res := reqGen.call(method, body, &b)
if res.Err != nil {
return b, fmt.Errorf("error getting block by number: %v", res.Err)
}
if b.Error != nil {
return b, fmt.Errorf("error populating response object: %v", b.Error)
}
return b, nil
}
func (req *requestGenerator) getBlockByNumber(blockNum uint64, withTxs bool) (RPCMethod, string) {
const template = `{"jsonrpc":"2.0","method":%q,"params":["0x%x",%t],"id":%d}`
return Methods.ETHGetBlockByNumber, fmt.Sprintf(template, Methods.ETHGetBlockByNumber, blockNum, withTxs, req.reqID)
}
func (req *requestGenerator) getBlockByNumberI(blockNum string, withTxs bool) (RPCMethod, string) {
const template = `{"jsonrpc":"2.0","method":%q,"params":["%s",%t],"id":%d}`
return Methods.ETHGetBlockByNumber, fmt.Sprintf(template, Methods.ETHGetBlockByNumber, blockNum, withTxs, req.reqID)
}
func (reqGen *requestGenerator) GetBlockByNumberDetails(blockNum string, withTxs bool) (map[string]interface{}, error) {
var b struct {
CommonResponse
Result interface{} `json:"result"`
}
method, body := reqGen.getBlockByNumberI(blockNum, withTxs)
res := reqGen.call(method, body, &b)
if res.Err != nil {
return nil, fmt.Errorf("error getting block by number: %v", res.Err)
}
if b.Error != nil {
return nil, fmt.Errorf("error populating response object: %v", b.Error)
}
m, ok := b.Result.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("cannot convert type")
}
return m, nil
}
func (reqGen *requestGenerator) GetTransactionCount(address libcommon.Address, blockNum BlockNumber) (*big.Int, error) {
var b EthGetTransactionCount
method, body := reqGen.getTransactionCount(address, blockNum)
if res := reqGen.call(method, body, &b); res.Err != nil {
return nil, fmt.Errorf("error getting transaction count: %v", res.Err)
}
if b.Error != nil {
return nil, fmt.Errorf("error populating response object: %v", b.Error)
}
return big.NewInt(int64(b.Result)), nil
}
func (req *requestGenerator) getTransactionCount(address libcommon.Address, blockNum BlockNumber) (RPCMethod, string) {
const template = `{"jsonrpc":"2.0","method":%q,"params":["0x%x","%v"],"id":%d}`
return Methods.ETHGetTransactionCount, fmt.Sprintf(template, Methods.ETHGetTransactionCount, address, blockNum, req.reqID)
}
func (reqGen *requestGenerator) SendTransaction(signedTx types.Transaction) (*libcommon.Hash, error) {
var b EthSendRawTransaction
var buf bytes.Buffer
if err := signedTx.MarshalBinary(&buf); err != nil {
return nil, fmt.Errorf("failed to marshal binary: %v", err)
}
method, body := reqGen.sendRawTransaction(buf.Bytes())
if res := reqGen.call(method, body, &b); res.Err != nil {
return nil, fmt.Errorf("could not make to request to eth_sendRawTransaction: %v", res.Err)
}
zeroHash := true
for _, hb := range b.TxnHash {
if hb != 0 {
zeroHash = false
break
}
}
if zeroHash {
return nil, fmt.Errorf("Request: %d, hash: %s, nonce %d: returned a zero transaction hash", b.RequestId, signedTx.Hash().Hex(), signedTx.GetNonce())
}
return &b.TxnHash, nil
}
func (req *requestGenerator) sendRawTransaction(signedTx []byte) (RPCMethod, string) {
const template = `{"jsonrpc":"2.0","method":%q,"params":["0x%x"],"id":%d}`
return Methods.ETHSendRawTransaction, fmt.Sprintf(template, Methods.ETHSendRawTransaction, signedTx, req.reqID)
}