mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-03 17:44:29 +00:00
321 lines
9.1 KiB
Go
321 lines
9.1 KiB
Go
package eth1_chain_reader
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/big"
|
|
"time"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/chain"
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
|
"github.com/ledgerwatch/erigon-lib/gointerfaces"
|
|
"github.com/ledgerwatch/erigon-lib/gointerfaces/execution"
|
|
types2 "github.com/ledgerwatch/erigon-lib/gointerfaces/types"
|
|
"github.com/ledgerwatch/erigon/core/types"
|
|
"github.com/ledgerwatch/erigon/turbo/execution/eth1/eth1_utils"
|
|
"github.com/ledgerwatch/log/v3"
|
|
"google.golang.org/protobuf/types/known/emptypb"
|
|
)
|
|
|
|
type ChainReaderWriterEth1 struct {
|
|
ctx context.Context
|
|
cfg *chain.Config
|
|
executionModule execution.ExecutionClient
|
|
|
|
fcuTimoutMillis uint64
|
|
}
|
|
|
|
func NewChainReaderEth1(ctx context.Context, cfg *chain.Config, executionModule execution.ExecutionClient, fcuTimoutMillis uint64) ChainReaderWriterEth1 {
|
|
return ChainReaderWriterEth1{
|
|
ctx: ctx,
|
|
cfg: cfg,
|
|
executionModule: executionModule,
|
|
fcuTimoutMillis: fcuTimoutMillis,
|
|
}
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) Config() *chain.Config {
|
|
return c.cfg
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) CurrentHeader() *types.Header {
|
|
resp, err := c.executionModule.CurrentHeader(c.ctx, &emptypb.Empty{})
|
|
if err != nil {
|
|
log.Error("GetHeader failed", "err", err)
|
|
return nil
|
|
}
|
|
if resp == nil || resp.Header == nil {
|
|
return nil
|
|
}
|
|
ret, err := eth1_utils.HeaderRpcToHeader(resp.Header)
|
|
if err != nil {
|
|
log.Error("GetHeader decoding", "err", err)
|
|
return nil
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) GetHeader(hash libcommon.Hash, number uint64) *types.Header {
|
|
resp, err := c.executionModule.GetHeader(c.ctx, &execution.GetSegmentRequest{
|
|
BlockNumber: &number,
|
|
BlockHash: gointerfaces.ConvertHashToH256(hash),
|
|
})
|
|
if err != nil {
|
|
log.Error("GetHeader failed", "err", err)
|
|
return nil
|
|
}
|
|
if resp == nil || resp.Header == nil {
|
|
return nil
|
|
}
|
|
ret, err := eth1_utils.HeaderRpcToHeader(resp.Header)
|
|
if err != nil {
|
|
log.Error("GetHeader decoding", "err", err)
|
|
return nil
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) GetBlockByHash(hash libcommon.Hash) *types.Block {
|
|
header := c.GetHeaderByHash(hash)
|
|
if header == nil {
|
|
return nil
|
|
}
|
|
|
|
number := header.Number.Uint64()
|
|
resp, err := c.executionModule.GetBody(c.ctx, &execution.GetSegmentRequest{
|
|
BlockNumber: &number,
|
|
BlockHash: gointerfaces.ConvertHashToH256(hash),
|
|
})
|
|
if err != nil {
|
|
log.Error("GetBlockByHash failed", "err", err)
|
|
return nil
|
|
}
|
|
if resp == nil || resp.Body == nil {
|
|
return nil
|
|
}
|
|
body := eth1_utils.ConvertRawBlockBodyFromRpc(resp.Body)
|
|
txs, err := types.DecodeTransactions(body.Transactions)
|
|
if err != nil {
|
|
log.Error("GetBlockByHash failed", "err", err)
|
|
return nil
|
|
}
|
|
return types.NewBlock(header, txs, nil, nil, body.Withdrawals)
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) GetBlockByNumber(number uint64) *types.Block {
|
|
header := c.GetHeaderByNumber(number)
|
|
if header == nil {
|
|
return nil
|
|
}
|
|
|
|
resp, err := c.executionModule.GetBody(c.ctx, &execution.GetSegmentRequest{
|
|
BlockNumber: &number,
|
|
})
|
|
if err != nil {
|
|
log.Error("GetBlockByNumber failed", "err", err)
|
|
return nil
|
|
}
|
|
if resp == nil || resp.Body == nil {
|
|
return nil
|
|
}
|
|
body := eth1_utils.ConvertRawBlockBodyFromRpc(resp.Body)
|
|
txs, err := types.DecodeTransactions(body.Transactions)
|
|
if err != nil {
|
|
log.Error("GetBlockByNumber failed", "err", err)
|
|
return nil
|
|
}
|
|
return types.NewBlock(header, txs, nil, nil, body.Withdrawals)
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) GetHeaderByHash(hash libcommon.Hash) *types.Header {
|
|
resp, err := c.executionModule.GetHeader(c.ctx, &execution.GetSegmentRequest{
|
|
BlockNumber: nil,
|
|
BlockHash: gointerfaces.ConvertHashToH256(hash),
|
|
})
|
|
if err != nil {
|
|
log.Error("GetHeaderByHash failed", "err", err)
|
|
return nil
|
|
}
|
|
if resp == nil || resp.Header == nil {
|
|
return nil
|
|
}
|
|
ret, err := eth1_utils.HeaderRpcToHeader(resp.Header)
|
|
if err != nil {
|
|
log.Error("GetHeaderByHash decoding", "err", err)
|
|
return nil
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) GetHeaderByNumber(number uint64) *types.Header {
|
|
resp, err := c.executionModule.GetHeader(c.ctx, &execution.GetSegmentRequest{
|
|
BlockNumber: &number,
|
|
BlockHash: nil,
|
|
})
|
|
if err != nil {
|
|
log.Error("GetHeaderByHash failed", "err", err)
|
|
return nil
|
|
}
|
|
if resp == nil || resp.Header == nil {
|
|
return nil
|
|
}
|
|
ret, err := eth1_utils.HeaderRpcToHeader(resp.Header)
|
|
if err != nil {
|
|
log.Error("GetHeaderByHash decoding", "err", err)
|
|
return nil
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) GetTd(hash libcommon.Hash, number uint64) *big.Int {
|
|
resp, err := c.executionModule.GetTD(c.ctx, &execution.GetSegmentRequest{
|
|
BlockNumber: &number,
|
|
BlockHash: gointerfaces.ConvertHashToH256(hash),
|
|
})
|
|
if err != nil {
|
|
log.Error("GetHeaderByHash failed", "err", err)
|
|
return nil
|
|
}
|
|
if resp == nil || resp.Td == nil {
|
|
return nil
|
|
}
|
|
return eth1_utils.ConvertBigIntFromRpc(resp.Td)
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) GetBodiesByHases(hashes []libcommon.Hash) []*types.RawBody {
|
|
grpcHashes := make([]*types2.H256, len(hashes))
|
|
for i := range grpcHashes {
|
|
grpcHashes[i] = gointerfaces.ConvertHashToH256(hashes[i])
|
|
}
|
|
resp, err := c.executionModule.GetBodiesByHashes(c.ctx, &execution.GetBodiesByHashesRequest{
|
|
Hashes: grpcHashes,
|
|
})
|
|
if err != nil {
|
|
log.Error("GetBodiesByHases failed", "err", err)
|
|
return nil
|
|
}
|
|
ret := make([]*types.RawBody, len(resp.Bodies))
|
|
for i := range ret {
|
|
ret[i] = eth1_utils.ConvertRawBlockBodyFromRpc(resp.Bodies[i])
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) GetBodiesByRange(start, count uint64) []*types.RawBody {
|
|
resp, err := c.executionModule.GetBodiesByRange(c.ctx, &execution.GetBodiesByRangeRequest{
|
|
Start: start,
|
|
Count: count,
|
|
})
|
|
if err != nil {
|
|
log.Error("GetBodiesByHases failed", "err", err)
|
|
return nil
|
|
}
|
|
ret := make([]*types.RawBody, len(resp.Bodies))
|
|
for i := range ret {
|
|
ret[i] = eth1_utils.ConvertRawBlockBodyFromRpc(resp.Bodies[i])
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) Ready() (bool, error) {
|
|
resp, err := c.executionModule.Ready(c.ctx, &emptypb.Empty{})
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return resp.Ready, nil
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) HeaderNumber(hash libcommon.Hash) (*uint64, error) {
|
|
resp, err := c.executionModule.GetHeaderHashNumber(c.ctx, gointerfaces.ConvertHashToH256(hash))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp == nil {
|
|
return nil, nil
|
|
}
|
|
return resp.BlockNumber, nil
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) IsCanonicalHash(hash libcommon.Hash) (bool, error) {
|
|
resp, err := c.executionModule.IsCanonicalHash(c.ctx, gointerfaces.ConvertHashToH256(hash))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if resp == nil {
|
|
return false, nil
|
|
}
|
|
return resp.Canonical, nil
|
|
}
|
|
|
|
func (ChainReaderWriterEth1) FrozenBlocks() uint64 {
|
|
panic("ChainReaderEth1.FrozenBlocks not implemented")
|
|
}
|
|
|
|
const retryTimeout = 10 * time.Millisecond
|
|
|
|
func (c ChainReaderWriterEth1) InsertBlocksAndWait(blocks []*types.Block) error {
|
|
request := &execution.InsertBlocksRequest{
|
|
Blocks: eth1_utils.ConvertBlocksToRPC(blocks),
|
|
}
|
|
response, err := c.executionModule.InsertBlocks(c.ctx, request)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
retryInterval := time.NewTicker(retryTimeout)
|
|
defer retryInterval.Stop()
|
|
for response.Result == execution.ExecutionStatus_Busy {
|
|
select {
|
|
case <-retryInterval.C:
|
|
response, err = c.executionModule.InsertBlocks(c.ctx, request)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case <-c.ctx.Done():
|
|
return context.Canceled
|
|
}
|
|
}
|
|
if response.Result != execution.ExecutionStatus_Success {
|
|
return fmt.Errorf("insertHeadersAndWait: invalid code recieved from execution module: %s", response.Result.String())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) InsertBlockAndWait(block *types.Block) error {
|
|
return c.InsertBlocksAndWait([]*types.Block{block})
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) ValidateChain(hash libcommon.Hash, number uint64) (execution.ExecutionStatus, libcommon.Hash, error) {
|
|
resp, err := c.executionModule.ValidateChain(c.ctx, &execution.ValidationRequest{
|
|
Hash: gointerfaces.ConvertHashToH256(hash),
|
|
Number: number,
|
|
})
|
|
if err != nil {
|
|
return 0, libcommon.Hash{}, err
|
|
}
|
|
return resp.ValidationStatus, gointerfaces.ConvertH256ToHash(resp.LatestValidHash), err
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) UpdateForkChoice(headHash, safeHash, finalizeHash libcommon.Hash) (execution.ExecutionStatus, libcommon.Hash, error) {
|
|
resp, err := c.executionModule.UpdateForkChoice(c.ctx, &execution.ForkChoice{
|
|
HeadBlockHash: gointerfaces.ConvertHashToH256(headHash),
|
|
SafeBlockHash: gointerfaces.ConvertHashToH256(safeHash),
|
|
FinalizedBlockHash: gointerfaces.ConvertHashToH256(finalizeHash),
|
|
Timeout: c.fcuTimoutMillis,
|
|
})
|
|
if err != nil {
|
|
return 0, libcommon.Hash{}, err
|
|
}
|
|
return resp.Status, gointerfaces.ConvertH256ToHash(resp.LatestValidHash), err
|
|
}
|
|
|
|
func (c ChainReaderWriterEth1) GetForkchoice() (headHash, finalizedHash, safeHash libcommon.Hash, err error) {
|
|
var resp *execution.ForkChoice
|
|
resp, err = c.executionModule.GetForkChoice(c.ctx, &emptypb.Empty{})
|
|
if err != nil {
|
|
log.Error("GetHeader failed", "err", err)
|
|
return
|
|
}
|
|
return gointerfaces.ConvertH256ToHash(resp.HeadBlockHash), gointerfaces.ConvertH256ToHash(resp.FinalizedBlockHash),
|
|
gointerfaces.ConvertH256ToHash(resp.SafeBlockHash), nil
|
|
}
|