Skip to content

Commit b0c94e7

Browse files
authored
Merge pull request #1219 from input-output-hk/ensemble/survive-conway-fork
Report error on unsupported era
2 parents cfac902 + a67ec3e commit b0c94e7

File tree

13 files changed

+227
-117
lines changed

13 files changed

+227
-117
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ changes.
3030
- Hydra.Options split into Hydra.Options.Common, Hydra.Options.Offline,
3131
Hydra.Options.Online, re-exported from Hydra.Options.
3232

33+
- Report error on unsupported era.
3334

3435
## [0.14.0] - 2023-12-04
3536

fourmolu.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ fixities:
1212
- infixr 1 &
1313
- infixl 3 <|>
1414
- infixr 3 &&
15+
- infixl 1 <&>

hydra-cluster/bench/Bench/EndToEnd.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ commitUTxO node clients Dataset{clientDatasets} =
257257
doCommit (client, ClientDataset{initialUTxO, clientKeys = ClientKeys{externalSigningKey}}) = do
258258
requestCommitTx client initialUTxO
259259
<&> signTx externalSigningKey
260-
>>= submitTx node
260+
>>= submitTx node
261261
pure initialUTxO
262262

263263
processTransactions :: [HydraClient] -> Dataset -> IO (Map.Map TxId Event)

hydra-cluster/config/devnet/genesis-conway.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"genDelegs": {},
23
"poolVotingThresholds": {
34
"pvtCommitteeNormal": 0.51,
45
"pvtCommitteeNoConfidence": 0.51,

hydra-cluster/config/devnet/genesis-shelley.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"epochLength": 432000,
2+
"epochLength": 5,
33
"activeSlotsCoeff": 1.0,
44
"slotLength": 0.1,
55
"securityParam": 2160,

hydra-cluster/src/CardanoNode.hs

Lines changed: 81 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ module CardanoNode where
44

55
import Hydra.Prelude
66

7-
import Control.Lens ((^?!))
7+
import Control.Lens ((?~), (^?!))
88
import Control.Tracer (Tracer, traceWith)
9-
import Data.Aeson ((.=))
9+
import Data.Aeson (Value (String), (.=))
1010
import Data.Aeson qualified as Aeson
11-
import Data.Aeson.KeyMap qualified as Aeson.KeyMap
12-
import Data.Aeson.Lens (key, _Number)
11+
import Data.Aeson.Lens (atKey, key, _Number)
1312
import Data.Fixed (Centi)
13+
import Data.Text qualified as Text
1414
import Data.Time.Clock.POSIX (posixSecondsToUTCTime, utcTimeToPOSIXSeconds)
1515
import Hydra.Cardano.Api (AsType (AsPaymentKey), File (..), NetworkId, PaymentKey, SigningKey, SocketPath, VerificationKey, generateSigningKey, getVerificationKey)
1616
import Hydra.Cardano.Api qualified as Api
@@ -77,7 +77,7 @@ defaultCardanoNodeArgs :: CardanoNodeArgs
7777
defaultCardanoNodeArgs =
7878
CardanoNodeArgs
7979
{ nodeSocket = "node.socket"
80-
, nodeConfigFile = "configuration.json"
80+
, nodeConfigFile = "cardano-node.json"
8181
, nodeByronGenesisFile = "genesis-byron.json"
8282
, nodeShelleyGenesisFile = "genesis-shelley.json"
8383
, nodeAlonzoGenesisFile = "genesis-alonzo.json"
@@ -117,64 +117,14 @@ withCardanoNodeDevnet ::
117117
(RunningNode -> IO a) ->
118118
IO a
119119
withCardanoNodeDevnet tracer stateDirectory action = do
120-
createDirectoryIfMissing True stateDirectory
121-
[dlgCert, signKey, vrfKey, kesKey, opCert] <-
122-
mapM
123-
copyDevnetCredential
124-
[ "byron-delegation.cert"
125-
, "byron-delegate.key"
126-
, "vrf.skey"
127-
, "kes.skey"
128-
, "opcert.cert"
129-
]
130-
let args =
131-
defaultCardanoNodeArgs
132-
{ nodeDlgCertFile = Just dlgCert
133-
, nodeSignKeyFile = Just signKey
134-
, nodeVrfKeyFile = Just vrfKey
135-
, nodeKesKeyFile = Just kesKey
136-
, nodeOpCertFile = Just opCert
137-
}
138-
copyDevnetFiles args
139-
refreshSystemStart stateDirectory args
140-
writeTopology [] args
141-
120+
args <- setupCardanoDevnet stateDirectory
142121
withCardanoNode tracer networkId stateDirectory args $ \rn -> do
143122
traceWith tracer MsgNodeIsReady
144123
action rn
145124
where
146125
-- NOTE: This needs to match what's in config/genesis-shelley.json
147126
networkId = defaultNetworkId
148127

149-
copyDevnetCredential file = do
150-
let destination = stateDirectory </> file
151-
unlessM (doesFileExist destination) $
152-
readConfigFile ("devnet" </> file)
153-
>>= writeFileBS destination
154-
setFileMode destination ownerReadMode
155-
pure file
156-
157-
copyDevnetFiles args = do
158-
readConfigFile ("devnet" </> "cardano-node.json")
159-
>>= writeFileBS
160-
(stateDirectory </> nodeConfigFile args)
161-
readConfigFile ("devnet" </> "genesis-byron.json")
162-
>>= writeFileBS
163-
(stateDirectory </> nodeByronGenesisFile args)
164-
readConfigFile ("devnet" </> "genesis-shelley.json")
165-
>>= writeFileBS
166-
(stateDirectory </> nodeShelleyGenesisFile args)
167-
readConfigFile ("devnet" </> "genesis-alonzo.json")
168-
>>= writeFileBS
169-
(stateDirectory </> nodeAlonzoGenesisFile args)
170-
readConfigFile ("devnet" </> "genesis-conway.json")
171-
>>= writeFileBS
172-
(stateDirectory </> nodeConwayGenesisFile args)
173-
174-
writeTopology peers args =
175-
Aeson.encodeFile (stateDirectory </> nodeTopologyFile args) $
176-
mkTopology peers
177-
178128
-- | Run a cardano-node as normal network participant on a known network.
179129
withCardanoNodeOnKnownNetwork ::
180130
Tracer IO NodeLog ->
@@ -205,7 +155,7 @@ withCardanoNodeOnKnownNetwork tracer workDir knownNetwork action = do
205155
readNetworkId = do
206156
shelleyGenesis :: Aeson.Value <- unsafeDecodeJson =<< readFileBS (workDir </> "shelley-genesis.json")
207157
if shelleyGenesis ^?! key "networkId" == "Mainnet"
208-
then pure $ Api.Mainnet
158+
then pure Api.Mainnet
209159
else do
210160
let magic = shelleyGenesis ^?! key "networkMagic" . _Number
211161
pure $ Api.Testnet (Api.NetworkMagic $ truncate magic)
@@ -241,6 +191,73 @@ withCardanoNodeOnKnownNetwork tracer workDir knownNetwork action = do
241191
fetchConfigFile path =
242192
parseRequestThrow path >>= httpBS <&> getResponseBody
243193

194+
-- | Setup the cardano-node to run a local devnet producing blocks. This copies
195+
-- the appropriate files and prepares 'CardanoNodeArgs' for 'withCardanoNode'.
196+
setupCardanoDevnet :: FilePath -> IO CardanoNodeArgs
197+
setupCardanoDevnet stateDirectory = do
198+
createDirectoryIfMissing True stateDirectory
199+
[dlgCert, signKey, vrfKey, kesKey, opCert] <-
200+
mapM
201+
copyDevnetCredential
202+
[ "byron-delegation.cert"
203+
, "byron-delegate.key"
204+
, "vrf.skey"
205+
, "kes.skey"
206+
, "opcert.cert"
207+
]
208+
let args =
209+
defaultCardanoNodeArgs
210+
{ nodeDlgCertFile = Just dlgCert
211+
, nodeSignKeyFile = Just signKey
212+
, nodeVrfKeyFile = Just vrfKey
213+
, nodeKesKeyFile = Just kesKey
214+
, nodeOpCertFile = Just opCert
215+
}
216+
copyDevnetFiles args
217+
refreshSystemStart stateDirectory args
218+
writeTopology [] args
219+
pure args
220+
where
221+
copyDevnetCredential file = do
222+
let destination = stateDirectory </> file
223+
unlessM (doesFileExist destination) $
224+
readConfigFile ("devnet" </> file)
225+
>>= writeFileBS destination
226+
setFileMode destination ownerReadMode
227+
pure file
228+
229+
copyDevnetFiles args = do
230+
readConfigFile ("devnet" </> "cardano-node.json")
231+
>>= writeFileBS
232+
(stateDirectory </> nodeConfigFile args)
233+
readConfigFile ("devnet" </> "genesis-byron.json")
234+
>>= writeFileBS
235+
(stateDirectory </> nodeByronGenesisFile args)
236+
readConfigFile ("devnet" </> "genesis-shelley.json")
237+
>>= writeFileBS
238+
(stateDirectory </> nodeShelleyGenesisFile args)
239+
readConfigFile ("devnet" </> "genesis-alonzo.json")
240+
>>= writeFileBS
241+
(stateDirectory </> nodeAlonzoGenesisFile args)
242+
readConfigFile ("devnet" </> "genesis-conway.json")
243+
>>= writeFileBS
244+
(stateDirectory </> nodeConwayGenesisFile args)
245+
246+
writeTopology peers args =
247+
Aeson.encodeFile (stateDirectory </> nodeTopologyFile args) $
248+
mkTopology peers
249+
250+
-- | Modify the cardano-node configuration to fork into conway at given era
251+
-- number.
252+
forkIntoConwayInEpoch :: FilePath -> CardanoNodeArgs -> Natural -> IO ()
253+
forkIntoConwayInEpoch stateDirectory args n = do
254+
config <-
255+
unsafeDecodeJsonFile @Aeson.Value (stateDirectory </> nodeConfigFile args)
256+
<&> atKey "TestConwayHardForkAtEpoch" ?~ toJSON n
257+
Aeson.encodeFile
258+
(stateDirectory </> nodeConfigFile args)
259+
config
260+
244261
withCardanoNode ::
245262
Tracer IO NodeLog ->
246263
NetworkId ->
@@ -341,19 +358,19 @@ refreshSystemStart stateDirectory args = do
341358
systemStart <- initSystemStart
342359
let startTime = round @_ @Int $ utcTimeToPOSIXSeconds systemStart
343360
byronGenesis <-
344-
unsafeDecodeJsonFile (stateDirectory </> nodeByronGenesisFile args)
345-
<&> addField "startTime" startTime
361+
unsafeDecodeJsonFile @Aeson.Value (stateDirectory </> nodeByronGenesisFile args)
362+
<&> atKey "startTime" ?~ toJSON startTime
346363

347364
let systemStartUTC =
348365
posixSecondsToUTCTime . fromRational . toRational $ startTime
349366
shelleyGenesis <-
350-
unsafeDecodeJsonFile (stateDirectory </> nodeShelleyGenesisFile args)
351-
<&> addField "systemStart" systemStartUTC
367+
unsafeDecodeJsonFile @Aeson.Value (stateDirectory </> nodeShelleyGenesisFile args)
368+
<&> atKey "systemStart" ?~ toJSON systemStartUTC
352369

353370
config <-
354-
unsafeDecodeJsonFile (stateDirectory </> nodeConfigFile args)
355-
<&> addField "ByronGenesisFile" (nodeByronGenesisFile args)
356-
<&> addField "ShelleyGenesisFile" (nodeShelleyGenesisFile args)
371+
unsafeDecodeJsonFile @Aeson.Value (stateDirectory </> nodeConfigFile args)
372+
<&> (atKey "ByronGenesisFile" ?~ toJSON (Text.pack $ nodeByronGenesisFile args))
373+
. (atKey "ShelleyGenesisFile" ?~ String (Text.pack $ nodeShelleyGenesisFile args))
357374

358375
Aeson.encodeFile
359376
(stateDirectory </> nodeByronGenesisFile args)
@@ -402,9 +419,6 @@ data NodeLog
402419
-- Helpers
403420
--
404421

405-
addField :: ToJSON a => Aeson.Key -> a -> Aeson.Value -> Aeson.Value
406-
addField k v = withObject (Aeson.KeyMap.insert k (toJSON v))
407-
408422
-- | Do something with an a JSON object. Fails if the given JSON value isn't an
409423
-- object.
410424
withObject :: (Aeson.Object -> Aeson.Object) -> Aeson.Value -> Aeson.Value

hydra-cluster/src/HydraNode.hs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ withHydraNode ::
367367
withHydraNode tracer chainConfig workDir hydraNodeId hydraSKey hydraVKeys allNodeIds hydraScriptsTxId action = do
368368
withLogFile logFilePath $ \logFileHandle -> do
369369
withHydraNode' chainConfig workDir hydraNodeId hydraSKey hydraVKeys allNodeIds hydraScriptsTxId (Just logFileHandle) $ do
370-
\_ processHandle -> do
370+
\_ _ processHandle -> do
371371
race
372372
(checkProcessHasNotDied ("hydra-node (" <> show hydraNodeId <> ")") processHandle)
373373
(withConnectionToNode tracer hydraNodeId action)
@@ -388,7 +388,7 @@ withHydraNode' ::
388388
TxId ->
389389
-- | If given use this as std out.
390390
Maybe Handle ->
391-
(Handle -> ProcessHandle -> IO a) ->
391+
(Handle -> Handle -> ProcessHandle -> IO a) ->
392392
IO a
393393
withHydraNode' chainConfig workDir hydraNodeId hydraSKey hydraVKeys allNodeIds hydraScriptsTxId mGivenStdOut action = do
394394
withSystemTempDirectory "hydra-node" $ \dir -> do
@@ -423,13 +423,13 @@ withHydraNode' chainConfig workDir hydraNodeId hydraSKey hydraVKeys allNodeIds h
423423
}
424424
)
425425
{ std_out = maybe CreatePipe UseHandle mGivenStdOut
426-
, std_err = Inherit
426+
, std_err = CreatePipe
427427
}
428-
withCreateProcess p $ \_stdin mCreatedHandle mErr processHandle ->
429-
case (mCreatedHandle, mGivenStdOut, mErr) of
430-
(Just out, _, _) -> action out processHandle
431-
(Nothing, Just out, _) -> action out processHandle
432-
(_, _, _) -> error "Should not happen™"
428+
withCreateProcess p $ \_stdin mCreatedStdOut mCreatedStdErr processHandle ->
429+
case (mCreatedStdOut <|> mGivenStdOut, mCreatedStdErr) of
430+
(Just out, Just err) -> action out err processHandle
431+
(Nothing, _) -> error "Should not happen™"
432+
(_, Nothing) -> error "Should not happen™"
433433
where
434434
peers =
435435
[ Host

0 commit comments

Comments
 (0)