Skip to content

Commit a2c8356

Browse files
lehinsfraser-iohk
authored andcommitted
Integrate KES agent functionality into ouroboros-consensus:
- Update to use newest cardano-crypto-class with unsound pure KES implementation - Use mlocked KES - Add KES agent connectivity - Rebase cleanup - Handle drop-key messages from KES Agent - Provide KESAgentClientTrace to BlockForging - Revert change to MockCrypto and require DSIGN only when running the KES agent - Bump kes-agent SRP to remove SerDoc dependency
1 parent 65285b2 commit a2c8356

File tree

58 files changed

+884
-290
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+884
-290
lines changed

cabal.project

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ repository cardano-haskell-packages
1414
-- update either of these.
1515
index-state:
1616
-- Bump this if you need newer packages from Hackage
17-
, hackage.haskell.org 2025-07-22T09:13:54Z
17+
, hackage.haskell.org 2025-08-05T11:23:47Z
1818
-- Bump this if you need newer packages from CHaP
19-
, cardano-haskell-packages 2025-07-28T14:33:19Z
19+
, cardano-haskell-packages 2025-08-06T09:39:20Z
2020

2121
packages:
2222
ouroboros-consensus
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
### Breaking
2+
3+
- Use new mlocked KES API for all internal KES sign key handling.
4+
- Add finalizers to all block forgings (required by `ouroboros-consensus`).
5+
- Change `ShelleyLeaderCredentials` to not contain the KES sign key itself
6+
anymore. Instead, the `CanBeLeader` data structure now contains a
7+
`praosCanBeLeaderCredentialsSource` field, which specifies how to obtain the
8+
actual credentials (OpCert and KES SignKey).

ouroboros-consensus-cardano/ouroboros-consensus-cardano.cabal

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ library
156156
cardano-strict-containers,
157157
cborg ^>=0.2.2,
158158
containers >=0.5 && <0.8,
159+
contra-tracer,
159160
crypton,
160161
deepseq,
161162
formatting >=6.3 && <7.3,
@@ -324,6 +325,8 @@ library unstable-shelley-testlib
324325
cardano-slotting,
325326
cardano-strict-containers,
326327
containers,
328+
contra-tracer,
329+
kes-agent,
327330
microlens,
328331
mtl,
329332
ouroboros-consensus:{ouroboros-consensus, unstable-consensus-testlib},
@@ -365,6 +368,7 @@ test-suite shelley-test
365368
cborg,
366369
constraints,
367370
containers,
371+
contra-tracer,
368372
filepath,
369373
measures,
370374
microlens,
@@ -416,6 +420,7 @@ library unstable-cardano-testlib
416420
cardano-strict-containers,
417421
cborg,
418422
containers,
423+
contra-tracer,
419424
mempack,
420425
microlens,
421426
mtl,

ouroboros-consensus-cardano/src/byron/Ouroboros/Consensus/Byron/Node.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ byronBlockForging creds =
143143
slot
144144
tickedPBftState
145145
, forgeBlock = \cfg -> return ....: forgeByronBlock cfg
146+
, finalize = pure ()
146147
}
147148
where
148149
canBeLeader = mkPBftCanBeLeader creds

ouroboros-consensus-cardano/src/ouroboros-consensus-cardano/Ouroboros/Consensus/Cardano/Node.hs

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,12 @@ import qualified Cardano.Ledger.Api.Transition as L
5555
import qualified Cardano.Ledger.BaseTypes as SL
5656
import qualified Cardano.Ledger.Shelley.API as SL
5757
import Cardano.Prelude (cborError)
58-
import qualified Cardano.Protocol.TPraos.OCert as Absolute
59-
( KESPeriod (..)
60-
, ocertKESPeriod
61-
)
58+
import qualified Cardano.Protocol.TPraos.OCert as Absolute (KESPeriod (..))
6259
import qualified Codec.CBOR.Decoding as CBOR
6360
import Codec.CBOR.Encoding (Encoding)
6461
import qualified Codec.CBOR.Encoding as CBOR
6562
import Control.Exception (assert)
63+
import qualified Control.Tracer as Tracer
6664
import qualified Data.ByteString.Short as Short
6765
import Data.Functor.These (These1 (..))
6866
import qualified Data.Map.Strict as Map
@@ -97,10 +95,11 @@ import Ouroboros.Consensus.Ledger.Tables.Utils (forgetLedgerTables)
9795
import Ouroboros.Consensus.Node.NetworkProtocolVersion
9896
import Ouroboros.Consensus.Node.ProtocolInfo
9997
import Ouroboros.Consensus.Node.Run
100-
import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey
10198
import Ouroboros.Consensus.Protocol.Praos (Praos, PraosParams (..))
99+
import Ouroboros.Consensus.Protocol.Praos.AgentClient
102100
import Ouroboros.Consensus.Protocol.Praos.Common
103-
( praosCanBeLeaderOpCert
101+
( PraosCanBeLeader (..)
102+
, instantiatePraosCredentials
104103
)
105104
import Ouroboros.Consensus.Protocol.TPraos (TPraos, TPraosParams (..))
106105
import qualified Ouroboros.Consensus.Protocol.TPraos as Shelley
@@ -122,7 +121,6 @@ import qualified Ouroboros.Consensus.Shelley.Node.TPraos as TPraos
122121
import Ouroboros.Consensus.Storage.Serialisation
123122
import Ouroboros.Consensus.TypeFamilyWrappers
124123
import Ouroboros.Consensus.Util.Assert
125-
import Ouroboros.Consensus.Util.IOLike
126124

127125
{-------------------------------------------------------------------------------
128126
SerialiseHFC
@@ -569,10 +567,12 @@ data CardanoProtocolParams c = CardanoProtocolParams
569567
-- for mainnet (check against @'SL.gNetworkId' == 'SL.Mainnet'@).
570568
protocolInfoCardano ::
571569
forall c m.
572-
(IOLike m, CardanoHardForkConstraints c) =>
570+
( CardanoHardForkConstraints c
571+
, KESAgentContext c m
572+
) =>
573573
CardanoProtocolParams c ->
574574
( ProtocolInfo (CardanoBlock c)
575-
, m [BlockForging m (CardanoBlock c)]
575+
, Tracer.Tracer m KESAgentClientTrace -> m [BlockForging m (CardanoBlock c)]
576576
)
577577
protocolInfoCardano paramsCardano
578578
| SL.Mainnet <- SL.sgNetworkId genesisShelley
@@ -585,7 +585,7 @@ protocolInfoCardano paramsCardano
585585
{ pInfoConfig = cfg
586586
, pInfoInitLedger = initExtLedgerStateCardano
587587
}
588-
, blockForging
588+
, mkBlockForgings
589589
)
590590
where
591591
CardanoProtocolParams
@@ -980,9 +980,9 @@ protocolInfoCardano paramsCardano
980980
-- credentials. If there are multiple Shelley credentials, we merge the
981981
-- Byron credentials with the first Shelley one but still have separate
982982
-- threads for the remaining Shelley ones.
983-
blockForging :: m [BlockForging m (CardanoBlock c)]
984-
blockForging = do
985-
shelleyBased <- traverse blockForgingShelleyBased credssShelleyBased
983+
mkBlockForgings :: Tracer.Tracer m KESAgentClientTrace -> m [BlockForging m (CardanoBlock c)]
984+
mkBlockForgings tr = do
985+
shelleyBased <- traverse (blockForgingShelleyBased tr) credssShelleyBased
986986
let blockForgings :: [NonEmptyOptNP (BlockForging m) (CardanoEras c)]
987987
blockForgings = case (mBlockForgingByron, shelleyBased) of
988988
(Nothing, shelleys) -> shelleys
@@ -1004,22 +1004,11 @@ protocolInfoCardano paramsCardano
10041004
return $ byronBlockForging creds `OptNP.at` IZ
10051005

10061006
blockForgingShelleyBased ::
1007+
Tracer.Tracer m KESAgentClientTrace ->
10071008
ShelleyLeaderCredentials c ->
10081009
m (NonEmptyOptNP (BlockForging m) (CardanoEras c))
1009-
blockForgingShelleyBased credentials = do
1010-
let ShelleyLeaderCredentials
1011-
{ shelleyLeaderCredentialsInitSignKey = initSignKey
1012-
, shelleyLeaderCredentialsCanBeLeader = canBeLeader
1013-
} = credentials
1014-
1015-
hotKey <- do
1016-
let maxKESEvo :: Word64
1017-
maxKESEvo = assert (tpraosMaxKESEvo == praosMaxKESEvo) praosMaxKESEvo
1018-
1019-
startPeriod :: Absolute.KESPeriod
1020-
startPeriod = Absolute.ocertKESPeriod $ praosCanBeLeaderOpCert canBeLeader
1021-
1022-
HotKey.mkHotKey @m @c initSignKey startPeriod maxKESEvo
1010+
blockForgingShelleyBased tr credentials = do
1011+
let canBeLeader = shelleyLeaderCredentialsCanBeLeader credentials
10231012

10241013
let slotToPeriod :: SlotNo -> Absolute.KESPeriod
10251014
slotToPeriod (SlotNo slot) =
@@ -1028,6 +1017,15 @@ protocolInfoCardano paramsCardano
10281017
fromIntegral $
10291018
slot `div` praosSlotsPerKESPeriod
10301019

1020+
maxKESEvo :: Word64
1021+
maxKESEvo = assert (tpraosMaxKESEvo == praosMaxKESEvo) praosMaxKESEvo
1022+
1023+
hotKey <-
1024+
instantiatePraosCredentials
1025+
maxKESEvo
1026+
tr
1027+
(praosCanBeLeaderCredentialsSource canBeLeader)
1028+
10311029
let tpraos ::
10321030
forall era.
10331031
ShelleyEraWithCrypto c (TPraos c) era =>

ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/HFEras.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ module Ouroboros.Consensus.Shelley.HFEras
1818
, StandardShelleyBlock
1919
) where
2020

21+
import Cardano.Protocol.Crypto
2122
import Ouroboros.Consensus.Protocol.Praos (Praos)
2223
import qualified Ouroboros.Consensus.Protocol.Praos as Praos
23-
import Ouroboros.Consensus.Protocol.TPraos (StandardCrypto, TPraos)
24+
import Ouroboros.Consensus.Protocol.TPraos (TPraos)
2425
import qualified Ouroboros.Consensus.Protocol.TPraos as TPraos
2526
import Ouroboros.Consensus.Shelley.Eras
2627
( AllegraEra

ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Node/Common.hs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ module Ouroboros.Consensus.Shelley.Node.Common
1919
, shelleyBlockIssuerVKey
2020
) where
2121

22-
import Cardano.Crypto.KES (UnsoundPureSignKeyKES)
2322
import Cardano.Ledger.BaseTypes (unNonZero)
2423
import qualified Cardano.Ledger.Keys as SL
2524
import qualified Cardano.Ledger.Shelley.API as SL
2625
import Cardano.Ledger.Slot
27-
import Cardano.Protocol.Crypto
2826
import Data.Text (Text)
2927
import Ouroboros.Consensus.Block
3028
( CannotForge
@@ -59,12 +57,7 @@ import Ouroboros.Consensus.Storage.ImmutableDB
5957
-------------------------------------------------------------------------------}
6058

6159
data ShelleyLeaderCredentials c = ShelleyLeaderCredentials
62-
{ shelleyLeaderCredentialsInitSignKey :: UnsoundPureSignKeyKES (KES c)
63-
-- ^ The unevolved signing KES key (at evolution 0).
64-
--
65-
-- Note that this is not inside 'ShelleyCanBeLeader' since it gets evolved
66-
-- automatically, whereas 'ShelleyCanBeLeader' does not change.
67-
, shelleyLeaderCredentialsCanBeLeader :: PraosCanBeLeader c
60+
{ shelleyLeaderCredentialsCanBeLeader :: PraosCanBeLeader c
6861
, shelleyLeaderCredentialsLabel :: Text
6962
-- ^ Identifier for this set of credentials.
7063
--

ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Node/Praos.hs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ import Ouroboros.Consensus.Protocol.Praos
2929
, PraosParams (..)
3030
, praosCheckCanForge
3131
)
32-
import Ouroboros.Consensus.Protocol.Praos.Common
33-
( PraosCanBeLeader (praosCanBeLeaderOpCert)
34-
)
3532
import Ouroboros.Consensus.Shelley.Ledger
3633
( ShelleyBlock
3734
, ShelleyCompatible
@@ -56,21 +53,13 @@ praosBlockForging ::
5653
, IOLike m
5754
) =>
5855
PraosParams ->
56+
HotKey.HotKey c m ->
5957
ShelleyLeaderCredentials c ->
60-
m (BlockForging m (ShelleyBlock (Praos c) era))
61-
praosBlockForging praosParams credentials = do
62-
hotKey <- HotKey.mkHotKey @m @c initSignKey startPeriod praosMaxKESEvo
63-
pure $ praosSharedBlockForging hotKey slotToPeriod credentials
58+
BlockForging m (ShelleyBlock (Praos c) era)
59+
praosBlockForging praosParams hotKey credentials =
60+
praosSharedBlockForging hotKey slotToPeriod credentials
6461
where
65-
PraosParams{praosMaxKESEvo, praosSlotsPerKESPeriod} = praosParams
66-
67-
ShelleyLeaderCredentials
68-
{ shelleyLeaderCredentialsInitSignKey = initSignKey
69-
, shelleyLeaderCredentialsCanBeLeader = canBeLeader
70-
} = credentials
71-
72-
startPeriod :: Absolute.KESPeriod
73-
startPeriod = SL.ocertKESPeriod $ praosCanBeLeaderOpCert canBeLeader
62+
PraosParams{praosSlotsPerKESPeriod} = praosParams
7463

7564
slotToPeriod :: SlotNo -> Absolute.KESPeriod
7665
slotToPeriod (SlotNo slot) =
@@ -95,7 +84,7 @@ praosSharedBlockForging
9584
ShelleyLeaderCredentials
9685
{ shelleyLeaderCredentialsCanBeLeader = canBeLeader
9786
, shelleyLeaderCredentialsLabel = label
98-
} = do
87+
} =
9988
BlockForging
10089
{ forgeLabel = label <> "_" <> T.pack (L.eraName @era)
10190
, canBeLeader = canBeLeader
@@ -111,4 +100,5 @@ praosSharedBlockForging
111100
hotKey
112101
canBeLeader
113102
cfg
103+
, finalize = HotKey.finalize hotKey
114104
}

ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Node/TPraos.hs

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
{-# LANGUAGE ScopedTypeVariables #-}
1111
{-# LANGUAGE TypeApplications #-}
1212
{-# LANGUAGE TypeFamilies #-}
13+
{-# LANGUAGE TypeOperators #-}
1314
{-# LANGUAGE UndecidableInstances #-}
1415
{-# LANGUAGE UndecidableSuperClasses #-}
1516
{-# OPTIONS_GHC -Wno-orphans #-}
@@ -43,6 +44,7 @@ import qualified Cardano.Protocol.TPraos.OCert as SL
4344
import Cardano.Slotting.EpochInfo
4445
import Cardano.Slotting.Time (mkSlotLength)
4546
import Control.Monad.Except (Except)
47+
import qualified Control.Tracer as Tracer
4648
import Data.Bifunctor (first)
4749
import qualified Data.Text as T
4850
import qualified Data.Text as Text
@@ -59,6 +61,7 @@ import Ouroboros.Consensus.Node.ProtocolInfo
5961
import Ouroboros.Consensus.Protocol.Abstract
6062
import Ouroboros.Consensus.Protocol.Ledger.HotKey (HotKey)
6163
import qualified Ouroboros.Consensus.Protocol.Ledger.HotKey as HotKey
64+
import Ouroboros.Consensus.Protocol.Praos.AgentClient
6265
import Ouroboros.Consensus.Protocol.Praos.Common
6366
import Ouroboros.Consensus.Protocol.TPraos
6467
import Ouroboros.Consensus.Shelley.Eras
@@ -91,21 +94,13 @@ shelleyBlockForging ::
9194
, IOLike m
9295
) =>
9396
TPraosParams ->
97+
HotKey c m ->
9498
ShelleyLeaderCredentials c ->
95-
m (BlockForging m (ShelleyBlock (TPraos c) era))
96-
shelleyBlockForging tpraosParams credentials = do
97-
hotKey <- HotKey.mkHotKey @m @c initSignKey startPeriod tpraosMaxKESEvo
98-
pure $ shelleySharedBlockForging hotKey slotToPeriod credentials
99+
BlockForging m (ShelleyBlock (TPraos c) era)
100+
shelleyBlockForging tpraosParams hotKey credentials = do
101+
shelleySharedBlockForging hotKey slotToPeriod credentials
99102
where
100-
TPraosParams{tpraosMaxKESEvo, tpraosSlotsPerKESPeriod} = tpraosParams
101-
102-
ShelleyLeaderCredentials
103-
{ shelleyLeaderCredentialsInitSignKey = initSignKey
104-
, shelleyLeaderCredentialsCanBeLeader = canBeLeader
105-
} = credentials
106-
107-
startPeriod :: Absolute.KESPeriod
108-
startPeriod = SL.ocertKESPeriod $ praosCanBeLeaderOpCert canBeLeader
103+
TPraosParams{tpraosSlotsPerKESPeriod} = tpraosParams
109104

110105
slotToPeriod :: SlotNo -> Absolute.KESPeriod
111106
slotToPeriod (SlotNo slot) =
@@ -141,6 +136,7 @@ shelleySharedBlockForging hotKey slotToPeriod credentials =
141136
hotKey
142137
canBeLeader
143138
cfg
139+
, finalize = HotKey.finalize hotKey
144140
}
145141
where
146142
ShelleyLeaderCredentials
@@ -173,14 +169,16 @@ validateGenesis = first errsToString . SL.validateGenesis
173169
protocolInfoShelley ::
174170
forall m c.
175171
( IOLike m
172+
, AgentCrypto c
176173
, ShelleyCompatible (TPraos c) ShelleyEra
177174
, TxLimits (ShelleyBlock (TPraos c) ShelleyEra)
175+
, MonadKESAgent m
178176
) =>
179177
SL.ShelleyGenesis ->
180178
ProtocolParamsShelleyBased c ->
181179
SL.ProtVer ->
182180
( ProtocolInfo (ShelleyBlock (TPraos c) ShelleyEra)
183-
, m [BlockForging m (ShelleyBlock (TPraos c) ShelleyEra)]
181+
, Tracer.Tracer m KESAgentClientTrace -> m [BlockForging m (ShelleyBlock (TPraos c) ShelleyEra)]
184182
)
185183
protocolInfoShelley
186184
shelleyGenesis
@@ -193,16 +191,16 @@ protocolInfoShelley
193191

194192
protocolInfoTPraosShelleyBased ::
195193
forall m era c.
196-
( IOLike m
197-
, ShelleyCompatible (TPraos c) era
194+
( ShelleyCompatible (TPraos c) era
198195
, TxLimits (ShelleyBlock (TPraos c) era)
196+
, KESAgentContext c m
199197
) =>
200198
ProtocolParamsShelleyBased c ->
201199
L.TransitionConfig era ->
202200
-- | see 'shelleyProtVer', mutatis mutandi
203201
SL.ProtVer ->
204202
( ProtocolInfo (ShelleyBlock (TPraos c) era)
205-
, m [BlockForging m (ShelleyBlock (TPraos c) era)]
203+
, Tracer.Tracer m KESAgentClientTrace -> m [BlockForging m (ShelleyBlock (TPraos c) era)]
206204
)
207205
protocolInfoTPraosShelleyBased
208206
ProtocolParamsShelleyBased
@@ -216,11 +214,24 @@ protocolInfoTPraosShelleyBased
216214
{ pInfoConfig = topLevelConfig
217215
, pInfoInitLedger = initExtLedgerState
218216
}
219-
, traverse
220-
(shelleyBlockForging tpraosParams)
221-
credentialss
217+
, \tr -> traverse (mkBlockForging tr) credentialss
222218
)
223219
where
220+
mkBlockForging ::
221+
Tracer.Tracer m KESAgentClientTrace ->
222+
ShelleyLeaderCredentials c ->
223+
m (BlockForging m (ShelleyBlock (TPraos c) era))
224+
mkBlockForging tr credentials = do
225+
let canBeLeader = shelleyLeaderCredentialsCanBeLeader credentials
226+
227+
hotKey :: HotKey c m <-
228+
instantiatePraosCredentials
229+
(tpraosMaxKESEvo tpraosParams)
230+
tr
231+
(praosCanBeLeaderCredentialsSource canBeLeader)
232+
233+
return $ shelleyBlockForging tpraosParams hotKey credentials
234+
224235
genesis :: SL.ShelleyGenesis
225236
genesis = transitionCfg ^. L.tcShelleyGenesisL
226237

0 commit comments

Comments
 (0)