diff --git a/chain/datasource/datasource.go b/chain/datasource/datasource.go index 2eb7f4efc..44d102ebf 100644 --- a/chain/datasource/datasource.go +++ b/chain/datasource/datasource.go @@ -18,6 +18,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/lotus/chain/vm" lru "github.com/hashicorp/golang-lru" "github.com/ipfs/go-cid" @@ -147,6 +148,10 @@ func (t *DataSource) TipSetBlockMessages(ctx context.Context, ts *types.TipSet) return t.node.MessagesForTipSetBlocks(ctx, ts) } +func (t *DataSource) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) { + return t.node.EthGetBlockByHash(ctx, blkHash, fullTxInfo) +} + // TipSetMessageReceipts returns the blocks and messages in `pts` and their corresponding receipts from `ts` matching block order in tipset (`pts`). // TODO replace with lotus chainstore method when https://github.com/filecoin-project/lotus/pull/9186 lands func (t *DataSource) TipSetMessageReceipts(ctx context.Context, ts, pts *types.TipSet) ([]*lens.BlockMessageReceipts, error) { diff --git a/chain/indexer/integrated/processor/state.go b/chain/indexer/integrated/processor/state.go index 51a09f01c..9722a2150 100644 --- a/chain/indexer/integrated/processor/state.go +++ b/chain/indexer/integrated/processor/state.go @@ -59,6 +59,7 @@ import ( msapprovaltask "github.com/filecoin-project/lily/tasks/msapprovals" // fevm task + fevmblockheadertask "github.com/filecoin-project/lily/tasks/fevm/blockheader" fevmactorstatstask "github.com/filecoin-project/lily/tasks/fevmactorstats" "github.com/filecoin-project/lily/chain/indexer/tasktype" @@ -641,6 +642,8 @@ func MakeProcessors(api tasks.DataSource, indexerTasks []string) (*IndexerProces // case tasktype.FEVMActorStats: out.TipsetProcessors[t] = fevmactorstatstask.NewTask(api) + case tasktype.FEVMBlockHeader: + out.TipsetsProcessors[t] = fevmblockheadertask.NewTask(api) case BuiltinTaskName: out.ReportProcessors[t] = indexertask.NewTask(api) diff --git a/chain/indexer/integrated/processor/state_internal_test.go b/chain/indexer/integrated/processor/state_internal_test.go index 95e8b7aac..22966ee1d 100644 --- a/chain/indexer/integrated/processor/state_internal_test.go +++ b/chain/indexer/integrated/processor/state_internal_test.go @@ -54,7 +54,7 @@ func TestNewProcessor(t *testing.T) { require.Equal(t, t.Name(), proc.name) require.Len(t, proc.actorProcessors, 24) require.Len(t, proc.tipsetProcessors, 10) - require.Len(t, proc.tipsetsProcessors, 9) + require.Len(t, proc.tipsetsProcessors, 10) require.Len(t, proc.builtinProcessors, 1) require.Equal(t, gasoutput.NewTask(nil), proc.tipsetsProcessors[tasktype.GasOutputs]) diff --git a/chain/indexer/integrated/processor/state_test.go b/chain/indexer/integrated/processor/state_test.go index 3ff4e4f96..7fe91205c 100644 --- a/chain/indexer/integrated/processor/state_test.go +++ b/chain/indexer/integrated/processor/state_test.go @@ -408,6 +408,6 @@ func TestMakeProcessorsAllTasks(t *testing.T) { require.NoError(t, err) require.Len(t, proc.ActorProcessors, 24) require.Len(t, proc.TipsetProcessors, 10) - require.Len(t, proc.TipsetsProcessors, 9) + require.Len(t, proc.TipsetsProcessors, 10) require.Len(t, proc.ReportProcessors, 1) } diff --git a/chain/indexer/tasktype/table_tasks.go b/chain/indexer/tasktype/table_tasks.go index 13e1ca4e3..e209711bd 100644 --- a/chain/indexer/tasktype/table_tasks.go +++ b/chain/indexer/tasktype/table_tasks.go @@ -45,6 +45,7 @@ const ( VerifiedRegistryVerifiedClient = "verified_registry_verified_client" VerifiedRegistryClaim = "verified_registry_claim" FEVMActorStats = "fevm_actor_stats" + FEVMBlockHeader = "fevm_block_header" ) var AllTableTasks = []string{ @@ -91,6 +92,7 @@ var AllTableTasks = []string{ VerifiedRegistryVerifiedClient, VerifiedRegistryClaim, FEVMActorStats, + FEVMBlockHeader, } var TableLookup = map[string]struct{}{ @@ -137,6 +139,7 @@ var TableLookup = map[string]struct{}{ VerifiedRegistryVerifiedClient: {}, VerifiedRegistryClaim: {}, FEVMActorStats: {}, + FEVMBlockHeader: {}, } var TableComment = map[string]string{ @@ -183,6 +186,7 @@ var TableComment = map[string]string{ VerifiedRegistryVerifiedClient: ``, VerifiedRegistryClaim: ``, FEVMActorStats: ``, + FEVMBlockHeader: ``, } var TableFieldComments = map[string]map[string]string{ @@ -286,4 +290,5 @@ var TableFieldComments = map[string]map[string]string{ VerifiedRegistryVerifiedClient: {}, VerifiedRegistryClaim: {}, FEVMActorStats: {}, + FEVMBlockHeader: {}, } diff --git a/chain/indexer/tasktype/tasks.go b/chain/indexer/tasktype/tasks.go index 6bed854cb..2272f2d61 100644 --- a/chain/indexer/tasktype/tasks.go +++ b/chain/indexer/tasktype/tasks.go @@ -93,6 +93,7 @@ var TaskLookup = map[string][]string{ }, FEVMTask: { FEVMActorStats, + FEVMBlockHeader, }, } diff --git a/chain/indexer/tasktype/tasks_test.go b/chain/indexer/tasktype/tasks_test.go index ecc0de66c..526e7c6fe 100644 --- a/chain/indexer/tasktype/tasks_test.go +++ b/chain/indexer/tasktype/tasks_test.go @@ -101,7 +101,7 @@ func TestMakeAllTaskAliasNames(t *testing.T) { } func TestMakeAllTaskNames(t *testing.T) { - const TotalTableTasks = 43 + const TotalTableTasks = 44 actual, err := tasktype.MakeTaskNames(tasktype.AllTableTasks) require.NoError(t, err) // if this test fails it means a new task name was added, update the above test diff --git a/lens/interface.go b/lens/interface.go index 0342aa3a8..2bb98ad95 100644 --- a/lens/interface.go +++ b/lens/interface.go @@ -11,6 +11,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/ipfs/go-cid" @@ -21,6 +22,7 @@ type API interface { ChainAPI StateAPI VMAPI + EthModuleAPI GetMessageExecutionsForTipSet(ctx context.Context, ts, pts *types.TipSet) ([]*MessageExecution, error) } @@ -74,6 +76,10 @@ type VMAPI interface { BurnFundsFn(ctx context.Context, ts *types.TipSet) (ShouldBurnFn, error) } +type EthModuleAPI interface { + EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) +} + type MessageExecution struct { Cid cid.Cid StateRoot cid.Cid diff --git a/lens/lily/api.go b/lens/lily/api.go index dd4fc7c5e..d8fda1a03 100644 --- a/lens/lily/api.go +++ b/lens/lily/api.go @@ -8,6 +8,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p/core/peer" @@ -40,20 +41,21 @@ type LilyAPI interface { // SyncState returns the current status of the chain sync system. SyncState(context.Context) (*api.SyncState, error) //perm:read - ChainHead(context.Context) (*types.TipSet, error) //perm:read - ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) //perm:read - ChainReadObj(context.Context, cid.Cid) ([]byte, error) //perm:read - ChainStatObj(context.Context, cid.Cid, cid.Cid) (api.ObjStat, error) //perm:read - ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) //perm:read - ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) //perm:read - ChainGetTipSetAfterHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) //perm:read - ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) //perm:read - ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error) //perm:read - ChainGetParentMessages(context.Context, cid.Cid) ([]api.Message, error) //perm:read - ChainSetHead(context.Context, types.TipSetKey) error //perm:read - ChainGetGenesis(context.Context) (*types.TipSet, error) //perm:read - ChainPrune(ctx context.Context, opts api.PruneOpts) error //perm:read - ChainHotGC(ctx context.Context, opts api.HotGCOpts) error //perm:read + ChainHead(context.Context) (*types.TipSet, error) //perm:read + ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) //perm:read + ChainReadObj(context.Context, cid.Cid) ([]byte, error) //perm:read + ChainStatObj(context.Context, cid.Cid, cid.Cid) (api.ObjStat, error) //perm:read + ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) //perm:read + ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) //perm:read + ChainGetTipSetAfterHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) //perm:read + ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) //perm:read + ChainGetParentReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error) //perm:read + ChainGetParentMessages(context.Context, cid.Cid) ([]api.Message, error) //perm:read + ChainSetHead(context.Context, types.TipSetKey) error //perm:read + ChainGetGenesis(context.Context) (*types.TipSet, error) //perm:read + ChainPrune(ctx context.Context, opts api.PruneOpts) error //perm:read + ChainHotGC(ctx context.Context, opts api.HotGCOpts) error //perm:read + EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) //perm:read // trigger graceful shutdown Shutdown(context.Context) error diff --git a/lens/lily/impl.go b/lens/lily/impl.go index 771c80cb7..db113d55c 100644 --- a/lens/lily/impl.go +++ b/lens/lily/impl.go @@ -15,6 +15,7 @@ import ( "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/node/impl/common" "github.com/filecoin-project/lotus/node/impl/full" @@ -55,6 +56,7 @@ type LilyNodeAPI struct { full.ChainAPI full.StateAPI full.SyncAPI + full.EthModuleAPI common.CommonAPI Events *events.Events Scheduler *schedule.Scheduler @@ -553,6 +555,10 @@ func (m *LilyNodeAPI) ComputeBaseFee(ctx context.Context, ts *types.TipSet) (abi return m.ChainAPI.Chain.ComputeBaseFee(ctx, ts) } +func (m *LilyNodeAPI) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) { + return m.EthModuleAPI.EthGetBlockByHash(ctx, blkHash, fullTxInfo) +} + // MessagesForTipSetBlocks returns messages stored in the blocks of the specified tipset, messages may be duplicated // across the returned set of BlockMessages. func (m *LilyNodeAPI) MessagesForTipSetBlocks(ctx context.Context, ts *types.TipSet) ([]*lens.BlockMessages, error) { diff --git a/lens/lily/struct.go b/lens/lily/struct.go index 5fd6a2f2a..2a5868921 100644 --- a/lens/lily/struct.go +++ b/lens/lily/struct.go @@ -7,6 +7,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log/v2" @@ -49,20 +50,21 @@ type LilyAPIStruct struct { SyncState func(ctx context.Context) (*api.SyncState, error) `perm:"read"` - ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"` - ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"` - ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"` - ChainStatObj func(context.Context, cid.Cid, cid.Cid) (api.ObjStat, error) `perm:"read"` - ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainGetBlockMessages func(context.Context, cid.Cid) (*api.BlockMessages, error) `perm:"read"` - ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"` - ChainGetTipSetAfterHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainSetHead func(context.Context, types.TipSetKey) error `perm:"read"` - ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"` - ChainPrune func(ctx context.Context, opts api.PruneOpts) error `perm:"read"` - ChainHotGC func(ctx context.Context, opts api.HotGCOpts) error `perm:"read"` + ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"` + ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"` + ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"` + ChainStatObj func(context.Context, cid.Cid, cid.Cid) (api.ObjStat, error) `perm:"read"` + ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetTipSetByHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetBlockMessages func(context.Context, cid.Cid) (*api.BlockMessages, error) `perm:"read"` + ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` + ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"` + ChainGetTipSetAfterHeight func(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainSetHead func(context.Context, types.TipSetKey) error `perm:"read"` + ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"` + ChainPrune func(ctx context.Context, opts api.PruneOpts) error `perm:"read"` + ChainHotGC func(ctx context.Context, opts api.HotGCOpts) error `perm:"read"` + EthGetBlockByHash func(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) `perm:"read"` LogList func(context.Context) ([]string, error) `perm:"read"` LogSetLevel func(context.Context, string, string) error `perm:"read"` @@ -268,3 +270,7 @@ func (s *LilyAPIStruct) LilyWalkNotify(ctx context.Context, cfg *LilyWalkNotifyC func (s *LilyAPIStruct) LilyGapFillNotify(ctx context.Context, cfg *LilyGapFillNotifyConfig) (*schedule.JobSubmitResult, error) { return s.Internal.LilyGapFillNotify(ctx, cfg) } + +func (s *LilyAPIStruct) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) { + return s.Internal.EthGetBlockByHash(ctx, blkHash, fullTxInfo) +} diff --git a/model/fevm/blockheader.go b/model/fevm/blockheader.go new file mode 100644 index 000000000..c93131a88 --- /dev/null +++ b/model/fevm/blockheader.go @@ -0,0 +1,58 @@ +package fevm + +import ( + "context" + + "go.opencensus.io/tag" + + "github.com/filecoin-project/lily/metrics" + "github.com/filecoin-project/lily/model" +) + +type FEVMBlockHeader struct { + tableName struct{} `pg:"fevm_block_header"` // nolint: structcheck + + // Height message was executed at. + Height int64 `pg:",pk,notnull,use_zero"` + + // ETH Hash + Hash string `pg:",notnull"` + + // Parent Block ETH Hash + ParentHash string `pg:",notnull"` + + Miner string `pg:",notnull"` + + StateRoot string `pg:",notnull"` + + TransactionsRoot string `pg:",notnull"` + ReceiptsRoot string `pg:",notnull"` + Difficulty uint64 `pg:",use_zero"` + Number uint64 `pg:",use_zero"` + GasLimit uint64 `pg:",use_zero"` + GasUsed uint64 `pg:",use_zero"` + Timestamp uint64 `pg:",use_zero"` + ExtraData string `pg:",notnull"` + MixHash string `pg:",notnull"` + Nonce string `pg:",notnull"` + BaseFeePerGas string `pg:",notnull"` + Size uint64 `pg:",use_zero"` + Sha3Uncles string `pg:",notnull"` +} + +func (f *FEVMBlockHeader) Persist(ctx context.Context, s model.StorageBatch, version model.Version) error { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Table, "fevm_block_header")) + metrics.RecordCount(ctx, metrics.PersistModel, 1) + return s.PersistModel(ctx, f) +} + +type FEVMBlockHeaderList []*FEVMBlockHeader + +func (f FEVMBlockHeaderList) Persist(ctx context.Context, s model.StorageBatch, version model.Version) error { + if len(f) == 0 { + return nil + } + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Table, "fevm_block_header")) + metrics.RecordCount(ctx, metrics.PersistModel, len(f)) + return s.PersistModel(ctx, f) +} diff --git a/schemas/v1/22_fevm_block_header.go b/schemas/v1/22_fevm_block_header.go new file mode 100644 index 000000000..36c14d2aa --- /dev/null +++ b/schemas/v1/22_fevm_block_header.go @@ -0,0 +1,30 @@ +package v1 + +func init() { + patches.Register( + 22, + ` + CREATE TABLE IF NOT EXISTS {{ .SchemaName | default "public"}}.fevm_block_header ( + height BIGINT NOT NULL, + hash TEXT, + parent_hash TEXT, + miner TEXT, + state_root TEXT, + transactions_root TEXT, + receipts_root TEXT, + difficulty BIGINT, + number BIGINT, + gas_limit BIGINT, + gas_used BIGINT, + timestamp BIGINT, + extra_data TEXT, + mix_hash TEXT, + nonce TEXT, + base_fee_per_gas TEXT, + size BIGINT, + sha3_uncles TEXT, + PRIMARY KEY(height) + ); +`, + ) +} diff --git a/storage/sql.go b/storage/sql.go index 73b7b0dfa..778a96445 100644 --- a/storage/sql.go +++ b/storage/sql.go @@ -94,6 +94,7 @@ var Models = []interface{}{ (*verifreg.VerifiedRegistryClaim)(nil), (*fevm.FEVMActorStats)(nil), + (*fevm.FEVMBlockHeader)(nil), } var log = logging.Logger("lily/storage") diff --git a/tasks/api.go b/tasks/api.go index d4148b938..dc0238b0d 100644 --- a/tasks/api.go +++ b/tasks/api.go @@ -7,6 +7,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/ipfs/go-cid" "github.com/filecoin-project/lily/chain/actors/adt" @@ -68,4 +69,6 @@ type DataSource interface { MinerLoad(store adt.Store, act *types.Actor) (miner.State, error) ShouldBurnFn(ctx context.Context, ts *types.TipSet) (lens.ShouldBurnFn, error) + + EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) } diff --git a/tasks/fevm/blockheader/tasks.go b/tasks/fevm/blockheader/tasks.go new file mode 100644 index 000000000..a3610ba14 --- /dev/null +++ b/tasks/fevm/blockheader/tasks.go @@ -0,0 +1,91 @@ +package fevmblockheader + +import ( + "context" + + "github.com/filecoin-project/lotus/chain/types" + logging "github.com/ipfs/go-log/v2" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + + "github.com/filecoin-project/lily/model" + "github.com/filecoin-project/lily/model/fevm" + visormodel "github.com/filecoin-project/lily/model/visor" + "github.com/filecoin-project/lily/tasks" + "github.com/filecoin-project/lotus/chain/types/ethtypes" +) + +var log = logging.Logger("lily/tasks/fevmblockheader") + +type Task struct { + node tasks.DataSource +} + +func NewTask(node tasks.DataSource) *Task { + return &Task{ + node: node, + } +} + +func (p *Task) ProcessTipSets(ctx context.Context, current *types.TipSet, executed *types.TipSet) (model.Persistable, *visormodel.ProcessingReport, error) { + ctx, span := otel.Tracer("").Start(ctx, "ProcessTipSets") + if span.IsRecording() { + span.SetAttributes( + attribute.String("current", current.String()), + attribute.Int64("current_height", int64(current.Height())), + attribute.String("executed", executed.String()), + attribute.Int64("executed_height", int64(executed.Height())), + attribute.String("processor", "fevm_block_header"), + ) + } + defer span.End() + + report := &visormodel.ProcessingReport{ + Height: int64(current.Height()), + StateRoot: current.ParentState().String(), + } + + cid, err := executed.Key().Cid() + if err != nil { + log.Errorf("Error at getting cid: [%v] err: %v", cid, err) + return nil, report, err + } + + hash, err := ethtypes.EthHashFromCid(cid) + if err != nil { + log.Errorf("Error at finding hash: [%v] err: %v", hash, err) + return nil, report, err + } + + ethBlock, err := p.node.EthGetBlockByHash(ctx, hash, false) + if err != nil { + log.Errorf("EthGetBlockByHash: [hash: %v] err: %v", hash.String(), err) + return nil, report, err + } + + if ethBlock.Number == 0 { + log.Warn("block number == 0") + return nil, report, err + } + + return &fevm.FEVMBlockHeader{ + Height: int64(executed.Height()), + Hash: hash.String(), + ParentHash: ethBlock.ParentHash.String(), + Miner: ethBlock.Miner.String(), + StateRoot: ethBlock.StateRoot.String(), + TransactionsRoot: ethBlock.TransactionsRoot.String(), + ReceiptsRoot: ethBlock.ReceiptsRoot.String(), + Difficulty: uint64(ethBlock.Difficulty), + Number: uint64(ethBlock.Number), + GasLimit: uint64(ethBlock.GasLimit), + GasUsed: uint64(ethBlock.GasUsed), + Timestamp: uint64(ethBlock.Timestamp), + ExtraData: string(ethBlock.Extradata), + MixHash: ethBlock.MixHash.String(), + Nonce: ethBlock.Nonce.String(), + BaseFeePerGas: ethBlock.BaseFeePerGas.String(), + Size: uint64(ethBlock.Size), + Sha3Uncles: ethBlock.Sha3Uncles.String(), + }, report, nil +}