Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a18e75f
feat: forced inclusion
julienrbrt Nov 21, 2025
5bbfe08
Merge branch 'main' into julien/fi
julienrbrt Nov 24, 2025
46087a4
Apply suggestions from code review
julienrbrt Nov 24, 2025
1412fc2
Merge branch 'main' into julien/fi
julienrbrt Nov 25, 2025
0fb6264
feat(evm): add force inclusion command
julienrbrt Nov 26, 2025
a928c93
docs: add description about da epoch
julienrbrt Nov 26, 2025
fcf4b08
add smoothing checks
julienrbrt Nov 26, 2025
d787575
add docs
julienrbrt Nov 26, 2025
379e793
Merge branch 'main' into julien/fi
julienrbrt Nov 27, 2025
f6c7b01
ai docs
julienrbrt Nov 27, 2025
3a211d3
Merge branch 'julien/fi' into julien/fi-evm-cmd
julienrbrt Nov 27, 2025
bc0bc97
wip
julienrbrt Nov 27, 2025
2786d7b
skip gibberish txs
julienrbrt Nov 27, 2025
d96c74c
use local go.mod
julienrbrt Nov 27, 2025
fe2f80c
cleanups
julienrbrt Nov 27, 2025
230263d
Merge branch 'main' into julien/fi
julienrbrt Nov 28, 2025
28b675d
feat: proxy all other msgs to ev-reth
julienrbrt Nov 28, 2025
fe51201
Merge branch 'julien/fi' into julien/fi-evm-cmd
julienrbrt Nov 28, 2025
e5ba965
implement feedback
julienrbrt Dec 1, 2025
d46db8c
feedback 2/2
julienrbrt Dec 1, 2025
550aceb
Merge branch 'main' into julien/fi
julienrbrt Dec 1, 2025
a587a45
chore: docs nits
julienrbrt Dec 1, 2025
55124ef
Merge branch 'main' into julien/fi
julienrbrt Dec 2, 2025
5755287
Merge branch 'julien/fi' into julien/fi-evm-cmd
julienrbrt Dec 2, 2025
aab910d
api break
julienrbrt Dec 2, 2025
689fdfa
Merge branch 'main' into julien/fi-evm-cmd
julienrbrt Dec 3, 2025
0d98330
merge conflict
julienrbrt Dec 3, 2025
2832ee4
optimize tx sanity checks
julienrbrt Dec 3, 2025
cc61206
modernize
julienrbrt Dec 3, 2025
bb4f511
chore: fix linting
julienrbrt Dec 4, 2025
91e83e5
add replaces
julienrbrt Dec 4, 2025
caa7fba
chore: disable feature again. Code cleanup
julienrbrt Dec 4, 2025
59bc5bb
Merge branch 'main' into julien/fi-evm-cmd
julienrbrt Dec 4, 2025
3a9144b
add changelog
julienrbrt Dec 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
implement feedback
  • Loading branch information
julienrbrt committed Dec 1, 2025
commit e5ba96540c2fd127535814307e47e47ad893518d
27 changes: 12 additions & 15 deletions block/internal/da/forced_inclusion_retriever.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (r *ForcedInclusionRetriever) RetrieveForcedIncludedTxs(ctx context.Context
return nil, ErrForceInclusionNotConfigured
}

epochStart, epochEnd := types.CalculateEpochBoundaries(daHeight, r.genesis.DAStartHeight, r.daEpochSize)
epochStart, epochEnd, currentEpochNumber := types.CalculateEpochBoundaries(daHeight, r.genesis.DAStartHeight, r.daEpochSize)

if daHeight != epochStart {
r.logger.Debug().
Expand All @@ -66,9 +66,6 @@ func (r *ForcedInclusionRetriever) RetrieveForcedIncludedTxs(ctx context.Context
}, nil
}

// We're at epoch start - fetch transactions from DA
currentEpochNumber := types.CalculateEpochNumber(daHeight, r.genesis.DAStartHeight, r.daEpochSize)

event := &ForcedInclusionEvent{
StartDaHeight: epochStart,
Txs: [][]byte{},
Expand All @@ -81,22 +78,22 @@ func (r *ForcedInclusionRetriever) RetrieveForcedIncludedTxs(ctx context.Context
Uint64("epoch_num", currentEpochNumber).
Msg("retrieving forced included transactions from DA")

epochStartResult := r.client.RetrieveForcedInclusion(ctx, epochStart)
if epochStartResult.Code == coreda.StatusHeightFromFuture {
epochEndResult := r.client.RetrieveForcedInclusion(ctx, epochEnd)
if epochEndResult.Code == coreda.StatusHeightFromFuture {
r.logger.Debug().
Uint64("epoch_start", epochStart).
Msg("epoch start height not yet available on DA - backoff required")
return nil, fmt.Errorf("%w: epoch start height %d not yet available", coreda.ErrHeightFromFuture, epochStart)
Uint64("epoch_end", epochEnd).
Msg("epoch end height not yet available on DA - backoff required")
return nil, fmt.Errorf("%w: epoch end height %d not yet available", coreda.ErrHeightFromFuture, epochEnd)
}

epochEndResult := epochStartResult
epochStartResult := epochEndResult
if epochStart != epochEnd {
epochEndResult = r.client.RetrieveForcedInclusion(ctx, epochEnd)
if epochEndResult.Code == coreda.StatusHeightFromFuture {
epochStartResult = r.client.RetrieveForcedInclusion(ctx, epochStart)
if epochStartResult.Code == coreda.StatusHeightFromFuture {
r.logger.Debug().
Uint64("epoch_end", epochEnd).
Msg("epoch end height not yet available on DA - backoff required")
return nil, fmt.Errorf("%w: epoch end height %d not yet available", coreda.ErrHeightFromFuture, epochEnd)
Uint64("epoch_start", epochStart).
Msg("epoch start height not yet available on DA - backoff required")
return nil, fmt.Errorf("%w: epoch start height %d not yet available", coreda.ErrHeightFromFuture, epochStart)
}
}

Expand Down
6 changes: 3 additions & 3 deletions block/internal/syncing/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ func (s *Syncer) verifyForcedInclusionTxs(currentState types.State, data *types.

// Check if any pending forced inclusion txs from previous epochs are included
var stillPending []pendingForcedInclusionTx
s.pendingForcedInclusionTxs.Range(func(key, value interface{}) bool {
s.pendingForcedInclusionTxs.Range(func(key, value any) bool {
pending := value.(pendingForcedInclusionTx)
if _, ok := blockTxMap[pending.TxHash]; ok {
s.logger.Debug().
Expand Down Expand Up @@ -752,7 +752,7 @@ func (s *Syncer) verifyForcedInclusionTxs(currentState types.State, data *types.
}

// Update pending map - clear old entries and store only remaining pending
s.pendingForcedInclusionTxs.Range(func(key, value interface{}) bool {
s.pendingForcedInclusionTxs.Range(func(key, value any) bool {
s.pendingForcedInclusionTxs.Delete(key)
return true
})
Expand All @@ -774,7 +774,7 @@ func (s *Syncer) verifyForcedInclusionTxs(currentState types.State, data *types.
if len(forcedIncludedTxsEvent.Txs) > 0 {
if newPendingCount > 0 {
totalPending := 0
s.pendingForcedInclusionTxs.Range(func(key, value interface{}) bool {
s.pendingForcedInclusionTxs.Range(func(key, value any) bool {
totalPending++
return true
})
Expand Down
6 changes: 3 additions & 3 deletions block/internal/syncing/syncer_forced_inclusion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ func TestVerifyForcedInclusionTxs_DeferralWithinEpoch(t *testing.T) {

// Verify that dataBin2 is now tracked as pending
pendingCount := 0
s.pendingForcedInclusionTxs.Range(func(key, value interface{}) bool {
s.pendingForcedInclusionTxs.Range(func(key, value any) bool {
pendingCount++
return true
})
Expand Down Expand Up @@ -593,7 +593,7 @@ func TestVerifyForcedInclusionTxs_DeferralWithinEpoch(t *testing.T) {

// Verify that pending queue is now empty (dataBin2 was included)
pendingCount = 0
s.pendingForcedInclusionTxs.Range(func(key, value interface{}) bool {
s.pendingForcedInclusionTxs.Range(func(key, value any) bool {
pendingCount++
return true
})
Expand Down Expand Up @@ -699,7 +699,7 @@ func TestVerifyForcedInclusionTxs_MaliciousAfterEpochEnd(t *testing.T) {

// Verify that the forced tx is tracked as pending
pendingCount := 0
s.pendingForcedInclusionTxs.Range(func(key, value interface{}) bool {
s.pendingForcedInclusionTxs.Range(func(key, value any) bool {
pendingCount++
return true
})
Expand Down
2 changes: 1 addition & 1 deletion docs/adr/adr-019-forced-inclusion-mechanism.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ func (s *Syncer) verifyForcedInclusionTxs(currentState State, data *Data) error

// 3. Check if any pending forced inclusion txs from previous epochs are included
var stillPending []pendingForcedInclusionTx
s.pendingForcedInclusionTxs.Range(func(key, value interface{}) bool {
s.pendingForcedInclusionTxs.Range(func(key, value any) bool {
pending := value.(pendingForcedInclusionTx)
if _, ok := blockTxMap[pending.TxHash]; ok {
// Transaction was included - remove from pending
Expand Down
11 changes: 6 additions & 5 deletions types/epoch.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,19 @@ func CalculateEpochNumber(daHeight, daStartHeight, daEpochSize uint64) uint64 {
// Returns:
// - start: The first DA height in the epoch (inclusive)
// - end: The last DA height in the epoch (inclusive)
func CalculateEpochBoundaries(daHeight, daStartHeight, daEpochSize uint64) (start, end uint64) {
func CalculateEpochBoundaries(daHeight, daStartHeight, daEpochSize uint64) (start, end, epochNum uint64) {
epochNum = CalculateEpochNumber(daHeight, daStartHeight, daEpochSize)

if daEpochSize == 0 {
return daStartHeight, daStartHeight
return daStartHeight, daStartHeight, epochNum
}

if daHeight < daStartHeight {
return daStartHeight, daStartHeight + daEpochSize - 1
return daStartHeight, daStartHeight + daEpochSize - 1, epochNum
}

epochNum := CalculateEpochNumber(daHeight, daStartHeight, daEpochSize)
start = daStartHeight + (epochNum-1)*daEpochSize
end = daStartHeight + epochNum*daEpochSize - 1

return start, end
return start, end, epochNum
}
6 changes: 3 additions & 3 deletions types/epoch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func TestCalculateEpochBoundaries(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
start, end := CalculateEpochBoundaries(tt.daHeight, tt.daStartHeight, tt.daEpochSize)
start, end, _ := CalculateEpochBoundaries(tt.daHeight, tt.daStartHeight, tt.daEpochSize)
assert.Equal(t, tt.expectedStart, start, "start height mismatch")
assert.Equal(t, tt.expectedEnd, end, "end height mismatch")
})
Expand Down Expand Up @@ -262,7 +262,7 @@ func TestEpochConsistency(t *testing.T) {
epochNum := CalculateEpochNumber(h, tt.daStartHeight, tt.daEpochSize)
assert.Equal(t, epoch, epochNum, "height %d should be in epoch %d", h, epoch)

start, end := CalculateEpochBoundaries(h, tt.daStartHeight, tt.daEpochSize)
start, end, _ := CalculateEpochBoundaries(h, tt.daStartHeight, tt.daEpochSize)
assert.Equal(t, expectedStart, start, "height %d should have start %d", h, expectedStart)
assert.Equal(t, expectedEnd, end, "height %d should have end %d", h, expectedEnd)
}
Expand Down Expand Up @@ -293,7 +293,7 @@ func TestEpochBoundaryTransitions(t *testing.T) {
epoch := CalculateEpochNumber(tr.height, daStartHeight, daEpochSize)
assert.Equal(t, tr.expectedEpoch, epoch, "height %d epoch mismatch", tr.height)

start, end := CalculateEpochBoundaries(tr.height, daStartHeight, daEpochSize)
start, end, _ := CalculateEpochBoundaries(tr.height, daStartHeight, daEpochSize)
assert.Equal(t, tr.expectedStart, start, "height %d start mismatch", tr.height)
assert.Equal(t, tr.expectedEnd, end, "height %d end mismatch", tr.height)
}
Expand Down