Skip to content

Commit

Permalink
feat(store): add Tail method
Browse files Browse the repository at this point in the history
  • Loading branch information
cristaloleg committed Jul 1, 2024
1 parent 7d9aad6 commit 7765cbd
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 2 deletions.
10 changes: 10 additions & 0 deletions headertest/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 6 additions & 0 deletions p2p/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
14 changes: 12 additions & 2 deletions store/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}

0 comments on commit 7765cbd

Please sign in to comment.