Skip to content

Commit c3bac1b

Browse files
committed
extract epoch calculation
1 parent 9f03c71 commit c3bac1b

4 files changed

Lines changed: 344 additions & 231 deletions

File tree

block/internal/syncing/da_retriever.go

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func (r *daRetriever) RetrieveForcedIncludedTxsFromDA(ctx context.Context, daHei
114114
}
115115

116116
// Calculate deterministic epoch boundaries
117-
epochStart, epochEnd := r.calculateEpochBoundaries(daHeight)
117+
epochStart, epochEnd := types.CalculateEpochBoundaries(daHeight, r.genesis.DAStartHeight, r.daEpochSize)
118118

119119
// Only fetch at epoch start to prevent double fetching as DA height progresses
120120
if daHeight != epochStart {
@@ -137,7 +137,7 @@ func (r *daRetriever) RetrieveForcedIncludedTxsFromDA(ctx context.Context, daHei
137137
Uint64("da_height", daHeight).
138138
Uint64("epoch_start", epochStart).
139139
Uint64("epoch_end", epochEnd).
140-
Uint64("epoch_num", r.calculateEpochNumber(daHeight)).
140+
Uint64("epoch_num", types.CalculateEpochNumber(daHeight, r.genesis.DAStartHeight, r.daEpochSize)).
141141
Msg("retrieving forced included transactions from DA")
142142

143143
// Check if both epoch start and end are available before fetching
@@ -247,38 +247,6 @@ func (r *daRetriever) processForcedInclusionBlobs(
247247
return nil
248248
}
249249

250-
// calculateEpochNumber returns the deterministic epoch number for a given DA height.
251-
// Epoch 1 starts at DAStartHeight.
252-
func (r *daRetriever) calculateEpochNumber(daHeight uint64) uint64 {
253-
if daHeight < r.genesis.DAStartHeight {
254-
return 0
255-
}
256-
257-
if r.daEpochSize == 0 {
258-
return 1
259-
}
260-
261-
return ((daHeight - r.genesis.DAStartHeight) / r.daEpochSize) + 1
262-
}
263-
264-
// calculateEpochBoundaries returns the start and end DA heights for the epoch
265-
// containing the given DA height. The boundaries are inclusive.
266-
func (r *daRetriever) calculateEpochBoundaries(daHeight uint64) (start, end uint64) {
267-
if daHeight < r.genesis.DAStartHeight {
268-
return r.genesis.DAStartHeight, r.genesis.DAStartHeight + r.daEpochSize - 1
269-
}
270-
271-
if r.daEpochSize == 0 {
272-
return r.genesis.DAStartHeight, r.genesis.DAStartHeight
273-
}
274-
275-
epochNum := r.calculateEpochNumber(daHeight)
276-
start = r.genesis.DAStartHeight + (epochNum-1)*r.daEpochSize
277-
end = r.genesis.DAStartHeight + epochNum*r.daEpochSize - 1
278-
279-
return start, end
280-
}
281-
282250
// fetchBlobs retrieves blobs from the DA layer
283251
func (r *daRetriever) fetchBlobs(ctx context.Context, daHeight uint64) (coreda.ResultRetrieve, error) {
284252
// Retrieve from both namespaces

block/internal/syncing/da_retriever_test.go

Lines changed: 0 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -624,203 +624,6 @@ func TestDARetriever_RetrieveForcedIncludedTxsFromDA_ExceedsMaxBlobSize(t *testi
624624
assert.Greater(t, totalSizeWithThird, int(common.DefaultMaxBlobSize))
625625
}
626626

627-
func TestDARetriever_CalculateEpochNumber(t *testing.T) {
628-
tests := []struct {
629-
name string
630-
daStartHeight uint64
631-
daEpochSize uint64
632-
daHeight uint64
633-
expectedEpoch uint64
634-
}{
635-
{
636-
name: "first epoch - start height",
637-
daStartHeight: 100,
638-
daEpochSize: 10,
639-
daHeight: 100,
640-
expectedEpoch: 1,
641-
},
642-
{
643-
name: "first epoch - middle",
644-
daStartHeight: 100,
645-
daEpochSize: 10,
646-
daHeight: 105,
647-
expectedEpoch: 1,
648-
},
649-
{
650-
name: "first epoch - last height",
651-
daStartHeight: 100,
652-
daEpochSize: 10,
653-
daHeight: 109,
654-
expectedEpoch: 1,
655-
},
656-
{
657-
name: "second epoch - start",
658-
daStartHeight: 100,
659-
daEpochSize: 10,
660-
daHeight: 110,
661-
expectedEpoch: 2,
662-
},
663-
{
664-
name: "second epoch - middle",
665-
daStartHeight: 100,
666-
daEpochSize: 10,
667-
daHeight: 115,
668-
expectedEpoch: 2,
669-
},
670-
{
671-
name: "tenth epoch",
672-
daStartHeight: 100,
673-
daEpochSize: 10,
674-
daHeight: 195,
675-
expectedEpoch: 10,
676-
},
677-
{
678-
name: "before start height",
679-
daStartHeight: 100,
680-
daEpochSize: 10,
681-
daHeight: 50,
682-
expectedEpoch: 0,
683-
},
684-
{
685-
name: "zero epoch size",
686-
daStartHeight: 100,
687-
daEpochSize: 0,
688-
daHeight: 200,
689-
expectedEpoch: 1,
690-
},
691-
{
692-
name: "large epoch size",
693-
daStartHeight: 1000,
694-
daEpochSize: 1000,
695-
daHeight: 2500,
696-
expectedEpoch: 2,
697-
},
698-
}
699-
700-
for _, tt := range tests {
701-
t.Run(tt.name, func(t *testing.T) {
702-
ds := dssync.MutexWrap(datastore.NewMapDatastore())
703-
st := store.New(ds)
704-
cm, err := cache.NewManager(config.DefaultConfig(), st, zerolog.Nop())
705-
require.NoError(t, err)
706-
707-
mockDA := testmocks.NewMockDA(t)
708-
gen := genesis.Genesis{DAStartHeight: tt.daStartHeight}
709-
cfg := config.DefaultConfig()
710-
cfg.DA.ForcedInclusionDAEpoch = tt.daEpochSize
711-
712-
r := NewDARetriever(mockDA, cm, cfg, gen, zerolog.Nop())
713-
epoch := r.calculateEpochNumber(tt.daHeight)
714-
715-
assert.Equal(t, tt.expectedEpoch, epoch)
716-
})
717-
}
718-
}
719-
720-
func TestDARetriever_CalculateEpochBoundaries(t *testing.T) {
721-
tests := []struct {
722-
name string
723-
daStartHeight uint64
724-
daEpochSize uint64
725-
daHeight uint64
726-
expectedStart uint64
727-
expectedEnd uint64
728-
}{
729-
{
730-
name: "first epoch",
731-
daStartHeight: 100,
732-
daEpochSize: 10,
733-
daHeight: 105,
734-
expectedStart: 100,
735-
expectedEnd: 109,
736-
},
737-
{
738-
name: "second epoch",
739-
daStartHeight: 100,
740-
daEpochSize: 10,
741-
daHeight: 110,
742-
expectedStart: 110,
743-
expectedEnd: 119,
744-
},
745-
{
746-
name: "third epoch - last height",
747-
daStartHeight: 100,
748-
daEpochSize: 10,
749-
daHeight: 129,
750-
expectedStart: 120,
751-
expectedEnd: 129,
752-
},
753-
{
754-
name: "before start height returns first epoch",
755-
daStartHeight: 100,
756-
daEpochSize: 10,
757-
daHeight: 50,
758-
expectedStart: 100,
759-
expectedEnd: 109,
760-
},
761-
{
762-
name: "zero epoch size",
763-
daStartHeight: 100,
764-
daEpochSize: 0,
765-
daHeight: 200,
766-
expectedStart: 100,
767-
expectedEnd: 100,
768-
},
769-
{
770-
name: "large epoch",
771-
daStartHeight: 1000,
772-
daEpochSize: 1000,
773-
daHeight: 1500,
774-
expectedStart: 1000,
775-
expectedEnd: 1999,
776-
},
777-
{
778-
name: "epoch boundary exact start",
779-
daStartHeight: 100,
780-
daEpochSize: 50,
781-
daHeight: 100,
782-
expectedStart: 100,
783-
expectedEnd: 149,
784-
},
785-
{
786-
name: "epoch boundary exact end of first epoch",
787-
daStartHeight: 100,
788-
daEpochSize: 50,
789-
daHeight: 149,
790-
expectedStart: 100,
791-
expectedEnd: 149,
792-
},
793-
{
794-
name: "epoch boundary exact start of second epoch",
795-
daStartHeight: 100,
796-
daEpochSize: 50,
797-
daHeight: 150,
798-
expectedStart: 150,
799-
expectedEnd: 199,
800-
},
801-
}
802-
803-
for _, tt := range tests {
804-
t.Run(tt.name, func(t *testing.T) {
805-
ds := dssync.MutexWrap(datastore.NewMapDatastore())
806-
st := store.New(ds)
807-
cm, err := cache.NewManager(config.DefaultConfig(), st, zerolog.Nop())
808-
require.NoError(t, err)
809-
810-
mockDA := testmocks.NewMockDA(t)
811-
gen := genesis.Genesis{DAStartHeight: tt.daStartHeight}
812-
cfg := config.DefaultConfig()
813-
cfg.DA.ForcedInclusionDAEpoch = tt.daEpochSize
814-
815-
r := NewDARetriever(mockDA, cm, cfg, gen, zerolog.Nop())
816-
start, end := r.calculateEpochBoundaries(tt.daHeight)
817-
818-
assert.Equal(t, tt.expectedStart, start, "start height mismatch")
819-
assert.Equal(t, tt.expectedEnd, end, "end height mismatch")
820-
})
821-
}
822-
}
823-
824627
func TestDARetriever_RetrieveForcedIncludedTxsFromDA_NotAtEpochStart(t *testing.T) {
825628
ds := dssync.MutexWrap(datastore.NewMapDatastore())
826629
st := store.New(ds)

types/epoch.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package types
2+
3+
// CalculateEpochNumber returns the deterministic epoch number for a given DA height.
4+
// Epoch 1 starts at daStartHeight.
5+
//
6+
// Parameters:
7+
// - daHeight: The DA height to calculate the epoch for
8+
// - daStartHeight: The genesis DA start height
9+
// - daEpochSize: The number of DA blocks per epoch (0 means all blocks in epoch 1)
10+
//
11+
// Returns:
12+
// - Epoch number (0 if before daStartHeight, 1+ otherwise)
13+
func CalculateEpochNumber(daHeight, daStartHeight, daEpochSize uint64) uint64 {
14+
if daHeight < daStartHeight {
15+
return 0
16+
}
17+
18+
if daEpochSize == 0 {
19+
return 1
20+
}
21+
22+
return ((daHeight - daStartHeight) / daEpochSize) + 1
23+
}
24+
25+
// CalculateEpochBoundaries returns the start and end DA heights for the epoch
26+
// containing the given DA height. The boundaries are inclusive.
27+
//
28+
// Parameters:
29+
// - daHeight: The DA height to calculate boundaries for
30+
// - daStartHeight: The genesis DA start height
31+
// - daEpochSize: The number of DA blocks per epoch (0 means single epoch)
32+
//
33+
// Returns:
34+
// - start: The first DA height in the epoch (inclusive)
35+
// - end: The last DA height in the epoch (inclusive)
36+
func CalculateEpochBoundaries(daHeight, daStartHeight, daEpochSize uint64) (start, end uint64) {
37+
if daHeight < daStartHeight {
38+
return daStartHeight, daStartHeight + daEpochSize - 1
39+
}
40+
41+
if daEpochSize == 0 {
42+
return daStartHeight, daStartHeight
43+
}
44+
45+
epochNum := CalculateEpochNumber(daHeight, daStartHeight, daEpochSize)
46+
start = daStartHeight + (epochNum-1)*daEpochSize
47+
end = daStartHeight + epochNum*daEpochSize - 1
48+
49+
return start, end
50+
}

0 commit comments

Comments
 (0)