diff --git a/cardano-testnet/cardano-testnet.cabal b/cardano-testnet/cardano-testnet.cabal index 840b12cd4bf..24126792346 100644 --- a/cardano-testnet/cardano-testnet.cabal +++ b/cardano-testnet/cardano-testnet.cabal @@ -79,7 +79,9 @@ library Testnet.Babbage Testnet.Cardano Testnet.Conf - Testnet.Genesis + Testnet.Commands.Genesis + Testnet.Commands.Governance + Testnet.Options Testnet.Run Testnet.Shelley Testnet.Utils diff --git a/cardano-testnet/src/Cardano/Testnet.hs b/cardano-testnet/src/Cardano/Testnet.hs index e000273204d..8146de6f5bd 100644 --- a/cardano-testnet/src/Cardano/Testnet.hs +++ b/cardano-testnet/src/Cardano/Testnet.hs @@ -37,9 +37,9 @@ module Cardano.Testnet ( ) where import Testnet -import Testnet.Babbage import Testnet.Cardano import Testnet.Conf hiding (base) +import Testnet.Options import Testnet.Shelley as Shelley import Testnet.Utils (waitUntilEpoch) diff --git a/cardano-testnet/src/Parsers/Babbage.hs b/cardano-testnet/src/Parsers/Babbage.hs index 84858d7b7c7..40108db4234 100644 --- a/cardano-testnet/src/Parsers/Babbage.hs +++ b/cardano-testnet/src/Parsers/Babbage.hs @@ -4,12 +4,12 @@ module Parsers.Babbage , runBabbageOptions ) where -import Prelude import Options.Applicative import qualified Options.Applicative as OA +import Prelude import Testnet -import Testnet.Babbage +import Testnet.Options import Testnet.Run (runTestnet) import Testnet.Util.Runtime (readNodeLoggingFormat) diff --git a/cardano-testnet/src/Testnet.hs b/cardano-testnet/src/Testnet.hs index 1b36bf6c878..22f81868b67 100644 --- a/cardano-testnet/src/Testnet.hs +++ b/cardano-testnet/src/Testnet.hs @@ -16,6 +16,8 @@ import Hedgehog.Extras.Test.Base (Integration, noteShow_) import Testnet.Babbage as Babbage import Testnet.Cardano as Cardano import Testnet.Conf +import qualified Testnet.Options as Options +import Testnet.Options import Testnet.Shelley as Shelley (ShelleyTestnetOptions, defaultTestnetOptions, shelleyTestnet) @@ -48,7 +50,7 @@ testnet options conf = case options of cardanoTestnet o conf babbageDefaultTestnetOptions :: BabbageTestnetOptions -babbageDefaultTestnetOptions = Babbage.defaultTestnetOptions +babbageDefaultTestnetOptions = Options.defaultTestnetOptions cardanoDefaultTestnetOptions :: CardanoTestnetOptions cardanoDefaultTestnetOptions = Cardano.defaultTestnetOptions diff --git a/cardano-testnet/src/Testnet/Babbage.hs b/cardano-testnet/src/Testnet/Babbage.hs index 487389bdd1c..1ef00fa88d8 100644 --- a/cardano-testnet/src/Testnet/Babbage.hs +++ b/cardano-testnet/src/Testnet/Babbage.hs @@ -8,20 +8,16 @@ {-# OPTIONS_GHC -Wno-unused-local-binds -Wno-unused-matches #-} module Testnet.Babbage - ( BabbageTestnetOptions(..) - , defaultTestnetOptions - , TestnetRuntime (..) + ( TestnetRuntime (..) , PaymentKeyPair(..) , babbageTestnet ) where -import Control.Monad -import Data.Aeson (encode, object, toJSON, (.=)) -import Hedgehog.Extras.Stock.Time (showUTCTimeSeconds) import Prelude -import System.FilePath.Posix (()) +import Control.Monad +import Data.Aeson (encode, object, toJSON, (.=)) import qualified Data.HashMap.Lazy as HM import qualified Data.List as L import qualified Data.Time.Clock as DTC @@ -29,10 +25,12 @@ import qualified Hedgehog.Extras.Stock.Aeson as J import qualified Hedgehog.Extras.Stock.OS as OS import qualified Hedgehog.Extras.Test.Base as H import qualified Hedgehog.Extras.Test.File as H +import System.FilePath.Posix (()) import qualified System.Info as OS +import Testnet.Commands.Genesis import qualified Testnet.Conf as H -import Testnet.Genesis +import Testnet.Options import qualified Testnet.Util.Assert as H import Testnet.Util.Process (execCli_) import Testnet.Util.Runtime (Delegator (..), NodeLoggingFormat (..), PaymentKeyPair (..), @@ -42,23 +40,6 @@ import Testnet.Util.Runtime (Delegator (..), NodeLoggingFormat (..), P {- HLINT ignore "Redundant flip" -} -data BabbageTestnetOptions = BabbageTestnetOptions - { babbageNumSpoNodes :: Int - , babbageSlotDuration :: Int - , babbageSecurityParam :: Int - , babbageTotalBalance :: Int - , babbageNodeLoggingFormat :: NodeLoggingFormat - } deriving (Eq, Show) - -defaultTestnetOptions :: BabbageTestnetOptions -defaultTestnetOptions = BabbageTestnetOptions - { babbageNumSpoNodes = 3 - , babbageSlotDuration = 1000 - , babbageSecurityParam = 10 - , babbageTotalBalance = 10020000000 - , babbageNodeLoggingFormat = NodeLoggingFormatAsJson - } - -- | For an unknown reason, CLI commands are a lot slower on Windows than on Linux and -- MacOS. We need to allow a lot more time to set up a testnet. startTimeOffsetSeconds :: DTC.NominalDiffTime @@ -75,20 +56,13 @@ babbageTestnet testnetOptions H.Conf {..} = do currentTime <- H.noteShowIO DTC.getCurrentTime startTime <- H.noteShow $ DTC.addUTCTime startTimeOffsetSeconds currentTime - execCli_ - [ "byron", "genesis", "genesis" - , "--protocol-magic", show @Int testnetMagic - , "--start-time", showUTCTimeSeconds startTime - , "--k", show @Int (babbageSecurityParam testnetOptions) - , "--n-poor-addresses", "0" - , "--n-delegate-addresses", show @Int (babbageNumSpoNodes testnetOptions) - , "--total-balance", show @Int (babbageTotalBalance testnetOptions) - , "--delegate-share", "1" - , "--avvm-entry-count", "0" - , "--avvm-entry-balance", "0" - , "--protocol-parameters-file", tempAbsPath "byron.genesis.spec.json" - , "--genesis-output-dir", tempAbsPath "byron-gen-command" - ] + createByronGenesis + testnetMagic + startTime + testnetOptions + (tempAbsPath "byron.genesis.spec.json") + (tempAbsPath "byron-gen-command") + -- Because in Babbage the overlay schedule and decentralization parameter -- are deprecated, we must use the "create-staked" cli command to create diff --git a/cardano-testnet/src/Testnet/Cardano.hs b/cardano-testnet/src/Testnet/Cardano.hs index 266689879bc..3374687c573 100644 --- a/cardano-testnet/src/Testnet/Cardano.hs +++ b/cardano-testnet/src/Testnet/Cardano.hs @@ -63,8 +63,9 @@ import qualified Hedgehog.Extras.Test.Concurrent as H import qualified Hedgehog.Extras.Test.File as H import qualified Hedgehog.Extras.Test.Network as H +import Testnet.Commands.Genesis +import Testnet.Commands.Governance import qualified Testnet.Conf as H -import Testnet.Genesis import qualified Testnet.Util.Assert as H import qualified Testnet.Util.Process as H import Testnet.Util.Process (execCli_) @@ -347,53 +348,31 @@ cardanoTestnet testnetOptions H.Conf {..} = do ] -- Update Proposal and votes - execCli_ - [ "byron", "governance", "create-update-proposal" - , "--filepath", tempAbsPath "update-proposal" - , "--testnet-magic", show @Int testnetMagic - , "--signing-key", tempAbsPath "byron/delegate-keys.000.key" - , "--protocol-version-major", "1" - , "--protocol-version-minor", "0" - , "--protocol-version-alt", "0" - , "--application-name", "cardano-sl" - , "--software-version-num", "1" - , "--system-tag", "linux" - , "--installer-hash", "0" - ] + createByronUpdateProposal + testnetMagic + (tempAbsPath "byron/delegate-keys.000.key") + (tempAbsPath "update-proposal") + 1 forM_ bftNodesN $ \n -> do - execCli_ - [ "byron", "governance", "create-proposal-vote" - , "--proposal-filepath", tempAbsPath "update-proposal" - , "--testnet-magic", show @Int testnetMagic - , "--signing-key", tempAbsPath "byron/delegate-keys.00" <> show @Int (n - 1) <> ".key" - , "--vote-yes" - , "--output-filepath", tempAbsPath "update-vote.00" <> show @Int (n - 1) - ] - - execCli_ - [ "byron", "governance", "create-update-proposal" - , "--filepath", tempAbsPath "update-proposal-1" - , "--testnet-magic", show @Int testnetMagic - , "--signing-key", tempAbsPath "byron/delegate-keys.000.key" - , "--protocol-version-major", "2" - , "--protocol-version-minor", "0" - , "--protocol-version-alt", "0" - , "--application-name", "cardano-sl" - , "--software-version-num", "1" - , "--system-tag", "linux" - , "--installer-hash", "0" - ] + createByronUpdateProposalVote + testnetMagic + (tempAbsPath "update-proposal") + (tempAbsPath "byron/delegate-keys.00" <> show @Int (n - 1) <> ".key") + (tempAbsPath "update-vote.00" <> show @Int (n - 1)) + + createByronUpdateProposal + testnetMagic + (tempAbsPath "byron/delegate-keys.000.key") + (tempAbsPath "update-proposal-1") + 2 forM_ bftNodesN $ \n -> - execCli_ - [ "byron", "governance", "create-proposal-vote" - , "--proposal-filepath", tempAbsPath "update-proposal-1" - , "--testnet-magic", show @Int testnetMagic - , "--signing-key", tempAbsPath "byron/delegate-keys.00" <> show @Int (n - 1) <> ".key" - , "--vote-yes" - , "--output-filepath", tempAbsPath "update-vote-1.00" <> show @Int (n - 1) - ] + createByronUpdateProposalVote + testnetMagic + (tempAbsPath "update-proposal-1") + (tempAbsPath "byron/delegate-keys.00" <> show @Int (n - 1) <> ".key") + (tempAbsPath "update-vote-1.00" <> show @Int (n - 1)) -- Generated genesis keys and genesis files H.noteEachM_ . H.listDirectory $ tempAbsPath "byron" @@ -644,11 +623,7 @@ cardanoTestnet testnetOptions H.Conf {..} = do -- 2. register the stake pool 1 -- 3. register the user1 stake address -- 4. delegate from the user1 stake address to the stake pool - txIn <- H.noteShow . S.strip =<< H.execCli - [ "genesis", "initial-txin" - , "--testnet-magic", show @Int testnetMagic - , "--verification-key-file", tempAbsPath "shelley/utxo-keys/utxo1.vkey" - ] + txIn <- H.noteShow . S.strip =<< createShelleyGenesisInitialTxIn testnetMagic (tempAbsPath "shelley/utxo-keys/utxo1.vkey") H.note_ txIn diff --git a/cardano-testnet/src/Testnet/Commands/Genesis.hs b/cardano-testnet/src/Testnet/Commands/Genesis.hs new file mode 100644 index 00000000000..01fd9f70710 --- /dev/null +++ b/cardano-testnet/src/Testnet/Commands/Genesis.hs @@ -0,0 +1,93 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TypeApplications #-} + +-- | All Byron and Shelley Genesis related functionality +module Testnet.Commands.Genesis + ( createShelleyGenesisInitialTxIn + , createByronGenesis + , defaultByronGenesisJsonValue + ) where + +import Prelude + +import Control.Monad.Catch +import Control.Monad.IO.Class +import Data.Aeson +import Data.Time.Clock (UTCTime) +import GHC.Stack (HasCallStack, withFrozenCallStack) + +import Hedgehog.Extras.Stock.Time (showUTCTimeSeconds) +import Hedgehog.Internal.Property + +import Testnet.Options +import Testnet.Util.Process + +-- | Creates a default Byron genesis. This is required for any testnet, predominantly because +-- we inject our ADA supply into our testnet via the Byron genesis. +createByronGenesis + :: (MonadTest m, MonadCatch m, MonadIO m, HasCallStack) + => Int + -> UTCTime + -> BabbageTestnetOptions + -> String + -> String + -> m () +createByronGenesis testnetMagic startTime testnetOptions pParamFp genOutputDir = + withFrozenCallStack $ execCli_ + [ "byron", "genesis", "genesis" + , "--protocol-magic", show testnetMagic + , "--start-time", showUTCTimeSeconds startTime + , "--k", show (babbageSecurityParam testnetOptions) + , "--n-poor-addresses", "0" + , "--n-delegate-addresses", show @Int (babbageNumSpoNodes testnetOptions) + , "--total-balance", show @Int (babbageTotalBalance testnetOptions) + , "--delegate-share", "1" + , "--avvm-entry-count", "0" + , "--avvm-entry-balance", "0" + , "--protocol-parameters-file", pParamFp + , "--genesis-output-dir", genOutputDir + ] + +-- | The Shelley initial UTxO is constructed from the 'sgInitialFunds' field which +-- is not a full UTxO but just a map from addresses to coin values. Therefore this +-- command creates a transaction input that defaults to the 0th index and therefore +-- we can spend spend this tx input in a transaction. +createShelleyGenesisInitialTxIn + :: (MonadTest m, MonadCatch m, MonadIO m, HasCallStack) + => Int -> FilePath -> m String +createShelleyGenesisInitialTxIn testnetMagic vKeyFp = + withFrozenCallStack $ execCli + [ "genesis", "initial-txin" + , "--testnet-magic", show @Int testnetMagic + , "--verification-key-file", vKeyFp + ] + +-- | We need a Byron genesis in order to be able to hardfork to the later Shelley based eras. +-- The values here don't matter as the testnet conditions are ultimately determined +-- by the Shelley genesis. +defaultByronGenesisJsonValue :: Value +defaultByronGenesisJsonValue = + object + [ "heavyDelThd" .= toJSON @String "300000000000" + , "maxBlockSize" .= toJSON @String "2000000" + , "maxTxSize" .= toJSON @String "4096" + , "maxHeaderSize" .= toJSON @String "2000000" + , "maxProposalSize" .= toJSON @String "700" + , "mpcThd" .= toJSON @String "20000000000000" + , "scriptVersion" .= toJSON @Int 0 + , "slotDuration" .= toJSON @String "1000" + , "softforkRule" .= object + [ "initThd" .= toJSON @String "900000000000000" + , "minThd" .= toJSON @String "600000000000000" + , "thdDecrement" .= toJSON @String "50000000000000" + ] + , "txFeePolicy" .= object + [ "multiplier" .= toJSON @String "43946000000" + , "summand" .= toJSON @String "155381000000000" + ] + , "unlockStakeEpoch" .= toJSON @String "18446744073709551615" + , "updateImplicit" .= toJSON @String "10000" + , "updateProposalThd" .= toJSON @String "100000000000000" + , "updateVoteThd" .= toJSON @String "1000000000000" + ] + diff --git a/cardano-testnet/src/Testnet/Commands/Governance.hs b/cardano-testnet/src/Testnet/Commands/Governance.hs new file mode 100644 index 00000000000..f815dc185f0 --- /dev/null +++ b/cardano-testnet/src/Testnet/Commands/Governance.hs @@ -0,0 +1,46 @@ +module Testnet.Commands.Governance + ( createByronUpdateProposal + , createByronUpdateProposalVote + ) where + +import Prelude + +import Control.Monad.Catch +import Control.Monad.IO.Class +import GHC.Stack (HasCallStack, withFrozenCallStack) + +import Testnet.Util.Process (execCli_) + +import Hedgehog.Internal.Property + + +createByronUpdateProposal + :: (MonadTest m, MonadCatch m, MonadIO m, HasCallStack) + => Int -> String -> String -> Int -> m () +createByronUpdateProposal testnetMagic signingKeyFp updateProposalFp ptclMajorVersion = + withFrozenCallStack $ execCli_ + [ "byron", "governance", "create-update-proposal" + , "--filepath", updateProposalFp + , "--testnet-magic", show testnetMagic + , "--signing-key", signingKeyFp + , "--protocol-version-major", show ptclMajorVersion + , "--protocol-version-minor", "0" + , "--protocol-version-alt", "0" + , "--application-name", "cardano-sl" + , "--software-version-num", "1" + , "--system-tag", "linux" + , "--installer-hash", "0" + ] + +createByronUpdateProposalVote + :: (MonadTest m, MonadCatch m, MonadIO m, HasCallStack) + => Int -> String -> String -> String -> m () +createByronUpdateProposalVote testnetMagic updateProposalFp signingKey outputFp = + withFrozenCallStack $ execCli_ + [ "byron", "governance", "create-proposal-vote" + , "--proposal-filepath", updateProposalFp + , "--testnet-magic", show testnetMagic + , "--signing-key", signingKey + , "--vote-yes" + , "--output-filepath", outputFp + ] diff --git a/cardano-testnet/src/Testnet/Genesis.hs b/cardano-testnet/src/Testnet/Genesis.hs deleted file mode 100644 index 80b32e9eba2..00000000000 --- a/cardano-testnet/src/Testnet/Genesis.hs +++ /dev/null @@ -1,40 +0,0 @@ -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE TypeApplications #-} - --- | All Byron and Shelley Genesis related functionality -module Testnet.Genesis - ( defaultByronGenesisJsonValue - ) where - -import Prelude - -import Data.Aeson - --- | We need a Byron genesis in order to be able to hardfork to the later Shelley based eras. --- The values here don't matter as the testnet conditions are ultimately determined --- by the Shelley genesis. -defaultByronGenesisJsonValue :: Value -defaultByronGenesisJsonValue = - object - [ "heavyDelThd" .= toJSON @String "300000000000" - , "maxBlockSize" .= toJSON @String "2000000" - , "maxTxSize" .= toJSON @String "4096" - , "maxHeaderSize" .= toJSON @String "2000000" - , "maxProposalSize" .= toJSON @String "700" - , "mpcThd" .= toJSON @String "20000000000000" - , "scriptVersion" .= toJSON @Int 0 - , "slotDuration" .= toJSON @String "1000" - , "softforkRule" .= object - [ "initThd" .= toJSON @String "900000000000000" - , "minThd" .= toJSON @String "600000000000000" - , "thdDecrement" .= toJSON @String "50000000000000" - ] - , "txFeePolicy" .= object - [ "multiplier" .= toJSON @String "43946000000" - , "summand" .= toJSON @String "155381000000000" - ] - , "unlockStakeEpoch" .= toJSON @String "18446744073709551615" - , "updateImplicit" .= toJSON @String "10000" - , "updateProposalThd" .= toJSON @String "100000000000000" - , "updateVoteThd" .= toJSON @String "1000000000000" - ] diff --git a/cardano-testnet/src/Testnet/Options.hs b/cardano-testnet/src/Testnet/Options.hs new file mode 100644 index 00000000000..9efce2c84ed --- /dev/null +++ b/cardano-testnet/src/Testnet/Options.hs @@ -0,0 +1,33 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} + +{-# OPTIONS_GHC -Wno-unused-local-binds -Wno-unused-matches #-} + +module Testnet.Options + ( BabbageTestnetOptions(..) + , defaultTestnetOptions + ) where + +import Prelude + +import Testnet.Util.Runtime (NodeLoggingFormat (..)) + +{- HLINT ignore "Redundant flip" -} + +data BabbageTestnetOptions = BabbageTestnetOptions + { babbageNumSpoNodes :: Int + , babbageSlotDuration :: Int + , babbageSecurityParam :: Int + , babbageTotalBalance :: Int + , babbageNodeLoggingFormat :: NodeLoggingFormat + } deriving (Eq, Show) + +defaultTestnetOptions :: BabbageTestnetOptions +defaultTestnetOptions = BabbageTestnetOptions + { babbageNumSpoNodes = 3 + , babbageSlotDuration = 200 + , babbageSecurityParam = 10 + , babbageTotalBalance = 10020000000 + , babbageNodeLoggingFormat = NodeLoggingFormatAsJson + } diff --git a/cardano-testnet/src/Testnet/Shelley.hs b/cardano-testnet/src/Testnet/Shelley.hs index 31f0cf26ea9..e2d384a6a01 100644 --- a/cardano-testnet/src/Testnet/Shelley.hs +++ b/cardano-testnet/src/Testnet/Shelley.hs @@ -53,6 +53,8 @@ import qualified Hedgehog.Extras.Test.Network as H import qualified Hedgehog.Extras.Test.Process as H import qualified System.Directory as IO import qualified System.Info as OS + +import Testnet.Commands.Genesis import qualified Testnet.Conf as H import qualified Testnet.Util.Base as H import qualified Testnet.Util.Process as H @@ -352,11 +354,9 @@ shelleyTestnet testnetOptions H.Conf {..} = do -- 2. register the stake pool n -- 3. register the usern stake address -- 4. delegate from the usern stake address to the stake pool - genesisTxinResult <- H.noteShowM $ S.strip <$> H.execCli - [ "genesis", "initial-txin" - , "--testnet-magic", show @Int testnetMagic - , "--verification-key-file", tempAbsPath "utxo-keys/utxo" <> n <> ".vkey" - ] + genesisTxinResult + <- H.noteShowM $ S.strip <$> createShelleyGenesisInitialTxIn testnetMagic (tempAbsPath "utxo-keys/utxo" <> n <> ".vkey") + userNAddr <- H.readFile $ tempAbsPath "addresses/user" <> n <> ".addr"