Skip to content

Commit 64c84c4

Browse files
committed
feat(store): store recovery
1 parent 8e8e803 commit 64c84c4

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

store/store.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,14 +612,16 @@ func (s *Store[H]) nextHead(ctx context.Context) (head H, changed bool) {
612612
return head, false
613613
}
614614

615-
for {
615+
for ctx.Err() == nil {
616616
h, err := s.getByHeight(ctx, head.Height()+1)
617617
if err != nil {
618618
return head, changed
619619
}
620620
head = h
621621
changed = true
622622
}
623+
624+
return head, changed
623625
}
624626

625627
// nextTail finds the new contiguous Tail by iterating the current Tail down until the older height Tail is found.
@@ -631,14 +633,16 @@ func (s *Store[H]) nextTail(ctx context.Context) (tail H, changed bool) {
631633
return tail, false
632634
}
633635

634-
for {
636+
for ctx.Err() == nil {
635637
h, err := s.getByHeight(ctx, tail.Height()-1)
636638
if err != nil {
637639
return tail, changed
638640
}
639641
tail = h
640642
changed = true
641643
}
644+
645+
return tail, changed
642646
}
643647

644648
func (s *Store[H]) loadHeadAndTail(ctx context.Context) error {

store/store_recover.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package store
2+
3+
import (
4+
"context"
5+
6+
"github.com/celestiaorg/go-header"
7+
)
8+
9+
// ResetTail resets the tail of the store to be at the given height.
10+
// The new tail must be present in the store.
11+
// WARNING: Only use this function if you know what you are doing.
12+
func ResetTail[H header.Header[H]](ctx context.Context, store *Store[H], height uint64) error {
13+
batch, err := store.ds.Batch(ctx)
14+
if err != nil {
15+
return err
16+
}
17+
18+
err = store.setTail(ctx, batch, height)
19+
if err != nil {
20+
return err
21+
}
22+
23+
err = batch.Commit(ctx)
24+
if err != nil {
25+
return err
26+
}
27+
return nil
28+
}
29+
30+
// ResetHead resets the head of the store to be at the given height.
31+
// The new head must be present in the store.
32+
// WARNING: Only use this function if you know what you are doing.
33+
func ResetHead[H header.Header[H]](ctx context.Context, store *Store[H], height uint64) error {
34+
batch, err := store.ds.Batch(ctx)
35+
if err != nil {
36+
return err
37+
}
38+
39+
newHead, err := store.getByHeight(ctx, height)
40+
if err != nil {
41+
return err
42+
}
43+
44+
if err := writeHeaderHashTo(ctx, batch, newHead, headKey); err != nil {
45+
return err
46+
}
47+
store.contiguousHead.Store(&newHead)
48+
49+
err = batch.Commit(ctx)
50+
if err != nil {
51+
return err
52+
}
53+
return nil
54+
}
55+
56+
// FindHeader forward iterates over the store starting from the given height until it finds any stored header
57+
// or the context is cancelled.
58+
func FindHeader[H header.Header[H]](ctx context.Context, store *Store[H], startFrom uint64) (H, error) {
59+
for height := startFrom; ctx.Err() == nil; height++ {
60+
header, err := store.getByHeight(ctx, height)
61+
if err == nil {
62+
return header, nil
63+
}
64+
}
65+
66+
var zero H
67+
return zero, ctx.Err()
68+
}

0 commit comments

Comments
 (0)