From 7765cbd95f4b7beea61ad3b185062f2ed6f1de42 Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Mon, 1 Jul 2024 15:05:49 +0200 Subject: [PATCH 1/2] feat(store): add Tail method --- headertest/store.go | 10 ++++++++++ interface.go | 3 +++ p2p/server_test.go | 6 ++++++ store/store.go | 16 ++++++++++++++++ store/store_test.go | 14 ++++++++++++-- 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/headertest/store.go b/headertest/store.go index 8eae0e99..a6456d2a 100644 --- a/headertest/store.go +++ b/headertest/store.go @@ -51,6 +51,16 @@ func (m *Store[H]) Head(context.Context, ...header.HeadOption[H]) (H, error) { return m.Headers[m.HeadHeight], nil } +func (m *Store[H]) Tail(context.Context) (H, error) { + var err error + // TODO(cristaloleg): for now trying to return genesis. Fix for real oldest header. + h, ok := m.Headers[1] + if !ok { + err = header.ErrNotFound + } + return h, err +} + func (m *Store[H]) Get(ctx context.Context, hash header.Hash) (H, error) { for _, header := range m.Headers { if bytes.Equal(header.Hash(), hash) { diff --git a/interface.go b/interface.go index a2ab3e56..14ac4ca2 100644 --- a/interface.go +++ b/interface.go @@ -67,6 +67,9 @@ type Store[H Header[H]] interface { // Init initializes Store with the given head, meaning it is initialized with the genesis header. Init(context.Context, H) error + // Tail returns the oldest known header. + Tail(context.Context) (H, error) + // Height reports current height of the chain head. Height() uint64 diff --git a/p2p/server_test.go b/p2p/server_test.go index 1e896b2e..7b6454be 100644 --- a/p2p/server_test.go +++ b/p2p/server_test.go @@ -135,6 +135,12 @@ func (timeoutStore[H]) Head(ctx context.Context, _ ...header.HeadOption[H]) (H, return zero, ctx.Err() } +func (timeoutStore[H]) Tail(ctx context.Context) (H, error) { + <-ctx.Done() + var zero H + return zero, ctx.Err() +} + func (timeoutStore[H]) Get(ctx context.Context, _ header.Hash) (H, error) { <-ctx.Done() var zero H diff --git a/store/store.go b/store/store.go index bd4cb3af..267fdcf3 100644 --- a/store/store.go +++ b/store/store.go @@ -191,6 +191,22 @@ func (s *Store[H]) Head(ctx context.Context, _ ...header.HeadOption[H]) (H, erro } } +// Tail implements [header.Store] interface. +func (s *Store[H]) Tail(ctx context.Context) (H, error) { + tailPtr := s.tailHeader.Load() + if tailPtr != nil { + return *tailPtr, nil + } + + // TODO(cristaloleg): for now we return genesis header, return real tail. + tail, err := s.GetByHeight(ctx, 1) + if err != nil { + var zero H + return zero, nil + } + return tail, nil +} + func (s *Store[H]) Get(ctx context.Context, hash header.Hash) (H, error) { var zero H if v, ok := s.cache.Get(hash.String()); ok { diff --git a/store/store_test.go b/store/store_test.go index 9213f0b0..230539d4 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -19,8 +19,9 @@ func TestStore(t *testing.T) { suite := headertest.NewTestSuite(t) + genesis := suite.Head() ds := sync.MutexWrap(datastore.NewMapDatastore()) - store := NewTestStore(t, ctx, ds, suite.Head()) + store := NewTestStore(t, ctx, ds, genesis) assert.Equal(t, *store.tailHeader.Load(), suite.Head()) @@ -86,6 +87,10 @@ func TestStore(t *testing.T) { require.NoError(t, err) assert.Equal(t, suite.Head().Hash(), head.Hash()) + tail, err := store.Tail(ctx) + require.NoError(t, err) + assert.Equal(t, tail.Hash(), genesis.Hash()) + out, err = store.getRangeByHeight(ctx, 1, 13) require.NoError(t, err) assert.Len(t, out, 12) @@ -278,6 +283,11 @@ func TestStoreInit(t *testing.T) { require.NoError(t, err) headers := suite.GenDummyHeaders(10) - err = store.Init(ctx, headers[len(headers)-1]) // init should work with any height, not only 1 + h := headers[len(headers)-1] + err = store.Init(ctx, h) // init should work with any height, not only 1 + require.NoError(t, err) + + tail, err := store.Tail(ctx) + assert.Equal(t, tail.Hash(), h.Hash()) require.NoError(t, err) } From e84f4089407c6b22f8b1683e58fb3e5ee3136cab Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Mon, 1 Jul 2024 17:59:54 +0200 Subject: [PATCH 2/2] store tailHeader --- store/store.go | 1 + 1 file changed, 1 insertion(+) diff --git a/store/store.go b/store/store.go index 267fdcf3..a003bb3d 100644 --- a/store/store.go +++ b/store/store.go @@ -204,6 +204,7 @@ func (s *Store[H]) Tail(ctx context.Context) (H, error) { var zero H return zero, nil } + s.tailHeader.Store(&tail) return tail, nil }