Skip to content

Commit

Permalink
Update protocol version in protocol parameters to 10 in mockchain and…
Browse files Browse the repository at this point in the history
… devnet. (#233)

* Add unit tests which verify that we can use latest ProtVer10 Plutus primitives (readbit, writebit) in mockchain.

* Update PV3 cost model

* Comment out broken withdrawal test. Will get fixed in another commit.
  • Loading branch information
koslambrou authored Nov 13, 2024
1 parent 75fc1de commit 25daac3
Show file tree
Hide file tree
Showing 12 changed files with 451 additions and 122 deletions.
8 changes: 8 additions & 0 deletions src/base/lib/Convex/NodeQueries.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module Convex.NodeQueries(
queryEpoch,
queryLocalState,
queryProtocolParameters,
queryProtocolParametersUpdate,
queryStakePools,
queryStakeAddresses,
queryUTxOFilter
Expand Down Expand Up @@ -267,6 +268,13 @@ queryProtocolParameters :: LocalNodeConnectInfo -> IO (PParams StandardConway)
queryProtocolParameters connectInfo = runEraQuery connectInfo $
EraQuery{eqQuery = CAPI.QueryProtocolParameters, eqResult = id}

-- | Get all the protocol parameter updates from the local cardano node
-- Throws 'QueryException' if the node's era is not conway or if the connection
-- to the node cannot be acquired
queryProtocolParametersUpdate :: LocalNodeConnectInfo -> IO (Map (CAPI.Hash CAPI.GenesisKey) CAPI.ProtocolParametersUpdate)
queryProtocolParametersUpdate connectInfo = runEraQuery @CAPI.ConwayEra connectInfo $
EraQuery{eqQuery = CAPI.QueryProtocolParametersUpdate, eqResult = id}

-- | Get the stake and the IDs of the stake pool for a set of stake credentials
-- Throws 'QueryException' if the node's era is not supported or if the connection
-- to the node cannot be acquired
Expand Down
1 change: 1 addition & 0 deletions src/coin-selection/convex-coin-selection.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ test-suite convex-coin-selection-test
QuickCheck,
lens,
cardano-ledger-api,
cardano-ledger-core,
cardano-ledger-conway,
cardano-ledger-shelley,
convex-coin-selection,
Expand Down
43 changes: 31 additions & 12 deletions src/coin-selection/test/Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
module Main(main) where

import qualified Cardano.Api as C
import qualified Cardano.Api.Ledger as C hiding (PlutusScript, TxId,
TxIn)
import qualified Cardano.Api.Ledger as Ledger hiding (PlutusScript,
TxId, TxIn)
import qualified Cardano.Api.Shelley as C
import qualified Cardano.Ledger.Api as Ledger
import qualified Cardano.Ledger.Conway.Rules as Rules
Expand Down Expand Up @@ -415,7 +415,7 @@ queryStakeAddressesTest = do

delegationCert =
C.makeStakeAddressDelegationCertificate
$ C.StakeDelegationRequirementsConwayOnwards C.ConwayEraOnwardsConway stakeCred (C.DelegStake $ C.unStakePoolKeyHash poolId)
$ C.StakeDelegationRequirementsConwayOnwards C.ConwayEraOnwardsConway stakeCred (Ledger.DelegStake $ C.unStakePoolKeyHash poolId)

stakeCertTx = BuildTx.execBuildTx $ do
BuildTx.addCertificate stakeCert
Expand All @@ -440,6 +440,7 @@ withdrawalTest :: forall m. (MonadIO m, MonadMockchain C.ConwayEra m, MonadError
withdrawalTest = do
poolId <- registerPool Wallet.w1
stakeKey <- C.generateSigningKey C.AsStakeKey
drepKey <- C.generateSigningKey C.AsDRepKey
let
withdrawalAmount = 10_000_000

Expand All @@ -452,28 +453,46 @@ withdrawalTest = do
C.makeStakeAddressRegistrationCertificate
. C.StakeAddrRegistrationConway C.ConwayEraOnwardsConway 0
$ stakeCred
stakeAddress = C.makeStakeAddress Defaults.networkId stakeCred

delegationCert =
C.makeStakeAddressDelegationCertificate
$ C.StakeDelegationRequirementsConwayOnwards C.ConwayEraOnwardsConway stakeCred (C.DelegStake $ C.unStakePoolKeyHash poolId)

stakeCertTx = BuildTx.execBuildTx $ do
BuildTx.addCertificate stakeCert

delegStake = Ledger.DelegStake $ C.unStakePoolKeyHash poolId
delegationCert =
C.makeStakeAddressDelegationCertificate
$ C.StakeDelegationRequirementsConwayOnwards C.ConwayEraOnwardsConway stakeCred delegStake
delegCertTx = BuildTx.execBuildTx $ do
BuildTx.addCertificate delegationCert

withdrawalTx = execBuildTx $ do
BuildTx.addWithdrawal stakeAddress withdrawalAmount (C.KeyWitness C.KeyWitnessForStakeAddr)
delegHash = C.verificationKeyHash . C.getVerificationKey $ drepKey
delegCred = Ledger.KeyHashObj $ C.unDRepKeyHash delegHash
drepCert = C.makeDrepRegistrationCertificate (C.DRepRegistrationRequirements C.ConwayEraOnwardsConway delegCred 0) Nothing
drepCertTx = BuildTx.execBuildTx $ BuildTx.addCertificate drepCert

-- delegationDrepCert = C.makeStakeAddressAndDRepDelegationCertificate
-- C.ConwayEraOnwardsConway
-- stakeCred
-- delegStake
-- 0
-- delegDrepCertTx = BuildTx.execBuildTx $ BuildTx.addCertificate delegationDrepCert

-- stakeAddress = C.makeStakeAddress Defaults.networkId stakeCred
-- withdrawalTx = execBuildTx $ do
-- BuildTx.addWithdrawal stakeAddress withdrawalAmount (C.KeyWitness C.KeyWitnessForStakeAddr)

-- activate stake
void $ tryBalanceAndSubmit mempty Wallet.w2 stakeCertTx TrailingChange [C.WitnessStakeKey stakeKey]
-- delegate to pool
void $ tryBalanceAndSubmit mempty Wallet.w2 delegCertTx TrailingChange [C.WitnessStakeKey stakeKey]
-- register drep
void $ tryBalanceAndSubmit mempty Wallet.w2 drepCertTx TrailingChange [C.WitnessDRepKey drepKey]
-- delegate to drep
-- FIXME (koslambrou) Need to fix this in order to enable withdrawal
-- void $ tryBalanceAndSubmit mempty Wallet.w2 delegDrepCertTx TrailingChange [C.WitnessStakeKey stakeKey]

-- modify the ledger state
setReward stakeCred (C.quantityToLovelace withdrawalAmount)

-- withdraw rewards
void $ tryBalanceAndSubmit mempty Wallet.w2 withdrawalTx TrailingChange [C.WitnessStakeKey stakeKey]
-- FIXME (koslambrou) After updating to Chang+1 protocol version 10, the following gives the following error:
-- Exception: user error (user error (ValidationError: ApplyTxFailure: ApplyTxError (ConwayWdrlNotDelegatedToDRep (KeyHash {unKeyHash = "d6f0088850dc2494b69cf89c27491031ca610041afacf98ad95a0d4a"} :| []) :| [])))
-- void $ tryBalanceAndSubmit mempty Wallet.w2 withdrawalTx TrailingChange [C.WitnessStakeKey stakeKey]
7 changes: 3 additions & 4 deletions src/devnet/config/devnet/cardano-node.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"LastKnownBlockVersion-Major": 6,
"LastKnownBlockVersion-Minor": 0,

"ExperimentalHardForksEnabled": true,
"ExperimentalProtocolsEnabled": true,
"TestShelleyHardForkAtEpoch": 0,
"TestAllegraHardForkAtEpoch": 0,
"TestMaryHardForkAtEpoch": 0,
Expand Down Expand Up @@ -74,8 +76,5 @@
"mapSubtrace": {
"cardano.node.metrics": { "subtrace": "Neutral" }
}
},

"ExperimentalHardForksEnabled": true,
"ExperimentalProtocolsEnabled": true
}
}
2 changes: 1 addition & 1 deletion src/devnet/config/devnet/genesis-shelley.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"nOpt": 100,
"poolDeposit": 0,
"protocolVersion": {
"major": 7,
"major": 2,
"minor": 0
},
"rho": 0.003,
Expand Down
31 changes: 22 additions & 9 deletions src/devnet/convex-devnet.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ library
build-depends:
base >= 4.14.0
, aeson
, lens-aeson
, text
, time
, bytestring
Expand Down Expand Up @@ -89,29 +88,43 @@ library
, contra-tracer
, iohk-monitoring

other-modules:
Paths_convex_devnet
autogen-modules:
Paths_convex_devnet
other-modules:
Paths_convex_devnet
autogen-modules:
Paths_convex_devnet

test-suite convex-devnet-test
import: lang
type: exitcode-stdio-1.0
main-is: Spec.hs
ghc-options: -threaded -rtsopts
other-modules:
Devnet.Test.LatestEraTransitionSpec
Devnet.Test.LatestEraTransitionSpec.PV2
Devnet.Test.LatestEraTransitionSpec.PV3
hs-source-dirs:
test
build-depends:
base >= 4.14.0
, tasty
, tasty-hunit
, convex-devnet
, convex-base
, convex-node-client
, convex-wallet
, convex-coin-selection
, convex-mockchain
build-depends:
, plutus-tx
, plutus-tx-plugin
, ouroboros-consensus-cardano
, plutus-core
, ouroboros-consensus-protocol
, cardano-api
, contra-tracer
, cardano-ledger-api
, cardano-ledger-core -any
build-depends:
base >= 4.14.0
, tasty
, tasty-hunit
, contra-tracer
, lens
, mtl
, aeson
Expand Down
10 changes: 1 addition & 9 deletions src/devnet/lib/Convex/Devnet/CardanoNode/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ module Convex.Devnet.CardanoNode.Types (
defaultStakePoolNodeParams,
-- * Genesis config changes
GenesisConfigChanges (..),
forkIntoConwayInEpoch,
allowLargeTransactions,
setEpochLength
) where
Expand All @@ -27,13 +26,11 @@ import Cardano.Ledger.BaseTypes (EpochSize)
import qualified Cardano.Ledger.Core as Core
import Cardano.Ledger.Shelley.API (Coin)
import Cardano.Ledger.Shelley.Genesis (ShelleyGenesis (..))
import Control.Lens (over, set)
import Control.Lens (over)
import Data.Aeson (FromJSON, ToJSON)
import qualified Data.Aeson as Aeson
import Data.Aeson.Lens (atKey)
import Data.Ratio ((%))
import GHC.Generics (Generic)
import Numeric.Natural (Natural)
import Ouroboros.Consensus.Shelley.Eras (ShelleyEra, StandardCrypto)

type Port = Int
Expand Down Expand Up @@ -122,11 +119,6 @@ instance Semigroup GenesisConfigChanges where
instance Monoid GenesisConfigChanges where
mempty = GenesisConfigChanges id id id id

-- | Set the 'TestConwayHardForkAtEpoch' field to the given value (can be 0)
forkIntoConwayInEpoch :: Natural -> GenesisConfigChanges
forkIntoConwayInEpoch n =
mempty{ cfNodeConfig = set (atKey "TestConwayHardForkAtEpoch") (Just $ Aeson.toJSON n) }

{-| Change the alonzo genesis config to allow transactions with up to twice the normal size
-}
allowLargeTransactions :: GenesisConfigChanges
Expand Down
100 changes: 100 additions & 0 deletions src/devnet/test/Devnet/Test/LatestEraTransitionSpec.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}

module Devnet.Test.LatestEraTransitionSpec
( tests
) where

import qualified Cardano.Api as C
import qualified Cardano.Api.Ledger as L
import Control.Lens ((&), (.~))
import Convex.BuildTx (execBuildTx,
mintPlutus)
import Convex.Class (MonadMockchain)
import Convex.CoinSelection (ChangeOutputPosition (TrailingChange))
import Convex.MockChain.CoinSelection (tryBalanceAndSubmit)
import qualified Convex.MockChain.Defaults as Defaults
import Convex.MockChain.Utils (mockchainFails,
mockchainFailsWith,
mockchainSucceeds)
import qualified Convex.NodeParams as Params
import Convex.Utils (failOnError)
import qualified Convex.Wallet.MockWallet as Wallet
import qualified Devnet.Test.LatestEraTransitionSpec.PV2 as LatestEraTransitionSpec.PV2
import qualified Devnet.Test.LatestEraTransitionSpec.PV3 as LatestEraTransitionSpec.PV3
import qualified PlutusTx.Builtins as BI
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (testCase)

tests :: TestTree
tests = do
testGroup "Latest era and protocol version tests"
[ testCase "usingReadBitInPlutusV2AndProtVer9ShouldFailSpec" usingReadBitInPlutusV2AndProtVer9ShouldFailSpec
, testCase "usingWriteBitInPlutusV2AndProtVer9ShouldFailSpec" usingWriteBitInPlutusV2AndProtVer9ShouldFailSpec
, testCase "usingReadBitInPlutusV3AndProtVer9ShouldFailSpec" usingReadBitInPlutusV3AndProtVer9ShouldFailSpec
, testCase "usingWriteBitInPlutusV3AndProtVer9ShouldFailSpec" usingWriteBitInPlutusV3AndProtVer9ShouldFailSpec
, testCase "usingReadBitInPlutusV2AndLatestProtVerShouldPassSpec" usingReadBitInPlutusV2AndLatestProtVerShouldPassSpec
, testCase "usingWriteBitInPlutusV2AndLatestProtVerShouldPassSpec" usingWriteBitInPlutusV2AndLatestProtVerShouldPassSpec
, testCase "usingReadBitInPlutusV3AndLatestProtVerShouldPassSpec" usingReadBitInPlutusV3AndLatestProtVerShouldPassSpec
, testCase "usingWriteBitInPlutusV3AndLatestProtVerShouldPassSpec" usingWriteBitInPlutusV3AndLatestProtVerShouldPassSpec
]

pv9NodeParams :: Params.NodeParams C.ConwayEra
pv9NodeParams =
Defaults.nodeParams
& Params.ledgerProtocolParameters . Params.protocolParameters . L.ppProtocolVersionL .~ L.ProtVer (toEnum 9) 0

usingReadBitInPlutusV2AndProtVer9ShouldFailSpec :: IO ()
usingReadBitInPlutusV2AndProtVer9ShouldFailSpec = do
mockchainFailsWith pv9NodeParams (mintTokenScriptTest (LatestEraTransitionSpec.PV2.readBitTestMintingPolicyScriptPV2 $ BI.mkB "0xF4")) (const $ pure ())

usingWriteBitInPlutusV2AndProtVer9ShouldFailSpec :: IO ()
usingWriteBitInPlutusV2AndProtVer9ShouldFailSpec = do
mockchainFailsWith pv9NodeParams (mintTokenScriptTest (LatestEraTransitionSpec.PV2.writeBitTestMintingPolicyScriptPV2 $ BI.mkB "0xFF")) (const $ pure ())

usingReadBitInPlutusV3AndProtVer9ShouldFailSpec :: IO ()
usingReadBitInPlutusV3AndProtVer9ShouldFailSpec = do
mockchainFailsWith pv9NodeParams (mintTokenScriptTest (LatestEraTransitionSpec.PV3.readBitTestMintingPolicyScriptPV3 $ BI.mkB "0xF4")) (const $ pure ())

usingWriteBitInPlutusV3AndProtVer9ShouldFailSpec :: IO ()
usingWriteBitInPlutusV3AndProtVer9ShouldFailSpec = do
mockchainFailsWith pv9NodeParams (mintTokenScriptTest (LatestEraTransitionSpec.PV3.writeBitTestMintingPolicyScriptPV3 $ BI.mkB "0xFF")) (const $ pure ())

usingReadBitInPlutusV2AndLatestProtVerShouldPassSpec :: IO ()
usingReadBitInPlutusV2AndLatestProtVerShouldPassSpec = do
mockchainFails (mintTokenScriptTest (LatestEraTransitionSpec.PV2.readBitTestMintingPolicyScriptPV2 $ BI.mkB "0xF4")) (const $ pure ())

usingWriteBitInPlutusV2AndLatestProtVerShouldPassSpec :: IO ()
usingWriteBitInPlutusV2AndLatestProtVerShouldPassSpec = do
mockchainFails (mintTokenScriptTest (LatestEraTransitionSpec.PV2.writeBitTestMintingPolicyScriptPV2 $ BI.mkB "0xFF")) (const $ pure ())

usingReadBitInPlutusV3AndLatestProtVerShouldPassSpec :: IO ()
usingReadBitInPlutusV3AndLatestProtVerShouldPassSpec = do
mockchainSucceeds (mintTokenScriptTest (LatestEraTransitionSpec.PV3.readBitTestMintingPolicyScriptPV3 $ BI.mkB "0xF4"))

usingWriteBitInPlutusV3AndLatestProtVerShouldPassSpec :: IO ()
usingWriteBitInPlutusV3AndLatestProtVerShouldPassSpec = do
mockchainSucceeds (mintTokenScriptTest (LatestEraTransitionSpec.PV3.writeBitTestMintingPolicyScriptPV3 $ BI.mkB "0xFF"))

mintTokenScriptTest ::
( MonadMockchain era m
, C.IsPlutusScriptLanguage lang
, C.HasScriptLanguageInEra lang era
, C.IsBabbageBasedEra era
, MonadFail m
)
=> C.PlutusScript lang
-> m (C.Tx era)
mintTokenScriptTest script = do
let txb =
execBuildTx $
mintPlutus script () (C.AssetName "ProtVer10Test") 1
failOnError $ tryBalanceAndSubmit mempty Wallet.w1 txb TrailingChange []
53 changes: 53 additions & 0 deletions src/devnet/test/Devnet/Test/LatestEraTransitionSpec/PV2.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}

{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:target-version=1.0.0 #-}
{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:preserve-logging #-}

module Devnet.Test.LatestEraTransitionSpec.PV2
( readBitTestMintingPolicyScriptPV2
, writeBitTestMintingPolicyScriptPV2
) where

import qualified Cardano.Api as C
import Convex.PlutusTx (compiledCodeToScript)
import qualified PlutusCore.Version as Version
import PlutusTx (CompiledCode)
import qualified PlutusTx
import qualified PlutusTx.Builtins.Internal as BI
import qualified PlutusTx.Prelude as PlutusTx

{-# INLINABLE readBitTestMintingPolicy #-}
readBitTestMintingPolicy :: PlutusTx.BuiltinData -> PlutusTx.BuiltinData -> PlutusTx.BuiltinData -> PlutusTx.BuiltinUnit
readBitTestMintingPolicy d _ _ =
if PlutusTx.readBit (BI.unsafeDataAsB d) 2 then BI.unitval else PlutusTx.error ()

readBitTestMintingPolicyScriptPV2 :: PlutusTx.BuiltinData -> C.PlutusScript C.PlutusScriptV2
readBitTestMintingPolicyScriptPV2 = compiledCodeToScript . readBitTestMintingPolicyCompiled
where
readBitTestMintingPolicyCompiled :: PlutusTx.BuiltinData -> CompiledCode (PlutusTx.BuiltinData -> PlutusTx.BuiltinData -> PlutusTx.BuiltinUnit)
readBitTestMintingPolicyCompiled str =
$$(PlutusTx.compile [|| \str' r c -> readBitTestMintingPolicy str' r c ||])
`PlutusTx.unsafeApplyCode` PlutusTx.liftCode Version.plcVersion100 str

{-# INLINABLE writeBitTestMintingPolicy #-}
writeBitTestMintingPolicy :: PlutusTx.BuiltinData -> PlutusTx.BuiltinData -> PlutusTx.BuiltinData -> PlutusTx.BuiltinUnit
writeBitTestMintingPolicy d _ _ =
let !_ = PlutusTx.writeBits (BI.unsafeDataAsB d) [0] False in BI.unitval

writeBitTestMintingPolicyScriptPV2 :: PlutusTx.BuiltinData -> C.PlutusScript C.PlutusScriptV2
writeBitTestMintingPolicyScriptPV2 = compiledCodeToScript . writeBitTestMintingPolicyCompiled
where
writeBitTestMintingPolicyCompiled :: PlutusTx.BuiltinData -> CompiledCode (PlutusTx.BuiltinData -> PlutusTx.BuiltinData -> PlutusTx.BuiltinUnit)
writeBitTestMintingPolicyCompiled str =
$$(PlutusTx.compile [|| \str' r c -> writeBitTestMintingPolicy str' r c ||])
`PlutusTx.unsafeApplyCode` PlutusTx.liftCode Version.plcVersion100 str
Loading

0 comments on commit 25daac3

Please sign in to comment.