@@ -56,48 +56,40 @@ func (nilHeaderStore) GetHeader(context.Context, uint64) (*types.SignedHeader, e
5656 return nil , nil
5757}
5858
59- func TestDetectDoubleSign_NilIncomingReturnsError (t * testing.T ) {
60- env := newDSTestEnv (t )
61- ev , err := detectDoubleSign (context .Background (), env .store , env .cache , nil , types .EvidenceSourceP2P )
62- require .Error (t , err )
63- require .Nil (t , ev )
64- }
65-
6659// A non-NotFound store failure must be surfaced, not swallowed.
67- func TestDetectDoubleSign_StoreErrorWrapped (t * testing.T ) {
60+ func TestFirstObservation_StoreErrorWrapped (t * testing.T ) {
6861 env := newDSTestEnv (t )
6962 wrapped := & errStore {Store : env .store , getHeaderErr : errors .New ("backend down" )}
7063
71- alt := env .signHeaderAtHeight (5 , 0x01 )
72- ev , err := detectDoubleSign (context .Background (), wrapped , env .cache , alt , types .EvidenceSourceP2P )
64+ prior , priorSource , err := firstObservation (context .Background (), wrapped , env .cache , 5 )
7365 require .Error (t , err )
74- require .Nil (t , ev )
66+ require .Nil (t , prior )
67+ require .Empty (t , priorSource )
7568 require .Contains (t , err .Error (), "lookup stored header" )
7669 require .ErrorContains (t , err , "backend down" )
7770}
7871
79- func TestDetectDoubleSign_StoredHeaderNilDefensive (t * testing.T ) {
72+ func TestFirstObservation_StoredHeaderNilDefensive (t * testing.T ) {
8073 env := newDSTestEnv (t )
8174 wrapped := nilHeaderStore {Store : env .store }
8275
83- alt := env .signHeaderAtHeight (5 , 0x01 )
84- ev , err := detectDoubleSign (context .Background (), wrapped , env .cache , alt , types .EvidenceSourceP2P )
76+ prior , priorSource , err := firstObservation (context .Background (), wrapped , env .cache , 5 )
8577 require .NoError (t , err )
86- require .Nil (t , ev )
78+ require .Nil (t , prior )
79+ require .Empty (t , priorSource )
8780}
8881
89- // Store-path detections must use the "stored" sentinel as FirstSource so
90- // downstream consumers can disambiguate it from in-flight observations.
91- func TestDetectDoubleSign_FirstSourceStoredSentinel (t * testing.T ) {
82+ // Store-path observations must use the "stored" sentinel as the source so
83+ // downstream consumers can disambiguate them from in-flight observations.
84+ func TestFirstObservation_StoredSourceSentinel (t * testing.T ) {
9285 env := newDSTestEnv (t )
9386 first := env .signHeaderAtHeight (5 , 0x01 )
9487 env .saveHeader (first )
9588
96- alt := env .signHeaderAtHeight (5 , 0x02 )
97- ev , err := detectDoubleSign (context .Background (), env .store , env .cache , alt , types .EvidenceSourceP2P )
89+ prior , priorSource , err := firstObservation (context .Background (), env .store , env .cache , first .Height ())
9890 require .NoError (t , err )
99- require .NotNil (t , ev )
100- require .Equal (t , types .EvidenceSourceStored , ev . FirstSource )
91+ require .NotNil (t , prior )
92+ require .Equal (t , types .EvidenceSourceStored , priorSource )
10193}
10294
10395// SetMetadata failures must include the canonical key so an operator can
@@ -118,7 +110,7 @@ func TestPersistEvidence_StoreError(t *testing.T) {
118110}
119111
120112// Persistence failure must not break the halt contract: metric still
121- // increments, criticalErr still fires, returned error still wraps ErrDoubleSign.
113+ // increments and the returned error still wraps ErrDoubleSign.
122114func TestReportDoubleSign_PersistFailureLoggedNotBlocking (t * testing.T ) {
123115 env := newDSTestEnv (t )
124116 wrapped := & errStore {Store : env .store , setMetadataErr : errors .New ("disk full" )}
@@ -132,16 +124,12 @@ func TestReportDoubleSign_PersistFailureLoggedNotBlocking(t *testing.T) {
132124 metrics := common .NopMetrics ()
133125 metrics .DoubleSignsDetected = & counterCtr {n : & dsCount }
134126
135- var fired atomic.Pointer [error ]
136- crit := func (err error ) { fired .Store (& err ) }
137-
138127 halt := reportDoubleSign (context .Background (), wrapped , metrics , zerolog .Nop (),
139- newDoubleSignDedup (), crit , ev )
128+ newDoubleSignDedup (), ev )
140129 require .Error (t , halt )
141130 require .ErrorIs (t , halt , ErrDoubleSign )
142131
143132 require .Equal (t , int64 (1 ), dsCount .Load ())
144- require .NotNil (t , fired .Load ())
145133}
146134
147135// Dedup is keyed on (height, altHash), so two distinct alts at the same
@@ -163,12 +151,11 @@ func TestReportDoubleSign_TwoDistinctAltsAtSameHeight(t *testing.T) {
163151 metrics .DoubleSignsDetected = & counterCtr {n : & dsCount }
164152
165153 seen := newDoubleSignDedup ()
166- noopCrit := func (error ) {}
167154
168155 require .Error (t , reportDoubleSign (context .Background (), env .store , metrics ,
169- zerolog .Nop (), seen , noopCrit , ev1 ))
156+ zerolog .Nop (), seen , ev1 ))
170157 require .Error (t , reportDoubleSign (context .Background (), env .store , metrics ,
171- zerolog .Nop (), seen , noopCrit , ev2 ))
158+ zerolog .Nop (), seen , ev2 ))
172159
173160 require .Equal (t , int64 (2 ), dsCount .Load ())
174161
@@ -189,14 +176,14 @@ func TestReportDoubleSign_NilSeenAndNilGuards(t *testing.T) {
189176
190177 t .Run ("nil seen still halts" , func (t * testing.T ) {
191178 halt := reportDoubleSign (context .Background (), env .store , common .NopMetrics (),
192- zerolog .Nop (), nil , func ( error ) {}, ev )
179+ zerolog .Nop (), nil , ev )
193180 require .Error (t , halt )
194181 require .ErrorIs (t , halt , ErrDoubleSign )
195182 })
196183
197184 t .Run ("nil metrics still halts" , func (t * testing.T ) {
198185 halt := reportDoubleSign (context .Background (), env .store , nil ,
199- zerolog .Nop (), newDoubleSignDedup (), func ( error ) {}, ev )
186+ zerolog .Nop (), newDoubleSignDedup (), ev )
200187 require .Error (t , halt )
201188 require .ErrorIs (t , halt , ErrDoubleSign )
202189 })
@@ -205,14 +192,7 @@ func TestReportDoubleSign_NilSeenAndNilGuards(t *testing.T) {
205192 m := common .NopMetrics ()
206193 m .DoubleSignsDetected = nil
207194 halt := reportDoubleSign (context .Background (), env .store , m ,
208- zerolog .Nop (), newDoubleSignDedup (), func (error ) {}, ev )
209- require .Error (t , halt )
210- require .ErrorIs (t , halt , ErrDoubleSign )
211- })
212-
213- t .Run ("nil criticalErr still halts" , func (t * testing.T ) {
214- halt := reportDoubleSign (context .Background (), env .store , common .NopMetrics (),
215- zerolog .Nop (), newDoubleSignDedup (), nil , ev )
195+ zerolog .Nop (), newDoubleSignDedup (), ev )
216196 require .Error (t , halt )
217197 require .ErrorIs (t , halt , ErrDoubleSign )
218198 })
@@ -270,7 +250,7 @@ func TestDARetriever_AbortsBatchOnDetection(t *testing.T) {
270250
271251 mockClient := newMockDAClient (t )
272252
273- r := NewDARetriever (mockClient , env .cache , env .gen , zerolog .Nop (), env .store , env . onDouble )
253+ r := NewDARetriever (mockClient , env .cache , env .gen , zerolog .Nop (), env .detectDoubleSign )
274254
275255 events := r .ProcessBlobs (context .Background (),
276256 [][]byte {firstBin , altBin , nextBin }, 100 )
@@ -290,7 +270,7 @@ func TestDARetriever_DetectorErrorWarnAndContinue(t *testing.T) {
290270
291271 mockClient := newMockDAClient (t )
292272
293- r := NewDARetriever (mockClient , env .cache , env .gen , zerolog .Nop (), wrapped , env .onDouble )
273+ r := NewDARetriever (mockClient , env .cache , env .gen , zerolog .Nop (), env .makeDetectDoubleSign ( wrapped ) )
294274
295275 _ = r .ProcessBlobs (context .Background (), [][]byte {bin }, 100 )
296276
@@ -324,7 +304,7 @@ func TestDARetriever_StrictModeEnvelopeDoubleSign(t *testing.T) {
324304
325305 mockClient := newMockDAClient (t )
326306
327- r := NewDARetriever (mockClient , env .cache , env .gen , zerolog .Nop (), env .store , env . onDouble )
307+ r := NewDARetriever (mockClient , env .cache , env .gen , zerolog .Nop (), env .detectDoubleSign )
328308
329309 events := r .ProcessBlobs (context .Background (), [][]byte {firstBin , altBin }, 100 )
330310 require .Empty (t , events )
@@ -348,12 +328,11 @@ func TestDARetriever_SetsPendingSignedHeaderOnFirstObservation(t *testing.T) {
348328
349329 mockClient := newMockDAClient (t )
350330
351- r := NewDARetriever (mockClient , env .cache , env .gen , zerolog .Nop (), env .store , env . onDouble )
331+ r := NewDARetriever (mockClient , env .cache , env .gen , zerolog .Nop (), env .detectDoubleSign )
352332 _ = r .ProcessBlobs (context .Background (), [][]byte {bin }, 100 )
353333
354334 got , src , ok := env .cache .GetPendingSignedHeader (5 )
355335 require .True (t , ok )
356336 require .Equal (t , first .Hash ().String (), got .Hash ().String ())
357337 require .Equal (t , types .EvidenceSourceDA , src )
358338}
359-
0 commit comments