Skip to content

Commit 6002345

Browse files
authored
Integrate KES agent functionality into ouroboros-consensus (#1620)
This PR supercedes #1487 includes the following squashed commit messages: - 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 # Description Please include a meaningful description of the PR and link the relevant issues this PR might resolve. Also note that: - New code should be properly tested (even if it does not add new features). - The fix for a regression should include a test that reproduces said regression.
2 parents 3bbf2f2 + 30d215b commit 6002345

File tree

64 files changed

+1143
-356
lines changed

Some content is hidden

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

64 files changed

+1143
-356
lines changed

cabal.project

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ 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
1919
, cardano-haskell-packages 2025-08-21T09:41:03Z
2020

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,
@@ -325,6 +326,8 @@ library unstable-shelley-testlib
325326
cardano-slotting,
326327
cardano-strict-containers,
327328
containers,
329+
contra-tracer,
330+
kes-agent,
328331
microlens,
329332
mtl,
330333
ouroboros-consensus:{ouroboros-consensus, unstable-consensus-testlib},
@@ -364,6 +367,7 @@ test-suite shelley-test
364367
cborg,
365368
constraints,
366369
containers,
370+
contra-tracer,
367371
filepath,
368372
measures,
369373
microlens,
@@ -415,6 +419,7 @@ library unstable-cardano-testlib
415419
cardano-strict-containers,
416420
cborg,
417421
containers,
422+
contra-tracer,
418423
mempack,
419424
microlens,
420425
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: 36 additions & 32 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 [MkBlockForging 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+
, pure . mkBlockForgings
589589
)
590590
where
591591
CardanoProtocolParams
@@ -980,46 +980,41 @@ 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
986-
let blockForgings :: [NonEmptyOptNP (BlockForging m) (CardanoEras c)]
983+
mkBlockForgings :: Tracer.Tracer m KESAgentClientTrace -> [MkBlockForging m (CardanoBlock c)]
984+
mkBlockForgings tr = do
985+
let shelleyBased = blockForgingShelleyBased tr <$> credssShelleyBased
986+
blockForgings :: [m (NonEmptyOptNP (BlockForging m) (CardanoEras c))]
987987
blockForgings = case (mBlockForgingByron, shelleyBased) of
988988
(Nothing, shelleys) -> shelleys
989989
(Just byron, []) -> [byron]
990990
(Just byron, shelley : shelleys) ->
991-
OptNP.zipWith merge byron shelley : shelleys
991+
(OptNP.zipWith merge <$> byron <*> shelley) : shelleys
992992
where
993993
-- When merging Byron with Shelley-based eras, we should never
994994
-- merge two from the same era.
995995
merge (These1 _ _) = error "forgings of the same era"
996996
merge (This1 x) = x
997997
merge (That1 y) = y
998998

999-
return $ hardForkBlockForging "Cardano" <$> blockForgings
999+
let mkHardForkBlockForgings ::
1000+
m (NonEmptyOptNP (BlockForging m) (CardanoEras c)) -> MkBlockForging m (CardanoBlock c)
1001+
mkHardForkBlockForgings mbfs = MkBlockForging $ do
1002+
bfs <- mbfs
1003+
mkBlockForging $ hardForkBlockForging (const "Cardano") (hmap (MkBlockForging . pure) bfs)
1004+
1005+
fmap mkHardForkBlockForgings blockForgings
10001006

1001-
mBlockForgingByron :: Maybe (NonEmptyOptNP (BlockForging m) (CardanoEras c))
1007+
mBlockForgingByron :: Maybe (m (NonEmptyOptNP (BlockForging m) (CardanoEras c)))
10021008
mBlockForgingByron = do
10031009
creds <- mCredsByron
1004-
return $ byronBlockForging creds `OptNP.at` IZ
1010+
return $ pure $ byronBlockForging creds `OptNP.at` IZ
10051011

10061012
blockForgingShelleyBased ::
1013+
Tracer.Tracer m KESAgentClientTrace ->
10071014
ShelleyLeaderCredentials c ->
10081015
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
1016+
blockForgingShelleyBased tr credentials = do
1017+
let canBeLeader = shelleyLeaderCredentialsCanBeLeader credentials
10231018

10241019
let slotToPeriod :: SlotNo -> Absolute.KESPeriod
10251020
slotToPeriod (SlotNo slot) =
@@ -1028,6 +1023,15 @@ protocolInfoCardano paramsCardano
10281023
fromIntegral $
10291024
slot `div` praosSlotsPerKESPeriod
10301025

1026+
maxKESEvo :: Word64
1027+
maxKESEvo = assert (tpraosMaxKESEvo == praosMaxKESEvo) praosMaxKESEvo
1028+
1029+
hotKey <-
1030+
instantiatePraosCredentials
1031+
maxKESEvo
1032+
tr
1033+
(praosCanBeLeaderCredentialsSource canBeLeader)
1034+
10311035
let tpraos ::
10321036
forall era.
10331037
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
}

0 commit comments

Comments
 (0)