Skip to content

Commit ea94830

Browse files
authored
[KLC-2400] fix flaky configITO ShouldError test: slot-relative ITO windows (#58)
* [KLC-2400] fix flaky configITO ShouldError test: slot-relative ITO windows The KAPP validates ITO windows against ctx.Block().GetTimestamp(), which in tests is genesis + slot*slotDuration — fully deterministic. The test was using time.Now().Add(4s) for StartTime, so on slow runners the configITO tx landed at a block whose timestamp had already passed StartTime and was rejected as invalid. Replace wall-clock offsets with slot-relative anchors so the window invariant blockTs(slot) < itoStart <= blockTs(slot+1) <= itoEnd < blockTs(slot+2) holds by construction. Verified: 20/20 passes in a -count=1 loop (previously ~40% failure on develop). * [KLC-2400] review fixes: rename slot0Ts; harden itoEnd boundary - Rename genesisTs → slot0Ts; the value is the proposer's slot-0 reference (SlotManagerMock captures time.Now() at node construction in block.go), not actual chain genesis. Tighten the explanatory comment to match. - Change itoEnd to slot0Ts + (slot+2)*slotDuration - 1 so the invariant itoEnd < blockTs(slot+2) holds regardless of slotDuration. With the previous +1, a 1s slotDuration would land itoEnd exactly at blockTs(slot+2) and the final "out of window" buy would silently pass the strict-less-than check at ito.go:336-337.
1 parent bfd4001 commit ea94830

1 file changed

Lines changed: 81 additions & 60 deletions

File tree

integrationTest/transaction/configITO/configITO_test.go

Lines changed: 81 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,27 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
195195
require.Nil(t, err)
196196
require.NotNil(t, asset)
197197

198+
// Block timestamps in tests are deterministic: blockTs(s) = slot0Ts + s*slotDuration,
199+
// where slot0Ts is the proposer's slot-0 reference time (SlotManagerMock captures
200+
// time.Now() at node construction — not actual chain genesis, just the anchor the
201+
// proposer uses to compute block timestamps in block.go).
202+
// Pin the ITO window to slot-relative anchors so it doesn't race wall-clock — KAPP
203+
// validates ITO windows against ctx.Block().GetTimestamp(), not time.Now().
204+
// configITOTxHash is processed at block(slot) → ts = slot0Ts + slot*slotDuration
205+
// buy txs are processed at block(slot+1) → ts = slot0Ts + (slot+1)*slotDuration
206+
// "out of window" buy at block(slot+2) → ts = slot0Ts + (slot+2)*slotDuration
207+
// Required: blockTs(slot) < itoStart ≤ blockTs(slot+1) ≤ itoEnd < blockTs(slot+2).
208+
slotDuration := int64(nodes[xidProposerBlock].SlotManager.TimeDuration().Seconds())
209+
slot0Ts := nodes[xidProposerBlock].SlotManager.Timestamp().Unix()
210+
itoStart := slot0Ts + int64(slot+1)*slotDuration
211+
// Strictly less than blockTs(slot+2) regardless of slotDuration — the buy rejection
212+
// at ito.go:336-337 is `EndTime < block.Timestamp`, so equality at block(slot+2)
213+
// would leave the final "out of window" buy in-window if slotDuration ever became 1s.
214+
itoEnd := slot0Ts + int64(slot+2)*slotDuration - 1
215+
// Deliberately end-before-start values for the two malformed-time test cases.
216+
itoTimeInvertedStart := slot0Ts + int64(slot+2)*slotDuration
217+
itoTimeInvertedEnd := itoStart
218+
198219
// ################### CONFIG ITO TESTS ###################
199220

200221
// error: invalid asset
@@ -211,10 +232,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
211232
DefaultLimitPerAddress: 10,
212233
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
213234
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
214-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
215-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
216-
StartTime: time.Now().Add(time.Second * 4).Unix(),
217-
EndTime: time.Now().Add(time.Second * 9).Unix(),
235+
WhitelistStartTime: itoStart,
236+
WhitelistEndTime: itoEnd,
237+
StartTime: itoStart,
238+
EndTime: itoEnd,
218239
},
219240
)
220241
require.Nil(t, err)
@@ -233,10 +254,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
233254
DefaultLimitPerAddress: 10,
234255
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
235256
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
236-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
237-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
238-
StartTime: time.Now().Add(time.Second * 4).Unix(),
239-
EndTime: time.Now().Add(time.Second * 9).Unix(),
257+
WhitelistStartTime: itoStart,
258+
WhitelistEndTime: itoEnd,
259+
StartTime: itoStart,
260+
EndTime: itoEnd,
240261
},
241262
)
242263
require.Error(t, err)
@@ -255,10 +276,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
255276
DefaultLimitPerAddress: 10,
256277
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
257278
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
258-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
259-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
260-
StartTime: time.Now().Add(time.Second * 4).Unix(),
261-
EndTime: time.Now().Add(time.Second * 9).Unix(),
279+
WhitelistStartTime: itoStart,
280+
WhitelistEndTime: itoEnd,
281+
StartTime: itoStart,
282+
EndTime: itoEnd,
262283
},
263284
)
264285
require.Error(t, err)
@@ -277,10 +298,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
277298
DefaultLimitPerAddress: 10,
278299
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
279300
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
280-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
281-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
282-
StartTime: time.Now().Add(time.Second * 4).Unix(),
283-
EndTime: time.Now().Add(time.Second * 9).Unix(),
301+
WhitelistStartTime: itoStart,
302+
WhitelistEndTime: itoEnd,
303+
StartTime: itoStart,
304+
EndTime: itoEnd,
284305
},
285306
)
286307
require.Error(t, err)
@@ -299,10 +320,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
299320
DefaultLimitPerAddress: 10,
300321
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
301322
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
302-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
303-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
304-
StartTime: time.Now().Add(time.Second * 4).Unix(),
305-
EndTime: time.Now().Add(time.Second * 9).Unix(),
323+
WhitelistStartTime: itoStart,
324+
WhitelistEndTime: itoEnd,
325+
StartTime: itoStart,
326+
EndTime: itoEnd,
306327
},
307328
)
308329
require.Error(t, err)
@@ -321,10 +342,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
321342
DefaultLimitPerAddress: 10,
322343
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
323344
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
324-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
325-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
326-
StartTime: time.Now().Add(time.Second * 4).Unix(),
327-
EndTime: time.Now().Add(time.Second * 9).Unix(),
345+
WhitelistStartTime: itoStart,
346+
WhitelistEndTime: itoEnd,
347+
StartTime: itoStart,
348+
EndTime: itoEnd,
328349
},
329350
)
330351
require.Error(t, err)
@@ -343,10 +364,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
343364
DefaultLimitPerAddress: 10,
344365
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
345366
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
346-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
347-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
348-
StartTime: time.Now().Add(time.Second * 4).Unix(),
349-
EndTime: time.Now().Add(time.Second * 9).Unix(),
367+
WhitelistStartTime: itoStart,
368+
WhitelistEndTime: itoEnd,
369+
StartTime: itoStart,
370+
EndTime: itoEnd,
350371
},
351372
)
352373
require.Nil(t, err)
@@ -365,10 +386,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
365386
DefaultLimitPerAddress: 10,
366387
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
367388
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
368-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
369-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
370-
StartTime: time.Now().Add(time.Second * 4).Unix(),
371-
EndTime: time.Now().Add(time.Second * 9).Unix(),
389+
WhitelistStartTime: itoStart,
390+
WhitelistEndTime: itoEnd,
391+
StartTime: itoStart,
392+
EndTime: itoEnd,
372393
},
373394
)
374395
require.Error(t, err)
@@ -387,10 +408,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
387408
DefaultLimitPerAddress: -10,
388409
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
389410
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
390-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
391-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
392-
StartTime: time.Now().Add(time.Second * 4).Unix(),
393-
EndTime: time.Now().Add(time.Second * 9).Unix(),
411+
WhitelistStartTime: itoStart,
412+
WhitelistEndTime: itoEnd,
413+
StartTime: itoStart,
414+
EndTime: itoEnd,
394415
},
395416
)
396417
require.Error(t, err)
@@ -409,10 +430,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
409430
DefaultLimitPerAddress: 10,
410431
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
411432
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
412-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
413-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
414-
StartTime: time.Now().Add(time.Second * 4).Unix(),
415-
EndTime: time.Now().Add(time.Second * 9).Unix(),
433+
WhitelistStartTime: itoStart,
434+
WhitelistEndTime: itoEnd,
435+
StartTime: itoStart,
436+
EndTime: itoEnd,
416437
},
417438
)
418439
require.Error(t, err)
@@ -431,10 +452,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
431452
DefaultLimitPerAddress: 10,
432453
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
433454
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, "INVALID": {Limit: 1}},
434-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
435-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
436-
StartTime: time.Now().Add(time.Second * 4).Unix(),
437-
EndTime: time.Now().Add(time.Second * 9).Unix(),
455+
WhitelistStartTime: itoStart,
456+
WhitelistEndTime: itoEnd,
457+
StartTime: itoStart,
458+
EndTime: itoEnd,
438459
},
439460
)
440461
require.Error(t, err)
@@ -453,10 +474,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
453474
DefaultLimitPerAddress: 10,
454475
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
455476
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: -1}, whitelistAddress2: {Limit: 1}},
456-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
457-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
458-
StartTime: time.Now().Add(time.Second * 4).Unix(),
459-
EndTime: time.Now().Add(time.Second * 9).Unix(),
477+
WhitelistStartTime: itoStart,
478+
WhitelistEndTime: itoEnd,
479+
StartTime: itoStart,
480+
EndTime: itoEnd,
460481
},
461482
)
462483
require.Error(t, err)
@@ -475,10 +496,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
475496
DefaultLimitPerAddress: 10,
476497
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
477498
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
478-
WhitelistStartTime: time.Now().Add(time.Second * 10).Unix(),
479-
WhitelistEndTime: time.Now().Add(time.Second * 5).Unix(),
480-
StartTime: time.Now().Add(time.Second * 4).Unix(),
481-
EndTime: time.Now().Add(time.Second * 9).Unix(),
499+
WhitelistStartTime: itoTimeInvertedStart,
500+
WhitelistEndTime: itoTimeInvertedEnd,
501+
StartTime: itoStart,
502+
EndTime: itoEnd,
482503
},
483504
)
484505
require.Error(t, err)
@@ -497,10 +518,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
497518
DefaultLimitPerAddress: 10,
498519
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
499520
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
500-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
501-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
502-
StartTime: time.Now().Add(time.Second * 10).Unix(),
503-
EndTime: time.Now().Add(time.Second * 5).Unix(),
521+
WhitelistStartTime: itoStart,
522+
WhitelistEndTime: itoEnd,
523+
StartTime: itoTimeInvertedStart,
524+
EndTime: itoTimeInvertedEnd,
504525
},
505526
)
506527
require.Error(t, err)
@@ -519,10 +540,10 @@ func TestTransaction_CreateConfigITO_ShouldError(t *testing.T) {
519540
DefaultLimitPerAddress: 10,
520541
WhitelistStatus: int32(*transaction.ConfigITOContract_ActiveITO.Enum()),
521542
WhitelistInfo: map[string]models.WhitelistInfoRequest{whitelistAddress1: {Limit: 1}, whitelistAddress2: {Limit: 1}},
522-
WhitelistStartTime: time.Now().Add(time.Second * 4).Unix(),
523-
WhitelistEndTime: time.Now().Add(time.Second * 9).Unix(),
524-
StartTime: time.Now().Add(time.Second * 4).Unix(),
525-
EndTime: time.Now().Add(time.Second * 9).Unix(),
543+
WhitelistStartTime: itoStart,
544+
WhitelistEndTime: itoEnd,
545+
StartTime: itoStart,
546+
EndTime: itoEnd,
526547
},
527548
)
528549
require.Nil(t, err)

0 commit comments

Comments
 (0)