Skip to content

Commit fc47bcc

Browse files
authored
Merge pull request #3 from 01builders/cian/export-da-height-for-latest-blob-submission
feat: add submission da height
2 parents 247b3ae + 07b4445 commit fc47bcc

File tree

4 files changed

+148
-14
lines changed

4 files changed

+148
-14
lines changed

.github/workflows/docker.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ on:
77
- master
88
tags:
99
- 'v*'
10+
pull_request:
11+
branches:
12+
- main
1013

1114
env:
1215
REGISTRY: ghcr.io
@@ -44,8 +47,8 @@ jobs:
4447
tags: |
4548
type=ref,event=branch
4649
type=ref,event=pr
47-
type=semver,pattern={{version}}
48-
type=semver,pattern={{major}}.{{minor}}
50+
type=semver,pattern=v{{version}}
51+
type=semver,pattern=v{{major}}.{{minor}}
4952
type=sha
5053
5154
- name: Build and push

cmd/verifier.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ func (v *BlockVerifier) VerifyHeadersAndData(ctx context.Context) error {
6666
}
6767
}
6868

69-
func (v *BlockVerifier) onVerified(namespace string, blockHeight uint64, verified bool) {
69+
func (v *BlockVerifier) onVerified(namespace string, blockHeight, daHeight uint64, verified bool) {
7070
if verified {
71+
v.metrics.RecordSubmissionDaHeight(v.chainID, namespace, daHeight)
7172
v.metrics.RemoveVerifiedBlock(v.chainID, namespace, blockHeight)
7273
} else {
7374
v.metrics.RecordMissingBlock(v.chainID, namespace, blockHeight)
@@ -153,7 +154,7 @@ func (v *BlockVerifier) retryBlock(ctx context.Context, header *types.Header) {
153154
Uint64("da_height", daHeight).
154155
Dur("duration", time.Since(startTime)).
155156
Msg("header blob verified on Celestia")
156-
v.onVerified(namespace, blockHeight, true)
157+
v.onVerified(namespace, blockHeight, daHeight, true)
157158
return
158159
}
159160

@@ -163,7 +164,7 @@ func (v *BlockVerifier) retryBlock(ctx context.Context, header *types.Header) {
163164
Uint64("da_height", daHeight).
164165
Dur("duration", time.Since(startTime)).
165166
Msg("max retries reached - header blob not verified")
166-
v.onVerified(namespace, blockHeight, false)
167+
v.onVerified(namespace, blockHeight, daHeight, false)
167168
return
168169
}
169170
logger.Warn().Uint64("da_height", daHeight).Int("attempt", retries).Msg("verification failed, will retry")
@@ -173,7 +174,7 @@ func (v *BlockVerifier) retryBlock(ctx context.Context, header *types.Header) {
173174
logger.Info().
174175
Dur("duration", time.Since(startTime)).
175176
Msg("empty data block - no verification needed")
176-
v.onVerified(namespace, blockHeight, true)
177+
v.onVerified(namespace, blockHeight, daHeight, true)
177178
return
178179
}
179180

@@ -189,7 +190,7 @@ func (v *BlockVerifier) retryBlock(ctx context.Context, header *types.Header) {
189190
Uint64("da_height", daHeight).
190191
Dur("duration", time.Since(startTime)).
191192
Msg("data blob verified on Celestia")
192-
v.onVerified(namespace, blockHeight, true)
193+
v.onVerified(namespace, blockHeight, daHeight, true)
193194
return
194195
}
195196

@@ -199,7 +200,7 @@ func (v *BlockVerifier) retryBlock(ctx context.Context, header *types.Header) {
199200
Uint64("da_height", daHeight).
200201
Dur("duration", time.Since(startTime)).
201202
Msg("max retries reached - data blob not verified")
202-
v.onVerified(namespace, blockHeight, false)
203+
v.onVerified(namespace, blockHeight, daHeight, false)
203204
return
204205
}
205206
logger.Warn().Uint64("da_height", daHeight).Int("attempt", retries).Msg("verification failed, will retry")
@@ -212,5 +213,5 @@ func (v *BlockVerifier) retryBlock(ctx context.Context, header *types.Header) {
212213

213214
// if loop completes without success, log final error
214215
logger.Error().Msg("max retries exhausted - ALERT: failed to verify block")
215-
v.onVerified(namespace, blockHeight, false)
216+
v.onVerified(namespace, blockHeight, 0, false)
216217
}

internal/metrics/metrics.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ type Metrics struct {
2323
CurrentBlockHeight *prometheus.GaugeVec
2424
// BlockHeightDrift tracks the drift between reference and target endpoints for a specific node.
2525
BlockHeightDrift *prometheus.GaugeVec
26+
// SubmissionDaHeight tracks the DA height at which blocks were submitted.
27+
SubmissionDaHeight *prometheus.GaugeVec
28+
29+
// internal tracking to ensure we only record increasing DA heights
30+
latestHeaderDaHeight uint64
31+
latestDataDaHeight uint64
2632

2733
mu sync.Mutex
2834
ranges map[string][]*blockRange // key: blobType -> sorted slice of ranges
@@ -90,10 +96,39 @@ func NewWithRegistry(namespace string, registerer prometheus.Registerer) *Metric
9096
},
9197
[]string{"chain_id", "target_endpoint"},
9298
),
99+
SubmissionDaHeight: factory.NewGaugeVec(
100+
prometheus.GaugeOpts{
101+
Namespace: namespace,
102+
Name: "submission_da_height",
103+
Help: "latest DA height for header and data submissions",
104+
},
105+
[]string{"chain_id", "type"},
106+
),
93107
ranges: make(map[string][]*blockRange),
94108
}
95109
}
96110

111+
// RecordSubmissionDaHeight records the DA height only if it's higher than previously recorded
112+
func (m *Metrics) RecordSubmissionDaHeight(chainID, submissionType string, daHeight uint64) {
113+
m.mu.Lock()
114+
defer m.mu.Unlock()
115+
116+
if submissionType == "header" {
117+
if daHeight > m.latestHeaderDaHeight {
118+
m.latestHeaderDaHeight = daHeight
119+
m.SubmissionDaHeight.WithLabelValues(chainID, "header").Set(float64(daHeight))
120+
}
121+
return
122+
}
123+
124+
if submissionType == "data" {
125+
if daHeight > m.latestDataDaHeight {
126+
m.latestDataDaHeight = daHeight
127+
m.SubmissionDaHeight.WithLabelValues(chainID, "data").Set(float64(daHeight))
128+
}
129+
}
130+
}
131+
97132
// RecordTotalMissingBlocks updates the total count of missing blocks metric.
98133
func (m *Metrics) RecordTotalMissingBlocks(chainID, blobType string) {
99134
ranges := m.ranges[blobType]

internal/metrics/metrics_test.go

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,11 @@ func TestMetrics_RecordMissingBlock(t *testing.T) {
138138

139139
func TestMetrics_RemoveVerifiedBlock(t *testing.T) {
140140
tests := []struct {
141-
name string
142-
setupBlocks []blockToRecord
143-
removeBlock blockToRemove
144-
expectedRanges []expectedRange
145-
expectNoRanges bool
141+
name string
142+
setupBlocks []blockToRecord
143+
removeBlock blockToRemove
144+
expectedRanges []expectedRange
145+
expectNoRanges bool
146146
}{
147147
{
148148
name: "remove single block range - deletes range",
@@ -320,6 +320,101 @@ func TestMetrics_RemoveVerifiedBlock(t *testing.T) {
320320
}
321321
}
322322

323+
func TestMetrics_RecordSubmissionDaHeight(t *testing.T) {
324+
325+
for _, tc := range []struct {
326+
name string
327+
daHeight uint64
328+
submissionType string
329+
setup func(m *Metrics)
330+
assertionFn func(t *testing.T, value float64)
331+
}{
332+
{
333+
"header: record first submission DA height",
334+
100,
335+
"header",
336+
nil,
337+
func(t *testing.T, value float64) {
338+
require.Equal(t, float64(100), value, "should have recorded first submission DA height")
339+
},
340+
},
341+
{
342+
"header: can't record lower height",
343+
100,
344+
"header",
345+
func(m *Metrics) {
346+
m.RecordSubmissionDaHeight("testchain", "header", 105)
347+
},
348+
func(t *testing.T, value float64) {
349+
require.Equal(t, float64(105), value, "should not have overridden with lower DA height")
350+
},
351+
},
352+
{
353+
"header: jump in height",
354+
10000,
355+
"header",
356+
func(m *Metrics) {
357+
m.RecordSubmissionDaHeight("testchain", "header", 100)
358+
},
359+
func(t *testing.T, value float64) {
360+
require.Equal(t, float64(10000), value, "should have been able to override a higher DA height")
361+
},
362+
},
363+
{
364+
"data: record first submission DA height",
365+
100,
366+
"data",
367+
nil,
368+
func(t *testing.T, value float64) {
369+
require.Equal(t, float64(100), value, "should have recorded first submission DA height")
370+
},
371+
},
372+
{
373+
"data: can't record lower height",
374+
100,
375+
"data",
376+
func(m *Metrics) {
377+
m.RecordSubmissionDaHeight("testchain", "data", 105)
378+
},
379+
func(t *testing.T, value float64) {
380+
require.Equal(t, float64(105), value, "should not have overridden with lower DA height")
381+
},
382+
},
383+
{
384+
"data: jump in height",
385+
10000,
386+
"data",
387+
func(m *Metrics) {
388+
m.RecordSubmissionDaHeight("testchain", "data", 100)
389+
},
390+
func(t *testing.T, value float64) {
391+
require.Equal(t, float64(10000), value, "should have been able to override a higher DA height")
392+
},
393+
},
394+
} {
395+
reg := prometheus.NewRegistry()
396+
m := NewWithRegistry("test", reg)
397+
398+
// perform any test setup before recording the submission height
399+
if tc.setup != nil {
400+
tc.setup(m)
401+
}
402+
403+
m.RecordSubmissionDaHeight("testchain", tc.submissionType, tc.daHeight)
404+
405+
// fetch the value of the metric for assertion.
406+
value := getMetricValue(t, reg, "test_submission_da_height", map[string]string{
407+
"chain_id": "testchain",
408+
"submission_type": tc.submissionType,
409+
})
410+
411+
t.Run(tc.name, func(t *testing.T) {
412+
tc.assertionFn(t, value)
413+
})
414+
}
415+
416+
}
417+
323418
func TestMetrics_ComplexScenario(t *testing.T) {
324419
reg := prometheus.NewRegistry()
325420
m := NewWithRegistry("test", reg)

0 commit comments

Comments
 (0)