@@ -26,6 +26,7 @@ module Cardano.Node.Run
2626import Cardano.Api (File (.. ), FileDirection (.. ))
2727import Cardano.Api.Error (displayError )
2828import qualified Cardano.Api as Api
29+ import Cardano.Ledger.Keys (coerceKeyRole , hashKey )
2930import System.Random (randomIO )
3031
3132import qualified Cardano.Crypto.Init as Crypto
@@ -48,7 +49,8 @@ import Cardano.Node.Protocol (ProtocolInstantiationError (..), mkConse
4849import Cardano.Node.Protocol.Byron (ByronProtocolInstantiationError (CredentialsError ))
4950import Cardano.Node.Protocol.Cardano (CardanoProtocolInstantiationError (.. ))
5051import Cardano.Node.Protocol.Shelley (PraosLeaderCredentialsError (.. ),
51- ShelleyProtocolInstantiationError (PraosLeaderCredentialsError ), readGenesis )
52+ ShelleyProtocolInstantiationError (PraosLeaderCredentialsError ), readGenesis )
53+ import Cardano.Node.Peras.Trace (PerasVoteForgingUpdateResult (.. ))
5254import Cardano.Node.Protocol.Types
5355import Cardano.Node.Queries
5456import Cardano.Rpc.Server
@@ -69,7 +71,13 @@ import Cardano.Slotting.Slot (WithOrigin (..))
6971import Cardano.Logging.Types (LogFormatting , TraceConfig )
7072import Cardano.Logging.Utils (showT )
7173
74+ import Ouroboros.Consensus.Cardano.Peras (mkCardanoPerasVoteForging )
75+ import Ouroboros.Consensus.Committee.Types (PoolId (.. ))
76+ import Ouroboros.Consensus.Peras.Crypto.BLS.Unsafe (unsafePerasBLSPrivateKeyFromEnv )
77+ import Ouroboros.Consensus.Protocol.Praos.Common (PraosCanBeLeader (.. ))
78+ import qualified Ouroboros.Consensus.Cardano.Node as CardanoConsensus
7279import qualified Ouroboros.Consensus.Config as Consensus
80+ import Ouroboros.Consensus.Shelley.Node.Common (ProtocolParamsShelleyBased (.. ), ShelleyLeaderCredentials (.. ))
7381import Ouroboros.Consensus.Config.SupportsNode (ConfigSupportsNode (.. ))
7482import Ouroboros.Consensus.Node (SnapshotPolicyArgs (.. ),
7583 NodeDatabasePaths (.. ), nonImmutableDbPath , RunNodeArgs (.. ), StdRunNodeArgs (.. ))
@@ -164,6 +172,7 @@ import System.Directory (canonicalizePath, createDirectoryIfMissing, d
164172 makeAbsolute )
165173import System.Environment (lookupEnv )
166174import System.FilePath (takeDirectory , (</>) )
175+ import System.IO.Error (isDoesNotExistError )
167176import System.IO (hPutStrLn )
168177#ifdef UNIX
169178import System.Posix.Files
@@ -417,8 +426,19 @@ handleSimpleNode blockType runP tracers forgingStateVar nc cmdPc networkMagic on
417426 -- set the initial block forging
418427 blockForging <- mkBlockForging (Consensus. kesAgentTracer $ consensusTracers tracers)
419428
420- unless (ncStartAsNonProducingNode nc) $
421- setBlockForging nodeKernel blockForging
429+ let installedBlockForging =
430+ if ncStartAsNonProducingNode nc then [] else blockForging
431+ blockForgingStatus =
432+ if null installedBlockForging
433+ then BlockForgingDisabled
434+ else BlockForgingEnabled runP
435+ setBlockForging nodeKernel installedBlockForging
436+
437+ updatePerasVoteForging
438+ (startupTracer tracers)
439+ blockType
440+ nodeKernel
441+ blockForgingStatus
422442
423443 maybeSpawnOnSlotSyncedShutdownHandler
424444 (ncShutdownConfig nc)
@@ -502,6 +522,7 @@ handleSimpleNode blockType runP tracers forgingStateVar nc cmdPc networkMagic on
502522 blockType nc cmdPc networkMagic nodeKernel localRootsVar publicRootsVar useLedgerVar
503523 useBootstrapVar ledgerPeerSnapshotPathVar ledgerPeerSnapshotVar
504524 rpcConfigVar
525+ rnNodeKernelHook nodeArgs registry nodeKernel
505526 -- populate node kernel access for RPC server
506527 (shelleyGenesisHash, shelleyGenesisFile) <- case ncProtocolConfig nc of
507528 NodeProtocolConfigurationCardano _ shelleyCfg _ _ _ _ _ ->
@@ -631,7 +652,9 @@ installSigHUPHandler startupTracer kesAgentTracer forgingStateVar blockType nc c
631652 void $ Signals. installHandler
632653 Signals. sigHUP
633654 (Signals. Catch $ do
634- updateBlockForging startupTracer kesAgentTracer forgingStateVar blockType nodeKernel nc
655+ blockForgingStatus <-
656+ updateBlockForging startupTracer kesAgentTracer forgingStateVar blockType nodeKernel nc
657+ updatePerasVoteForging startupTracer blockType nodeKernel blockForgingStatus
635658 updateTopologyConfiguration startupTracer nc localRootsVar publicRootsVar
636659 useLedgerVar useBootstrapPeersVar ledgerPeerSnapshotPathVar
637660 void $ updateLedgerPeerSnapshot
@@ -648,14 +671,22 @@ installSigHUPHandler startupTracer kesAgentTracer forgingStateVar blockType nc c
648671#endif
649672
650673
674+ -- | Whether reloading produced a protocol snapshot and whether block forging
675+ -- is installed. 'BlockForgingUnchanged' means the reload was rejected and both
676+ -- the current block and Peras forgers must be preserved.
677+ data BlockForgingStatus blk
678+ = BlockForgingEnabled (Api. ProtocolInfoArgs IO blk )
679+ | BlockForgingDisabled
680+ | BlockForgingUnchanged
681+
651682#ifdef UNIX
652683updateBlockForging :: Tracer IO (StartupTrace blk )
653684 -> Tracer IO KESAgentClientTrace
654685 -> ForgingStateVar
655686 -> Api. BlockType blk
656687 -> NodeKernel IO RemoteAddress (ConnectionId LocalAddress ) blk
657688 -> NodeConfiguration
658- -> IO ()
689+ -> IO (BlockForgingStatus blk )
659690updateBlockForging startupTracer kesAgentTracer forgingStateVar blockType nodeKernel nc = do
660691 eitherSomeProtocol <-
661692 runExceptT $
@@ -669,8 +700,10 @@ updateBlockForging startupTracer kesAgentTracer forgingStateVar blockType nodeKe
669700 noteForgingState forgingStateVar False
670701 traceWith startupTracer (BlockForgingUpdate DisabledBlockForging )
671702 setBlockForging nodeKernel []
672- _NothingOrOtherFileError ->
703+ pure BlockForgingDisabled
704+ _NothingOrOtherFileError -> do
673705 traceWith startupTracer (BlockForgingUpdateError err)
706+ pure BlockForgingUnchanged
674707 Right (SomeConsensusProtocol blockType' runP', _) ->
675708 case Api. reflBlockType blockType blockType' of
676709 Just Refl -> do
@@ -689,12 +722,15 @@ updateBlockForging startupTracer kesAgentTracer forgingStateVar blockType nodeKe
689722 then EnabledBlockForging
690723 else DisabledBlockForging ))
691724 setBlockForging nodeKernel blockForging
692- Nothing ->
725+ pure $ if enabled
726+ then BlockForgingEnabled runP'
727+ else BlockForgingDisabled
728+ Nothing -> do
693729 traceWith startupTracer
694730 $ BlockForgingBlockTypeMismatch
695731 (Api. SomeBlockType blockType)
696732 (Api. SomeBlockType blockType')
697- return ()
733+ pure BlockForgingUnchanged
698734 where
699735 wasFileRemovedFromScope :: ProtocolInstantiationError
700736 -> Maybe (Api. FileError Api. TextEnvelopeError )
@@ -712,7 +748,63 @@ updateBlockForging startupTracer kesAgentTracer forgingStateVar blockType nodeKe
712748 wasFileRemovedFromScope (ShelleyProtocolInstantiationError _) = Nothing
713749 wasFileRemovedFromScope (CardanoProtocolInstantiationError _) = Nothing
714750
751+ #endif
752+
753+ updatePerasVoteForging
754+ :: forall blk .
755+ Tracer IO (StartupTrace blk )
756+ -> Api. BlockType blk
757+ -> NodeKernel IO RemoteAddress (ConnectionId LocalAddress ) blk
758+ -> BlockForgingStatus blk
759+ -> IO ()
760+ updatePerasVoteForging startupTracer blockType nodeKernel blockForgingStatus = do
761+ case blockForgingStatus of
762+ BlockForgingUnchanged ->
763+ pure ()
764+ BlockForgingDisabled -> do
765+ setPerasVoteForging nodeKernel Nothing
766+ tracePerasVoteForgingUpdate PerasVoteForgingCleared
767+ BlockForgingEnabled args ->
768+ updateFromProtocolArgs args
769+ where
770+ updateFromProtocolArgs args =
771+ case blockType of
772+ Api. CardanoBlockType ->
773+ case poolIdFromProtocolInfoArgs args of
774+ Nothing -> do
775+ setPerasVoteForging nodeKernel Nothing
776+ tracePerasVoteForgingUpdate PerasVoteForgingCleared
777+ Just poolId -> do
778+ case perasPrivateKey of
779+ Left err ->
780+ tracePerasVoteForgingUpdate (PerasVoteForgingRetainedAfterError (show err))
781+ Right privateKey -> do
782+ let voteForging = mkCardanoPerasVoteForging poolId privateKey
783+ setPerasVoteForging nodeKernel (Just voteForging)
784+ tracePerasVoteForgingUpdate PerasVoteForgingInstalled
785+ _ -> do
786+ setPerasVoteForging nodeKernel Nothing
787+ tracePerasVoteForgingUpdate PerasVoteForgingDisabledUnsupported
788+
789+ perasPrivateKey =
790+ unsafePerasBLSPrivateKeyFromEnv
791+
792+ poolIdFromProtocolInfoArgs (Api. ProtocolInfoArgsCardano _ params) =
793+ case shelleyBasedLeaderCredentials (CardanoConsensus. shelleyBasedProtocolParams params) of
794+ [credential] -> Just (poolIdFromShelleyLeaderCredentials credential)
795+ _ -> Nothing
796+
797+ poolIdFromShelleyLeaderCredentials =
798+ PoolId
799+ . hashKey
800+ . coerceKeyRole
801+ . praosCanBeLeaderColdVerKey
802+ . shelleyLeaderCredentialsCanBeLeader
803+
804+ tracePerasVoteForgingUpdate =
805+ traceWith startupTracer . PerasVoteForgingUpdate
715806
807+ #ifdef UNIX
716808updateTopologyConfiguration :: Tracer IO (StartupTrace blk )
717809 -> NodeConfiguration
718810 -> StrictTVar IO [(HotValency , WarmValency , Map RelayAccessPoint (LocalRootConfig PeerTrustable ))]
0 commit comments