Skip to content

Commit 08958b9

Browse files
committed
Add genCoreNodeKeys that can be used in consensus
Create some helper functions and instances to make this possible
1 parent 685f1da commit 08958b9

File tree

8 files changed

+115
-46
lines changed

8 files changed

+115
-46
lines changed

eras/shelley/test-suite/CHANGELOG.md

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

33
## 1.6.0.0
44

5+
* Add `genCoreNodeKeys` and `genIssuerKeys`
56
* Move `VRFNatVal` into `cardano-protocol-tpraos:testlib`
67
* Account for removal of crypto parametrization
78
* Remove crypto parametrization from `PoolSetUpArgs`, `PoolInfo`, `RewardUpdateOld`

eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Generator/Presets.hs

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
-- Functions in this module make specific assumptions about the sets of keys
1111
-- involved, and thus cannot be used as generic generators.
1212
module Test.Cardano.Ledger.Shelley.Generator.Presets (
13+
genCoreNodeKeys,
14+
genIssuerKeys,
1315
coreNodeKeys,
1416
keySpace,
1517
genEnv,
@@ -28,25 +30,20 @@ import Cardano.Ledger.Keys (
2830
coerceKeyRole,
2931
hashKey,
3032
)
31-
import Cardano.Protocol.Crypto (hashVerKeyVRF)
32-
import Cardano.Protocol.TPraos.OCert (KESPeriod (..))
33-
import Data.List.NonEmpty (NonEmpty ((:|)))
33+
import Cardano.Protocol.Crypto (Crypto, hashVerKeyVRF)
3434
import Data.Map.Strict (Map)
3535
import qualified Data.Map.Strict as Map
3636
import Data.Proxy (Proxy (..))
3737
import Data.Word (Word64)
38+
import Test.Cardano.Ledger.Common
3839
import Test.Cardano.Ledger.Core.KeyPair (KeyPair (..))
3940
import Test.Cardano.Ledger.Shelley.ConcreteCryptoTypes (MockCrypto)
4041
import Test.Cardano.Ledger.Shelley.Constants (Constants (..))
4142
import Test.Cardano.Ledger.Shelley.Generator.Core
4243
import Test.Cardano.Ledger.Shelley.Generator.EraGen (EraGen (..), allScripts, someKeyPairs)
4344
import Test.Cardano.Ledger.Shelley.Generator.ScriptClass (keyPairs)
44-
import Test.Cardano.Ledger.Shelley.Utils (
45-
maxKESIterations,
46-
mkKESKeyPair,
47-
mkVRFKeyPair,
48-
slotsPerKESIteration,
49-
)
45+
import Test.Cardano.Ledger.Shelley.Utils (maxKESIterations, slotsPerKESIteration)
46+
import Test.Cardano.Protocol.TPraos.Create (genAllIssuerKeys)
5047

5148
-- =================================================================
5249

@@ -97,62 +94,47 @@ keySpace c =
9794
-- NOTE: we use a seed range in the [1000...] range
9895
-- to create keys that don't overlap with any of the other generated keys
9996
coreNodeKeys ::
97+
Crypto c =>
10098
Constants ->
101-
[(KeyPair 'Genesis, AllIssuerKeys MockCrypto 'GenesisDelegate)]
102-
coreNodeKeys c@Constants {numCoreNodes} =
103-
[ ( (toKeyPair . mkGenKey) (RawSeed x 0 0 0 0)
104-
, issuerKeys c 0 x
105-
)
106-
| x <- [1001 .. 1000 + numCoreNodes]
107-
]
108-
where
109-
toKeyPair (sk, vk) = KeyPair vk sk
99+
[(KeyPair 'Genesis, AllIssuerKeys c 'GenesisDelegate)]
100+
coreNodeKeys = runGen 1000 30 . genCoreNodeKeys
101+
102+
genCoreNodeKeys ::
103+
Crypto c =>
104+
Constants ->
105+
Gen [(KeyPair 'Genesis, AllIssuerKeys c 'GenesisDelegate)]
106+
genCoreNodeKeys c@Constants {numCoreNodes} =
107+
replicateM (fromIntegral numCoreNodes) $ (,) <$> arbitrary <*> genIssuerKeys c
110108

111109
-- Pre-generate a set of keys to use for genesis delegates.
112-
genesisDelegates :: Constants -> [AllIssuerKeys MockCrypto 'GenesisDelegate]
110+
genesisDelegates :: Crypto c => Constants -> [AllIssuerKeys c 'GenesisDelegate]
113111
genesisDelegates c =
114112
[ issuerKeys c 20 x
115113
| x <- [0 .. 50]
116114
]
117115

118116
-- Pre-generate a set of keys to use for stake pools.
119-
stakePoolKeys :: Constants -> [AllIssuerKeys MockCrypto 'StakePool]
117+
stakePoolKeys :: Crypto c => Constants -> [AllIssuerKeys c 'StakePool]
120118
stakePoolKeys c =
121119
[ issuerKeys c 10 x
122120
| x <- [0 .. 50]
123121
]
124122

125123
-- | Generate all keys for any entity which will be issuing blocks.
126124
issuerKeys ::
125+
Crypto c =>
127126
Constants ->
128127
-- | Namespace parameter. Can be used to differentiate between different
129128
-- "types" of issuer.
130129
Word64 ->
131130
Word64 ->
132-
AllIssuerKeys MockCrypto r
133-
issuerKeys Constants {maxSlotTrace} ns x =
134-
let (skCold, vkCold) = mkKeyPair (RawSeed x 0 0 0 (ns + 1))
135-
iters =
136-
0
137-
:| [ 1
138-
.. 1
139-
+ ( maxSlotTrace
140-
`div` fromIntegral (maxKESIterations * slotsPerKESIteration)
141-
)
142-
]
143-
in AllIssuerKeys
144-
{ aikCold = KeyPair vkCold skCold
145-
, aikHot =
146-
fmap
147-
( \iter ->
148-
( KESPeriod (fromIntegral (iter * fromIntegral maxKESIterations))
149-
, mkKESKeyPair (RawSeed x 0 0 (fromIntegral iter) (ns + 3))
150-
)
151-
)
152-
iters
153-
, aikVrf = mkVRFKeyPair (RawSeed x 0 0 0 (ns + 2))
154-
, aikColdKeyHash = hashKey vkCold
155-
}
131+
AllIssuerKeys c r
132+
issuerKeys c ns x =
133+
runGen (fromIntegral x) 30 $ variant ns (genIssuerKeys c)
134+
135+
genIssuerKeys :: Crypto c => Constants -> Gen (AllIssuerKeys c r)
136+
genIssuerKeys Constants {maxSlotTrace} =
137+
genAllIssuerKeys maxSlotTrace maxKESIterations slotsPerKESIteration
156138

157139
genesisDelegs0 ::
158140
Constants ->
@@ -164,7 +146,7 @@ genesisDelegs0 c =
164146
(coerceKeyRole . hashVKey $ aikCold pkeys)
165147
(hashVerKeyVRF @MockCrypto . vrfVerKey $ aikVrf pkeys)
166148
)
167-
| (gkey, pkeys) <- coreNodeKeys c
149+
| (gkey, pkeys) <- coreNodeKeys @MockCrypto c
168150
]
169151
where
170152
hashVKey = hashKey . vKey

libs/cardano-ledger-core/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Move `Cardano.Ledger.SnapShots` module contents into `Cardano.Ledger.State` and deprecated the former
88
* Move `Cardano.Ledger.UTxO` module contents into `Cardano.Ledger.State` and deprecated the former
99
* Add `CanGetUTxO` and `CanSetUTxO` type classes
10-
* Add `CanGetUTxO` and `CanSetUTxO` instances for `UTxO`
10+
* Add `CanGetUTxO` and `CanSetUTxO` instances for `UTxO`
1111
* Add `DecShareCBOR` instances for `DRep` and `DRepState`
1212
* Added `ToPlutusData` instance for `NonZero`
1313
* `maxpool'` now expects `nOpt` to be a `NonZero Word16`
@@ -99,6 +99,7 @@
9999

100100
### `testlib`
101101

102+
* Add `runGen`
102103
* Added `Arbitrary` and `ToExpr` instances for `NonZero`
103104
* Deprecate `genBadPtr`, `genAddrBadPtr` and `genCompactAddrBadPtr`
104105
* Remove crypto parametrization from types: `KeyPair` and `KeyPairs`

libs/cardano-ledger-core/testlib/Test/Cardano/Ledger/Common.hs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module Test.Cardano.Ledger.Common (
44
ledgerTestMainWith,
55
ledgerHspecConfig,
66
NFData,
7+
runGen,
78

89
-- * Expr
910
ToExpr (..),
@@ -63,6 +64,8 @@ import Test.Hspec.Runner
6364
import Test.ImpSpec (ansiDocToString, impSpecConfig, impSpecMainWithConfig)
6465
import Test.ImpSpec.Expectations
6566
import Test.QuickCheck as X
67+
import Test.QuickCheck.Gen (Gen (..))
68+
import Test.QuickCheck.Random (mkQCGen)
6669
import UnliftIO.Exception (evaluateDeep)
6770

6871
infix 1 `shouldBeExpr`
@@ -110,3 +113,13 @@ shouldBeLeftExpr e x = expectLeftExpr e >>= (`shouldBeExpr` x)
110113
-- | Same as `Test.QuickCheck.discard` but outputs a debug trace message
111114
tracedDiscard :: String -> a
112115
tracedDiscard message = (if False then Debug.trace $ "\nDiscarded trace: " ++ message else id) discard
116+
117+
runGen ::
118+
-- | Seed
119+
Int ->
120+
-- | Size
121+
Int ->
122+
-- | Generator to run.
123+
Gen a ->
124+
a
125+
runGen seed size gen = unGen gen (mkQCGen seed) size

libs/cardano-protocol-tpraos/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
### `testlib`
1616

17+
* Add `genAllIssuerKeys`
18+
* Add `Arbitrary` instances for `KESKeyPair` and `VRFKeyPair`
1719
* Move `VRFNatVal` from `cardano-ledger-shelley-test` in here.
1820
* Change type of `kesSignKey` in `KESKeyPair` and result of `evolveKESUntil` from `SignKeyKES` to `UnsoundPureSignKeyKES`
1921

libs/cardano-protocol-tpraos/testlib/Test/Cardano/Protocol/Crypto/KES.hs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
{-# LANGUAGE FlexibleContexts #-}
22
{-# LANGUAGE FlexibleInstances #-}
3+
{-# LANGUAGE ScopedTypeVariables #-}
34
{-# LANGUAGE StandaloneDeriving #-}
5+
{-# LANGUAGE TypeApplications #-}
46
{-# LANGUAGE UndecidableInstances #-}
57

68
module Test.Cardano.Protocol.Crypto.KES (
79
KESKeyPair (..),
810
) where
911

12+
import Cardano.Crypto.KES (
13+
UnsoundPureKESAlgorithm (..),
14+
seedSizeKES,
15+
unsoundPureDeriveVerKeyKES,
16+
unsoundPureGenKeyKES,
17+
)
1018
import qualified Cardano.Crypto.KES.Class as KES
19+
import Cardano.Crypto.Seed
1120
import Cardano.Protocol.Crypto
21+
import Data.Proxy
22+
import Test.Cardano.Ledger.Binary.Arbitrary (genByteString)
23+
import Test.Cardano.Ledger.Common
1224

1325
data KESKeyPair c = KESKeyPair
1426
{ kesSignKey :: !(KES.UnsoundPureSignKeyKES (KES c))
@@ -19,3 +31,20 @@ instance Show (KES.VerKeyKES (KES c)) => Show (KESKeyPair c) where
1931
show (KESKeyPair _ vk) =
2032
-- showing `SignKeyKES` is impossible for security reasons.
2133
"KESKeyPair <SignKeyKES> " <> show vk
34+
35+
-- TODO: upstream into `cardano-base`
36+
37+
-- | Generate a `Seed` with specified number of bytes, which can only be positive.
38+
genSeedN :: HasCallStack => Int -> Gen Seed
39+
genSeedN n
40+
| n >= 1 = mkSeedFromBytes <$> genByteString n
41+
| otherwise = error $ "Seed cannot be empty. Supplied " ++ show n ++ " for the size of the seed"
42+
43+
instance Crypto c => Arbitrary (KESKeyPair c) where
44+
arbitrary = do
45+
signKey <- unsoundPureGenKeyKES <$> genSeedN (fromIntegral (seedSizeKES (Proxy @(KES c))))
46+
pure $
47+
KESKeyPair
48+
{ kesSignKey = signKey
49+
, kesVerKey = unsoundPureDeriveVerKeyKES signKey
50+
}

libs/cardano-protocol-tpraos/testlib/Test/Cardano/Protocol/Crypto/VRF.hs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module Test.Cardano.Protocol.Crypto.VRF (
99

1010
import qualified Cardano.Crypto.VRF.Class as VRF
1111
import Cardano.Protocol.Crypto
12+
import Test.Cardano.Ledger.Common
1213

1314
data VRFKeyPair c = VRFKeyPair
1415
{ vrfSignKey :: !(VRF.SignKeyVRF (VRF c))
@@ -17,3 +18,12 @@ data VRFKeyPair c = VRFKeyPair
1718

1819
deriving instance
1920
(Show (VRF.SignKeyVRF (VRF c)), Show (VRF.VerKeyVRF (VRF c))) => Show (VRFKeyPair c)
21+
22+
instance (Crypto c, Arbitrary (VRF.SignKeyVRF (VRF c))) => Arbitrary (VRFKeyPair c) where
23+
arbitrary = do
24+
signKey <- arbitrary
25+
pure $
26+
VRFKeyPair
27+
{ vrfSignKey = signKey
28+
, vrfVerKey = VRF.deriveVerKeyVRF signKey
29+
}

libs/cardano-protocol-tpraos/testlib/Test/Cardano/Protocol/TPraos/Create.hs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
{-# LANGUAGE KindSignatures #-}
66
{-# LANGUAGE ScopedTypeVariables #-}
77
{-# LANGUAGE StandaloneDeriving #-}
8+
{-# LANGUAGE TupleSections #-}
89
{-# LANGUAGE TypeApplications #-}
910
{-# LANGUAGE TypeFamilies #-}
1011
{-# LANGUAGE TypeOperators #-}
1112
{-# LANGUAGE UndecidableInstances #-}
1213

1314
module Test.Cardano.Protocol.TPraos.Create (
1415
AllIssuerKeys (..),
16+
genAllIssuerKeys,
1517
KESKeyPair (..),
1618
VRFKeyPair (..),
1719
mkOCert,
@@ -52,12 +54,14 @@ import Cardano.Protocol.TPraos.OCert (
5254
OCert (..),
5355
OCertSignable (..),
5456
)
57+
import Control.Monad (forM)
5558
import Data.Coerce
5659
import Data.List.NonEmpty as NE
5760
import Data.Ratio (denominator, numerator, (%))
5861
import Data.Sequence.Strict as StrictSeq
5962
import Data.Word
6063
import Numeric.Natural
64+
import Test.Cardano.Ledger.Common
6165
import Test.Cardano.Ledger.Core.KeyPair (KeyPair (..))
6266
import Test.Cardano.Protocol.Crypto.KES (KESKeyPair (..))
6367
import Test.Cardano.Protocol.Crypto.VRF (VRFKeyPair (..))
@@ -74,6 +78,33 @@ deriving instance
7478
(Show (VRF.SignKeyVRF (VRF c)), Show (VRF.VerKeyVRF (VRF c)), Show (KES.VerKeyKES (KES c))) =>
7579
Show (AllIssuerKeys c r)
7680

81+
genAllIssuerKeys ::
82+
Crypto c =>
83+
-- | Maxium slot number
84+
Int ->
85+
-- | This corresponds to number of KES evolutions `Cardano.Ledger.BaseTypes.maxKESEvo` from
86+
-- `Cardano.Ledger.BaseTypes.Globals`.
87+
Word64 ->
88+
-- | This corresponds to number of KES evolutions `Cardano.Ledger.BaseTypes.slotsPerKESPeriod` from
89+
-- `Cardano.Ledger.BaseTypes.Globals`.
90+
Word64 ->
91+
Gen (AllIssuerKeys c r)
92+
genAllIssuerKeys maxSlotNumber maxKESIterations slotsPerKESPeriod = do
93+
coldKeyPair <- arbitrary
94+
let maxIter =
95+
maxSlotNumber `div` fromIntegral (maxKESIterations * slotsPerKESPeriod)
96+
iters = 0 :| [1 .. 1 + maxIter]
97+
hotKESKeys <- forM iters $ \iter ->
98+
(KESPeriod (fromIntegral (iter * fromIntegral maxKESIterations)),) <$> arbitrary
99+
vrfKeyPair <- arbitrary
100+
pure $
101+
AllIssuerKeys
102+
{ aikCold = coldKeyPair
103+
, aikHot = hotKESKeys
104+
, aikVrf = vrfKeyPair
105+
, aikColdKeyHash = hashKey (vKey coldKeyPair)
106+
}
107+
77108
mkOCert ::
78109
forall c r.
79110
Crypto c =>

0 commit comments

Comments
 (0)