diff --git a/polygon/heimdall/checkpoint.go b/polygon/heimdall/checkpoint.go index 37ba2baa999..35feb699219 100644 --- a/polygon/heimdall/checkpoint.go +++ b/polygon/heimdall/checkpoint.go @@ -10,8 +10,6 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" ) -var _ Waypoint = Checkpoint{} - type CheckpointId uint64 // Checkpoint defines a response object type of bor checkpoint @@ -20,50 +18,53 @@ type Checkpoint struct { Fields WaypointFields } -func (c Checkpoint) RawId() uint64 { +var _ Entity = &Checkpoint{} +var _ Waypoint = &Checkpoint{} + +func (c *Checkpoint) RawId() uint64 { return uint64(c.Id) } -func (c Checkpoint) StartBlock() *big.Int { +func (c *Checkpoint) StartBlock() *big.Int { return c.Fields.StartBlock } -func (c Checkpoint) EndBlock() *big.Int { +func (c *Checkpoint) EndBlock() *big.Int { return c.Fields.EndBlock } -func (c Checkpoint) BlockNumRange() ClosedRange { +func (c *Checkpoint) BlockNumRange() ClosedRange { return ClosedRange{ Start: c.StartBlock().Uint64(), End: c.EndBlock().Uint64(), } } -func (c Checkpoint) RootHash() libcommon.Hash { +func (c *Checkpoint) RootHash() libcommon.Hash { return c.Fields.RootHash } -func (c Checkpoint) Timestamp() uint64 { +func (c *Checkpoint) Timestamp() uint64 { return c.Fields.Timestamp } -func (c Checkpoint) Length() uint64 { +func (c *Checkpoint) Length() uint64 { return c.Fields.Length() } -func (c Checkpoint) CmpRange(n uint64) int { +func (c *Checkpoint) CmpRange(n uint64) int { return c.Fields.CmpRange(n) } -func (m Checkpoint) String() string { +func (c *Checkpoint) String() string { return fmt.Sprintf( "Checkpoint {%v (%d:%d) %v %v %v}", - m.Fields.Proposer.String(), - m.Fields.StartBlock, - m.Fields.EndBlock, - m.Fields.RootHash.Hex(), - m.Fields.ChainID, - m.Fields.Timestamp, + c.Fields.Proposer.String(), + c.Fields.StartBlock, + c.Fields.EndBlock, + c.Fields.RootHash.Hex(), + c.Fields.ChainID, + c.Fields.Timestamp, ) } diff --git a/polygon/heimdall/entity_fetcher.go b/polygon/heimdall/entity_fetcher.go index bb5bad50ab3..d1b54c1d8f9 100644 --- a/polygon/heimdall/entity_fetcher.go +++ b/polygon/heimdall/entity_fetcher.go @@ -10,29 +10,29 @@ import ( "github.com/ledgerwatch/log/v3" ) -type entityFetcher interface { +type entityFetcher[TEntity Entity] interface { FetchLastEntityId(ctx context.Context) (uint64, error) - FetchEntitiesRange(ctx context.Context, idRange ClosedRange) ([]Entity, error) + FetchEntitiesRange(ctx context.Context, idRange ClosedRange) ([]TEntity, error) } -type entityFetcherImpl struct { +type entityFetcherImpl[TEntity Entity] struct { name string fetchLastEntityId func(ctx context.Context) (int64, error) - fetchEntity func(ctx context.Context, id int64) (Entity, error) - fetchEntitiesPage func(ctx context.Context, page uint64, limit uint64) ([]Entity, error) + fetchEntity func(ctx context.Context, id int64) (TEntity, error) + fetchEntitiesPage func(ctx context.Context, page uint64, limit uint64) ([]TEntity, error) logger log.Logger } -func newEntityFetcher( +func newEntityFetcher[TEntity Entity]( name string, fetchLastEntityId func(ctx context.Context) (int64, error), - fetchEntity func(ctx context.Context, id int64) (Entity, error), - fetchEntitiesPage func(ctx context.Context, page uint64, limit uint64) ([]Entity, error), + fetchEntity func(ctx context.Context, id int64) (TEntity, error), + fetchEntitiesPage func(ctx context.Context, page uint64, limit uint64) ([]TEntity, error), logger log.Logger, -) entityFetcher { - return &entityFetcherImpl{ +) entityFetcher[TEntity] { + return &entityFetcherImpl[TEntity]{ name: name, fetchLastEntityId: fetchLastEntityId, fetchEntity: fetchEntity, @@ -41,12 +41,12 @@ func newEntityFetcher( } } -func (f *entityFetcherImpl) FetchLastEntityId(ctx context.Context) (uint64, error) { +func (f *entityFetcherImpl[TEntity]) FetchLastEntityId(ctx context.Context) (uint64, error) { id, err := f.fetchLastEntityId(ctx) return uint64(id), err } -func (f *entityFetcherImpl) FetchEntitiesRange(ctx context.Context, idRange ClosedRange) ([]Entity, error) { +func (f *entityFetcherImpl[TEntity]) FetchEntitiesRange(ctx context.Context, idRange ClosedRange) ([]TEntity, error) { count := idRange.Len() const batchFetchThreshold = 100 @@ -62,20 +62,20 @@ func (f *entityFetcherImpl) FetchEntitiesRange(ctx context.Context, idRange Clos return f.FetchEntitiesRangeSequentially(ctx, idRange) } -func (f *entityFetcherImpl) FetchEntitiesRangeSequentially(ctx context.Context, idRange ClosedRange) ([]Entity, error) { - return ClosedRangeMap(idRange, func(id uint64) (Entity, error) { +func (f *entityFetcherImpl[TEntity]) FetchEntitiesRangeSequentially(ctx context.Context, idRange ClosedRange) ([]TEntity, error) { + return ClosedRangeMap(idRange, func(id uint64) (TEntity, error) { return f.fetchEntity(ctx, int64(id)) }) } -func (f *entityFetcherImpl) FetchAllEntities(ctx context.Context) ([]Entity, error) { +func (f *entityFetcherImpl[TEntity]) FetchAllEntities(ctx context.Context) ([]TEntity, error) { // TODO: once heimdall API is fixed to return sorted items in pages we can only fetch // // the new pages after lastStoredCheckpointId using the checkpoints/list paging API // (for now we have to fetch all of them) // and also remove sorting we do after fetching - var entities []Entity + var entities []TEntity fetchStartTime := time.Now() progressLogTicker := time.NewTicker(30 * time.Second) @@ -106,7 +106,7 @@ func (f *entityFetcherImpl) FetchAllEntities(ctx context.Context) ([]Entity, err } } - slices.SortFunc(entities, func(e1, e2 Entity) int { + slices.SortFunc(entities, func(e1, e2 TEntity) int { n1 := e1.BlockNumRange().Start n2 := e2.BlockNumRange().Start return cmp.Compare(n1, n2) diff --git a/polygon/heimdall/entity_store.go b/polygon/heimdall/entity_store.go index 0d73cb03f07..42d002da0a5 100644 --- a/polygon/heimdall/entity_store.go +++ b/polygon/heimdall/entity_store.go @@ -10,23 +10,23 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/iter" ) -type entityStore interface { +type entityStore[TEntity Entity] interface { Prepare(ctx context.Context) error Close() GetLastEntityId(ctx context.Context) (uint64, bool, error) - GetLastEntity(ctx context.Context) (Entity, error) - GetEntity(ctx context.Context, id uint64) (Entity, error) - PutEntity(ctx context.Context, id uint64, entity Entity) error - FindByBlockNum(ctx context.Context, blockNum uint64) (Entity, error) - RangeFromId(ctx context.Context, startId uint64) ([]Entity, error) - RangeFromBlockNum(ctx context.Context, startBlockNum uint64) ([]Entity, error) + GetLastEntity(ctx context.Context) (TEntity, error) + GetEntity(ctx context.Context, id uint64) (TEntity, error) + PutEntity(ctx context.Context, id uint64, entity TEntity) error + FindByBlockNum(ctx context.Context, blockNum uint64) (TEntity, error) + RangeFromId(ctx context.Context, startId uint64) ([]TEntity, error) + RangeFromBlockNum(ctx context.Context, startBlockNum uint64) ([]TEntity, error) } -type entityStoreImpl struct { +type entityStoreImpl[TEntity Entity] struct { tx kv.RwTx table string - makeEntity func() Entity + makeEntity func() TEntity getLastEntityId func(ctx context.Context, tx kv.Tx) (uint64, bool, error) loadEntityBytes func(ctx context.Context, tx kv.Getter, id uint64) ([]byte, error) @@ -35,15 +35,15 @@ type entityStoreImpl struct { prepareOnce sync.Once } -func newEntityStore( +func newEntityStore[TEntity Entity]( tx kv.RwTx, table string, - makeEntity func() Entity, + makeEntity func() TEntity, getLastEntityId func(ctx context.Context, tx kv.Tx) (uint64, bool, error), loadEntityBytes func(ctx context.Context, tx kv.Getter, id uint64) ([]byte, error), blockNumToIdIndexFactory func(ctx context.Context) (*RangeIndex, error), -) entityStore { - return &entityStoreImpl{ +) entityStore[TEntity] { + return &entityStoreImpl[TEntity]{ tx: tx, table: table, @@ -55,7 +55,7 @@ func newEntityStore( } } -func (s *entityStoreImpl) Prepare(ctx context.Context) error { +func (s *entityStoreImpl[TEntity]) Prepare(ctx context.Context) error { var err error s.prepareOnce.Do(func() { s.blockNumToIdIndex, err = s.blockNumToIdIndexFactory(ctx) @@ -68,22 +68,30 @@ func (s *entityStoreImpl) Prepare(ctx context.Context) error { return err } -func (s *entityStoreImpl) Close() { +func (s *entityStoreImpl[TEntity]) Close() { s.blockNumToIdIndex.Close() } -func (s *entityStoreImpl) GetLastEntityId(ctx context.Context) (uint64, bool, error) { +func (s *entityStoreImpl[TEntity]) GetLastEntityId(ctx context.Context) (uint64, bool, error) { return s.getLastEntityId(ctx, s.tx) } -func (s *entityStoreImpl) GetLastEntity(ctx context.Context) (Entity, error) { +// Zero value of any type T +// https://stackoverflow.com/questions/70585852/return-default-value-for-generic-type) +// https://go.dev/ref/spec#The_zero_value +func Zero[T any]() T { + var value T + return value +} + +func (s *entityStoreImpl[TEntity]) GetLastEntity(ctx context.Context) (TEntity, error) { id, ok, err := s.GetLastEntityId(ctx) if err != nil { - return nil, err + return Zero[TEntity](), err } // not found if !ok { - return nil, nil + return Zero[TEntity](), nil } return s.GetEntity(ctx, id) } @@ -94,28 +102,28 @@ func entityStoreKey(id uint64) [8]byte { return key } -func (s *entityStoreImpl) entityUnmarshalJSON(jsonBytes []byte) (Entity, error) { +func (s *entityStoreImpl[TEntity]) entityUnmarshalJSON(jsonBytes []byte) (TEntity, error) { entity := s.makeEntity() if err := json.Unmarshal(jsonBytes, entity); err != nil { - return nil, err + return Zero[TEntity](), err } return entity, nil } -func (s *entityStoreImpl) GetEntity(ctx context.Context, id uint64) (Entity, error) { +func (s *entityStoreImpl[TEntity]) GetEntity(ctx context.Context, id uint64) (TEntity, error) { jsonBytes, err := s.loadEntityBytes(ctx, s.tx, id) if err != nil { - return nil, err + return Zero[TEntity](), err } // not found if jsonBytes == nil { - return nil, nil + return Zero[TEntity](), nil } return s.entityUnmarshalJSON(jsonBytes) } -func (s *entityStoreImpl) PutEntity(ctx context.Context, id uint64, entity Entity) error { +func (s *entityStoreImpl[TEntity]) PutEntity(ctx context.Context, id uint64, entity TEntity) error { jsonBytes, err := json.Marshal(entity) if err != nil { return err @@ -131,27 +139,27 @@ func (s *entityStoreImpl) PutEntity(ctx context.Context, id uint64, entity Entit return s.blockNumToIdIndex.Put(ctx, entity.BlockNumRange(), id) } -func (s *entityStoreImpl) FindByBlockNum(ctx context.Context, blockNum uint64) (Entity, error) { +func (s *entityStoreImpl[TEntity]) FindByBlockNum(ctx context.Context, blockNum uint64) (TEntity, error) { id, err := s.blockNumToIdIndex.Lookup(ctx, blockNum) if err != nil { - return nil, err + return Zero[TEntity](), err } // not found if id == 0 { - return nil, nil + return Zero[TEntity](), nil } return s.GetEntity(ctx, id) } -func (s *entityStoreImpl) RangeFromId(_ context.Context, startId uint64) ([]Entity, error) { +func (s *entityStoreImpl[TEntity]) RangeFromId(_ context.Context, startId uint64) ([]TEntity, error) { startKey := entityStoreKey(startId) it, err := s.tx.Range(s.table, startKey[:], nil) if err != nil { return nil, err } - var entities []Entity + var entities []TEntity for it.HasNext() { _, jsonBytes, err := it.Next() if err != nil { @@ -167,7 +175,7 @@ func (s *entityStoreImpl) RangeFromId(_ context.Context, startId uint64) ([]Enti return entities, nil } -func (s *entityStoreImpl) RangeFromBlockNum(ctx context.Context, startBlockNum uint64) ([]Entity, error) { +func (s *entityStoreImpl[TEntity]) RangeFromBlockNum(ctx context.Context, startBlockNum uint64) ([]TEntity, error) { id, err := s.blockNumToIdIndex.Lookup(ctx, startBlockNum) if err != nil { return nil, err @@ -180,11 +188,11 @@ func (s *entityStoreImpl) RangeFromBlockNum(ctx context.Context, startBlockNum u return s.RangeFromId(ctx, id) } -func buildBlockNumToIdIndex( +func buildBlockNumToIdIndex[TEntity Entity]( ctx context.Context, index *RangeIndex, iteratorFactory func() (iter.KV, error), - entityUnmarshalJSON func([]byte) (Entity, error), + entityUnmarshalJSON func([]byte) (TEntity, error), ) error { it, err := iteratorFactory() if err != nil { diff --git a/polygon/heimdall/milestone.go b/polygon/heimdall/milestone.go index 3d74dac7fcc..57436b96b35 100644 --- a/polygon/heimdall/milestone.go +++ b/polygon/heimdall/milestone.go @@ -10,52 +10,53 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" ) -var _ Waypoint = Milestone{} - type MilestoneId uint64 -// milestone defines a response object type of bor milestone +// Milestone defines a response object type of bor milestone type Milestone struct { Id MilestoneId Fields WaypointFields } -func (m Milestone) RawId() uint64 { +var _ Entity = &Milestone{} +var _ Waypoint = &Milestone{} + +func (m *Milestone) RawId() uint64 { return uint64(m.Id) } -func (m Milestone) StartBlock() *big.Int { +func (m *Milestone) StartBlock() *big.Int { return m.Fields.StartBlock } -func (m Milestone) EndBlock() *big.Int { +func (m *Milestone) EndBlock() *big.Int { return m.Fields.EndBlock } -func (m Milestone) BlockNumRange() ClosedRange { +func (m *Milestone) BlockNumRange() ClosedRange { return ClosedRange{ Start: m.StartBlock().Uint64(), End: m.EndBlock().Uint64(), } } -func (m Milestone) RootHash() libcommon.Hash { +func (m *Milestone) RootHash() libcommon.Hash { return m.Fields.RootHash } -func (m Milestone) Timestamp() uint64 { +func (m *Milestone) Timestamp() uint64 { return m.Fields.Timestamp } -func (m Milestone) Length() uint64 { +func (m *Milestone) Length() uint64 { return m.Fields.Length() } -func (m Milestone) CmpRange(n uint64) int { +func (m *Milestone) CmpRange(n uint64) int { return m.Fields.CmpRange(n) } -func (m Milestone) String() string { +func (m *Milestone) String() string { return fmt.Sprintf( "Milestone {%v (%d:%d) %v %v %v}", m.Fields.Proposer.String(), @@ -88,7 +89,6 @@ func (m *Milestone) MarshalJSON() ([]byte, error) { } func (m *Milestone) UnmarshalJSON(b []byte) error { - // TODO - do we want to handle milestone_id ? // (example format: 043353d6-d83f-47f8-a38f-f5062e82a6d4 - 0x142987cad41cf7111b2f186da6ab89e460037f7f) dto := struct { diff --git a/polygon/heimdall/scraper.go b/polygon/heimdall/scraper.go index a95b4412e5a..86e9a94efe6 100644 --- a/polygon/heimdall/scraper.go +++ b/polygon/heimdall/scraper.go @@ -12,9 +12,9 @@ import ( ) type Scraper struct { - checkpointStore entityStore - milestoneStore entityStore - spanStore entityStore + checkpointStore entityStore[*Checkpoint] + milestoneStore entityStore[*Milestone] + spanStore entityStore[*Span] client HeimdallClient pollDelay time.Duration @@ -31,9 +31,9 @@ type Scraper struct { } func NewScraper( - checkpointStore entityStore, - milestoneStore entityStore, - spanStore entityStore, + checkpointStore entityStore[*Checkpoint], + milestoneStore entityStore[*Milestone], + spanStore entityStore[*Span], client HeimdallClient, pollDelay time.Duration, logger log.Logger, @@ -58,11 +58,12 @@ func NewScraper( } } -func (s *Scraper) syncEntity( +func syncEntity[TEntity Entity]( ctx context.Context, - store entityStore, - fetcher entityFetcher, - callback func([]Entity), + s *Scraper, + store entityStore[TEntity], + fetcher entityFetcher[TEntity], + callback func([]TEntity), syncEvent *polygoncommon.EventNotifier, ) error { defer store.Close() @@ -114,36 +115,27 @@ func (s *Scraper) syncEntity( return ctx.Err() } -func newCheckpointFetcher(client HeimdallClient, logger log.Logger) entityFetcher { - fetchEntity := func(ctx context.Context, id int64) (Entity, error) { return client.FetchCheckpoint(ctx, id) } - - fetchEntitiesPage := func(ctx context.Context, page uint64, limit uint64) ([]Entity, error) { - entities, err := client.FetchCheckpoints(ctx, page, limit) - return libcommon.SliceMap(entities, func(c *Checkpoint) Entity { return c }), err - } - +func newCheckpointFetcher(client HeimdallClient, logger log.Logger) entityFetcher[*Checkpoint] { return newEntityFetcher( "CheckpointFetcher", client.FetchCheckpointCount, - fetchEntity, - fetchEntitiesPage, + client.FetchCheckpoint, + client.FetchCheckpoints, logger, ) } -func newMilestoneFetcher(client HeimdallClient, logger log.Logger) entityFetcher { - fetchEntity := func(ctx context.Context, id int64) (Entity, error) { return client.FetchMilestone(ctx, id) } - +func newMilestoneFetcher(client HeimdallClient, logger log.Logger) entityFetcher[*Milestone] { return newEntityFetcher( "MilestoneFetcher", client.FetchMilestoneCount, - fetchEntity, + client.FetchMilestone, nil, logger, ) } -func newSpanFetcher(client HeimdallClient, logger log.Logger) entityFetcher { +func newSpanFetcher(client HeimdallClient, logger log.Logger) entityFetcher[*Span] { fetchLastEntityId := func(ctx context.Context) (int64, error) { span, err := client.FetchLatestSpan(ctx) if err != nil { @@ -152,7 +144,7 @@ func newSpanFetcher(client HeimdallClient, logger log.Logger) entityFetcher { return int64(span.Id), nil } - fetchEntity := func(ctx context.Context, id int64) (Entity, error) { + fetchEntity := func(ctx context.Context, id int64) (*Span, error) { return client.FetchSpan(ctx, uint64(id)) } @@ -165,27 +157,6 @@ func newSpanFetcher(client HeimdallClient, logger log.Logger) entityFetcher { ) } -func downcastCheckpointEntity(e Entity) *Checkpoint { - if e == nil { - return nil - } - return e.(*Checkpoint) -} - -func downcastMilestoneEntity(e Entity) *Milestone { - if e == nil { - return nil - } - return e.(*Milestone) -} - -func downcastSpanEntity(e Entity) *Span { - if e == nil { - return nil - } - return e.(*Span) -} - func (s *Scraper) RegisterCheckpointObserver(observer func([]*Checkpoint)) polygoncommon.UnregisterFunc { return s.checkpointObservers.Register(observer) } @@ -209,39 +180,36 @@ func (s *Scraper) Run(parentCtx context.Context) error { // sync checkpoints group.Go(func() error { - return s.syncEntity( + return syncEntity( ctx, + s, s.checkpointStore, newCheckpointFetcher(s.client, s.logger), - func(entities []Entity) { - s.checkpointObservers.Notify(libcommon.SliceMap(entities, downcastCheckpointEntity)) - }, + s.checkpointObservers.Notify, s.checkpointSyncEvent, ) }) // sync milestones group.Go(func() error { - return s.syncEntity( + return syncEntity( ctx, + s, s.milestoneStore, newMilestoneFetcher(s.client, s.logger), - func(entities []Entity) { - s.milestoneObservers.Notify(libcommon.SliceMap(entities, downcastMilestoneEntity)) - }, + s.milestoneObservers.Notify, s.milestoneSyncEvent, ) }) // sync spans group.Go(func() error { - return s.syncEntity( + return syncEntity( ctx, + s, s.spanStore, newSpanFetcher(s.client, s.logger), - func(entities []Entity) { - s.spanObservers.Notify(libcommon.SliceMap(entities, downcastSpanEntity)) - }, + s.spanObservers.Notify, s.spanSyncEvent, ) }) diff --git a/polygon/heimdall/service.go b/polygon/heimdall/service.go index ddeff5c28bf..5fc6a4a7381 100644 --- a/polygon/heimdall/service.go +++ b/polygon/heimdall/service.go @@ -21,23 +21,23 @@ type Service interface { type service struct { scraper *Scraper - checkpointStore entityStore - milestoneStore entityStore - spanStore entityStore + checkpointStore entityStore[*Checkpoint] + milestoneStore entityStore[*Milestone] + spanStore entityStore[*Span] } -func newCheckpointStore(tx kv.RwTx, reader services.BorCheckpointReader, blockNumToIdIndexFactory func(context.Context) (*RangeIndex, error)) entityStore { - makeEntity := func() Entity { return new(Checkpoint) } +func newCheckpointStore(tx kv.RwTx, reader services.BorCheckpointReader, blockNumToIdIndexFactory func(context.Context) (*RangeIndex, error)) entityStore[*Checkpoint] { + makeEntity := func() *Checkpoint { return new(Checkpoint) } return newEntityStore(tx, kv.BorCheckpoints, makeEntity, reader.LastCheckpointId, reader.Checkpoint, blockNumToIdIndexFactory) } -func newMilestoneStore(tx kv.RwTx, reader services.BorMilestoneReader, blockNumToIdIndexFactory func(context.Context) (*RangeIndex, error)) entityStore { - makeEntity := func() Entity { return new(Milestone) } +func newMilestoneStore(tx kv.RwTx, reader services.BorMilestoneReader, blockNumToIdIndexFactory func(context.Context) (*RangeIndex, error)) entityStore[*Milestone] { + makeEntity := func() *Milestone { return new(Milestone) } return newEntityStore(tx, kv.BorMilestones, makeEntity, reader.LastMilestoneId, reader.Milestone, blockNumToIdIndexFactory) } -func newSpanStore(tx kv.RwTx, reader services.BorSpanReader, blockNumToIdIndexFactory func(context.Context) (*RangeIndex, error)) entityStore { - makeEntity := func() Entity { return new(Span) } +func newSpanStore(tx kv.RwTx, reader services.BorSpanReader, blockNumToIdIndexFactory func(context.Context) (*RangeIndex, error)) entityStore[*Span] { + makeEntity := func() *Span { return new(Span) } return newEntityStore(tx, kv.BorSpans, makeEntity, reader.LastSpanId, reader.Span, blockNumToIdIndexFactory) } @@ -92,24 +92,23 @@ func NewService( func (s *service) FetchLatestSpan(ctx context.Context) (*Span, error) { s.scraper.Synchronize(ctx) - entity, err := s.spanStore.GetLastEntity(ctx) - return downcastSpanEntity(entity), err + return s.spanStore.GetLastEntity(ctx) } -func castEntityToWaypoint(entity Entity) Waypoint { - return entity.(Waypoint) +func castEntityToWaypoint[TEntity Waypoint](entity TEntity) Waypoint { + return entity } func (s *service) FetchCheckpointsFromBlock(ctx context.Context, startBlock uint64) (Waypoints, error) { s.scraper.Synchronize(ctx) entities, err := s.checkpointStore.RangeFromBlockNum(ctx, startBlock) - return libcommon.SliceMap(entities, castEntityToWaypoint), err + return libcommon.SliceMap(entities, castEntityToWaypoint[*Checkpoint]), err } func (s *service) FetchMilestonesFromBlock(ctx context.Context, startBlock uint64) (Waypoints, error) { s.scraper.Synchronize(ctx) entities, err := s.milestoneStore.RangeFromBlockNum(ctx, startBlock) - return libcommon.SliceMap(entities, castEntityToWaypoint), err + return libcommon.SliceMap(entities, castEntityToWaypoint[*Milestone]), err } // TODO: this limit is a temporary solution to avoid piping thousands of events diff --git a/polygon/heimdall/span.go b/polygon/heimdall/span.go index 6083395f4aa..4021b241a82 100644 --- a/polygon/heimdall/span.go +++ b/polygon/heimdall/span.go @@ -15,6 +15,8 @@ type Span struct { ChainID string `json:"bor_chain_id,omitempty" yaml:"bor_chain_id"` } +var _ Entity = &Span{} + func (s *Span) RawId() uint64 { return uint64(s.Id) } @@ -26,13 +28,13 @@ func (s *Span) BlockNumRange() ClosedRange { } } -func (hs *Span) Less(other btree.Item) bool { +func (s *Span) Less(other btree.Item) bool { otherHs := other.(*Span) - if hs.EndBlock == 0 || otherHs.EndBlock == 0 { + if s.EndBlock == 0 || otherHs.EndBlock == 0 { // if endblock is not specified in one of the items, allow search by ID - return hs.Id < otherHs.Id + return s.Id < otherHs.Id } - return hs.EndBlock < otherHs.EndBlock + return s.EndBlock < otherHs.EndBlock } func (s *Span) CmpRange(n uint64) int { diff --git a/polygon/heimdall/waypoint.go b/polygon/heimdall/waypoint.go index 565191e9d25..7cf93b47926 100644 --- a/polygon/heimdall/waypoint.go +++ b/polygon/heimdall/waypoint.go @@ -8,6 +8,7 @@ import ( ) type Waypoint interface { + Entity fmt.Stringer StartBlock() *big.Int EndBlock() *big.Int