Skip to content

Commit

Permalink
Merge pull request #1219 from input-output-hk/ensemble/survive-conway…
Browse files Browse the repository at this point in the history
…-fork

Report error on unsupported era
  • Loading branch information
ffakenz authored Dec 22, 2023
2 parents cfac902 + a67ec3e commit b0c94e7
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 117 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ changes.
- Hydra.Options split into Hydra.Options.Common, Hydra.Options.Offline,
Hydra.Options.Online, re-exported from Hydra.Options.

- Report error on unsupported era.

## [0.14.0] - 2023-12-04

Expand Down
1 change: 1 addition & 0 deletions fourmolu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ fixities:
- infixr 1 &
- infixl 3 <|>
- infixr 3 &&
- infixl 1 <&>
2 changes: 1 addition & 1 deletion hydra-cluster/bench/Bench/EndToEnd.hs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ commitUTxO node clients Dataset{clientDatasets} =
doCommit (client, ClientDataset{initialUTxO, clientKeys = ClientKeys{externalSigningKey}}) = do
requestCommitTx client initialUTxO
<&> signTx externalSigningKey
>>= submitTx node
>>= submitTx node
pure initialUTxO

processTransactions :: [HydraClient] -> Dataset -> IO (Map.Map TxId Event)
Expand Down
1 change: 1 addition & 0 deletions hydra-cluster/config/devnet/genesis-conway.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"genDelegs": {},
"poolVotingThresholds": {
"pvtCommitteeNormal": 0.51,
"pvtCommitteeNoConfidence": 0.51,
Expand Down
2 changes: 1 addition & 1 deletion hydra-cluster/config/devnet/genesis-shelley.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"epochLength": 432000,
"epochLength": 5,
"activeSlotsCoeff": 1.0,
"slotLength": 0.1,
"securityParam": 2160,
Expand Down
148 changes: 81 additions & 67 deletions hydra-cluster/src/CardanoNode.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ module CardanoNode where

import Hydra.Prelude

import Control.Lens ((^?!))
import Control.Lens ((?~), (^?!))
import Control.Tracer (Tracer, traceWith)
import Data.Aeson ((.=))
import Data.Aeson (Value (String), (.=))
import Data.Aeson qualified as Aeson
import Data.Aeson.KeyMap qualified as Aeson.KeyMap
import Data.Aeson.Lens (key, _Number)
import Data.Aeson.Lens (atKey, key, _Number)
import Data.Fixed (Centi)
import Data.Text qualified as Text
import Data.Time.Clock.POSIX (posixSecondsToUTCTime, utcTimeToPOSIXSeconds)
import Hydra.Cardano.Api (AsType (AsPaymentKey), File (..), NetworkId, PaymentKey, SigningKey, SocketPath, VerificationKey, generateSigningKey, getVerificationKey)
import Hydra.Cardano.Api qualified as Api
Expand Down Expand Up @@ -77,7 +77,7 @@ defaultCardanoNodeArgs :: CardanoNodeArgs
defaultCardanoNodeArgs =
CardanoNodeArgs
{ nodeSocket = "node.socket"
, nodeConfigFile = "configuration.json"
, nodeConfigFile = "cardano-node.json"
, nodeByronGenesisFile = "genesis-byron.json"
, nodeShelleyGenesisFile = "genesis-shelley.json"
, nodeAlonzoGenesisFile = "genesis-alonzo.json"
Expand Down Expand Up @@ -117,64 +117,14 @@ withCardanoNodeDevnet ::
(RunningNode -> IO a) ->
IO a
withCardanoNodeDevnet tracer stateDirectory action = do
createDirectoryIfMissing True stateDirectory
[dlgCert, signKey, vrfKey, kesKey, opCert] <-
mapM
copyDevnetCredential
[ "byron-delegation.cert"
, "byron-delegate.key"
, "vrf.skey"
, "kes.skey"
, "opcert.cert"
]
let args =
defaultCardanoNodeArgs
{ nodeDlgCertFile = Just dlgCert
, nodeSignKeyFile = Just signKey
, nodeVrfKeyFile = Just vrfKey
, nodeKesKeyFile = Just kesKey
, nodeOpCertFile = Just opCert
}
copyDevnetFiles args
refreshSystemStart stateDirectory args
writeTopology [] args

args <- setupCardanoDevnet stateDirectory
withCardanoNode tracer networkId stateDirectory args $ \rn -> do
traceWith tracer MsgNodeIsReady
action rn
where
-- NOTE: This needs to match what's in config/genesis-shelley.json
networkId = defaultNetworkId

copyDevnetCredential file = do
let destination = stateDirectory </> file
unlessM (doesFileExist destination) $
readConfigFile ("devnet" </> file)
>>= writeFileBS destination
setFileMode destination ownerReadMode
pure file

copyDevnetFiles args = do
readConfigFile ("devnet" </> "cardano-node.json")
>>= writeFileBS
(stateDirectory </> nodeConfigFile args)
readConfigFile ("devnet" </> "genesis-byron.json")
>>= writeFileBS
(stateDirectory </> nodeByronGenesisFile args)
readConfigFile ("devnet" </> "genesis-shelley.json")
>>= writeFileBS
(stateDirectory </> nodeShelleyGenesisFile args)
readConfigFile ("devnet" </> "genesis-alonzo.json")
>>= writeFileBS
(stateDirectory </> nodeAlonzoGenesisFile args)
readConfigFile ("devnet" </> "genesis-conway.json")
>>= writeFileBS
(stateDirectory </> nodeConwayGenesisFile args)

writeTopology peers args =
Aeson.encodeFile (stateDirectory </> nodeTopologyFile args) $
mkTopology peers

-- | Run a cardano-node as normal network participant on a known network.
withCardanoNodeOnKnownNetwork ::
Tracer IO NodeLog ->
Expand Down Expand Up @@ -205,7 +155,7 @@ withCardanoNodeOnKnownNetwork tracer workDir knownNetwork action = do
readNetworkId = do
shelleyGenesis :: Aeson.Value <- unsafeDecodeJson =<< readFileBS (workDir </> "shelley-genesis.json")
if shelleyGenesis ^?! key "networkId" == "Mainnet"
then pure $ Api.Mainnet
then pure Api.Mainnet
else do
let magic = shelleyGenesis ^?! key "networkMagic" . _Number
pure $ Api.Testnet (Api.NetworkMagic $ truncate magic)
Expand Down Expand Up @@ -241,6 +191,73 @@ withCardanoNodeOnKnownNetwork tracer workDir knownNetwork action = do
fetchConfigFile path =
parseRequestThrow path >>= httpBS <&> getResponseBody

-- | Setup the cardano-node to run a local devnet producing blocks. This copies
-- the appropriate files and prepares 'CardanoNodeArgs' for 'withCardanoNode'.
setupCardanoDevnet :: FilePath -> IO CardanoNodeArgs
setupCardanoDevnet stateDirectory = do
createDirectoryIfMissing True stateDirectory
[dlgCert, signKey, vrfKey, kesKey, opCert] <-
mapM
copyDevnetCredential
[ "byron-delegation.cert"
, "byron-delegate.key"
, "vrf.skey"
, "kes.skey"
, "opcert.cert"
]
let args =
defaultCardanoNodeArgs
{ nodeDlgCertFile = Just dlgCert
, nodeSignKeyFile = Just signKey
, nodeVrfKeyFile = Just vrfKey
, nodeKesKeyFile = Just kesKey
, nodeOpCertFile = Just opCert
}
copyDevnetFiles args
refreshSystemStart stateDirectory args
writeTopology [] args
pure args
where
copyDevnetCredential file = do
let destination = stateDirectory </> file
unlessM (doesFileExist destination) $
readConfigFile ("devnet" </> file)
>>= writeFileBS destination
setFileMode destination ownerReadMode
pure file

copyDevnetFiles args = do
readConfigFile ("devnet" </> "cardano-node.json")
>>= writeFileBS
(stateDirectory </> nodeConfigFile args)
readConfigFile ("devnet" </> "genesis-byron.json")
>>= writeFileBS
(stateDirectory </> nodeByronGenesisFile args)
readConfigFile ("devnet" </> "genesis-shelley.json")
>>= writeFileBS
(stateDirectory </> nodeShelleyGenesisFile args)
readConfigFile ("devnet" </> "genesis-alonzo.json")
>>= writeFileBS
(stateDirectory </> nodeAlonzoGenesisFile args)
readConfigFile ("devnet" </> "genesis-conway.json")
>>= writeFileBS
(stateDirectory </> nodeConwayGenesisFile args)

writeTopology peers args =
Aeson.encodeFile (stateDirectory </> nodeTopologyFile args) $
mkTopology peers

-- | Modify the cardano-node configuration to fork into conway at given era
-- number.
forkIntoConwayInEpoch :: FilePath -> CardanoNodeArgs -> Natural -> IO ()
forkIntoConwayInEpoch stateDirectory args n = do
config <-
unsafeDecodeJsonFile @Aeson.Value (stateDirectory </> nodeConfigFile args)
<&> atKey "TestConwayHardForkAtEpoch" ?~ toJSON n
Aeson.encodeFile
(stateDirectory </> nodeConfigFile args)
config

withCardanoNode ::
Tracer IO NodeLog ->
NetworkId ->
Expand Down Expand Up @@ -341,19 +358,19 @@ refreshSystemStart stateDirectory args = do
systemStart <- initSystemStart
let startTime = round @_ @Int $ utcTimeToPOSIXSeconds systemStart
byronGenesis <-
unsafeDecodeJsonFile (stateDirectory </> nodeByronGenesisFile args)
<&> addField "startTime" startTime
unsafeDecodeJsonFile @Aeson.Value (stateDirectory </> nodeByronGenesisFile args)
<&> atKey "startTime" ?~ toJSON startTime

let systemStartUTC =
posixSecondsToUTCTime . fromRational . toRational $ startTime
shelleyGenesis <-
unsafeDecodeJsonFile (stateDirectory </> nodeShelleyGenesisFile args)
<&> addField "systemStart" systemStartUTC
unsafeDecodeJsonFile @Aeson.Value (stateDirectory </> nodeShelleyGenesisFile args)
<&> atKey "systemStart" ?~ toJSON systemStartUTC

config <-
unsafeDecodeJsonFile (stateDirectory </> nodeConfigFile args)
<&> addField "ByronGenesisFile" (nodeByronGenesisFile args)
<&> addField "ShelleyGenesisFile" (nodeShelleyGenesisFile args)
unsafeDecodeJsonFile @Aeson.Value (stateDirectory </> nodeConfigFile args)
<&> (atKey "ByronGenesisFile" ?~ toJSON (Text.pack $ nodeByronGenesisFile args))
. (atKey "ShelleyGenesisFile" ?~ String (Text.pack $ nodeShelleyGenesisFile args))

Aeson.encodeFile
(stateDirectory </> nodeByronGenesisFile args)
Expand Down Expand Up @@ -402,9 +419,6 @@ data NodeLog
-- Helpers
--

addField :: ToJSON a => Aeson.Key -> a -> Aeson.Value -> Aeson.Value
addField k v = withObject (Aeson.KeyMap.insert k (toJSON v))

-- | Do something with an a JSON object. Fails if the given JSON value isn't an
-- object.
withObject :: (Aeson.Object -> Aeson.Object) -> Aeson.Value -> Aeson.Value
Expand Down
16 changes: 8 additions & 8 deletions hydra-cluster/src/HydraNode.hs
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ withHydraNode ::
withHydraNode tracer chainConfig workDir hydraNodeId hydraSKey hydraVKeys allNodeIds hydraScriptsTxId action = do
withLogFile logFilePath $ \logFileHandle -> do
withHydraNode' chainConfig workDir hydraNodeId hydraSKey hydraVKeys allNodeIds hydraScriptsTxId (Just logFileHandle) $ do
\_ processHandle -> do
\_ _ processHandle -> do
race
(checkProcessHasNotDied ("hydra-node (" <> show hydraNodeId <> ")") processHandle)
(withConnectionToNode tracer hydraNodeId action)
Expand All @@ -388,7 +388,7 @@ withHydraNode' ::
TxId ->
-- | If given use this as std out.
Maybe Handle ->
(Handle -> ProcessHandle -> IO a) ->
(Handle -> Handle -> ProcessHandle -> IO a) ->
IO a
withHydraNode' chainConfig workDir hydraNodeId hydraSKey hydraVKeys allNodeIds hydraScriptsTxId mGivenStdOut action = do
withSystemTempDirectory "hydra-node" $ \dir -> do
Expand Down Expand Up @@ -423,13 +423,13 @@ withHydraNode' chainConfig workDir hydraNodeId hydraSKey hydraVKeys allNodeIds h
}
)
{ std_out = maybe CreatePipe UseHandle mGivenStdOut
, std_err = Inherit
, std_err = CreatePipe
}
withCreateProcess p $ \_stdin mCreatedHandle mErr processHandle ->
case (mCreatedHandle, mGivenStdOut, mErr) of
(Just out, _, _) -> action out processHandle
(Nothing, Just out, _) -> action out processHandle
(_, _, _) -> error "Should not happen™"
withCreateProcess p $ \_stdin mCreatedStdOut mCreatedStdErr processHandle ->
case (mCreatedStdOut <|> mGivenStdOut, mCreatedStdErr) of
(Just out, Just err) -> action out err processHandle
(Nothing, _) -> error "Should not happen™"
(_, Nothing) -> error "Should not happen™"
where
peers =
[ Host
Expand Down
Loading

0 comments on commit b0c94e7

Please sign in to comment.