-
Notifications
You must be signed in to change notification settings - Fork 749
Description
Problem
The interface between createTestnetEnv (step 1) and cardanoTestnet (step 2) is entirely implicit — it is a directory layout with naming conventions scattered across Defaults.hs, Configuration.hs, and Cardano.hs. Critical information like node count and types is not persisted, forcing the user to re-specify CLI options consistently across both invocations. Other data like testnetMagic must be re-parsed from genesis files.
This makes the cross-phase contract fragile: adding a new file in step 1 and forgetting to read it in step 2 is not caught by the compiler.
Proposed fix
Define a TestnetEnvManifest type that captures everything step 1 produces that step 2 needs:
data TestnetEnvManifest = TestnetEnvManifest
{ manifestNodes :: NonEmpty NodeManifestEntry
, manifestUtxoKeys :: Int
, manifestTestnetMagic :: Int
, manifestCreatedAt :: UTCTime
, manifestEra :: AnyShelleyBasedEra
} deriving (Eq, Show, Generic)
deriving anyclass (ToJSON, FromJSON)
data NodeManifestEntry = NodeManifestEntry
{ manifestNodeId :: Int
, manifestNodeType :: NodeType -- SPO | Relay
} deriving (Eq, Show, Generic)
deriving anyclass (ToJSON, FromJSON)createTestnetEnvwritestestnet-env.jsonas its final step.cardanoTestnetreads it as its first step when running from a pre-existing env.- In the direct
cardanopath, the manifest is constructed in-memory and passed directly (no disk round-trip needed).
The manifest file is human-readable, so users can inspect what create-env produced.
Adding a new cross-phase datum = adding a field to TestnetEnvManifest -> compiler forces both sides to update.
Depends on
- cardano-testnet: Split CardanoTestnetOptions into EnvCreationOptions and RuntimeOptions #6459 (split options records — so the manifest carries
EnvCreationOptionsfields cleanly)