Skip to content

Commit 0bf6d79

Browse files
committed
Sanity check works!
1 parent 64ed665 commit 0bf6d79

File tree

21 files changed

+621
-206
lines changed

21 files changed

+621
-206
lines changed

cardano-node/src/Cardano/Node/Protocol/Byron.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import Cardano.Tracing.OrphanInstances.Shelley ()
3636
import Ouroboros.Consensus.Cardano
3737
import qualified Ouroboros.Consensus.Cardano as Consensus
3838

39+
import Control.Exception
3940
import qualified Data.ByteString.Lazy as LB
4041
import Data.Maybe (fromMaybe)
4142
import Data.Text (Text)
@@ -167,6 +168,9 @@ data ByronProtocolInstantiationError =
167168
| SigningKeyFilepathNotSpecified
168169
deriving Show
169170

171+
instance Exception ByronProtocolInstantiationError where
172+
displayException = docToString . prettyError
173+
170174
instance Error ByronProtocolInstantiationError where
171175
prettyError (CanonicalDecodeFailure fp failure) =
172176
"Canonical decode failure in " <> pshow fp

cardano-testnet/cardano-testnet.cabal

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ library
8686
, process
8787
, resourcet
8888
, retry
89+
, rio
90+
, rio-orphans
8991
, safe-exceptions
9092
, scientific
9193
, si-timers
@@ -111,17 +113,20 @@ library
111113
Testnet.EpochStateProcessing
112114
Testnet.Filepath
113115
Testnet.Handlers
116+
Testnet.Orphans
114117
Testnet.Ping
115118
Testnet.Process.Cli.DRep
116119
Testnet.Process.Cli.Keys
117120
Testnet.Process.Cli.SPO
118121
Testnet.Process.Cli.Transaction
122+
Testnet.Process.NewRun
119123
Testnet.Process.Run
120124
Testnet.Property.Assert
121125
Testnet.Property.Run
122126
Testnet.Property.Util
123127
Testnet.Runtime
124128
Testnet.Start.Byron
129+
Testnet.Start.Cardano
125130
Testnet.Start.Types
126131
Testnet.SubmitApi
127132
Testnet.TestQueryCmds
@@ -130,7 +135,6 @@ library
130135
other-modules: Parsers.Cardano
131136
Parsers.Help
132137
Parsers.Version
133-
Testnet.Start.Cardano
134138
Testnet.TestEnumGenerator
135139
Paths_cardano_testnet
136140

cardano-testnet/src/Parsers/Run.hs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{-# LANGUAGE GADTs #-}
22
{-# LANGUAGE LambdaCase #-}
3-
{-# LANGUAGE NamedFieldPuns #-}
43
{-# LANGUAGE ScopedTypeVariables #-}
54

65
module Parsers.Run
@@ -11,12 +10,14 @@ module Parsers.Run
1110
) where
1211

1312
import Cardano.CLI.Environment
13+
import Control.Monad
1414

1515
import Data.Default.Class (def)
1616
import Data.Foldable
1717
import Options.Applicative
1818
import qualified Options.Applicative as Opt
19-
19+
import RIO (runRIO)
20+
import RIO.Orphans
2021
import Testnet.Property.Run
2122
import Testnet.Start.Cardano
2223
import Testnet.Start.Types
@@ -61,34 +62,35 @@ createEnvOptions CardanoTestnetCreateEnvOptions
6162
, createEnvOutputDir=outputDir
6263
, createEnvCreateEnvOptions=ceOptions
6364
} =
64-
testnetRoutine (UserProvidedEnv outputDir) $ \conf -> do
65-
createTestnetEnv
66-
testnetOptions genesisOptions ceOptions
67-
-- Do not add hashes to the main config file, so that genesis files
68-
-- can be modified without having to recompute hashes every time.
69-
conf{genesisHashesPolicy = WithoutHashes}
65+
testnetRoutine (UserProvidedEnv outputDir) $ \conf -> do
66+
liftToIntegration $
67+
createTestnetEnv
68+
testnetOptions genesisOptions ceOptions
69+
-- Do not add hashes to the main config file, so that genesis files
70+
-- can be modified without having to recompute hashes every time.
71+
conf{genesisHashesPolicy = WithoutHashes}
7072

7173
runCardanoOptions :: CardanoTestnetCliOptions -> IO ()
7274
runCardanoOptions CardanoTestnetCliOptions
73-
{ cliTestnetOptions=testnetOptions@CardanoTestnetOptions{cardanoOutputDir}
75+
{ cliTestnetOptions=testnetOptions
7476
, cliGenesisOptions=genesisOptions
7577
, cliNodeEnvironment=env
76-
, cliUpdateTimestamps=updateTimestamps
78+
, cliUpdateTimestamps=updateTimestamps'
7779
} =
7880
case env of
79-
NoUserProvidedEnv ->
81+
NoUserProvidedEnv -> do
8082
-- Create the sandbox, then run cardano-testnet.
8183
-- It is not necessary to honor `cliUpdateTimestamps` here, because
8284
-- the genesis files will be created with up-to-date stamps already.
83-
runTestnet cardanoOutputDir $ \conf -> do
84-
createTestnetEnv
85-
testnetOptions genesisOptions def
86-
conf
87-
cardanoTestnet testnetOptions conf
88-
UserProvidedEnv nodeEnvPath ->
85+
conf <- mkConfigAbs "testnet"
86+
runRIO () $ createTestnetEnv
87+
testnetOptions genesisOptions def
88+
conf
89+
withResourceMap (\rm -> void . runRIO rm $ cardanoTestnet testnetOptions conf)
90+
UserProvidedEnv nodeEnvPath -> do
8991
-- Run cardano-testnet in the sandbox provided by the user
9092
-- In that case, 'cardanoOutputDir' is not used
91-
runTestnet (UserProvidedEnv nodeEnvPath) $ \conf ->
92-
cardanoTestnet
93+
conf <- mkConfigAbs nodeEnvPath
94+
withResourceMap (\rm -> void . runRIO rm $ cardanoTestnet
9395
testnetOptions
94-
conf{updateTimestamps=updateTimestamps}
96+
conf{updateTimestamps=updateTimestamps'})

cardano-testnet/src/Testnet/Components/Configuration.hs

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,18 @@ import Cardano.Network.PeerSelection.Bootstrap
3333
import Cardano.Network.PeerSelection.PeerTrustable
3434
import qualified Cardano.Node.Configuration.Topology as NonP2P
3535
import qualified Cardano.Node.Configuration.TopologyP2P as P2P
36+
import Cardano.Node.Protocol.Byron
3637
import Ouroboros.Network.NodeToNode (DiffusionMode (..))
3738
import Ouroboros.Network.PeerSelection.LedgerPeers
3839
import Ouroboros.Network.PeerSelection.State.LocalRootPeers
3940

40-
import Control.Exception.Safe (MonadCatch)
4141
import Control.Monad
4242
import Control.Monad.Extra
4343
import Data.Aeson
4444
import qualified Data.Aeson as Aeson
4545
import qualified Data.Aeson.Encode.Pretty as A
4646
import Data.Aeson.Key hiding (fromString)
4747
import Data.Aeson.KeyMap hiding (map)
48-
import Data.Bifunctor (first)
4948
import qualified Data.ByteString as BS
5049
import qualified Data.ByteString.Lazy as LBS
5150
import qualified Data.List as List
@@ -57,25 +56,26 @@ import Data.Word (Word64)
5756
import GHC.Stack (HasCallStack)
5857
import qualified GHC.Stack as GHC
5958
import qualified Network.HTTP.Simple as HTTP
59+
import RIO (Exception(..), MonadThrow, throwM)
6060
import qualified System.Directory as System
6161
import System.FilePath.Posix (takeDirectory, (</>))
6262

63+
6364
import Testnet.Blockfrost (blockfrostToGenesis)
6465
import qualified Testnet.Defaults as Defaults
6566
import Testnet.Filepath
66-
import Testnet.Process.Run (execCli_)
67+
import Testnet.Process.NewRun (execCli_)
6768
import Testnet.Start.Types
6869

69-
import Hedgehog
70-
import qualified Hedgehog as H
7170
import qualified Hedgehog.Extras.Stock.OS as OS
7271
import qualified Hedgehog.Extras.Stock.Time as DTC
73-
import qualified Hedgehog.Extras.Test.Base as H
74-
import qualified Hedgehog.Extras.Test.File as H
72+
7573

7674
-- | Returns JSON encoded hashes of the era, as well as the hard fork configuration toggle.
7775
createConfigJson :: ()
78-
=> (MonadTest m, MonadIO m, HasCallStack)
76+
=> HasCallStack
77+
=> MonadIO m
78+
=> MonadThrow m
7979
=> TmpAbsolutePath
8080
-> ShelleyBasedEra era -- ^ The era used for generating the hard fork configuration toggle
8181
-> m (KeyMap Aeson.Value)
@@ -93,7 +93,7 @@ createConfigJson (TmpAbsolutePath tempAbsPath) sbe = GHC.withFrozenCallStack $ d
9393
, Defaults.defaultYamlHardforkViaConfig sbe
9494
]
9595
where
96-
getHash :: (MonadTest m, MonadIO m) => CardanoEra a -> Text.Text -> m (KeyMap Value)
96+
getHash :: MonadIO m => CardanoEra a -> Text.Text -> m (KeyMap Value)
9797
getHash e = getShelleyGenesisHash (tempAbsPath </> Defaults.defaultGenesisFilepath e)
9898

9999
createConfigJsonNoHash :: ()
@@ -104,22 +104,25 @@ createConfigJsonNoHash = Defaults.defaultYamlHardforkViaConfig
104104
-- Generate hashes for genesis.json files
105105

106106
getByronGenesisHash
107-
:: (H.MonadTest m, MonadIO m)
107+
:: MonadIO m
108+
=> MonadThrow m
108109
=> FilePath
109110
-> m (KeyMap Aeson.Value)
110111
getByronGenesisHash path = do
111112
e <- runExceptT $ readGenesisData path
112-
(_, genesisHash) <- H.leftFail e
113-
let genesisHash' = unGenesisHash genesisHash
114-
pure . singleton "ByronGenesisHash" $ toJSON genesisHash'
113+
case e of
114+
Left err -> throwM $ GenesisReadError path err
115+
Right (_, genesisHash) -> do
116+
let genesisHash' = unGenesisHash genesisHash
117+
pure . singleton "ByronGenesisHash" $ toJSON genesisHash'
115118

116119
getShelleyGenesisHash
117-
:: (H.MonadTest m, MonadIO m)
120+
:: MonadIO m
118121
=> FilePath
119122
-> Text
120123
-> m (KeyMap Aeson.Value)
121124
getShelleyGenesisHash path key = do
122-
content <- H.evalIO $ BS.readFile path
125+
content <- liftIO $ BS.readFile path
123126
let genesisHash = Crypto.hashWith id content :: Crypto.Hash Crypto.Blake2b_256 BS.ByteString
124127
pure . singleton (fromText key) $ toJSON genesisHash
125128

@@ -130,32 +133,44 @@ startTimeOffsetSeconds = if OS.isWin32 then 90 else 15
130133

131134
-- | A start time and 'ShelleyGenesis' value that are fit to pass to 'cardanoTestnet'
132135
getDefaultShelleyGenesis :: ()
133-
=> HasCallStack
134136
=> MonadIO m
135-
=> MonadTest m
136137
=> AnyShelleyBasedEra
137138
-> Word64 -- ^ The max supply
138139
-> GenesisOptions
139140
-> m ShelleyGenesis
140141
getDefaultShelleyGenesis asbe maxSupply opts = do
141-
currentTime <- H.noteShowIO DTC.getCurrentTime
142-
startTime <- H.noteShow $ DTC.addUTCTime startTimeOffsetSeconds currentTime
142+
currentTime <- liftIO DTC.getCurrentTime
143+
let startTime = DTC.addUTCTime startTimeOffsetSeconds currentTime
143144
return $ Defaults.defaultShelleyGenesis asbe startTime maxSupply opts
144145

145146
-- | An 'AlonzoGenesis' value that is fit to pass to 'cardanoTestnet'
146147
getDefaultAlonzoGenesis :: ()
147148
=> HasCallStack
148-
=> MonadTest m
149+
=> MonadThrow m
149150
=> ShelleyBasedEra era
150151
-> m AlonzoGenesis
151152
getDefaultAlonzoGenesis sbe =
152-
H.evalEither $ first prettyError (Defaults.defaultAlonzoGenesis sbe)
153+
case Defaults.defaultAlonzoGenesis sbe of
154+
Right genesis -> return genesis
155+
Left err -> throwM err
156+
153157

154158
numSeededUTxOKeys :: Int
155159
numSeededUTxOKeys = 3
156160

161+
-- TODO: So that we don't lose
162+
-- logging power. We should catch the exception
163+
-- and use the MonadTest instance of the Integration
164+
-- monad to log the exception and also log additional
165+
-- information from the function.
166+
-- Once we lift to Integration monad we can
167+
-- use the various hedgehog-extra functions
168+
-- for logging purposes. No reason for the annotations
169+
-- to be littered within the functions
157170
createSPOGenesisAndFiles
158-
:: (MonadTest m, MonadCatch m, MonadIO m, HasCallStack)
171+
:: MonadIO m
172+
=> HasCallStack
173+
=> MonadThrow m
159174
=> CardanoTestnetOptions -- ^ The options to use
160175
-> GenesisOptions
161176
-> TestnetOnChainParams
@@ -168,7 +183,8 @@ createSPOGenesisAndFiles
168183
AnyShelleyBasedEra sbe <- pure cardanoNodeEra
169184

170185
let genesisShelleyDirAbs = takeDirectory inputGenesisShelleyFp
171-
genesisShelleyDir <- H.createDirectoryIfMissing genesisShelleyDirAbs
186+
187+
genesisShelleyDir <- liftIO $ System.createDirectoryIfMissing True genesisShelleyDirAbs >> pure genesisShelleyDirAbs
172188
let -- At least there should be a delegator per DRep
173189
-- otherwise some won't be representing anybody
174190
numStakeDelegators = max 3 (fromIntegral cardanoNumDReps) :: Int
@@ -184,23 +200,25 @@ createSPOGenesisAndFiles
184200
alonzoGenesis' <- getDefaultAlonzoGenesis sbe
185201
let conwayGenesis' = Defaults.defaultConwayGenesis
186202

187-
(alonzoGenesis, conwayGenesis, shelleyGenesis) <- resolveOnChainParams onChainParams
188-
(alonzoGenesis', conwayGenesis', shelleyGenesis')
203+
(alonzoGenesis, conwayGenesis, shelleyGenesis)
204+
<- resolveOnChainParams onChainParams
205+
(alonzoGenesis', conwayGenesis', shelleyGenesis')
189206

190207
-- Write Genesis files to disk, so they can be picked up by create-testnet-data
191-
H.evalIO $ do
208+
-- H.evalIO $ do
209+
liftIO $ do
192210
LBS.writeFile inputGenesisAlonzoFp $ A.encodePretty alonzoGenesis
193211
LBS.writeFile inputGenesisConwayFp $ A.encodePretty conwayGenesis
194212
LBS.writeFile inputGenesisShelleyFp $ A.encodePretty shelleyGenesis
195213

196-
H.note_ $ "Number of pools: " <> show nPoolNodes
197-
H.note_ $ "Number of stake delegators: " <> show numStakeDelegators
198-
H.note_ $ "Number of seeded UTxO keys: " <> show numSeededUTxOKeys
214+
-- TODO: H.note_ $ "Number of pools: " <> show nPoolNodes
215+
-- TODO: H.note_ $ "Number of stake delegators: " <> show numStakeDelegators
216+
-- TODO: H.note_ $ "Number of seeded UTxO keys: " <> show numSeededUTxOKeys
199217

200218
let era = toCardanoEra sbe
201219

202-
currentTime <- H.noteShowIO DTC.getCurrentTime
203-
startTime <- H.noteShow $ DTC.addUTCTime startTimeOffsetSeconds currentTime
220+
currentTime <- liftIO DTC.getCurrentTime
221+
let startTime = DTC.addUTCTime startTimeOffsetSeconds currentTime
204222

205223
execCli_ $
206224
[ eraToString sbe, "genesis", "create-testnet-data" ]
@@ -225,8 +243,8 @@ createSPOGenesisAndFiles
225243
]
226244
(\fp -> liftIO $ whenM (System.doesFileExist fp) (System.removeFile fp))
227245

228-
files <- H.listDirectory tempAbsPath
229-
forM_ files H.note
246+
_files <- liftIO $ System.listDirectory tempAbsPath
247+
-- forM_ files H.note
230248

231249
return genesisShelleyDir
232250
where
@@ -287,11 +305,23 @@ mkTopologyConfig numNodes allPorts port True = A.encodePretty topologyP2P
287305
DontUseBootstrapPeers
288306
Nothing
289307

308+
309+
data BlockfrostParamsError = BlockfrostParamsDecodeError FilePath String
310+
deriving Show
311+
312+
instance Exception BlockfrostParamsError where
313+
displayException (BlockfrostParamsDecodeError fp err) =
314+
"Failed to decode Blockfrost on-chain parameters from file "
315+
<> fp
316+
<> ": "
317+
<> err
318+
290319
-- | Resolves different kinds of user-provided on-chain parameters
291320
-- into a unified, consistent set of Genesis files
292321
resolveOnChainParams :: ()
293-
=> (MonadTest m, MonadIO m)
294322
=> HasCallStack
323+
=> MonadIO m
324+
=> MonadThrow m
295325
=> TestnetOnChainParams
296326
-> (AlonzoGenesis, ConwayGenesis, ShelleyGenesis)
297327
-> m (AlonzoGenesis, ConwayGenesis, ShelleyGenesis)
@@ -300,10 +330,11 @@ resolveOnChainParams onChainParams geneses = case onChainParams of
300330
DefaultParams -> pure geneses
301331

302332
OnChainParamsFile file -> do
303-
eParams <- H.readJsonFile file
304-
params <- H.leftFail eParams
305-
pure $ blockfrostToGenesis geneses params
333+
eParams <- eitherDecode <$> liftIO (LBS.readFile file)
334+
case eParams of
335+
Right params -> pure $ blockfrostToGenesis geneses params
336+
Left err -> throwM $ BlockfrostParamsDecodeError file err
306337

307338
OnChainParamsMainnet -> do
308-
mainnetParams <- H.evalIO $ HTTP.getResponseBody <$> HTTP.httpJSON mainnetParamsRequest
339+
mainnetParams <- liftIO $ HTTP.getResponseBody <$> HTTP.httpJSON mainnetParamsRequest
309340
pure $ blockfrostToGenesis geneses mainnetParams

cardano-testnet/src/Testnet/Defaults.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import Ouroboros.Network.PeerSelection.State.LocalRootPeers (HotValenc
7474

7575
import Prelude
7676

77+
import Control.Exception (Exception (..))
7778
import Control.Monad.Identity (Identity)
7879
import Data.Aeson (ToJSON (..), Value, (.=))
7980
import qualified Data.Aeson as Aeson
@@ -107,6 +108,10 @@ newtype AlonzoGenesisError
107108
= AlonzoGenErrTooMuchPrecision Rational
108109
deriving Show
109110

111+
instance Exception AlonzoGenesisError where
112+
displayException = Api.docToString . Api.prettyError
113+
114+
110115
defaultAlonzoGenesis :: ShelleyBasedEra era -> Either AlonzoGenesisError AlonzoGenesis
111116
defaultAlonzoGenesis sbe = do
112117
let genesis = Api.alonzoGenesisDefaults (toCardanoEra sbe)

0 commit comments

Comments
 (0)