Skip to content

Commit 0748db1

Browse files
committed
Make ticking a bit more realistic in Imp tests
Current implementation of ticking in ImpSpec is a bit naive, since it calls `TICK` rule for every slot. This is not only slow, but it also does not match the reality. On an actual running node TICK is called on every block, which happens on average every `1/activeSlotCoefficient` number of slots. On mainnet this is about every 20 slots or every 20 seconds. Switching to this approach makes imp tests significantly faster, namely about 80% faster on the example of Conway imp tests.
1 parent 2e373d8 commit 0748db1

File tree

3 files changed

+54
-18
lines changed

3 files changed

+54
-18
lines changed

eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/ImpTest.hs

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ import Data.List.NonEmpty (NonEmpty)
259259
import Data.Map.Strict (Map)
260260
import qualified Data.Map.Strict as Map
261261
import Data.Maybe (catMaybes, isNothing, mapMaybe)
262-
import Data.Ratio ((%))
262+
import Data.Ratio (denominator, numerator, (%))
263263
import Data.Sequence.Strict (StrictSeq (..))
264264
import qualified Data.Sequence.Strict as SSeq
265265
import qualified Data.Set as Set
@@ -1343,27 +1343,46 @@ passTick = do
13431343
impLastTickL += 1
13441344
impNESL .= nes
13451345

1346+
-- | Win with supplied probability
1347+
gambleWithProbability ::
1348+
HasStatefulGen g m =>
1349+
-- | Probability with which this action should produce `True`
1350+
UnitInterval ->
1351+
m Bool
1352+
gambleWithProbability probability = do
1353+
let p = unboundRational probability
1354+
n <- uniformRM (1, denominator p)
1355+
pure (n <= numerator p)
1356+
13461357
-- | Runs the TICK rule until the next epoch is reached
13471358
passEpoch ::
13481359
forall era.
13491360
(ShelleyEraImp era, HasCallStack) =>
13501361
ImpTestM era ()
13511362
passEpoch = do
1363+
globals <- use impGlobalsL
1364+
preNES <- gets impNES
13521365
let
1353-
tickUntilNewEpoch curEpochNo = do
1354-
oldNES <- getsNES id
1355-
passTick @era
1356-
newEpochNo <- getsNES nesELL
1357-
if newEpochNo > curEpochNo
1366+
curEpochNo = preNES ^. nesELL
1367+
ticksPerSlot =
1368+
positiveUnitIntervalRelaxToUnitInterval (activeSlotVal (activeSlotCoeff globals))
1369+
tickUntilNewEpoch = do
1370+
tickHasBlock <- gambleWithProbability ticksPerSlot
1371+
if tickHasBlock
13581372
then do
1359-
globals <- use impGlobalsL
1360-
newNES <- getsNES id
1361-
asks itePostEpochBoundaryHook >>= (\f -> f globals (TRC ((), oldNES, newEpochNo)) newNES)
1362-
else tickUntilNewEpoch curEpochNo
1363-
preNES <- gets impNES
1364-
let startEpoch = preNES ^. nesELL
1365-
logDoc $ "Entering " <> ansiExpr (succ startEpoch)
1366-
tickUntilNewEpoch startEpoch
1373+
oldNES <- getsNES id
1374+
passTick @era
1375+
newEpochNo <- getsNES nesELL
1376+
if newEpochNo > curEpochNo
1377+
then do
1378+
newNES <- getsNES id
1379+
asks itePostEpochBoundaryHook >>= (\f -> f globals (TRC ((), oldNES, newEpochNo)) newNES)
1380+
else tickUntilNewEpoch
1381+
else do
1382+
impLastTickL += 1
1383+
tickUntilNewEpoch
1384+
logDoc $ "Entering " <> ansiExpr (succ curEpochNo)
1385+
tickUntilNewEpoch
13671386
gets impNES >>= epochBoundaryCheck preNES
13681387

13691388
epochBoundaryCheck ::
@@ -1869,7 +1888,8 @@ whenMajorVersion ::
18691888
, MinVersion <= v
18701889
, v <= MaxVersion
18711890
) =>
1872-
ImpTestM era () -> ImpTestM era ()
1891+
ImpTestM era () ->
1892+
ImpTestM era ()
18731893
whenMajorVersion a = do
18741894
pv <- getProtVer
18751895
when (pvMajor pv == natVersion @v) a
@@ -1881,7 +1901,8 @@ whenMajorVersionAtLeast ::
18811901
, MinVersion <= v
18821902
, v <= MaxVersion
18831903
) =>
1884-
ImpTestM era () -> ImpTestM era ()
1904+
ImpTestM era () ->
1905+
ImpTestM era ()
18851906
whenMajorVersionAtLeast a = do
18861907
pv <- getProtVer
18871908
when (pvMajor pv >= natVersion @v) a
@@ -1893,7 +1914,8 @@ whenMajorVersionAtMost ::
18931914
, MinVersion <= v
18941915
, v <= MaxVersion
18951916
) =>
1896-
ImpTestM era () -> ImpTestM era ()
1917+
ImpTestM era () ->
1918+
ImpTestM era ()
18971919
whenMajorVersionAtMost a = do
18981920
pv <- getProtVer
18991921
when (pvMajor pv <= natVersion @v) a
@@ -1905,7 +1927,8 @@ unlessMajorVersion ::
19051927
, MinVersion <= v
19061928
, v <= MaxVersion
19071929
) =>
1908-
ImpTestM era () -> ImpTestM era ()
1930+
ImpTestM era () ->
1931+
ImpTestM era ()
19091932
unlessMajorVersion a = do
19101933
pv <- getProtVer
19111934
unless (pvMajor pv == natVersion @v) a

libs/cardano-ledger-core/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## 1.19.0.0
44

5+
* Add `positiveUnitIntervalRelaxToUnitInterval`, `positiveUnitIntervalRelaxToPositiveInterval` and `positiveIntervalRelaxToNonNegativeInterval`
56
* Limit `DecCBORGroup` decoding of `ProtVer` fields to `Word32` starting from protocol version `12`
67
* Change `Relation` type to only be visible at the type level
78
* Change `KeyRole` type to only be visible at the type level

libs/cardano-ledger-core/src/Cardano/Ledger/BaseTypes.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ module Cardano.Ledger.BaseTypes (
3737
PositiveUnitInterval,
3838
PositiveInterval,
3939
NonNegativeInterval,
40+
positiveUnitIntervalRelaxToUnitInterval,
41+
positiveUnitIntervalRelaxToPositiveInterval,
42+
positiveIntervalRelaxToNonNegativeInterval,
4043
BoundedRational (..),
4144
fpPrecision,
4245
integralToBounded,
@@ -485,6 +488,15 @@ instance Bounded (BoundedRatio PositiveUnitInterval Word64) where
485488
minBound = positiveIntervalEpsilon
486489
maxBound = BoundedRatio (1 % 1)
487490

491+
positiveUnitIntervalRelaxToUnitInterval :: PositiveUnitInterval -> UnitInterval
492+
positiveUnitIntervalRelaxToUnitInterval = coerce
493+
494+
positiveUnitIntervalRelaxToPositiveInterval :: PositiveUnitInterval -> PositiveInterval
495+
positiveUnitIntervalRelaxToPositiveInterval = coerce
496+
497+
positiveIntervalRelaxToNonNegativeInterval :: PositiveInterval -> NonNegativeInterval
498+
positiveIntervalRelaxToNonNegativeInterval = coerce
499+
488500
-- | Type to represent a value in the unit interval [0; 1]
489501
newtype UnitInterval
490502
= UnitInterval (BoundedRatio UnitInterval Word64)

0 commit comments

Comments
 (0)