diff --git a/eras/allegra/impl/CHANGELOG.md b/eras/allegra/impl/CHANGELOG.md index e2d905388c6..1c209b76b1f 100644 --- a/eras/allegra/impl/CHANGELOG.md +++ b/eras/allegra/impl/CHANGELOG.md @@ -17,6 +17,7 @@ ### `testlib` +* Added `EraSpecificSpec AllegraEra` instance * Added `Examples` module with: `ledgerExamples`, `exampleAllegraTxBody`, `exampleAllegraTxAuxData` * Added `Arbitrary` instance for `TransitionConfig AllegraEra` * Added `Era` module with `AllegraEraTest` class diff --git a/eras/allegra/impl/testlib/Test/Cardano/Ledger/Allegra/Imp.hs b/eras/allegra/impl/testlib/Test/Cardano/Ledger/Allegra/Imp.hs index 13f4c2f8100..487baf07490 100644 --- a/eras/allegra/impl/testlib/Test/Cardano/Ledger/Allegra/Imp.hs +++ b/eras/allegra/impl/testlib/Test/Cardano/Ledger/Allegra/Imp.hs @@ -4,9 +4,11 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} +{-# OPTIONS_GHC -Wno-orphans #-} module Test.Cardano.Ledger.Allegra.Imp (spec) where +import Cardano.Ledger.Allegra (AllegraEra) import Cardano.Ledger.Core import Cardano.Ledger.Shelley.Rules ( ShelleyPoolPredFailure, @@ -14,13 +16,14 @@ import Cardano.Ledger.Shelley.Rules ( ShelleyUtxowPredFailure, ) import qualified Test.Cardano.Ledger.Allegra.Imp.UtxowSpec as UtxowSpec +import Test.Cardano.Ledger.Allegra.ImpTest import Test.Cardano.Ledger.Imp.Common import qualified Test.Cardano.Ledger.Shelley.Imp as ShelleyImp -import Test.Cardano.Ledger.Shelley.ImpTest spec :: forall era. ( ShelleyEraImp era + , EraSpecificSpec era , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxoPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era @@ -30,3 +33,6 @@ spec = do ShelleyImp.spec @era describe "AllegraImpSpec" . withEachEraVersion @era $ UtxowSpec.spec + +instance EraSpecificSpec AllegraEra where + eraSpecificSpec = ShelleyImp.shelleyEraSpecificSpec diff --git a/eras/alonzo/impl/CHANGELOG.md b/eras/alonzo/impl/CHANGELOG.md index 8e52a310575..ec06dec4f18 100644 --- a/eras/alonzo/impl/CHANGELOG.md +++ b/eras/alonzo/impl/CHANGELOG.md @@ -54,6 +54,7 @@ ### `testlib` +* Added `EraSpecificSpec AlonzoEra` instance * Added shrinking to `AlonzoTxAuxData`, `Redeemers`, `TxDats` * Added `Examples` module with: `ledgerExamples`, `mkLedgerExamples`, `exampleTx`, `exampleDatum`, `exampleAlonzoGenesis` * Added `Twiddle` instances for Alonzo core types diff --git a/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp.hs b/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp.hs index 7dd2d942479..d48ce1235d7 100644 --- a/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp.hs +++ b/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp.hs @@ -4,9 +4,11 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} +{-# OPTIONS_GHC -Wno-orphans #-} module Test.Cardano.Ledger.Alonzo.Imp where +import Cardano.Ledger.Alonzo (AlonzoEra) import Cardano.Ledger.Alonzo.Core import Cardano.Ledger.Alonzo.Rules ( AlonzoUtxoPredFailure, @@ -25,11 +27,12 @@ import qualified Test.Cardano.Ledger.Alonzo.Imp.UtxowSpec as Utxow import Test.Cardano.Ledger.Alonzo.ImpTest import Test.Cardano.Ledger.Imp.Common import qualified Test.Cardano.Ledger.Mary.Imp as MaryImp +import qualified Test.Cardano.Ledger.Shelley.Imp.PoolSpec as ShelleyImp spec :: forall era. ( AlonzoEraImp era - , InjectRuleFailure "LEDGER" ShelleyDelegPredFailure era + , EraSpecificSpec era , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxoPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era @@ -40,8 +43,25 @@ spec :: Spec spec = do MaryImp.spec @era - withEachEraVersion @era $ do - describe "AlonzoImpSpec" $ do - Utxo.spec - Utxos.spec - Utxow.spec + describe "AlonzoImpSpec" . withEachEraVersion @era $ do + Utxo.spec + Utxos.spec + Utxow.spec + +alonzoEraSpecificSpec :: + forall era. + ( AlonzoEraImp era + , ShelleyEraTxCert era + , InjectRuleFailure "LEDGER" ShelleyDelegPredFailure era + , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era + , InjectRuleFailure "LEDGER" AlonzoUtxosPredFailure era + , InjectRuleFailure "LEDGER" AlonzoUtxowPredFailure era + ) => + SpecWith (ImpInit (LedgerSpec era)) +alonzoEraSpecificSpec = do + describe "Alonzo era specific Imp spec" $ + describe "Certificates without deposits" $ + Utxow.alonzoEraSpecificSpec + +instance EraSpecificSpec AlonzoEra where + eraSpecificSpec = ShelleyImp.shelleyEraSpecificSpec >> alonzoEraSpecificSpec diff --git a/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec.hs b/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec.hs index e7290ad5ac2..184fb41ac68 100644 --- a/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec.hs +++ b/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec.hs @@ -5,9 +5,9 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -module Test.Cardano.Ledger.Alonzo.Imp.UtxowSpec (spec) where +module Test.Cardano.Ledger.Alonzo.Imp.UtxowSpec (spec, alonzoEraSpecificSpec) where -import Cardano.Ledger.Alonzo.Core (InjectRuleFailure) +import Cardano.Ledger.Alonzo.Core import Cardano.Ledger.Alonzo.Rules ( AlonzoUtxosPredFailure, AlonzoUtxowPredFailure, @@ -21,7 +21,6 @@ import Test.Cardano.Ledger.Common spec :: forall era. ( AlonzoEraImp era - , InjectRuleFailure "LEDGER" ShelleyDelegPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era , InjectRuleFailure "LEDGER" AlonzoUtxosPredFailure era , InjectRuleFailure "LEDGER" AlonzoUtxowPredFailure era @@ -31,3 +30,18 @@ spec = do describe "UTXOW" $ do Valid.spec Invalid.spec + +alonzoEraSpecificSpec :: + forall era. + ( AlonzoEraImp era + , ShelleyEraTxCert era + , InjectRuleFailure "LEDGER" ShelleyDelegPredFailure era + , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era + , InjectRuleFailure "LEDGER" AlonzoUtxosPredFailure era + , InjectRuleFailure "LEDGER" AlonzoUtxowPredFailure era + ) => + SpecWith (ImpInit (LedgerSpec era)) +alonzoEraSpecificSpec = do + describe "UTXOW" $ do + Valid.alonzoEraSpecificSpec + Invalid.alonzoEraSpecificSpec diff --git a/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec/Invalid.hs b/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec/Invalid.hs index db69fd42f5e..44d9ab5a8ae 100644 --- a/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec/Invalid.hs +++ b/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec/Invalid.hs @@ -7,7 +7,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} -module Test.Cardano.Ledger.Alonzo.Imp.UtxowSpec.Invalid (spec) where +module Test.Cardano.Ledger.Alonzo.Imp.UtxowSpec.Invalid (spec, alonzoEraSpecificSpec) where import Cardano.Ledger.Allegra.Scripts (AllegraEraScript (..)) import Cardano.Ledger.Alonzo (AlonzoEra) @@ -73,7 +73,6 @@ spec = describe "Invalid transactions" $ do describe (show lang) $ do let redeemerSameAsDatumHash = hashPlutusScript $ redeemerSameAsDatum slang alwaysSucceedsWithDatumHash = hashPlutusScript $ alwaysSucceedsWithDatum slang - alwaysSucceedsNoDatumHash = hashPlutusScript $ alwaysSucceedsNoDatum slang it "MissingRedeemers" $ do let scriptHash = redeemerSameAsDatumHash @@ -156,25 +155,6 @@ spec = describe "Invalid transactions" $ do then submitPhase2Invalid_ tx else submitFailingTx tx [injectFailure $ UnspendableUTxONoDatumHash [txIn]] - it "No ExtraRedeemers on same script certificates" $ do - Positive n <- arbitrary - replicateM_ n $ freshKeyHash >>= registerPool - pools <- getsNES $ nesEsL . epochStateStakePoolsL - poolId <- elements $ Map.keys pools - let scriptHash = alwaysSucceedsNoDatumHash - cred = ScriptHashObj scriptHash - certs = - [ mkRegTxCert cred - , mkDelegStakeTxCert cred poolId - , mkUnRegTxCert cred - ] - tx <- submitTx $ mkBasicTx (mkBasicTxBody & certsTxBodyL .~ certs) - let redeemers = tx ^. witsTxL . rdmrsTxWitsL . unRedeemersL - Map.keys redeemers - `shouldBe` [ mkCertifyingPurpose $ AsIx 1 - , mkCertifyingPurpose $ AsIx 2 - ] - it "Missing phase-2 script witness" $ do let scriptHash = alwaysSucceedsWithDatumHash txIn <- produceScript scriptHash @@ -252,6 +232,43 @@ spec = describe "Invalid transactions" $ do it "Spending" $ testPurpose (mkSpendingPurpose $ AsIx 99) +alonzoEraSpecificSpec :: + forall era. + ( AlonzoEraImp era + , ShelleyEraTxCert era + , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era + , InjectRuleFailure "LEDGER" AlonzoUtxowPredFailure era + ) => + SpecWith (ImpInit (LedgerSpec era)) +alonzoEraSpecificSpec = describe "Invalid transactions" $ do + forM_ (eraLanguages @era) $ \lang -> + withSLanguage lang $ \slang -> + describe (show lang) $ do + let alwaysSucceedsWithDatumHash = hashPlutusScript $ alwaysSucceedsWithDatum slang + alwaysSucceedsNoDatumHash = hashPlutusScript $ alwaysSucceedsNoDatum slang + + it "No ExtraRedeemers on same script certificates" $ do + Positive n <- arbitrary + replicateM_ n $ freshKeyHash >>= registerPool + pools <- getsNES $ nesEsL . epochStateStakePoolsL + poolId <- elements $ Map.keys pools + let scriptHash = alwaysSucceedsNoDatumHash + cred = ScriptHashObj scriptHash + certs = + [ mkRegTxCert cred + , mkDelegStakeTxCert cred poolId + , mkUnRegTxCert cred + ] + tx <- submitTx $ mkBasicTx (mkBasicTxBody & certsTxBodyL .~ certs) + let redeemers = tx ^. witsTxL . rdmrsTxWitsL . unRedeemersL + Map.keys redeemers + `shouldBe` [ mkCertifyingPurpose $ AsIx 1 + , mkCertifyingPurpose $ AsIx 2 + ] + + -- Post-Alonzo eras produce additional post-Alonzo predicate failures that we can't include here + unless (lang > eraMaxLanguage @AlonzoEra) $ do + describe "Extra Redeemer" $ do it "Multiple equal plutus-locked certs" $ do let scriptHash = alwaysSucceedsWithDatumHash Positive n <- arbitrary diff --git a/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec/Valid.hs b/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec/Valid.hs index eacafa8d417..326938e661f 100644 --- a/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec/Valid.hs +++ b/eras/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Imp/UtxowSpec/Valid.hs @@ -8,7 +8,7 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} -module Test.Cardano.Ledger.Alonzo.Imp.UtxowSpec.Valid (spec) where +module Test.Cardano.Ledger.Alonzo.Imp.UtxowSpec.Valid (spec, alonzoEraSpecificSpec) where import Cardano.Ledger.Allegra.Scripts ( pattern RequireTimeExpire, @@ -47,7 +47,6 @@ import Test.Cardano.Ledger.Plutus.Examples spec :: forall era. ( AlonzoEraImp era - , InjectRuleFailure "LEDGER" ShelleyDelegPredFailure era , InjectRuleFailure "LEDGER" AlonzoUtxosPredFailure era ) => SpecWith (ImpInit (LedgerSpec era)) @@ -88,6 +87,51 @@ spec = describe "Valid transactions" $ do mkBasicTx $ mkBasicTxBody & inputsTxBodyL .~ [txIn] + it "Validating MINT script" $ do + submitTx_ =<< mkTokenMintingTx alwaysSucceedsNoDatumHash + + it "Not validating MINT script" $ do + submitPhase2Invalid_ =<< mkTokenMintingTx alwaysFailsNoDatumHash + + it "Acceptable supplementary datum" $ do + inputAddr <- freshKeyHash @'Payment + amount <- Coin <$> choose (2_000_000, 8_000_000) + txIn <- sendCoinTo (mkAddr inputAddr StakeRefNull) amount + let + datum = Data (P.I 123) + datumHash = hashData datum + txOut = + mkBasicTxOut + (mkAddr alwaysSucceedsWithDatumHash StakeRefNull) + (MaryValue amount mempty) + & dataHashTxOutL .~ SJust datumHash + txBody = + mkBasicTxBody + & inputsTxBodyL .~ [txIn] + & outputsTxBodyL .~ [txOut] + tx = + mkBasicTx txBody + & witsTxL . datsTxWitsL . unTxDatsL %~ Map.insert datumHash datum + submitTx_ tx + +alonzoEraSpecificSpec :: + forall era. + ( AlonzoEraImp era + , ShelleyEraTxCert era + , InjectRuleFailure "LEDGER" ShelleyDelegPredFailure era + , InjectRuleFailure "LEDGER" AlonzoUtxosPredFailure era + ) => + SpecWith (ImpInit (LedgerSpec era)) +alonzoEraSpecificSpec = do + forM_ (eraLanguages @era) $ \lang -> + withSLanguage lang $ \slang -> + describe (show lang) $ do + let + alwaysSucceedsWithDatumHash = hashPlutusScript $ alwaysSucceedsWithDatum slang :: ScriptHash + alwaysSucceedsNoDatumHash = hashPlutusScript $ alwaysSucceedsNoDatum slang :: ScriptHash + alwaysFailsWithDatumHash = hashPlutusScript $ alwaysFailsWithDatum slang :: ScriptHash + alwaysFailsNoDatumHash = hashPlutusScript $ alwaysFailsNoDatum slang :: ScriptHash + it "Validating CERT script" $ do txIn <- produceScript alwaysSucceedsWithDatumHash let txCert = RegTxCert $ ScriptHashObj alwaysSucceedsNoDatumHash @@ -118,12 +162,6 @@ spec = describe "Valid transactions" $ do mkBasicTx $ mkBasicTxBody & withdrawalsTxBodyL .~ Withdrawals [(account, mempty)] - it "Validating MINT script" $ do - submitTx_ =<< mkTokenMintingTx alwaysSucceedsNoDatumHash - - it "Not validating MINT script" $ do - submitPhase2Invalid_ =<< mkTokenMintingTx alwaysFailsNoDatumHash - -- Process a transaction with a succeeding script in every place possible, -- and also with succeeding timelock scripts. it "Validating scripts everywhere" $ do @@ -162,27 +200,6 @@ spec = describe "Valid transactions" $ do & outputsTxBodyL .~ [txOut] submitTx_ $ mkBasicTx txBody - it "Acceptable supplementary datum" $ do - inputAddr <- freshKeyHash @'Payment - amount <- Coin <$> choose (2_000_000, 8_000_000) - txIn <- sendCoinTo (mkAddr inputAddr StakeRefNull) amount - let - datum = Data (P.I 123) - datumHash = hashData datum - txOut = - mkBasicTxOut - (mkAddr alwaysSucceedsWithDatumHash StakeRefNull) - (MaryValue amount mempty) - & dataHashTxOutL .~ SJust datumHash - txBody = - mkBasicTxBody - & inputsTxBodyL .~ [txIn] - & outputsTxBodyL .~ [txOut] - tx = - mkBasicTx txBody - & witsTxL . datsTxWitsL . unTxDatsL %~ Map.insert datumHash datum - submitTx_ tx - it "Multiple identical certificates" $ do let scriptHash = alwaysSucceedsNoDatumHash void . registerStakeCredential $ ScriptHashObj scriptHash diff --git a/eras/babbage/impl/CHANGELOG.md b/eras/babbage/impl/CHANGELOG.md index bb8a62b63b1..6a527ccc47a 100644 --- a/eras/babbage/impl/CHANGELOG.md +++ b/eras/babbage/impl/CHANGELOG.md @@ -18,6 +18,7 @@ ### `testlib` +* Added `EraSpecificSpec BabbageEra` instance * Added `Examples` module with: `ledgerExamples`, `exampleBabbageNewEpochState`, `exampleCollateralOutput` * Added `Twiddle` instances for Babbage core types * Added `TxInfoSpec` (moved from `cardano-ledger-babbage-test`) diff --git a/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp.hs b/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp.hs index 6bceca0ce84..51d51233e78 100644 --- a/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp.hs +++ b/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp.hs @@ -4,8 +4,9 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} +{-# OPTIONS_GHC -Wno-orphans #-} -module Test.Cardano.Ledger.Babbage.Imp (spec) where +module Test.Cardano.Ledger.Babbage.Imp (spec, babbageEraSpecificSpec) where import Cardano.Ledger.Alonzo.Plutus.Context (ContextError) import Cardano.Ledger.Alonzo.Rules ( @@ -13,12 +14,12 @@ import Cardano.Ledger.Alonzo.Rules ( AlonzoUtxosPredFailure, AlonzoUtxowPredFailure, ) -import Cardano.Ledger.Babbage.Core (BabbageEraTxBody, InjectRuleFailure) +import Cardano.Ledger.Babbage (BabbageEra) +import Cardano.Ledger.Babbage.Core (BabbageEraTxBody, InjectRuleFailure, ShelleyEraTxCert) import Cardano.Ledger.Babbage.Rules (BabbageUtxoPredFailure, BabbageUtxowPredFailure) import Cardano.Ledger.Babbage.TxInfo (BabbageContextError) import Cardano.Ledger.BaseTypes (Inject) import Cardano.Ledger.Shelley.Rules ( - ShelleyDelegPredFailure, ShelleyPoolPredFailure, ShelleyUtxoPredFailure, ShelleyUtxowPredFailure, @@ -29,12 +30,13 @@ import qualified Test.Cardano.Ledger.Babbage.Imp.UtxoSpec as Utxo import qualified Test.Cardano.Ledger.Babbage.Imp.UtxosSpec as Utxos import qualified Test.Cardano.Ledger.Babbage.Imp.UtxowSpec as Utxow import Test.Cardano.Ledger.Imp.Common +import qualified Test.Cardano.Ledger.Shelley.Imp.PoolSpec as ShelleyImp spec :: forall era. ( AlonzoEraImp era + , EraSpecificSpec era , BabbageEraTxBody era - , InjectRuleFailure "LEDGER" ShelleyDelegPredFailure era , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxoPredFailure era , InjectRuleFailure "LEDGER" AlonzoUtxoPredFailure era @@ -49,7 +51,25 @@ spec :: spec = do AlonzoImp.spec @era withEachEraVersion @era $ - describe "BabbageImpSpec" $ do + describe "BabbageImpSpec - era generic tests" $ do Utxo.spec Utxow.spec Utxos.spec @era + +babbageEraSpecificSpec :: + forall era. + ( AlonzoEraImp era + , ShelleyEraTxCert era + , BabbageEraTxBody era + ) => + SpecWith (ImpInit (LedgerSpec era)) +babbageEraSpecificSpec = do + describe "Babbage era specific Imp spec" $ + describe "Certificates without deposits" $ + describe "UTXOW" Utxow.babbageEraSpecificSpec + +instance EraSpecificSpec BabbageEra where + eraSpecificSpec = + ShelleyImp.shelleyEraSpecificSpec + >> AlonzoImp.alonzoEraSpecificSpec + >> babbageEraSpecificSpec diff --git a/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp/UtxowSpec.hs b/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp/UtxowSpec.hs index cb9a481c89b..f1c429fe272 100644 --- a/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp/UtxowSpec.hs +++ b/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp/UtxowSpec.hs @@ -4,11 +4,11 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -module Test.Cardano.Ledger.Babbage.Imp.UtxowSpec (spec) where +module Test.Cardano.Ledger.Babbage.Imp.UtxowSpec (spec, babbageEraSpecificSpec) where import Cardano.Ledger.Alonzo.Plutus.Context (ContextError) import Cardano.Ledger.Alonzo.Rules (AlonzoUtxosPredFailure, AlonzoUtxowPredFailure) -import Cardano.Ledger.Babbage.Core (BabbageEraTxBody, InjectRuleFailure) +import Cardano.Ledger.Babbage.Core (BabbageEraTxBody, InjectRuleFailure, ShelleyEraTxCert) import Cardano.Ledger.Babbage.Rules (BabbageUtxowPredFailure) import Cardano.Ledger.Babbage.TxInfo (BabbageContextError) import Cardano.Ledger.BaseTypes (Inject) @@ -33,3 +33,14 @@ spec = do describe "UTXOW" $ do Valid.spec Invalid.spec + +babbageEraSpecificSpec :: + forall era. + ( AlonzoEraImp era + , BabbageEraTxBody era + , ShelleyEraTxCert era + ) => + SpecWith (ImpInit (LedgerSpec era)) +babbageEraSpecificSpec = do + describe "UTXOW - certificates without deposits" $ do + Valid.babbageEraSpecificSpec diff --git a/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp/UtxowSpec/Valid.hs b/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp/UtxowSpec/Valid.hs index f083b5a436b..e28c7dbfceb 100644 --- a/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp/UtxowSpec/Valid.hs +++ b/eras/babbage/impl/testlib/Test/Cardano/Ledger/Babbage/Imp/UtxowSpec/Valid.hs @@ -3,7 +3,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} -module Test.Cardano.Ledger.Babbage.Imp.UtxowSpec.Valid (spec) where +module Test.Cardano.Ledger.Babbage.Imp.UtxowSpec.Valid (spec, babbageEraSpecificSpec) where import Cardano.Ledger.Alonzo.TxWits (unTxDatsL) import Cardano.Ledger.Babbage.Core @@ -171,6 +171,17 @@ spec = describe "Valid" $ do & bodyTxL . inputsTxBodyL .~ [txInAt 0 txInitial] & bodyTxL . referenceInputsTxBodyL .~ [txInAt 1 txInitial] +babbageEraSpecificSpec :: + forall era. + ( AlonzoEraImp era + , BabbageEraTxBody era + , ShelleyEraTxCert era + ) => + SpecWith (ImpInit (LedgerSpec era)) +babbageEraSpecificSpec = describe "Valid" $ do + forM_ @[] [PlutusV2 .. eraMaxLanguage @era] $ \slang -> do + describe (show slang) $ do + withSLanguage slang $ \lang -> do it "Use a reference script to authorize a delegation certificate" $ do addr <- freshKeyAddr_ plutus <- mkPlutusScript $ alwaysSucceedsNoDatum lang diff --git a/eras/conway/impl/CHANGELOG.md b/eras/conway/impl/CHANGELOG.md index 9349ff5f214..5543187af01 100644 --- a/eras/conway/impl/CHANGELOG.md +++ b/eras/conway/impl/CHANGELOG.md @@ -2,6 +2,12 @@ ## 1.20.0.0 +* Decoupled `ConwayEraTxCert` from `ShelleyEraTxCert`, so added `ShelleyEraTxCert` constraint to: + * `DecCBOR ConwayTxCert` + * `transTxCert` + * `transTxCertV1V2` +* Added `conwayGovCertVKeyWitness` +* Added `conwayTxCertDelegDecoder` * Changed `MaxTxSizeUTxO` to use `Word32` * Rename `transScriptPurpose` to `transPlutusPurposeV3` * Make `transValidityInterval` implicit to eras instead of protocol versions. @@ -92,6 +98,25 @@ ### `testlib` +* Added `EraSpecificSpec ConwayEra` instance +* Added `registerRewardAccountWithDeposit` +* Added `regDelegToDRep` +* Generalised the following helpers and thus changed their constraints to `ConwayEraImp`: + * `setupPoolWithStake` + * `setupPoolWithoutStake` + * `trySubmitGovAction` + * `trySubmitGovActions` + * `mkProposal` + * `submitGovAction` + * `submitGovAction_` + * `submitGovActions` + * `submitTreasuryWithdrawals` + * `submitFailingGovAction` +* Decoupled `ConwayEraTxCert` from `ShelleyEraTxCert`, so added `ShelleyEraTxCert` constraint to: + * `genUnRegTxCert` + * `genRegTxCert` +* Added `registerPoolWithDeposit` +* Added `registerStakeCredentialWithDeposit` * Added `Examples` module with: `ledgerExamples`, `exampleConwayCerts` * Fix CDDL for `MultiAsset` in `TxOut` as well as the `Tx` mint field. * Add `mkConwayTestAccountState` and `conwayAccountsToUMap` diff --git a/eras/conway/impl/src/Cardano/Ledger/Conway/TxCert.hs b/eras/conway/impl/src/Cardano/Ledger/Conway/TxCert.hs index 866a91d0404..c6162097592 100644 --- a/eras/conway/impl/src/Cardano/Ledger/Conway/TxCert.hs +++ b/eras/conway/impl/src/Cardano/Ledger/Conway/TxCert.hs @@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-} +{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} @@ -14,6 +15,9 @@ {-# LANGUAGE UndecidableSuperClasses #-} {-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -Wno-orphans #-} +#if __GLASGOW_HASKELL__ >= 908 +{-# OPTIONS_GHC -Wno-x-unsafe-ledger-internal #-} +#endif module Cardano.Ledger.Conway.TxCert ( ConwayTxCert (..), @@ -23,10 +27,12 @@ module Cardano.Ledger.Conway.TxCert ( Delegatee (..), mkDelegatee, ConwayEraTxCert (..), + conwayTxCertDelegDecoder, fromShelleyDelegCert, toShelleyDelegCert, getScriptWitnessConwayTxCert, getVKeyWitnessConwayTxCert, + conwayGovCertVKeyWitness, getDelegateeTxCert, getStakePoolDelegatee, getDRepDelegatee, @@ -72,6 +78,7 @@ import Cardano.Ledger.Credential ( credScriptHash, ) import Cardano.Ledger.DRep (DRep) +import Cardano.Ledger.Internal.Era (DijkstraEra) import Cardano.Ledger.Shelley.TxCert ( ShelleyDelegCert (..), encodePoolCert, @@ -162,7 +169,7 @@ instance ShelleyEraTxCert ConwayEra where mkMirTxCert = notSupportedInThisEra getMirTxCert = const Nothing -class ShelleyEraTxCert era => ConwayEraTxCert era where +class EraTxCert era => ConwayEraTxCert era where mkRegDepositTxCert :: StakeCredential -> Coin -> TxCert era getRegDepositTxCert :: TxCert era -> Maybe (StakeCredential, Coin) @@ -348,6 +355,21 @@ pattern UpdateDRepTxCert cred mAnchor <- (getUpdateDRepTxCert -> Just (cred, mAn ConwayEra #-} +{-# COMPLETE + RegPoolTxCert + , RetirePoolTxCert + , RegDepositTxCert + , UnRegDepositTxCert + , DelegTxCert + , RegDepositDelegTxCert + , AuthCommitteeHotKeyTxCert + , ResignCommitteeColdTxCert + , RegDRepTxCert + , UnRegDRepTxCert + , UpdateDRepTxCert :: + DijkstraEra + #-} + getDelegateeTxCert :: ConwayEraTxCert era => TxCert era -> Maybe Delegatee getDelegateeTxCert = \case DelegTxCert _ delegatee -> Just delegatee @@ -622,7 +644,8 @@ instance fromCBOR = fromEraCBOR @era instance - ( ConwayEraTxCert era + ( ShelleyEraTxCert era + , ConwayEraTxCert era , TxCert era ~ ConwayTxCert era ) => DecCBOR (ConwayTxCert era) @@ -749,15 +772,15 @@ getVKeyWitnessConwayTxCert = \case ConwayDelegCert cred _ -> credKeyHashWitness cred ConwayRegDelegCert cred _ _ -> credKeyHashWitness cred ConwayTxCertPool poolCert -> Just $ poolCertKeyHashWitness poolCert - ConwayTxCertGov govCert -> govWitness govCert - where - govWitness :: ConwayGovCert -> Maybe (KeyHash 'Witness) - govWitness = \case - ConwayAuthCommitteeHotKey coldCred _hotCred -> credKeyHashWitness coldCred - ConwayResignCommitteeColdKey coldCred _ -> credKeyHashWitness coldCred - ConwayRegDRep cred _ _ -> credKeyHashWitness cred - ConwayUnRegDRep cred _ -> credKeyHashWitness cred - ConwayUpdateDRep cred _ -> credKeyHashWitness cred + ConwayTxCertGov govCert -> conwayGovCertVKeyWitness govCert + +conwayGovCertVKeyWitness :: ConwayGovCert -> Maybe (KeyHash 'Witness) +conwayGovCertVKeyWitness = \case + ConwayAuthCommitteeHotKey coldCred _hotCred -> credKeyHashWitness coldCred + ConwayResignCommitteeColdKey coldCred _ -> credKeyHashWitness coldCred + ConwayRegDRep cred _ _ -> credKeyHashWitness cred + ConwayUnRegDRep cred _ -> credKeyHashWitness cred + ConwayUpdateDRep cred _ -> credKeyHashWitness cred -- | Determine the total deposit amount needed from a TxBody. -- The block may (legitimately) contain multiple registration certificates diff --git a/eras/conway/impl/src/Cardano/Ledger/Conway/TxInfo.hs b/eras/conway/impl/src/Cardano/Ledger/Conway/TxInfo.hs index a81c9ec6d6c..b3e10447b3e 100644 --- a/eras/conway/impl/src/Cardano/Ledger/Conway/TxInfo.hs +++ b/eras/conway/impl/src/Cardano/Ledger/Conway/TxInfo.hs @@ -381,7 +381,8 @@ guardConwayFeaturesForPlutusV1V2 tx = do Left $ inject $ CurrentTreasuryFieldNotSupported @era treasury transTxCertV1V2 :: - ( ConwayEraTxCert era + ( ShelleyEraTxCert era + , ConwayEraTxCert era , Inject (ConwayContextError era) (ContextError era) ) => TxCert era -> @@ -546,7 +547,8 @@ transTxBodyWithdrawals txBody = -- version 9 has been exercised on Mainnet, therefore this conditional translation can never be -- removed for Conway era (#4863) transTxCert :: - (ConwayEraTxCert era, TxCert era ~ ConwayTxCert era) => ProtVer -> TxCert era -> PV3.TxCert + (ShelleyEraTxCert era, ConwayEraTxCert era, TxCert era ~ ConwayTxCert era) => + ProtVer -> TxCert era -> PV3.TxCert transTxCert pv = \case RegPoolTxCert PoolParams {ppId, ppVrf} -> PV3.TxCertPoolRegister diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Examples.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Examples.hs index cf85268cbe2..30cb4379f82 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Examples.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Examples.hs @@ -7,7 +7,6 @@ module Test.Cardano.Ledger.Conway.Examples ( ledgerExamples, - exampleConwayCerts, ) where import Cardano.Ledger.Babbage.TxBody (BabbageTxOut (..)) diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp.hs index 1b58d0f7959..3cfd0aa063e 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp.hs @@ -5,8 +5,9 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} +{-# OPTIONS_GHC -Wno-orphans #-} -module Test.Cardano.Ledger.Conway.Imp (spec, conwaySpec) where +module Test.Cardano.Ledger.Conway.Imp (spec) where import Cardano.Ledger.Alonzo.Plutus.Context (EraPlutusContext (ContextError)) import Cardano.Ledger.Alonzo.Rules ( @@ -17,6 +18,7 @@ import Cardano.Ledger.Alonzo.Rules ( import Cardano.Ledger.Babbage.Rules (BabbageUtxoPredFailure, BabbageUtxowPredFailure) import Cardano.Ledger.Babbage.TxInfo (BabbageContextError) import Cardano.Ledger.BaseTypes (Inject) +import Cardano.Ledger.Conway (ConwayEra) import Cardano.Ledger.Conway.Core import Cardano.Ledger.Conway.Rules ( ConwayBbodyPredFailure, @@ -34,13 +36,13 @@ import Cardano.Ledger.Conway.Rules ( import Cardano.Ledger.Conway.TxInfo (ConwayContextError) import Cardano.Ledger.Shelley.API.Mempool (ApplyTx (..)) import Cardano.Ledger.Shelley.Rules ( - ShelleyDelegPredFailure, ShelleyPoolPredFailure, ShelleyUtxoPredFailure, ShelleyUtxowPredFailure, ) import Control.State.Transition.Extended import Data.Typeable (Typeable) +import qualified Test.Cardano.Ledger.Alonzo.Imp as AlonzoImp import qualified Test.Cardano.Ledger.Babbage.Imp as BabbageImp import qualified Test.Cardano.Ledger.Conway.Imp.BbodySpec as Bbody import qualified Test.Cardano.Ledger.Conway.Imp.CertsSpec as Certs @@ -57,10 +59,12 @@ import qualified Test.Cardano.Ledger.Conway.Imp.UtxosSpec as Utxos import qualified Test.Cardano.Ledger.Conway.Imp.UtxowSpec as Utxow import Test.Cardano.Ledger.Conway.ImpTest import Test.Cardano.Ledger.Imp.Common +import qualified Test.Cardano.Ledger.Shelley.Imp as ShelleyImp spec :: forall era. ( ConwayEraImp era + , EraSpecificSpec era , Inject (BabbageContextError era) (ContextError era) , Inject (ConwayContextError era) (ContextError era) , InjectRuleFailure "LEDGER" ConwayGovPredFailure era @@ -70,7 +74,6 @@ spec :: , InjectRuleFailure "LEDGER" AlonzoUtxoPredFailure era , InjectRuleFailure "LEDGER" AlonzoUtxosPredFailure era , InjectRuleFailure "LEDGER" AlonzoUtxowPredFailure era - , InjectRuleFailure "LEDGER" ShelleyDelegPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxoPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era @@ -94,9 +97,9 @@ spec :: Spec spec = do BabbageImp.spec @era - withEachEraVersion @era $ conwaySpec @era + withEachEraVersion @era $ conwayEraGenericSpec @era -conwaySpec :: +conwayEraGenericSpec :: forall era. ( ConwayEraImp era , Inject (BabbageContextError era) (ContextError era) @@ -126,7 +129,7 @@ conwaySpec :: , ToExpr (Event (EraRule "BBODY" era)) ) => SpecWith (ImpInit (LedgerSpec era)) -conwaySpec = do +conwayEraGenericSpec = do describe "BBODY" Bbody.spec describe "CERTS" Certs.spec describe "DELEG" Deleg.spec @@ -140,3 +143,21 @@ conwaySpec = do describe "UTXO" Utxo.spec describe "UTXOS" Utxos.spec describe "UTXOW" Utxow.spec + +conwayEraSpecificSpec :: + ( ConwayEraImp era + , ShelleyEraTxCert era + ) => + SpecWith (ImpInit (LedgerSpec era)) +conwayEraSpecificSpec = do + describe "Conway era specific Imp spec" $ + describe "Certificates without deposits" $ do + describe "DELEG" Deleg.conwayEraSpecificSpec + describe "UTXO" Utxo.conwayEraSpecificSpec + +instance EraSpecificSpec ConwayEra where + eraSpecificSpec = + ShelleyImp.shelleyEraSpecificSpec + >> AlonzoImp.alonzoEraSpecificSpec + >> BabbageImp.babbageEraSpecificSpec + >> conwayEraSpecificSpec diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/CertsSpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/CertsSpec.hs index 22af2ff3d14..fa2912137d7 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/CertsSpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/CertsSpec.hs @@ -57,8 +57,8 @@ spec = do ] } ) - (registeredRwdAccount, reward, stakeKey2) <- setupRewardAccount - void $ delegateToDRep (KeyHashObj stakeKey2) (Coin 1_000_000) DRepAlwaysNoConfidence + (registeredRwdAccount, reward, _stakeKey2) <- + setupRewardAccount (Coin 1_000_000) DRepAlwaysNoConfidence let tx = mkBasicTx $ @@ -84,10 +84,8 @@ spec = do it "Withdrawing the wrong amount" $ do modifyPParams $ ppGovActionLifetimeL .~ EpochInterval 2 - (rwdAccount1, reward1, stakeKey1) <- setupRewardAccount - (rwdAccount2, reward2, stakeKey2) <- setupRewardAccount - void $ delegateToDRep (KeyHashObj stakeKey1) (Coin 1_000_000) DRepAlwaysAbstain - void $ delegateToDRep (KeyHashObj stakeKey2) (Coin 1_000_000) DRepAlwaysAbstain + (rwdAccount1, reward1, _stakeKey1) <- setupRewardAccount (Coin 1_000_000) DRepAlwaysAbstain + (rwdAccount2, reward2, _stakeKey2) <- setupRewardAccount (Coin 1_000_000) DRepAlwaysAbstain submitFailingTx ( mkBasicTx $ mkBasicTxBody @@ -111,10 +109,11 @@ spec = do ) [injectFailure $ WithdrawalsNotInRewardsCERTS $ Withdrawals [(rwdAccount1, zero)]] where - setupRewardAccount = do + setupRewardAccount stake dRep = do kh <- freshKeyHash let cred = KeyHashObj kh - ra <- registerStakeCredential cred + void $ regDelegToDRep cred stake dRep + ra <- getRewardAccountFor cred submitAndExpireProposalToMakeReward cred b <- getBalance cred pure (ra, b, kh) diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/DelegSpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/DelegSpec.hs index 1f10e1d3cad..7ff26d3c731 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/DelegSpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/DelegSpec.hs @@ -10,6 +10,7 @@ module Test.Cardano.Ledger.Conway.Imp.DelegSpec ( spec, + conwayEraSpecificSpec, ) where import Cardano.Ledger.Address (RewardAccount (..)) @@ -56,14 +57,6 @@ spec = do it "With correct deposit or without any deposit" $ do expectedDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL - freshKeyHash >>= \kh -> do - let cred = KeyHashObj kh - regTxCert <- genRegTxCert cred - submitTx_ $ - mkBasicTx mkBasicTxBody - & bodyTxL . certsTxBodyL .~ [regTxCert] - expectRegistered cred - freshKeyHash >>= \kh -> do submitTx_ $ mkBasicTx mkBasicTxBody @@ -221,23 +214,23 @@ spec = do & ppKeyDepositL .~ keyDeposit & ppGovActionDepositL .~ govActionDeposit stakeCred <- KeyHashObj <$> freshKeyHash - rewardAccount <- registerStakeCredential stakeCred + rewardAccount <- getRewardAccountFor stakeCred otherStakeCred <- KeyHashObj <$> freshKeyHash - otherRewardAccount <- registerStakeCredential otherStakeCred + otherRewardAccount <- getRewardAccountFor otherStakeCred khStakePool <- freshKeyHash - registerPool khStakePool + registerPoolWithDeposit khStakePool submitTx_ . mkBasicTx $ mkBasicTxBody & certsTxBodyL .~ SSeq.fromList - [ DelegTxCert stakeCred (DelegStakeVote khStakePool DRepAlwaysAbstain) - , DelegTxCert otherStakeCred (DelegStakeVote khStakePool DRepAlwaysAbstain) + [ RegDepositDelegTxCert stakeCred (DelegStakeVote khStakePool DRepAlwaysAbstain) keyDeposit + , RegDepositDelegTxCert otherStakeCred (DelegStakeVote khStakePool DRepAlwaysAbstain) keyDeposit ] expectRegisteredRewardAddress rewardAccount expectRegisteredRewardAddress otherRewardAccount submitAndExpireProposalToMakeReward otherStakeCred getBalance otherStakeCred `shouldReturn` govActionDeposit - unRegTxCert <- genUnRegTxCert stakeCred + let unRegTxCert = UnRegDepositTxCert stakeCred keyDeposit submitTx_ . mkBasicTx $ mkBasicTxBody & certsTxBodyL .~ SSeq.fromList [unRegTxCert] @@ -262,7 +255,7 @@ spec = do .~ [RegDepositTxCert cred expectedDeposit] poolKh <- freshKeyHash - registerPool poolKh + registerPoolWithDeposit poolKh submitTx_ $ mkBasicTx mkBasicTxBody @@ -274,17 +267,8 @@ spec = do it "Register and delegate in the same transaction" $ do expectedDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL - cred <- KeyHashObj <$> freshKeyHash poolKh <- freshKeyHash - registerPool poolKh - submitTx_ $ - mkBasicTx mkBasicTxBody - & bodyTxL . certsTxBodyL - .~ [ RegDepositTxCert cred expectedDeposit - , DelegTxCert cred (DelegStake poolKh) - ] - expectDelegatedToPool cred poolKh - + registerPoolWithDeposit poolKh freshKeyHash >>= \kh -> do submitTx_ $ mkBasicTx mkBasicTxBody @@ -292,19 +276,10 @@ spec = do .~ [RegDepositDelegTxCert (KeyHashObj kh) (DelegStake poolKh) expectedDeposit] expectDelegatedToPool (KeyHashObj kh) poolKh - freshKeyHash >>= \kh -> do - submitTx_ $ - mkBasicTx mkBasicTxBody - & bodyTxL . certsTxBodyL - .~ [ RegDepositTxCert (KeyHashObj kh) expectedDeposit - , DelegStakeTxCert (KeyHashObj kh) poolKh -- using the pattern from Shelley - ] - expectDelegatedToPool (KeyHashObj kh) poolKh - it "Delegate unregistered stake credentials" $ do cred <- KeyHashObj <$> freshKeyHash poolKh <- freshKeyHash - registerPool poolKh + registerPoolWithDeposit poolKh submitFailingTx ( mkBasicTx mkBasicTxBody & bodyTxL . certsTxBodyL @@ -338,7 +313,7 @@ spec = do cred <- KeyHashObj <$> freshKeyHash poolKh <- freshKeyHash - registerPool poolKh + registerPoolWithDeposit poolKh submitTx_ $ mkBasicTx mkBasicTxBody & bodyTxL . certsTxBodyL @@ -353,7 +328,7 @@ spec = do expectDelegatedToPool cred poolKh poolKh1 <- freshKeyHash - registerPool poolKh1 + registerPoolWithDeposit poolKh1 submitTx_ $ mkBasicTx mkBasicTxBody & bodyTxL . certsTxBodyL @@ -361,9 +336,9 @@ spec = do expectDelegatedToPool cred poolKh1 poolKh2 <- freshKeyHash - registerPool poolKh2 + registerPoolWithDeposit poolKh2 poolKh3 <- freshKeyHash - registerPool poolKh3 + registerPoolWithDeposit poolKh3 submitTx_ $ mkBasicTx mkBasicTxBody @@ -379,12 +354,11 @@ spec = do cred <- KeyHashObj <$> freshKeyHash poolKh <- freshKeyHash - registerPool poolKh + registerPoolWithDeposit poolKh submitTx_ $ mkBasicTx mkBasicTxBody & bodyTxL . certsTxBodyL - .~ [ RegDepositTxCert cred expectedDeposit - , DelegTxCert cred (DelegStake poolKh) + .~ [ RegDepositDelegTxCert cred (DelegStake poolKh) expectedDeposit , UnRegDepositTxCert cred expectedDeposit ] expectNotRegistered cred @@ -427,7 +401,7 @@ spec = do expectDelegatedVote cred (DRepCredential drepCred) it "Delegate vote of registered stake credentials to unregistered drep" $ do - RewardAccount _ cred <- registerRewardAccount + RewardAccount _ cred <- registerRewardAccountWithDeposit drepCred <- KeyHashObj <$> freshKeyHash let tx = mkBasicTx mkBasicTxBody @@ -548,7 +522,7 @@ spec = do rewardAccount <- getRewardAccountFor cred submitTx_ $ mkBasicTx mkBasicTxBody - & bodyTxL . certsTxBodyL .~ [UnRegTxCert cred] + & bodyTxL . certsTxBodyL .~ [UnRegDepositTxCert cred expectedDeposit] & bodyTxL . withdrawalsTxBodyL .~ Withdrawals (Map.singleton rewardAccount withdrawalAmount) expectNotRegistered cred @@ -575,7 +549,7 @@ spec = do submitTx_ $ mkBasicTx mkBasicTxBody & bodyTxL . certsTxBodyL - .~ [UnRegTxCert cred] + .~ [UnRegDepositTxCert cred expectedDeposit] & bodyTxL . withdrawalsTxBodyL .~ Withdrawals (Map.singleton rewardAccount withdrawalAmount) expectNotRegistered cred @@ -589,8 +563,8 @@ spec = do expectedDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL cred <- KeyHashObj <$> freshKeyHash poolKh <- freshKeyHash - rewardAccount <- registerRewardAccount - registerPool poolKh + rewardAccount <- registerRewardAccountWithDeposit + registerPoolWithDeposit poolKh drepCred <- KeyHashObj <$> registerDRep submitTx_ $ @@ -658,7 +632,7 @@ spec = do cred <- KeyHashObj <$> freshKeyHash poolKh <- freshKeyHash - registerPool poolKh + registerPoolWithDeposit poolKh drepCred <- KeyHashObj <$> registerDRep submitTx_ $ @@ -683,7 +657,7 @@ spec = do cred <- KeyHashObj <$> freshKeyHash poolKh <- freshKeyHash - registerPool poolKh + registerPoolWithDeposit poolKh drepCred <- KeyHashObj <$> registerDRep submitTx_ $ @@ -698,7 +672,7 @@ spec = do expectDelegatedVote cred (DRepCredential drepCred) poolKh' <- freshKeyHash - registerPool poolKh' + registerPoolWithDeposit poolKh' submitTx_ $ mkBasicTx mkBasicTxBody & bodyTxL . certsTxBodyL @@ -706,30 +680,13 @@ spec = do expectDelegatedToPool cred poolKh' expectDelegatedVote cred (DRepCredential drepCred) where - expectRegistered :: HasCallStack => Credential 'Staking -> ImpTestM era () - expectRegistered cred = do - accounts <- getsNES $ nesEsL . esLStateL . lsCertStateL . certDStateL . accountsL - expectedDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL - - accountState <- expectJust $ lookupAccountState cred accounts - impAnn (show cred <> " expected to be in Accounts with the correct deposit") $ do - accountState ^. depositAccountStateL `shouldBe` compactCoinOrError expectedDeposit - - expectNotRegistered :: HasCallStack => Credential 'Staking -> ImpTestM era () + expectNotRegistered :: Credential 'Staking -> ImpTestM era () expectNotRegistered cred = do accounts <- getsNES $ nesEsL . esLStateL . lsCertStateL . certDStateL . accountsL impAnn (show cred <> " expected to not be in Accounts") $ do expectNothingExpr $ lookupAccountState cred accounts - expectDelegatedToPool :: - HasCallStack => Credential 'Staking -> KeyHash 'StakePool -> ImpTestM era () - expectDelegatedToPool cred poolKh = do - accounts <- getsNES $ nesEsL . esLStateL . lsCertStateL . certDStateL . accountsL - impAnn (show cred <> " expected to have delegated to " <> show poolKh) $ do - accountState <- expectJust $ lookupAccountState cred accounts - accountState ^. stakePoolDelegationAccountStateL `shouldBe` Just poolKh - - expectNotDelegatedToPool :: HasCallStack => Credential 'Staking -> ImpTestM era () + expectNotDelegatedToPool :: Credential 'Staking -> ImpTestM era () expectNotDelegatedToPool cred = do accounts <- getsNES $ nesEsL . esLStateL . lsCertStateL . certDStateL . accountsL impAnn (show cred <> " expected to not have delegated to a stake pool") $ do @@ -756,8 +713,66 @@ spec = do (cred `Set.member` drepDelegs drepState) _ -> pure () - expectNotDelegatedVote :: HasCallStack => Credential 'Staking -> ImpTestM era () + expectNotDelegatedVote :: Credential 'Staking -> ImpTestM era () expectNotDelegatedVote cred = do accounts <- getsNES $ nesEsL . esLStateL . lsCertStateL . certDStateL . accountsL impAnn (show cred <> " expected to not have their vote delegated") $ expectNothingExpr (lookupDRepDelegation cred accounts) + +conwayEraSpecificSpec :: + forall era. + ( ConwayEraImp era + , ShelleyEraTxCert era + ) => + SpecWith (ImpInit (LedgerSpec era)) +conwayEraSpecificSpec = do + describe "Register stake credential" $ do + it "Without any deposit" $ do + freshKeyHash >>= \kh -> do + let cred = KeyHashObj kh + regTxCert <- genRegTxCert cred + submitTx_ $ + mkBasicTx mkBasicTxBody + & bodyTxL . certsTxBodyL .~ [regTxCert] + expectRegistered cred + + describe "Delegate stake" $ do + it "Register and delegate in the same transaction" $ do + expectedDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL + + cred <- KeyHashObj <$> freshKeyHash + poolKh <- freshKeyHash + registerPoolWithDeposit poolKh + submitTx_ $ + mkBasicTx mkBasicTxBody + & bodyTxL . certsTxBodyL + .~ [ RegDepositTxCert cred expectedDeposit + , DelegTxCert cred (DelegStake poolKh) + ] + expectDelegatedToPool cred poolKh + + freshKeyHash >>= \kh -> do + submitTx_ $ + mkBasicTx mkBasicTxBody + & bodyTxL . certsTxBodyL + .~ [ RegDepositTxCert (KeyHashObj kh) expectedDeposit + , DelegStakeTxCert (KeyHashObj kh) poolKh -- using the pattern from Shelley + ] + expectDelegatedToPool (KeyHashObj kh) poolKh + +expectRegistered :: (HasCallStack, ConwayEraImp era) => Credential 'Staking -> ImpTestM era () +expectRegistered cred = do + accounts <- getsNES $ nesEsL . esLStateL . lsCertStateL . certDStateL . accountsL + expectedDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL + + accountState <- expectJust $ lookupAccountState cred accounts + impAnn (show cred <> " expected to be in Accounts with the correct deposit") $ do + accountState ^. depositAccountStateL `shouldBe` compactCoinOrError expectedDeposit + +expectDelegatedToPool :: + (HasCallStack, ConwayEraImp era) => Credential 'Staking -> KeyHash 'StakePool -> ImpTestM era () +expectDelegatedToPool cred poolKh = do + accounts <- getsNES $ nesEsL . esLStateL . lsCertStateL . certDStateL . accountsL + impAnn (show cred <> " expected to have delegated to " <> show poolKh) $ do + accountState <- expectJust $ lookupAccountState cred accounts + accountState ^. stakePoolDelegationAccountStateL `shouldBe` Just poolKh diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/EnactSpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/EnactSpec.hs index 51ac70389b1..f9c671094e9 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/EnactSpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/EnactSpec.hs @@ -80,7 +80,7 @@ treasuryWithdrawalsSpec = describe "Treasury withdrawals" $ do -- Treasury withdrawals are disallowed in bootstrap, so we're running these tests only post-bootstrap it "Modify EnactState as expected" $ whenPostBootstrap $ do - rewardAcount1 <- registerRewardAccount + rewardAcount1 <- registerRewardAccountWithDeposit govActionId <- submitTreasuryWithdrawals [(rewardAcount1, Coin 666)] gas <- getGovActionState govActionId let govAction = gasAction gas @@ -97,7 +97,7 @@ treasuryWithdrawalsSpec = enactState' <- runImpRule @"ENACT" () enactState signal ensWithdrawals enactState' `shouldBe` [(raCredential rewardAcount1, Coin 666)] - rewardAcount2 <- registerRewardAccount + rewardAcount2 <- registerRewardAccountWithDeposit let withdrawals' = [ (rewardAcount1, Coin 111) , (rewardAcount2, Coin 222) @@ -188,7 +188,7 @@ treasuryWithdrawalsSpec = sumRewardAccounts withdrawals = mconcat <$> traverse (getAccountBalance . fst) withdrawals genWithdrawalsExceeding (Coin val) n = do vals <- genValuesExceeding val n - forM (Coin <$> vals) $ \coin -> (,coin) <$> registerRewardAccount + forM (Coin <$> vals) $ \coin -> (,coin) <$> registerRewardAccountWithDeposit checkNoWithdrawal initialTreasury withdrawals = do getsNES treasuryL `shouldReturn` initialTreasury sumRewardAccounts withdrawals `shouldReturn` zero @@ -285,7 +285,8 @@ hardForkInitiationNoDRepsSpec = ] getProtVer `shouldReturn` nextProtVer -pparamPredictionSpec :: ConwayEraImp era => SpecWith (ImpInit (LedgerSpec era)) +pparamPredictionSpec :: + ConwayEraImp era => SpecWith (ImpInit (LedgerSpec era)) pparamPredictionSpec = it "futurePParams" $ do committeeMembers' <- registerInitialCommittee @@ -306,7 +307,8 @@ pparamPredictionSpec = passEpoch getProtVer `shouldReturn` nextProtVer -noConfidenceSpec :: forall era. ConwayEraImp era => SpecWith (ImpInit (LedgerSpec era)) +noConfidenceSpec :: + forall era. ConwayEraImp era => SpecWith (ImpInit (LedgerSpec era)) noConfidenceSpec = it "NoConfidence" $ whenPostBootstrap $ do modifyPParams $ \pp -> diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/EpochSpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/EpochSpec.hs index 251a7ae374a..2e77141bf82 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/EpochSpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/EpochSpec.hs @@ -88,7 +88,7 @@ proposalsSpec = pp & ppGovActionLifetimeL .~ EpochInterval 1 & ppGovActionDepositL .~ deposit - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit initialValue <- getsNES (nesEsL . curPParamsEpochStateL . ppMinFeeAL) @@ -398,8 +398,8 @@ treasurySpec = it "TreasuryWithdrawalExtra" $ whenPostBootstrap $ do disableTreasuryExpansion - rewardAccount <- registerRewardAccount - rewardAccountOther <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit + rewardAccountOther <- registerRewardAccountWithDeposit govPolicy <- getGovPolicy treasuryWithdrawalExpectation [ TreasuryWithdrawals (Map.singleton rewardAccount (Coin 667)) govPolicy @@ -424,7 +424,7 @@ treasuryWithdrawalExpectation extraWithdrawals = do (dRepCred, _, _) <- setupSingleDRep 1_000_000 treasuryStart <- getsNES treasuryL treasuryStart `shouldBe` withdrawalAmount - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit govPolicy <- getGovPolicy (govActionId NE.:| _) <- submitGovActions $ @@ -443,7 +443,8 @@ treasuryWithdrawalExpectation extraWithdrawals = do impAnn "Withdrawal received by reward account" $ getBalance (raCredential rewardAccount) `shouldReturn` withdrawalAmount -depositMovesToTreasuryWhenStakingAddressUnregisters :: ConwayEraImp era => ImpTestM era () +depositMovesToTreasuryWhenStakingAddressUnregisters :: + ConwayEraImp era => ImpTestM era () depositMovesToTreasuryWhenStakingAddressUnregisters = do disableTreasuryExpansion initialTreasury <- getsNES treasuryL @@ -452,8 +453,9 @@ depositMovesToTreasuryWhenStakingAddressUnregisters = do & ppGovActionLifetimeL .~ EpochInterval 8 & ppGovActionDepositL .~ Coin 100 & ppCommitteeMaxTermLengthL .~ EpochInterval 0 - returnAddr <- registerRewardAccount + returnAddr <- registerRewardAccountWithDeposit govActionDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppGovActionDepositL + keyDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL govPolicy <- getGovPolicy gaid <- mkProposalWithRewardAccount @@ -472,7 +474,7 @@ depositMovesToTreasuryWhenStakingAddressUnregisters = do mkBasicTx mkBasicTxBody & bodyTxL . certsTxBodyL .~ SSeq.singleton - (UnRegTxCert $ raCredential returnAddr) + (UnRegDepositTxCert (raCredential returnAddr) keyDeposit) expectNotRegisteredRewardAddress returnAddr replicateM_ 5 passEpoch expectMissingGovActionId gaid @@ -499,6 +501,7 @@ eventsSpec = describe "Events" $ do & ppPoolVotingThresholdsL . pvtPPSecurityGroupL .~ 1 %! 1 whenPostBootstrap (modifyPParams $ ppDRepVotingThresholdsL . dvtPPEconomicGroupL .~ def) propDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppGovActionDepositL + keyDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL let proposeParameterChange = do newVal <- CoinPerByte . Coin <$> choose (3000, 6500) @@ -507,7 +510,7 @@ eventsSpec = describe "Events" $ do (proposal, getsNES (nesEsL . curPParamsEpochStateL . ppCoinsPerUTxOByteL) `shouldReturn` newVal) (proposalA, checkProposedParameterA) <- proposeParameterChange (proposalB, _) <- proposeParameterChange - rewardAccount@(RewardAccount _ rewardCred) <- registerRewardAccount + rewardAccount@(RewardAccount _ rewardCred) <- registerRewardAccountWithDeposit passEpoch -- prevent proposalC expiry and force it's deletion due to conflit. proposalC <- impAnn "proposalC" $ do newVal <- CoinPerByte . Coin <$> choose (3000, 6500) @@ -536,7 +539,7 @@ eventsSpec = describe "Events" $ do submitTx_ $ mkBasicTx mkBasicTxBody & bodyTxL . certsTxBodyL - .~ SSeq.singleton (UnRegTxCert rewardCred) + .~ SSeq.singleton (UnRegDepositTxCert rewardCred keyDeposit) passEpochWithNoDroppedActions (_, evs) <- listen passEpoch checkProposedParameterA diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/GovSpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/GovSpec.hs index b12869d0ba8..61647a72806 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/GovSpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/GovSpec.hs @@ -119,7 +119,7 @@ predicateFailuresSpec = } it "ProposalDepositIncorrect" $ do - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit actionDeposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppGovActionDepositL anchor <- arbitrary submitFailingProposal @@ -709,7 +709,7 @@ proposalsSpec = do it "Proposals are stored in the expected order" $ whenPostBootstrap $ do modifyPParams $ ppMaxValSizeL .~ 1_000_000_000 ens <- getEnactState - returnAddr <- registerRewardAccount + returnAddr <- registerRewardAccountWithDeposit withdrawal <- (: []) . (returnAddr,) . Coin . getPositive <$> (arbitrary :: ImpTestM era (Positive Integer)) @@ -886,7 +886,7 @@ votingSpec = conAnchor `shouldNotBe` anchor it "can submit SPO votes" $ do spoHash <- freshKeyHash - registerPool spoHash + registerPoolWithDeposit spoHash passNEpochs 3 gaId <- submitParameterChange SNothing $ @@ -1006,7 +1006,7 @@ policySpec = mkProposal (ParameterChange SNothing pparamsUpdate (SJust scriptHash)) >>= submitProposal_ impAnn "TreasuryWithdrawals with correct policy succeeds" $ do - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit let withdrawals = Map.fromList [(rewardAccount, Coin 1000)] mkProposal (TreasuryWithdrawals withdrawals (SJust scriptHash)) >>= submitProposal_ @@ -1018,7 +1018,7 @@ policySpec = [injectFailure $ InvalidPolicyHash (SJust wrongScriptHash) (SJust scriptHash)] impAnn "TreasuryWithdrawals with invalid policy fails" $ do - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit let withdrawals = Map.fromList [(rewardAccount, Coin 1000)] mkProposal (TreasuryWithdrawals withdrawals (SJust wrongScriptHash)) >>= flip @@ -1072,7 +1072,7 @@ withdrawalsSpec = it "Fails predicate when treasury withdrawal has nonexistent return address" $ do policy <- getGovPolicy unregisteredRewardAccount <- freshKeyHash >>= getRewardAccountFor . KeyHashObj - registeredRewardAccount <- registerRewardAccount + registeredRewardAccount <- registerRewardAccountWithDeposit let genPositiveCoin = Coin . getPositive <$> arbitrary withdrawals <- sequence @@ -1117,10 +1117,10 @@ withdrawalsSpec = it "Fails for empty withdrawals" $ do mkTreasuryWithdrawalsGovAction [] >>= expectZeroTreasuryFailurePostBootstrap - rwdAccount1 <- registerRewardAccount + rwdAccount1 <- registerRewardAccountWithDeposit mkTreasuryWithdrawalsGovAction [(rwdAccount1, zero)] >>= expectZeroTreasuryFailurePostBootstrap - rwdAccount2 <- registerRewardAccount + rwdAccount2 <- registerRewardAccountWithDeposit let withdrawals = [(rwdAccount1, zero), (rwdAccount2, zero)] mkTreasuryWithdrawalsGovAction withdrawals >>= expectZeroTreasuryFailurePostBootstrap @@ -1149,7 +1149,7 @@ withdrawalsSpec = -- | Tests the first hardfork in the Conway era where the PrevGovActionID is SNothing firstHardForkFollows :: forall era. - (ShelleyEraImp era, ConwayEraTxBody era) => + ConwayEraImp era => (ProtVer -> ProtVer) -> ImpTestM era () firstHardForkFollows computeNewFromOld = do @@ -1159,8 +1159,7 @@ firstHardForkFollows computeNewFromOld = do -- | Negative (deliberatey failing) first hardfork in the Conway era where the PrevGovActionID is SNothing firstHardForkCantFollow :: forall era. - ( ShelleyEraImp era - , ConwayEraTxBody era + ( ConwayEraImp era , InjectRuleFailure "LEDGER" ConwayGovPredFailure era ) => ImpTestM era () @@ -1182,7 +1181,7 @@ firstHardForkCantFollow = do -- | Tests a second hardfork in the Conway era where the PrevGovActionID is SJust secondHardForkFollows :: forall era. - (ShelleyEraImp era, ConwayEraTxBody era) => + ConwayEraImp era => (ProtVer -> ProtVer) -> ImpTestM era () secondHardForkFollows computeNewFromOld = do @@ -1195,8 +1194,7 @@ secondHardForkFollows computeNewFromOld = do -- | Negative (deliberatey failing) first hardfork in the Conway era where the PrevGovActionID is SJust secondHardForkCantFollow :: forall era. - ( ShelleyEraImp era - , ConwayEraTxBody era + ( ConwayEraImp era , InjectRuleFailure "LEDGER" ConwayGovPredFailure era ) => ImpTestM era () @@ -1294,7 +1292,7 @@ bootstrapPhaseSpec = submitYesVote_ (StakePoolVoter spo) gid submitYesVote_ (CommitteeVoter committee) gid it "Treasury withdrawal" $ do - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit action <- mkTreasuryWithdrawalsGovAction [(rewardAccount, Coin 1000)] proposal <- mkProposalWithRewardAccount action rewardAccount checkProposalFailure proposal diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/HardForkSpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/HardForkSpec.hs index 3c8d7e021ba..b71e9d0b3c3 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/HardForkSpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/HardForkSpec.hs @@ -99,7 +99,7 @@ spec = do passNEpochs 2 getProtVer `shouldReturn` pv11 registerStakePoolTx kh vrf = do - pps <- registerRewardAccount >>= freshPoolParams kh + pps <- registerRewardAccountWithDeposit >>= freshPoolParams kh pure $ mkBasicTx mkBasicTxBody & bodyTxL . certsTxBodyL .~ [RegPoolTxCert $ pps & ppVrfL .~ vrf] diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/LedgerSpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/LedgerSpec.hs index d31484ef0de..b5f98dab3c2 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/LedgerSpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/LedgerSpec.hs @@ -81,7 +81,7 @@ spec = do modifyPParams $ ppGovActionLifetimeL .~ EpochInterval 2 kh <- freshKeyHash let cred = KeyHashObj kh - ra <- registerStakeCredential cred + ra <- registerStakeCredentialWithDeposit cred submitAndExpireProposalToMakeReward cred balance <- getBalance cred @@ -106,14 +106,12 @@ spec = do modifyPParams $ ppGovActionLifetimeL .~ EpochInterval 2 kh <- freshKeyHash let cred = KeyHashObj kh - ra <- registerStakeCredential cred + ra <- registerStakeCredentialWithDeposit cred submitAndExpireProposalToMakeReward cred balance <- getBalance cred (drep, _, _) <- setupSingleDRep 1_000_000 - _ <- delegateToDRep cred (Coin 1_000_000) (DRepCredential drep) - unRegisterDRep drep expectDRepNotRegistered drep let tx = @@ -127,9 +125,9 @@ spec = do it "Withdraw and unregister staking credential in the same transaction" $ do refund <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL - kh <- freshKeyHash - let cred = KeyHashObj kh - ra <- registerStakeCredential cred + (_, cred, _) <- setupSingleDRep 1_000_000 + ra <- getRewardAccountFor cred + Positive newDeposit <- arbitrary modifyPParams $ \pp -> pp @@ -139,10 +137,6 @@ spec = do submitAndExpireProposalToMakeReward cred balance <- getBalance cred - (drep, _, _) <- setupSingleDRep 1_000_000 - - _ <- delegateToDRep cred (Coin 1_000_000) (DRepCredential drep) - let tx = mkBasicTx $ mkBasicTxBody @@ -157,7 +151,7 @@ spec = do & ppDRepActivityL .~ EpochInterval 1 kh <- freshKeyHash let cred = KeyHashObj kh - ra <- registerStakeCredential cred + ra <- registerStakeCredentialWithDeposit cred submitAndExpireProposalToMakeReward cred balance <- getBalance cred @@ -182,16 +176,11 @@ spec = do pp & ppGovActionLifetimeL .~ EpochInterval 4 & ppDRepActivityL .~ EpochInterval 1 - kh <- freshKeyHash - let cred = KeyHashObj kh - ra <- registerStakeCredential cred + (drep, cred, _) <- setupSingleDRep 1_000_000 + ra <- getRewardAccountFor cred submitAndExpireProposalToMakeReward cred balance <- getBalance cred - (drep, _, _) <- setupSingleDRep 1_000_000 - - _ <- delegateToDRep cred (Coin 1_000_000) (DRepCredential drep) - -- expire the drep after delegation mkMinFeeUpdateGovAction SNothing >>= submitGovAction_ @@ -209,7 +198,8 @@ spec = do modifyPParams $ ppGovActionLifetimeL .~ EpochInterval 2 let scriptHash = hashPlutusScript $ alwaysSucceedsNoDatum SPlutusV3 let cred = ScriptHashObj scriptHash - ra <- registerStakeCredential cred + void $ regDelegToDRep cred (Coin 1_000_000) DRepAlwaysAbstain + ra <- getRewardAccountFor cred submitAndExpireProposalToMakeReward cred balance <- getBalance cred @@ -217,7 +207,6 @@ spec = do mkBasicTx $ mkBasicTxBody & withdrawalsTxBodyL .~ Withdrawals [(ra, balance)] - _ <- delegateToDRep cred (Coin 1_000_000) DRepAlwaysAbstain submitTx_ $ mkBasicTx $ mkBasicTxBody & withdrawalsTxBodyL .~ Withdrawals [(ra, mempty)] @@ -285,7 +274,7 @@ spec = do mkBasicTx (mkBasicTxBody & proposalProceduresTxBodyL .~ [proposal]) ccHot <- registerCommitteeHotKey ccCold govActionId <- do - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit submitTreasuryWithdrawals [(rewardAccount, Coin 1)] let diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/RatifySpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/RatifySpec.hs index 679ea826221..6f6399db1ed 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/RatifySpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/RatifySpec.hs @@ -458,7 +458,7 @@ committeeMinSizeAffectsInFlightProposalsSpec = describe "CommitteeMinSize affects in-flight proposals" $ do let setCommitteeMinSize n = modifyPParams $ ppCommitteeMinSizeL .~ n submitTreasuryWithdrawal amount = do - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit submitTreasuryWithdrawals [(rewardAccount, amount)] it "TreasuryWithdrawal fails to ratify due to an increase in CommitteeMinSize" $ whenPostBootstrap $ do disableTreasuryExpansion @@ -812,7 +812,7 @@ votingSpec = calculateDRepAcceptedRatio paramChangeGovId `shouldReturn` 1 % 2 kh <- freshKeyHash - _ <- registerStakeCredential (KeyHashObj kh) + _ <- registerStakeCredentialWithDeposit (KeyHashObj kh) _ <- delegateToDRep (KeyHashObj kh) (Coin 1_000_000) DRepAlwaysNoConfidence passEpoch -- AlwaysNoConfidence vote acts like a 'No' vote for actions other than NoConfidence @@ -873,7 +873,7 @@ votingSpec = (drep2, drep2Staking, _) <- setupSingleDRep 1_000_000 - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit govId <- submitTreasuryWithdrawals [(rewardAccount, initialTreasury)] submitYesVote_ (CommitteeVoter comMember) govId @@ -900,9 +900,8 @@ votingSpec = & ppDRepVotingThresholdsL . dvtMotionNoConfidenceL .~ 1 %! 1 & ppCoinsPerUTxOByteL .~ CoinPerByte (Coin 1) (drep, _, committeeId) <- electBasicCommittee - kh <- freshKeyHash - _ <- registerStakeCredential (KeyHashObj kh) - _ <- delegateToDRep (KeyHashObj kh) (Coin 300) DRepAlwaysNoConfidence + cred <- KeyHashObj <$> freshKeyHash + void $ regDelegToDRep cred (Coin 300) DRepAlwaysNoConfidence noConfidence <- submitGovAction (NoConfidence (SJust committeeId)) submitYesVote_ (DRepVoter drep) noConfidence logAcceptedRatio noConfidence diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/UtxoSpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/UtxoSpec.hs index 81a71fd5e0f..6cd94d7362b 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/UtxoSpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/UtxoSpec.hs @@ -8,7 +8,10 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} -module Test.Cardano.Ledger.Conway.Imp.UtxoSpec (spec) where +module Test.Cardano.Ledger.Conway.Imp.UtxoSpec ( + spec, + conwayEraSpecificSpec, +) where import Cardano.Ledger.Address import Cardano.Ledger.Alonzo.Plutus.Context (EraPlutusContext (..)) @@ -75,11 +78,11 @@ spec = do [ RegPoolTxCert poolParams , RegDRepTxCert dRepCred dRepDeposit anchor , RegDepositDelegTxCert cred0 delegatee accountDeposit - , RegTxCert cred1 + , RegDepositTxCert cred1 accountDeposit , RegDepositTxCert cred2 accountDeposit , RegDepositTxCert cred3 accountDeposit - , UnRegTxCert cred2 , UnRegDepositTxCert cred1 accountDeposit + , UnRegDepositTxCert cred2 accountDeposit , RegDepositTxCert cred4 accountDeposit ] utxoAfterRegister <- getUTxO @@ -106,7 +109,7 @@ spec = do .~ SSeq.fromList [ RetirePoolTxCert poolId (succ curEpochNo) , UnRegDRepTxCert dRepCred dRepDeposit - , UnRegTxCert cred3 + , UnRegDepositTxCert cred3 accountDeposit , UnRegDepositTxCert cred4 accountDeposit ] utxoAfterUnRegister <- getUTxO @@ -178,3 +181,79 @@ spec = do [ injectFailure $ CollectErrors [BadTranslation . inject $ ReferenceInputsNotDisjointFromInputs @era [txIn]] ] + +conwayEraSpecificSpec :: + forall era. + ( ConwayEraImp era + , ShelleyEraTxCert era + ) => + SpecWith (ImpInit (LedgerSpec era)) +conwayEraSpecificSpec = do + describe "Certificates" $ do + it "Reg/UnReg collect and refund correct amounts" $ do + utxoStart <- getUTxO + accountDeposit <- getsPParams ppKeyDepositL + stakePoolDeposit <- getsPParams ppPoolDepositL + dRepDeposit <- getsPParams ppDRepDepositL + cred0 <- KeyHashObj <$> freshKeyHash @'Staking + cred1 <- KeyHashObj <$> freshKeyHash @'Staking + cred2 <- KeyHashObj <$> freshKeyHash @'Staking + cred3 <- KeyHashObj <$> freshKeyHash @'Staking + cred4 <- KeyHashObj <$> freshKeyHash @'Staking + poolId <- freshKeyHash + poolParams <- freshPoolParams poolId (RewardAccount Testnet cred0) + dRepCred <- KeyHashObj <$> freshKeyHash @'DRepRole + let delegatee = DelegStakeVote poolId (DRepCredential dRepCred) + anchor <- arbitrary + txRegister <- + submitTx $ + mkBasicTx mkBasicTxBody + & bodyTxL . certsTxBodyL + .~ SSeq.fromList + [ RegPoolTxCert poolParams + , RegDRepTxCert dRepCred dRepDeposit anchor + , RegDepositDelegTxCert cred0 delegatee accountDeposit + , RegTxCert cred1 + , RegDepositTxCert cred2 accountDeposit + , RegDepositTxCert cred3 accountDeposit + , UnRegTxCert cred2 + , UnRegDepositTxCert cred1 accountDeposit + , RegDepositTxCert cred4 accountDeposit + ] + utxoAfterRegister <- getUTxO + -- Overwrite deposit protocol parameters in order to ensure they does not affect refunds + modifyPParams + ( \pp -> + pp + & ppKeyDepositL .~ Coin 1 + & ppPoolDepositL .~ Coin 2 + & ppDRepDepositL .~ Coin 3 + ) + (sumUTxO utxoStart <-> sumUTxO utxoAfterRegister) + `shouldBe` inject + ( (txRegister ^. bodyTxL . feeTxBodyL) + <+> ((3 :: Int) <×> accountDeposit) -- Only three accounts retained that are still registered + <+> stakePoolDeposit + <+> dRepDeposit + ) + curEpochNo <- getsNES nesELL + txUnRegister <- + submitTx $ + mkBasicTx mkBasicTxBody + & bodyTxL . certsTxBodyL + .~ SSeq.fromList + [ RetirePoolTxCert poolId (succ curEpochNo) + , UnRegDRepTxCert dRepCred dRepDeposit + , UnRegTxCert cred3 + , UnRegDepositTxCert cred4 accountDeposit + ] + utxoAfterUnRegister <- getUTxO + let totalFees = (txRegister ^. bodyTxL . feeTxBodyL) <+> (txUnRegister ^. bodyTxL . feeTxBodyL) + fees <- getsNES (nesEsL . esLStateL . lsUTxOStateL . utxosFeesL) + totalFees `shouldBe` fees + -- only deposits for stake pool and its account are not refunded at this point + (sumUTxO utxoStart <-> sumUTxO utxoAfterUnRegister) + `shouldBe` inject (totalFees <+> stakePoolDeposit <+> accountDeposit) + passEpoch + -- Check for successfull pool refund + getBalance cred0 `shouldReturn` stakePoolDeposit diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/UtxosSpec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/UtxosSpec.hs index 3665fecb2c3..50486e1f265 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/UtxosSpec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Imp/UtxosSpec.hs @@ -269,7 +269,7 @@ conwayFeaturesPlutusV1V2FailureSpec = do describe "ProposalProcedures" $ do it "V1" $ do deposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppGovActionDepositL - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit let badField = OSet.singleton $ ProposalProcedure deposit rewardAccount InfoAction def testPlutusV1V2Failure (hashPlutusScript $ redeemerSameAsDatum SPlutusV1) @@ -279,7 +279,7 @@ conwayFeaturesPlutusV1V2FailureSpec = do $ ProposalProceduresFieldNotSupported badField it "V2" $ do deposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppGovActionDepositL - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit let badField = OSet.singleton $ ProposalProcedure deposit rewardAccount InfoAction def testPlutusV1V2Failure (hashPlutusScript $ redeemerSameAsDatum SPlutusV2) @@ -479,7 +479,7 @@ govPolicySpec = do submitFailingTx tx [injectFailure $ ScriptWitnessNotValidatingUTXOW [scriptHash]] impAnn "TreasuryWithdrawals" $ do - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit let withdrawals = Map.fromList [(rewardAccount, Coin 1000)] let govAction = TreasuryWithdrawals withdrawals (SJust scriptHash) proposal <- mkProposal govAction @@ -500,7 +500,7 @@ govPolicySpec = do (Constitution anchor (SJust alwaysSucceedsSh)) dRep committeeMembers' - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit impAnn "ParameterChange" $ do let pparamsUpdate = def & ppuCommitteeMinSizeL .~ SJust 1 @@ -527,7 +527,7 @@ govPolicySpec = do submitPhase2Invalid_ tx impAnn "TreasuryWithdrawals" $ do - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit let withdrawals = Map.fromList [(rewardAccount, Coin 1000)] let govAction = TreasuryWithdrawals withdrawals (SJust alwaysFailsSh) proposal <- mkProposal govAction diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/ImpTest.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/ImpTest.hs index f787c2cf734..4c39fe4a442 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/ImpTest.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/ImpTest.hs @@ -52,6 +52,7 @@ module Test.Cardano.Ledger.Conway.ImpTest ( updateDRep, delegateToDRep, setupSingleDRep, + regDelegToDRep, setupDRepWithoutStake, setupPoolWithStake, setupPoolWithoutStake, @@ -133,6 +134,9 @@ module Test.Cardano.Ledger.Conway.ImpTest ( FailBoth (..), delegateSPORewardAddressToDRep_, getCommittee, + registerStakeCredentialWithDeposit, + registerPoolWithDeposit, + registerRewardAccountWithDeposit, ) where import Cardano.Ledger.Address (RewardAccount (..)) @@ -146,6 +150,7 @@ import Cardano.Ledger.BaseTypes ( addEpochInterval, binOpEpochNo, inject, + networkId, textToUrl, ) import Cardano.Ledger.Coin (Coin (..)) @@ -173,7 +178,7 @@ import Cardano.Ledger.Conway.Rules ( ) import Cardano.Ledger.Conway.State import Cardano.Ledger.Conway.TxCert (Delegatee (..)) -import Cardano.Ledger.Credential (Credential (..)) +import Cardano.Ledger.Credential (Credential (..), credToText) import Cardano.Ledger.DRep import Cardano.Ledger.Plutus.Language (Language (..), SLanguage (..), hashPlutusScript) import Cardano.Ledger.Shelley.LedgerState ( @@ -213,6 +218,7 @@ import qualified Data.Text as T import Data.Tree import qualified GHC.Exts as GHC (fromList) import Lens.Micro +import Lens.Micro.Mtl (use) import Prettyprinter (align, hsep, viaShow, vsep) import Test.Cardano.Ledger.Babbage.ImpTest import Test.Cardano.Ledger.Conway.Arbitrary () @@ -309,7 +315,6 @@ instance AlonzoEraImp ConwayEra where class ( AlonzoEraImp era , ConwayEraTest era - , ConwayEraTxCert era , STS (EraRule "ENACT" era) , BaseM (EraRule "ENACT" era) ~ ShelleyBase , State (EraRule "ENACT" era) ~ EnactState era @@ -371,6 +376,7 @@ unRegisterDRep drep = do genUnRegTxCert :: forall era. ( ShelleyEraImp era + , ShelleyEraTxCert era , ConwayEraTxCert era ) => Credential 'Staking -> @@ -388,6 +394,7 @@ genUnRegTxCert stakingCredential = do genRegTxCert :: forall era. ( ShelleyEraImp era + , ShelleyEraTxCert era , ConwayEraTxCert era ) => Credential 'Staking -> @@ -441,16 +448,33 @@ setupSingleDRep :: ImpTestM era (Credential 'DRepRole, Credential 'Staking, KeyPair 'Payment) setupSingleDRep stake = do drepKH <- registerDRep - delegatorKH <- freshKeyHash + kh <- freshKeyHash + (delegatorKH, spendingKP) <- + regDelegToDRep (KeyHashObj kh) (Coin stake) (DRepCredential (KeyHashObj drepKH)) + pure (KeyHashObj drepKH, delegatorKH, spendingKP) + +regDelegToDRep :: + ConwayEraImp era => + Credential 'Staking -> + Coin -> + DRep -> + ImpTestM era (Credential 'Staking, KeyPair 'Payment) +regDelegToDRep cred stake dRep = do deposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL + (_, spendingKP) <- freshKeyPair let tx = mkBasicTx mkBasicTxBody + & bodyTxL . outputsTxBodyL + .~ SSeq.singleton (mkBasicTxOut (mkAddr spendingKP cred) (inject stake)) & bodyTxL . certsTxBodyL - .~ SSeq.fromList [RegDepositTxCert (KeyHashObj delegatorKH) deposit] + .~ SSeq.fromList + [ RegDepositDelegTxCert + cred + (DelegVote dRep) + deposit + ] submitTx_ tx - spendingKP <- - delegateToDRep (KeyHashObj delegatorKH) (Coin stake) (DRepCredential (KeyHashObj drepKH)) - pure (KeyHashObj drepKH, KeyHashObj delegatorKH, spendingKP) + pure (cred, spendingKP) delegateToDRep :: ConwayEraImp era => @@ -485,12 +509,12 @@ getDRepState dRepCred = do -- in Conway. The Shelley version of this function would have to separately -- register the staking credential and then delegate it. setupPoolWithStake :: - (ShelleyEraImp era, ConwayEraTxCert era) => + ConwayEraImp era => Coin -> ImpTestM era (KeyHash 'StakePool, Credential 'Payment, Credential 'Staking) setupPoolWithStake delegCoin = do khPool <- freshKeyHash - registerPool khPool + registerPoolWithDeposit khPool credDelegatorPayment <- KeyHashObj <$> freshKeyHash credDelegatorStaking <- KeyHashObj <$> freshKeyHash sendCoinTo_ (mkAddr credDelegatorPayment credDelegatorStaking) delegCoin @@ -507,11 +531,11 @@ setupPoolWithStake delegCoin = do pure (khPool, credDelegatorPayment, credDelegatorStaking) setupPoolWithoutStake :: - (ShelleyEraImp era, ConwayEraTxCert era) => + ConwayEraImp era => ImpTestM era (KeyHash 'StakePool, Credential 'Staking) setupPoolWithoutStake = do khPool <- freshKeyHash - registerPool khPool + registerPoolWithDeposit khPool credDelegatorStaking <- KeyHashObj <$> freshKeyHash deposit <- getsNES $ nesEsL . curPParamsEpochStateL . ppKeyDepositL submitTxAnn_ "Delegate to stake pool" $ @@ -681,9 +705,7 @@ submitFailingProposal proposal expectedFailure = -- | Submits a transaction that proposes the given governance action. For proposing -- multiple actions in the same transaciton use `trySubmitGovActions` instead. trySubmitGovAction :: - ( ShelleyEraImp era - , ConwayEraTxBody era - ) => + ConwayEraImp era => GovAction era -> ImpTestM era (Either (NonEmpty (PredicateFailure (EraRule "LEDGER" era))) GovActionId) trySubmitGovAction ga = do @@ -713,7 +735,7 @@ submitAndExpireProposalToMakeReward stakingC = do -- | Submits a transaction that proposes the given governance action trySubmitGovActions :: - (ShelleyEraImp era, ConwayEraTxBody era) => + ConwayEraImp era => NE.NonEmpty (GovAction era) -> ImpTestM era (Either (NonEmpty (PredicateFailure (EraRule "LEDGER" era)), Tx era) (Tx era)) trySubmitGovActions gas = do @@ -737,17 +759,16 @@ mkProposalWithRewardAccount ga rewardAccount = do } mkProposal :: - (ShelleyEraImp era, ConwayEraTxBody era) => + ConwayEraImp era => GovAction era -> ImpTestM era (ProposalProcedure era) mkProposal ga = do - rewardAccount <- registerRewardAccount + rewardAccount <- registerRewardAccountWithDeposit mkProposalWithRewardAccount ga rewardAccount submitGovAction :: forall era. - ( ShelleyEraImp era - , ConwayEraTxBody era + ( ConwayEraImp era , HasCallStack ) => GovAction era -> @@ -758,8 +779,7 @@ submitGovAction ga = do submitGovAction_ :: forall era. - ( ShelleyEraImp era - , ConwayEraTxBody era + ( ConwayEraImp era , HasCallStack ) => GovAction era -> @@ -768,8 +788,7 @@ submitGovAction_ = void . submitGovAction submitGovActions :: forall era. - ( ShelleyEraImp era - , ConwayEraTxBody era + ( ConwayEraImp era , HasCallStack ) => NE.NonEmpty (GovAction era) -> @@ -787,10 +806,7 @@ mkTreasuryWithdrawalsGovAction wdrls = TreasuryWithdrawals (Map.fromList wdrls) <$> getGovPolicy submitTreasuryWithdrawals :: - ( ShelleyEraImp era - , ConwayEraTxBody era - , ConwayEraGov era - ) => + ConwayEraImp era => [(RewardAccount, Coin)] -> ImpTestM era GovActionId submitTreasuryWithdrawals wdrls = @@ -840,8 +856,7 @@ getGovPolicy = submitFailingGovAction :: forall era. - ( ShelleyEraImp era - , ConwayEraTxBody era + ( ConwayEraImp era , HasCallStack ) => GovAction era -> @@ -1802,3 +1817,32 @@ instance InjectRuleFailure "DELEG" ShelleyDelegPredFailure ConwayEra where getCommittee :: ConwayEraGov era => ImpTestM era (StrictMaybe (Committee era)) getCommittee = getsNES $ nesEsL . epochStateGovStateL . committeeGovStateL + +registerStakeCredentialWithDeposit :: + forall era. + ConwayEraImp era => + Credential 'Staking -> + ImpTestM era RewardAccount +registerStakeCredentialWithDeposit cred = do + deposit <- getsNES (nesEsL . curPParamsEpochStateL . ppKeyDepositL) + submitTxAnn_ ("Register Reward Account: " <> T.unpack (credToText cred)) $ + mkBasicTx mkBasicTxBody + & bodyTxL . certsTxBodyL + .~ SSeq.fromList [RegDepositTxCert cred deposit] + networkId <- use (impGlobalsL . to networkId) + pure $ RewardAccount networkId cred + +registerPoolWithDeposit :: + ConwayEraImp era => + KeyHash 'StakePool -> + ImpTestM era () +registerPoolWithDeposit khPool = + (freshKeyHash >>= registerStakeCredentialWithDeposit . KeyHashObj) + >>= registerPoolWithRewardAccount khPool + +registerRewardAccountWithDeposit :: + forall era. + ConwayEraImp era => + ImpTestM era RewardAccount +registerRewardAccountWithDeposit = do + freshKeyHash >>= registerStakeCredentialWithDeposit . KeyHashObj diff --git a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Spec.hs b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Spec.hs index f0c558dca29..e09c6e6fbb9 100644 --- a/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Spec.hs +++ b/eras/conway/impl/testlib/Test/Cardano/Ledger/Conway/Spec.hs @@ -18,18 +18,7 @@ import Cardano.Ledger.Babbage.Rules (BabbageUtxoPredFailure, BabbageUtxowPredFai import Cardano.Ledger.Babbage.TxInfo (BabbageContextError) import Cardano.Ledger.BaseTypes (Inject) import Cardano.Ledger.Binary (DecCBOR) -import Cardano.Ledger.Conway.Core ( - AlonzoEraScript (..), - AsIx, - EraRule, - EraTx (..), - EraTxBody (..), - EraTxCert (..), - EraTxWits (..), - InjectRuleEvent, - InjectRuleFailure, - SafeToHash, - ) +import Cardano.Ledger.Conway.Core import Cardano.Ledger.Conway.Rules ( ConwayBbodyPredFailure, ConwayCertsPredFailure, @@ -49,7 +38,6 @@ import Cardano.Ledger.Plutus.Language (SLanguage (..)) import Cardano.Ledger.Shelley.API (ApplyTx) import Cardano.Ledger.Shelley.LedgerState (StashedAVVMAddresses) import Cardano.Ledger.Shelley.Rules ( - ShelleyDelegPredFailure, ShelleyPoolPredFailure, ShelleyUtxoPredFailure, ShelleyUtxowPredFailure, @@ -65,7 +53,7 @@ import qualified Test.Cardano.Ledger.Conway.BinarySpec as Binary import qualified Test.Cardano.Ledger.Conway.CommitteeRatifySpec as CommitteeRatify import qualified Test.Cardano.Ledger.Conway.DRepRatifySpec as DRepRatify import qualified Test.Cardano.Ledger.Conway.Imp as Imp -import Test.Cardano.Ledger.Conway.ImpTest (ConwayEraImp) +import Test.Cardano.Ledger.Conway.ImpTest (ConwayEraImp, EraSpecificSpec) import qualified Test.Cardano.Ledger.Conway.Proposals as Proposals import qualified Test.Cardano.Ledger.Conway.SPORatifySpec as SPORatifySpec import qualified Test.Cardano.Ledger.Conway.TxInfoSpec as TxInfo @@ -76,6 +64,7 @@ spec :: forall era. ( RuleListEra era , ConwayEraImp era + , EraSpecificSpec era , ApplyTx era , DecCBOR (TxWits era) , DecCBOR (TxBody era) @@ -96,7 +85,6 @@ spec :: , InjectRuleFailure "LEDGER" AlonzoUtxoPredFailure era , InjectRuleFailure "LEDGER" AlonzoUtxosPredFailure era , InjectRuleFailure "LEDGER" AlonzoUtxowPredFailure era - , InjectRuleFailure "LEDGER" ShelleyDelegPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxoPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era @@ -111,6 +99,7 @@ spec :: , Eq (Event (EraRule "ENACT" era)) , Typeable (Event (EraRule "ENACT" era)) , ToExpr (Event (EraRule "BBODY" era)) + , ShelleyEraTxCert era , TxCert era ~ ConwayTxCert era ) => Spec @@ -122,7 +111,7 @@ spec = CommitteeRatify.spec @era SPORatifySpec.spec @era roundTripJsonEraSpec @era - describe "Imp" $ + describe "Imp" $ do Imp.spec @era describe "CostModels" $ do CostModelsSpec.spec @era diff --git a/eras/dijkstra/cardano-ledger-dijkstra.cabal b/eras/dijkstra/cardano-ledger-dijkstra.cabal index 15715054566..1d816026165 100644 --- a/eras/dijkstra/cardano-ledger-dijkstra.cabal +++ b/eras/dijkstra/cardano-ledger-dijkstra.cabal @@ -80,6 +80,7 @@ library build-depends: aeson, base >=4.14 && <5, + cardano-crypto-class, cardano-data, cardano-ledger-allegra, cardano-ledger-alonzo, @@ -97,6 +98,7 @@ library microlens, nothunks, plutus-ledger-api, + small-steps >=1.1.2, if flag(asserts) ghc-options: -fno-ignore-asserts @@ -112,6 +114,7 @@ library testlib Test.Cardano.Ledger.Dijkstra.CDDL Test.Cardano.Ledger.Dijkstra.Era Test.Cardano.Ledger.Dijkstra.Examples + Test.Cardano.Ledger.Dijkstra.Imp Test.Cardano.Ledger.Dijkstra.ImpTest Test.Cardano.Ledger.Dijkstra.TreeDiff @@ -130,7 +133,7 @@ library testlib base, bytestring, cardano-data, - cardano-ledger-alonzo:testlib, + cardano-ledger-alonzo:{cardano-ledger-alonzo, testlib}, cardano-ledger-babbage:{cardano-ledger-babbage, testlib}, cardano-ledger-binary, cardano-ledger-conway:{cardano-ledger-conway, testlib}, @@ -191,7 +194,6 @@ test-suite tests build-depends: base, - cardano-ledger-conway:testlib, cardano-ledger-core:testlib, cardano-ledger-dijkstra:{cardano-ledger-dijkstra, testlib}, cardano-ledger-shelley:testlib, diff --git a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Era.hs b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Era.hs index 1d2bb66fe0f..5ad65391602 100644 --- a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Era.hs +++ b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Era.hs @@ -8,6 +8,7 @@ module Cardano.Ledger.Dijkstra.Era ( DijkstraEra, + DijkstraCERT, ) where import Cardano.Ledger.Conway (ConwayEra) @@ -90,7 +91,9 @@ type instance EraRule "RATIFY" DijkstraEra = ConwayRATIFY DijkstraEra type instance EraRule "CERTS" DijkstraEra = ConwayCERTS DijkstraEra -type instance EraRule "CERT" DijkstraEra = ConwayCERT DijkstraEra +data DijkstraCERT era + +type instance EraRule "CERT" DijkstraEra = DijkstraCERT DijkstraEra type instance EraRule "DELEG" DijkstraEra = ConwayDELEG DijkstraEra diff --git a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Rules/Cert.hs b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Rules/Cert.hs index baab5422456..91ad8ad6014 100644 --- a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Rules/Cert.hs +++ b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Rules/Cert.hs @@ -1,19 +1,35 @@ {-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} module Cardano.Ledger.Dijkstra.Rules.Cert () where +import Cardano.Ledger.BaseTypes (ShelleyBase, StrictMaybe (..)) import Cardano.Ledger.Conway.Rules ( + CertEnv (..), ConwayCertEvent, ConwayCertPredFailure (..), + ConwayDelegEnv (..), ConwayDelegPredFailure, + ConwayGovCertEnv (..), ConwayGovCertPredFailure, ) -import Cardano.Ledger.Dijkstra.Core (EraRuleEvent, EraRuleFailure, InjectRuleFailure (..)) -import Cardano.Ledger.Dijkstra.Era (DijkstraEra) -import Cardano.Ledger.Shelley.Rules (ShelleyPoolPredFailure) +import Cardano.Ledger.Conway.TxCert +import Cardano.Ledger.Dijkstra.Core +import Cardano.Ledger.Dijkstra.Era +import Cardano.Ledger.Dijkstra.State +import Cardano.Ledger.Dijkstra.TxCert +import Cardano.Ledger.Shelley.Rules (PoolEnv (..), ShelleyPoolPredFailure) +import Control.State.Transition.Extended +import Lens.Micro ((&), (.~), (^.)) type instance EraRuleFailure "CERT" DijkstraEra = ConwayCertPredFailure DijkstraEra @@ -29,3 +45,70 @@ instance InjectRuleFailure "CERT" ShelleyPoolPredFailure DijkstraEra where instance InjectRuleFailure "CERT" ConwayGovCertPredFailure DijkstraEra where injectFailure = GovCertFailure + +instance + ( Era era + , State (EraRule "DELEG" era) ~ CertState era + , State (EraRule "POOL" era) ~ PState era + , State (EraRule "GOVCERT" era) ~ CertState era + , Environment (EraRule "DELEG" era) ~ ConwayDelegEnv era + , Environment (EraRule "POOL" era) ~ PoolEnv era + , Environment (EraRule "GOVCERT" era) ~ ConwayGovCertEnv era + , Signal (EraRule "DELEG" era) ~ ConwayDelegCert + , Signal (EraRule "POOL" era) ~ PoolCert + , Signal (EraRule "GOVCERT" era) ~ ConwayGovCert + , Embed (EraRule "DELEG" era) (DijkstraCERT era) + , Embed (EraRule "POOL" era) (DijkstraCERT era) + , Embed (EraRule "GOVCERT" era) (DijkstraCERT era) + , TxCert era ~ DijkstraTxCert era + , EraCertState era + ) => + STS (DijkstraCERT era) + where + type State (DijkstraCERT era) = CertState era + type Signal (DijkstraCERT era) = TxCert era + type Environment (DijkstraCERT era) = CertEnv era + type BaseM (DijkstraCERT era) = ShelleyBase + type PredicateFailure (DijkstraCERT era) = ConwayCertPredFailure era + type Event (DijkstraCERT era) = ConwayCertEvent era + + transitionRules = [certTransition @era] + +certTransition :: + forall era. + ( State (EraRule "DELEG" era) ~ CertState era + , State (EraRule "POOL" era) ~ PState era + , State (EraRule "GOVCERT" era) ~ CertState era + , Environment (EraRule "DELEG" era) ~ ConwayDelegEnv era + , Environment (EraRule "POOL" era) ~ PoolEnv era + , Environment (EraRule "GOVCERT" era) ~ ConwayGovCertEnv era + , Signal (EraRule "DELEG" era) ~ ConwayDelegCert + , Signal (EraRule "POOL" era) ~ PoolCert + , Signal (EraRule "GOVCERT" era) ~ ConwayGovCert + , Embed (EraRule "DELEG" era) (DijkstraCERT era) + , Embed (EraRule "POOL" era) (DijkstraCERT era) + , Embed (EraRule "GOVCERT" era) (DijkstraCERT era) + , TxCert era ~ DijkstraTxCert era + , EraCertState era + ) => + TransitionRule (DijkstraCERT era) +certTransition = do + TRC (CertEnv pp currentEpoch committee committeeProposals, certState, c) <- judgmentContext + let + certPState = certState ^. certPStateL + pools = psStakePools certPState + case c of + DijkstraTxCertDeleg delegCert -> + let conwayDelegCert = case delegCert of + DijkstraRegCert cred coin -> ConwayRegCert cred (SJust coin) + DijkstraUnRegCert cred coin -> ConwayUnRegCert cred (SJust coin) + DijkstraDelegCert cred d -> ConwayDelegCert cred d + DijkstraRegDelegCert sc d coin -> ConwayRegDelegCert sc d coin + in trans @(EraRule "DELEG" era) $ + TRC (ConwayDelegEnv pp pools, certState, conwayDelegCert) + DijkstraTxCertPool poolCert -> do + newPState <- trans @(EraRule "POOL" era) $ TRC (PoolEnv currentEpoch pp, certPState, poolCert) + pure $ certState & certPStateL .~ newPState + DijkstraTxCertGov govCert -> do + trans @(EraRule "GOVCERT" era) $ + TRC (ConwayGovCertEnv pp currentEpoch committee committeeProposals, certState, govCert) diff --git a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Rules/Certs.hs b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Rules/Certs.hs index 4c94359950b..ee6c321b729 100644 --- a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Rules/Certs.hs +++ b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/Rules/Certs.hs @@ -1,21 +1,30 @@ {-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -Wno-orphans #-} module Cardano.Ledger.Dijkstra.Rules.Certs () where +import Cardano.Ledger.BaseTypes import Cardano.Ledger.Conway.Rules ( - ConwayCertPredFailure, - ConwayCertsEvent, + ConwayCERTS, + ConwayCertEvent (..), + ConwayCertPredFailure (..), + ConwayCertsEvent (..), ConwayCertsPredFailure (..), + ConwayDELEG, ConwayDelegPredFailure, + ConwayGOVCERT, ConwayGovCertPredFailure, ) -import Cardano.Ledger.Dijkstra.Core (EraRuleEvent, EraRuleFailure, InjectRuleFailure (..)) -import Cardano.Ledger.Dijkstra.Era (DijkstraEra) +import Cardano.Ledger.Dijkstra.Core +import Cardano.Ledger.Dijkstra.Era import Cardano.Ledger.Dijkstra.Rules.Cert () -import Cardano.Ledger.Shelley.Rules (ShelleyPoolPredFailure) +import Cardano.Ledger.Shelley.Rules (PoolEvent, ShelleyPOOL, ShelleyPoolPredFailure) +import Control.State.Transition.Extended +import GHC.Base (absurd) type instance EraRuleFailure "CERTS" DijkstraEra = ConwayCertsPredFailure DijkstraEra @@ -34,3 +43,48 @@ instance InjectRuleFailure "CERTS" ShelleyPoolPredFailure DijkstraEra where instance InjectRuleFailure "CERTS" ConwayGovCertPredFailure DijkstraEra where injectFailure = CertFailure . injectFailure + +instance + ( Era era + , STS (DijkstraCERT era) + , BaseM (EraRule "CERT" era) ~ ShelleyBase + , Event (EraRule "CERT" era) ~ ConwayCertEvent era + , PredicateFailure (EraRule "CERT" era) ~ ConwayCertPredFailure era + ) => + Embed (DijkstraCERT era) (ConwayCERTS era) + where + wrapFailed = CertFailure + wrapEvent = CertEvent + +instance + ( Era era + , STS (ConwayDELEG era) + , PredicateFailure (EraRule "DELEG" era) ~ ConwayDelegPredFailure era + ) => + Embed (ConwayDELEG era) (DijkstraCERT era) + where + wrapFailed = DelegFailure + wrapEvent = absurd + +instance + ( Era era + , STS (ShelleyPOOL era) + , Event (EraRule "POOL" era) ~ PoolEvent era + , PredicateFailure (EraRule "POOL" era) ~ ShelleyPoolPredFailure era + , PredicateFailure (ShelleyPOOL era) ~ ShelleyPoolPredFailure era + , BaseM (ShelleyPOOL era) ~ ShelleyBase + ) => + Embed (ShelleyPOOL era) (DijkstraCERT era) + where + wrapFailed = PoolFailure + wrapEvent = PoolEvent + +instance + ( Era era + , STS (ConwayGOVCERT era) + , PredicateFailure (EraRule "GOVCERT" era) ~ ConwayGovCertPredFailure era + ) => + Embed (ConwayGOVCERT era) (DijkstraCERT era) + where + wrapFailed = GovCertFailure + wrapEvent = absurd diff --git a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/TxCert.hs b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/TxCert.hs index 8e3b9b375de..96cb83d8702 100644 --- a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/TxCert.hs +++ b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/TxCert.hs @@ -1,69 +1,270 @@ {-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableSuperClasses #-} {-# OPTIONS_GHC -Wno-orphans #-} -module Cardano.Ledger.Dijkstra.TxCert () where - +module Cardano.Ledger.Dijkstra.TxCert ( + DijkstraTxCertUpgradeError, + DijkstraTxCert (..), + DijkstraDelegCert (..), +) where + +import Cardano.Ledger.BaseTypes (kindObject) +import Cardano.Ledger.Binary ( + DecCBOR (..), + EncCBOR (..), + FromCBOR (..), + ToCBOR (..), + decodeRecordSum, + encodeListLen, + encodeWord8, + invalidKey, + toPlainEncoding, + ) +import Cardano.Ledger.Coin (Coin) import Cardano.Ledger.Conway.Core ( ConwayEraTxCert, - ShelleyEraTxCert (..), - notSupportedInThisEra, + poolCertKeyHashWitness, + pattern AuthCommitteeHotKeyTxCert, + pattern DelegTxCert, + pattern RegDRepTxCert, pattern RegDepositDelegTxCert, pattern RegDepositTxCert, + pattern RegPoolTxCert, pattern RegTxCert, + pattern ResignCommitteeColdTxCert, + pattern RetirePoolTxCert, + pattern UnRegDRepTxCert, pattern UnRegDepositTxCert, pattern UnRegTxCert, + pattern UpdateDRepTxCert, ) import Cardano.Ledger.Conway.TxCert ( - ConwayDelegCert (..), ConwayEraTxCert (..), ConwayGovCert (..), - ConwayTxCert (..), + Delegatee (..), + conwayGovCertVKeyWitness, conwayTotalDepositsTxCerts, conwayTotalRefundsTxCerts, - getScriptWitnessConwayTxCert, - getVKeyWitnessConwayTxCert, - pattern ConwayRegCert, - pattern DelegStake, + conwayTxCertDelegDecoder, + ) +import Cardano.Ledger.Core ( + Era, + EraTxCert (..), + KeyHash, + KeyRole (..), + PoolCert (..), + ScriptHash, + Value, + eraProtVerLow, + fromEraCBOR, ) -import Cardano.Ledger.Core (EraTxCert (..), PoolCert (..)) +import Cardano.Ledger.Credential (StakeCredential, credKeyHashWitness, credScriptHash) import Cardano.Ledger.Dijkstra.Era (DijkstraEra) import Cardano.Ledger.Dijkstra.PParams () -import Data.Coerce (coerce) -import Data.Maybe.Strict (StrictMaybe (..)) -import Data.Void (Void) +import Cardano.Ledger.Shelley.TxCert ( + ShelleyDelegCert (..), + encodePoolCert, + encodeShelleyDelegCert, + poolTxCertDecoder, + ) +import Cardano.Ledger.Val (Val) +import Control.DeepSeq (NFData) +import Data.Aeson (KeyValue ((.=)), ToJSON (..)) +import GHC.Generics (Generic) +import NoThunks.Class (NoThunks) + +data DijkstraDelegCert + = DijkstraRegCert !StakeCredential !Coin + | DijkstraUnRegCert !StakeCredential !Coin + | DijkstraDelegCert !StakeCredential !Delegatee + | DijkstraRegDelegCert !StakeCredential !Delegatee !Coin + deriving (Show, Generic, Eq, Ord) + +instance EncCBOR DijkstraDelegCert where + encCBOR = \case + DijkstraRegCert cred deposit -> + encodeListLen 3 + <> encodeWord8 7 + <> encCBOR cred + <> encCBOR deposit + DijkstraUnRegCert cred deposit -> + encodeListLen 3 + <> encodeWord8 8 + <> encCBOR cred + <> encCBOR deposit + DijkstraDelegCert cred (DelegStake poolId) -> encodeShelleyDelegCert $ ShelleyDelegCert cred poolId + DijkstraDelegCert cred (DelegVote drep) -> + encodeListLen 3 + <> encodeWord8 9 + <> encCBOR cred + <> encCBOR drep + DijkstraDelegCert cred (DelegStakeVote poolId dRep) -> + encodeListLen 4 + <> encodeWord8 10 + <> encCBOR cred + <> encCBOR poolId + <> encCBOR dRep + DijkstraRegDelegCert cred (DelegStake poolId) deposit -> + encodeListLen 4 + <> encodeWord8 11 + <> encCBOR cred + <> encCBOR poolId + <> encCBOR deposit + DijkstraRegDelegCert cred (DelegVote drep) deposit -> + encodeListLen 4 + <> encodeWord8 12 + <> encCBOR cred + <> encCBOR drep + <> encCBOR deposit + DijkstraRegDelegCert cred (DelegStakeVote poolId dRep) deposit -> + encodeListLen 5 + <> encodeWord8 13 + <> encCBOR cred + <> encCBOR poolId + <> encCBOR dRep + <> encCBOR deposit + +instance NFData DijkstraDelegCert + +instance NoThunks DijkstraDelegCert + +instance ToJSON DijkstraDelegCert where + toJSON = \case + DijkstraRegCert cred deposit -> + kindObject + "RegCert" + [ "credential" .= toJSON cred + , "deposit" .= toJSON deposit + ] + DijkstraUnRegCert cred refund -> + kindObject + "UnRegCert" + [ "credential" .= toJSON cred + , "refund" .= toJSON refund + ] + DijkstraDelegCert cred delegatee -> + kindObject + "DelegCert" + [ "credential" .= toJSON cred + , "delegatee" .= toJSON delegatee + ] + DijkstraRegDelegCert cred delegatee deposit -> + kindObject + "RegDelegCert" + [ "credential" .= toJSON cred + , "delegatee" .= toJSON delegatee + , "deposit" .= toJSON deposit + ] + +data DijkstraTxCert era + = DijkstraTxCertDeleg !DijkstraDelegCert + | DijkstraTxCertPool !PoolCert + | DijkstraTxCertGov !ConwayGovCert + deriving (Show, Generic, Eq, Ord) + +data DijkstraTxCertUpgradeError + = RegTxCertExpunged + | UnRegTxCertExpunged + deriving (Eq, Show) + +instance NFData (DijkstraTxCert era) + +instance NoThunks (DijkstraTxCert era) + +instance Era era => ToJSON (DijkstraTxCert era) where + toJSON = \case + DijkstraTxCertDeleg delegCert -> toJSON delegCert + DijkstraTxCertPool poolCert -> toJSON poolCert + DijkstraTxCertGov govCert -> toJSON govCert + +instance + ( EraTxCert era + , TxCert era ~ DijkstraTxCert era + ) => + FromCBOR (DijkstraTxCert era) + where + fromCBOR = fromEraCBOR @era + +instance + ( ConwayEraTxCert era + , TxCert era ~ DijkstraTxCert era + ) => + DecCBOR (DijkstraTxCert era) + where + decCBOR = decodeRecordSum "DijkstraTxCert" $ \case + t + | 0 <= t && t < 2 -> fail "Certificates without deposits are no longer supported" + | t == 2 -> do + cred <- decCBOR + stakePool <- decCBOR + pure (3, DelegTxCert cred (DelegStake stakePool)) + | 3 <= t && t < 5 -> poolTxCertDecoder t + | t == 5 -> fail "Genesis delegation certificates are no longer supported" + | t == 6 -> fail "MIR certificates are no longer supported" + | 7 <= t -> conwayTxCertDelegDecoder t + t -> invalidKey t + +instance (Era era, Val (Value era)) => ToCBOR (DijkstraTxCert era) where + toCBOR = toPlainEncoding (eraProtVerLow @era) . encCBOR + +instance (Era era, Val (Value era)) => EncCBOR (DijkstraTxCert era) where + encCBOR = \case + DijkstraTxCertDeleg delegCert -> encCBOR delegCert + DijkstraTxCertPool poolCert -> encodePoolCert poolCert + DijkstraTxCertGov govCert -> encCBOR govCert instance EraTxCert DijkstraEra where - type TxCert DijkstraEra = ConwayTxCert DijkstraEra - - type TxCertUpgradeError DijkstraEra = Void - - upgradeTxCert = Right . coerce - - getVKeyWitnessTxCert = getVKeyWitnessConwayTxCert - - getScriptWitnessTxCert = getScriptWitnessConwayTxCert - - mkRegPoolTxCert = ConwayTxCertPool . RegPool - - getRegPoolTxCert (ConwayTxCertPool (RegPool poolParams)) = Just poolParams + type TxCert DijkstraEra = DijkstraTxCert DijkstraEra + + type TxCertUpgradeError DijkstraEra = DijkstraTxCertUpgradeError + + upgradeTxCert = \case + RegPoolTxCert poolParams -> Right $ RegPoolTxCert poolParams + RetirePoolTxCert poolId epochNo -> Right $ RetirePoolTxCert poolId epochNo + RegDepositTxCert cred c -> Right $ RegDepositTxCert cred c + UnRegDepositTxCert cred c -> Right $ UnRegDepositTxCert cred c + DelegTxCert cred d -> Right $ DelegTxCert cred d + RegDepositDelegTxCert cred d c -> Right $ RegDepositDelegTxCert cred d c + AuthCommitteeHotKeyTxCert ck hk -> Right $ AuthCommitteeHotKeyTxCert ck hk + ResignCommitteeColdTxCert ck a -> Right $ ResignCommitteeColdTxCert ck a + RegDRepTxCert cred deposit mAnchor -> Right $ RegDRepTxCert cred deposit mAnchor + UnRegDRepTxCert cred deposit -> Right $ UnRegDRepTxCert cred deposit + UpdateDRepTxCert cred mAnchor -> Right $ UpdateDRepTxCert cred mAnchor + RegTxCert {} -> Left RegTxCertExpunged + UnRegTxCert {} -> Left UnRegTxCertExpunged + -- Using wildcard here in order to workaround ghc disrespecting + -- the completeness pragma in presence of `PreviousEra` type family. + _ -> error "Impossible: all patterns have been accounted for" + + getVKeyWitnessTxCert = getVKeyWitnessDijkstraTxCert + + getScriptWitnessTxCert = getScriptWitnessDijkstraTxCert + + mkRegPoolTxCert = DijkstraTxCertPool . RegPool + + getRegPoolTxCert (DijkstraTxCertPool (RegPool poolParams)) = Just poolParams getRegPoolTxCert _ = Nothing - mkRetirePoolTxCert poolId epochNo = ConwayTxCertPool $ RetirePool poolId epochNo + mkRetirePoolTxCert poolId epochNo = DijkstraTxCertPool $ RetirePool poolId epochNo - getRetirePoolTxCert (ConwayTxCertPool (RetirePool poolId epochNo)) = Just (poolId, epochNo) + getRetirePoolTxCert (DijkstraTxCertPool (RetirePool poolId epochNo)) = Just (poolId, epochNo) getRetirePoolTxCert _ = Nothing lookupRegStakeTxCert = \case - RegTxCert c -> Just c RegDepositTxCert c _ -> Just c RegDepositDelegTxCert c _ _ -> Just c _ -> Nothing lookupUnRegStakeTxCert = \case - UnRegTxCert c -> Just c UnRegDepositTxCert c _ -> Just c _ -> Nothing @@ -71,65 +272,75 @@ instance EraTxCert DijkstraEra where getTotalDepositsTxCerts = conwayTotalDepositsTxCerts -instance ShelleyEraTxCert DijkstraEra where - mkRegTxCert c = ConwayTxCertDeleg $ ConwayRegCert c SNothing - - getRegTxCert (ConwayTxCertDeleg (ConwayRegCert c SNothing)) = Just c - getRegTxCert _ = Nothing - - mkUnRegTxCert c = ConwayTxCertDeleg $ ConwayUnRegCert c SNothing - - getUnRegTxCert (ConwayTxCertDeleg (ConwayUnRegCert c SNothing)) = Just c - getUnRegTxCert _ = Nothing - - mkDelegStakeTxCert c kh = ConwayTxCertDeleg $ ConwayDelegCert c (DelegStake kh) - - getDelegStakeTxCert (ConwayTxCertDeleg (ConwayDelegCert c (DelegStake kh))) = Just (c, kh) - getDelegStakeTxCert _ = Nothing - - mkGenesisDelegTxCert = notSupportedInThisEra - getGenesisDelegTxCert _ = Nothing - - mkMirTxCert = notSupportedInThisEra - getMirTxCert = const Nothing +getScriptWitnessDijkstraTxCert :: DijkstraTxCert era -> Maybe ScriptHash +getScriptWitnessDijkstraTxCert = \case + DijkstraTxCertDeleg delegCert -> + case delegCert of + DijkstraRegCert cred _ -> credScriptHash cred + DijkstraUnRegCert cred _ -> credScriptHash cred + DijkstraDelegCert cred _ -> credScriptHash cred + DijkstraRegDelegCert cred _ _ -> credScriptHash cred + DijkstraTxCertPool {} -> Nothing + DijkstraTxCertGov govCert -> govWitness govCert + where + govWitness :: ConwayGovCert -> Maybe ScriptHash + govWitness = \case + ConwayAuthCommitteeHotKey coldCred _hotCred -> credScriptHash coldCred + ConwayResignCommitteeColdKey coldCred _ -> credScriptHash coldCred + ConwayRegDRep cred _ _ -> credScriptHash cred + ConwayUnRegDRep cred _ -> credScriptHash cred + ConwayUpdateDRep cred _ -> credScriptHash cred + +getVKeyWitnessDijkstraTxCert :: DijkstraTxCert era -> Maybe (KeyHash 'Witness) +getVKeyWitnessDijkstraTxCert = \case + DijkstraTxCertDeleg delegCert -> + case delegCert of + DijkstraRegCert cred _ -> credKeyHashWitness cred + DijkstraUnRegCert cred _ -> credKeyHashWitness cred + DijkstraDelegCert cred _ -> credKeyHashWitness cred + DijkstraRegDelegCert cred _ _ -> credKeyHashWitness cred + DijkstraTxCertPool poolCert -> Just $ poolCertKeyHashWitness poolCert + DijkstraTxCertGov govCert -> conwayGovCertVKeyWitness govCert instance ConwayEraTxCert DijkstraEra where - mkRegDepositTxCert cred c = ConwayTxCertDeleg $ ConwayRegCert cred $ SJust c + mkRegDepositTxCert cred c = DijkstraTxCertDeleg $ DijkstraRegCert cred c - getRegDepositTxCert (ConwayTxCertDeleg (ConwayRegCert cred (SJust c))) = Just (cred, c) + getRegDepositTxCert (DijkstraTxCertDeleg (DijkstraRegCert cred c)) = Just (cred, c) getRegDepositTxCert _ = Nothing - mkUnRegDepositTxCert cred c = ConwayTxCertDeleg $ ConwayUnRegCert cred (SJust c) - getUnRegDepositTxCert (ConwayTxCertDeleg (ConwayUnRegCert cred (SJust c))) = Just (cred, c) + mkUnRegDepositTxCert cred c = DijkstraTxCertDeleg $ DijkstraUnRegCert cred c + + getUnRegDepositTxCert (DijkstraTxCertDeleg (DijkstraUnRegCert cred c)) = Just (cred, c) getUnRegDepositTxCert _ = Nothing - mkDelegTxCert cred d = ConwayTxCertDeleg $ ConwayDelegCert cred d - getDelegTxCert (ConwayTxCertDeleg (ConwayDelegCert cred d)) = Just (cred, d) + mkDelegTxCert cred d = DijkstraTxCertDeleg $ DijkstraDelegCert cred d + + getDelegTxCert (DijkstraTxCertDeleg (DijkstraDelegCert cred d)) = Just (cred, d) getDelegTxCert _ = Nothing - mkRegDepositDelegTxCert cred d c = ConwayTxCertDeleg $ ConwayRegDelegCert cred d c - getRegDepositDelegTxCert (ConwayTxCertDeleg (ConwayRegDelegCert cred d c)) = Just (cred, d, c) + mkRegDepositDelegTxCert cred d c = DijkstraTxCertDeleg $ DijkstraRegDelegCert cred d c + getRegDepositDelegTxCert (DijkstraTxCertDeleg (DijkstraRegDelegCert cred d c)) = Just (cred, d, c) getRegDepositDelegTxCert _ = Nothing - mkAuthCommitteeHotKeyTxCert ck hk = ConwayTxCertGov $ ConwayAuthCommitteeHotKey ck hk - getAuthCommitteeHotKeyTxCert (ConwayTxCertGov (ConwayAuthCommitteeHotKey ck hk)) = Just (ck, hk) + mkAuthCommitteeHotKeyTxCert ck hk = DijkstraTxCertGov $ ConwayAuthCommitteeHotKey ck hk + getAuthCommitteeHotKeyTxCert (DijkstraTxCertGov (ConwayAuthCommitteeHotKey ck hk)) = Just (ck, hk) getAuthCommitteeHotKeyTxCert _ = Nothing - mkResignCommitteeColdTxCert ck a = ConwayTxCertGov $ ConwayResignCommitteeColdKey ck a - getResignCommitteeColdTxCert (ConwayTxCertGov (ConwayResignCommitteeColdKey ck a)) = Just (ck, a) + mkResignCommitteeColdTxCert ck a = DijkstraTxCertGov $ ConwayResignCommitteeColdKey ck a + getResignCommitteeColdTxCert (DijkstraTxCertGov (ConwayResignCommitteeColdKey ck a)) = Just (ck, a) getResignCommitteeColdTxCert _ = Nothing - mkRegDRepTxCert cred deposit mAnchor = ConwayTxCertGov $ ConwayRegDRep cred deposit mAnchor + mkRegDRepTxCert cred deposit mAnchor = DijkstraTxCertGov $ ConwayRegDRep cred deposit mAnchor getRegDRepTxCert = \case - ConwayTxCertGov (ConwayRegDRep cred deposit mAnchor) -> Just (cred, deposit, mAnchor) + DijkstraTxCertGov (ConwayRegDRep cred deposit mAnchor) -> Just (cred, deposit, mAnchor) _ -> Nothing - mkUnRegDRepTxCert cred deposit = ConwayTxCertGov $ ConwayUnRegDRep cred deposit + mkUnRegDRepTxCert cred deposit = DijkstraTxCertGov $ ConwayUnRegDRep cred deposit getUnRegDRepTxCert = \case - ConwayTxCertGov (ConwayUnRegDRep cred deposit) -> Just (cred, deposit) + DijkstraTxCertGov (ConwayUnRegDRep cred deposit) -> Just (cred, deposit) _ -> Nothing - mkUpdateDRepTxCert cred mAnchor = ConwayTxCertGov $ ConwayUpdateDRep cred mAnchor + mkUpdateDRepTxCert cred mAnchor = DijkstraTxCertGov $ ConwayUpdateDRep cred mAnchor getUpdateDRepTxCert = \case - ConwayTxCertGov (ConwayUpdateDRep cred mAnchor) -> Just (cred, mAnchor) + DijkstraTxCertGov (ConwayUpdateDRep cred mAnchor) -> Just (cred, mAnchor) _ -> Nothing diff --git a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/TxInfo.hs b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/TxInfo.hs index 711dc265be3..40b2a49cd84 100644 --- a/eras/dijkstra/src/Cardano/Ledger/Dijkstra/TxInfo.hs +++ b/eras/dijkstra/src/Cardano/Ledger/Dijkstra/TxInfo.hs @@ -16,6 +16,7 @@ module Cardano.Ledger.Dijkstra.TxInfo ( transPlutusPurposeV3, ) where +import Cardano.Crypto.Hash.Class (hashToBytes) import Cardano.Ledger.Alonzo.Plutus.Context ( EraPlutusContext (..), EraPlutusTxInfo (..), @@ -31,12 +32,13 @@ import qualified Cardano.Ledger.Babbage.TxInfo as Babbage import Cardano.Ledger.BaseTypes (Inject (..), ProtVer (..), strictMaybe) import Cardano.Ledger.Coin (Coin (..)) import Cardano.Ledger.Conway.Scripts (ConwayPlutusPurpose (..)) +import Cardano.Ledger.Conway.TxCert (Delegatee (..)) import Cardano.Ledger.Conway.TxInfo (ConwayContextError (..), ConwayEraPlutusTxInfo (..)) import qualified Cardano.Ledger.Conway.TxInfo as Conway import Cardano.Ledger.Dijkstra.Core import Cardano.Ledger.Dijkstra.Era (DijkstraEra) import Cardano.Ledger.Dijkstra.Scripts (DijkstraPlutusPurpose (..), PlutusScript (..)) -import Cardano.Ledger.Dijkstra.TxCert () +import Cardano.Ledger.Dijkstra.TxCert (DijkstraTxCert) import Cardano.Ledger.Dijkstra.UTxO () import Cardano.Ledger.Plutus ( Language (..), @@ -45,10 +47,14 @@ import Cardano.Ledger.Plutus ( TxOutSource (..), transCoinToLovelace, transCoinToValue, + transCred, transDatum, + transEpochNo, + transKeyHash, ) import Cardano.Ledger.Plutus.Data (Data) import Cardano.Ledger.Plutus.ToPlutusData (ToPlutusData (..)) +import Cardano.Ledger.State (PoolParams (..)) import Control.Monad (zipWithM) import Data.Foldable (Foldable (..)) import qualified Data.Foldable as F @@ -135,7 +141,7 @@ transPlutusPurposeV3 pv = \case Left $ inject $ PlutusPurposeNotSupported @era . hoistPlutusPurpose @era toAsItem $ inject purpose instance EraPlutusTxInfo 'PlutusV1 DijkstraEra where - toPlutusTxCert _ _ = Conway.transTxCertV1V2 + toPlutusTxCert _ _ = transTxCertV1V2 toPlutusScriptPurpose proxy pv = transPlutusPurposeV1V2 proxy pv . hoistPlutusPurpose toAsItem @@ -169,8 +175,30 @@ instance EraPlutusTxInfo 'PlutusV1 DijkstraEra where toPlutusArgs = Alonzo.toPlutusV1Args +transTxCertV1V2 :: + ( ConwayEraTxCert era + , Inject (ConwayContextError era) (ContextError era) + ) => + TxCert era -> + Either (ContextError era) PV1.DCert +transTxCertV1V2 = \case + RegDepositTxCert stakeCred _deposit -> + Right $ PV1.DCertDelegRegKey (PV1.StakingHash (transCred stakeCred)) + UnRegDepositTxCert stakeCred _refund -> + Right $ PV1.DCertDelegDeRegKey (PV1.StakingHash (transCred stakeCred)) + DelegTxCert stakeCred (DelegStake keyHash) -> + Right $ PV1.DCertDelegDelegate (PV1.StakingHash (transCred stakeCred)) (transKeyHash keyHash) + RegPoolTxCert (PoolParams {ppId, ppVrf}) -> + Right $ + PV1.DCertPoolRegister + (transKeyHash ppId) + (PV1.PubKeyHash (PV1.toBuiltin (hashToBytes (unVRFVerKeyHash ppVrf)))) + RetirePoolTxCert poolId retireEpochNo -> + Right $ PV1.DCertPoolRetire (transKeyHash poolId) (transEpochNo retireEpochNo) + txCert -> Left $ inject $ CertificateNotSupported txCert + instance EraPlutusTxInfo 'PlutusV2 DijkstraEra where - toPlutusTxCert _ _ = Conway.transTxCertV1V2 + toPlutusTxCert _ _ = transTxCertV1V2 toPlutusScriptPurpose proxy pv = transPlutusPurposeV1V2 proxy pv . hoistPlutusPurpose toAsItem @@ -208,7 +236,7 @@ instance EraPlutusTxInfo 'PlutusV2 DijkstraEra where toPlutusArgs = Babbage.toPlutusV2Args instance EraPlutusTxInfo 'PlutusV3 DijkstraEra where - toPlutusTxCert _ pv = pure . Conway.transTxCert pv + toPlutusTxCert _ _ = pure . transTxCert toPlutusScriptPurpose _ = transPlutusPurposeV3 @@ -261,6 +289,40 @@ instance EraPlutusTxInfo 'PlutusV3 DijkstraEra where toPlutusArgs = Conway.toPlutusV3Args +transTxCert :: + (ConwayEraTxCert era, TxCert era ~ DijkstraTxCert era) => TxCert era -> PV3.TxCert +transTxCert = \case + RegPoolTxCert PoolParams {ppId, ppVrf} -> + PV3.TxCertPoolRegister + (transKeyHash ppId) + (PV3.PubKeyHash (PV3.toBuiltin (hashToBytes (unVRFVerKeyHash ppVrf)))) + RetirePoolTxCert poolId retireEpochNo -> + PV3.TxCertPoolRetire (transKeyHash poolId) (transEpochNo retireEpochNo) + RegDepositTxCert stakeCred deposit -> + PV3.TxCertRegStaking (transCred stakeCred) (Just $ transCoinToLovelace deposit) + UnRegDepositTxCert stakeCred refund -> + PV3.TxCertUnRegStaking (transCred stakeCred) (Just $ transCoinToLovelace refund) + DelegTxCert stakeCred delegatee -> + PV3.TxCertDelegStaking (transCred stakeCred) (Conway.transDelegatee delegatee) + RegDepositDelegTxCert stakeCred delegatee deposit -> + PV3.TxCertRegDeleg + (transCred stakeCred) + (Conway.transDelegatee delegatee) + (transCoinToLovelace deposit) + AuthCommitteeHotKeyTxCert coldCred hotCred -> + PV3.TxCertAuthHotCommittee + (Conway.transColdCommitteeCred coldCred) + (Conway.transHotCommitteeCred hotCred) + ResignCommitteeColdTxCert coldCred _anchor -> + PV3.TxCertResignColdCommittee (Conway.transColdCommitteeCred coldCred) + RegDRepTxCert drepCred deposit _anchor -> + PV3.TxCertRegDRep (Conway.transDRepCred drepCred) (transCoinToLovelace deposit) + UnRegDRepTxCert drepCred refund -> + PV3.TxCertUnRegDRep (Conway.transDRepCred drepCred) (transCoinToLovelace refund) + UpdateDRepTxCert drepCred _anchor -> + PV3.TxCertUpdateDRep (Conway.transDRepCred drepCred) + _ -> error "Impossible: All TxCerts should have been accounted for" + instance ConwayEraPlutusTxInfo 'PlutusV3 DijkstraEra where toPlutusChangedParameters _ x = PV3.ChangedParameters (PV3.dataToBuiltinData (toPlutusData x)) @@ -268,7 +330,7 @@ instance ConwayEraPlutusTxInfo 'PlutusV4 DijkstraEra where toPlutusChangedParameters _ x = PV3.ChangedParameters (PV3.dataToBuiltinData (toPlutusData x)) instance EraPlutusTxInfo 'PlutusV4 DijkstraEra where - toPlutusTxCert _ pv = pure . Conway.transTxCert pv + toPlutusTxCert _ _ = pure . transTxCert toPlutusScriptPurpose _ = error "stub: PlutusV4 not yet implemented" diff --git a/eras/dijkstra/test/Main.hs b/eras/dijkstra/test/Main.hs index 192f5213522..d887af81eed 100644 --- a/eras/dijkstra/test/Main.hs +++ b/eras/dijkstra/test/Main.hs @@ -5,17 +5,18 @@ module Main where import Cardano.Ledger.Dijkstra (DijkstraEra) import Cardano.Ledger.Dijkstra.Rules () import Test.Cardano.Ledger.Common -import qualified Test.Cardano.Ledger.Conway.Spec as ConwaySpec import Test.Cardano.Ledger.Dijkstra.Binary.Annotator () import Test.Cardano.Ledger.Dijkstra.Binary.RoundTrip () import qualified Test.Cardano.Ledger.Dijkstra.GoldenSpec as GoldenSpec +import qualified Test.Cardano.Ledger.Dijkstra.Imp as Imp import Test.Cardano.Ledger.Dijkstra.ImpTest () import Test.Cardano.Ledger.Shelley.JSON (roundTripJsonShelleyEraSpec) main :: IO () main = - ledgerTestMain $ do + ledgerTestMain $ describe "Dijkstra" $ do - ConwaySpec.spec @DijkstraEra - roundTripJsonShelleyEraSpec @DijkstraEra - GoldenSpec.spec + GoldenSpec.spec + roundTripJsonShelleyEraSpec @DijkstraEra + describe "Imp" $ do + Imp.spec @DijkstraEra diff --git a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs index da94dcc4123..57f1bc02ba4 100644 --- a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs +++ b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs @@ -11,16 +11,17 @@ module Test.Cardano.Ledger.Dijkstra.Arbitrary () where import Cardano.Ledger.BaseTypes (StrictMaybe) import Cardano.Ledger.Dijkstra (DijkstraEra) -import Cardano.Ledger.Dijkstra.Core (EraTx (..), EraTxBody (..)) +import Cardano.Ledger.Dijkstra.Core (Era, EraTx (..), EraTxBody (..)) import Cardano.Ledger.Dijkstra.Genesis (DijkstraGenesis (..)) import Cardano.Ledger.Dijkstra.PParams (DijkstraPParams, UpgradeDijkstraPParams) import Cardano.Ledger.Dijkstra.Scripts (DijkstraPlutusPurpose) import Cardano.Ledger.Dijkstra.Transition (TransitionConfig (..)) import Cardano.Ledger.Dijkstra.Tx (Tx (..)) import Cardano.Ledger.Dijkstra.TxBody (TxBody (..)) +import Cardano.Ledger.Dijkstra.TxCert import Data.Functor.Identity (Identity) import Generic.Random (genericArbitraryU) -import Test.Cardano.Ledger.Common (Arbitrary (..), scale) +import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Conway.Arbitrary () instance Arbitrary (DijkstraPParams Identity DijkstraEra) where @@ -68,3 +69,14 @@ instance arbitrary = genericArbitraryU deriving newtype instance Arbitrary (Tx DijkstraEra) + +instance Era era => Arbitrary (DijkstraTxCert era) where + arbitrary = + oneof + [ DijkstraTxCertDeleg <$> arbitrary + , DijkstraTxCertPool <$> arbitrary + , DijkstraTxCertGov <$> arbitrary + ] + +instance Arbitrary DijkstraDelegCert where + arbitrary = DijkstraRegDelegCert <$> arbitrary <*> arbitrary <*> arbitrary diff --git a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Era.hs b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Era.hs index fbf8349db37..25c81897757 100644 --- a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Era.hs +++ b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Era.hs @@ -1,7 +1,9 @@ +{-# LANGUAGE UndecidableSuperClasses #-} {-# OPTIONS_GHC -Wno-orphans #-} module Test.Cardano.Ledger.Dijkstra.Era ( module Test.Cardano.Ledger.Conway.Era, + DijkstraEraTest, ) where import Cardano.Ledger.Dijkstra (DijkstraEra) @@ -22,6 +24,10 @@ instance EraTest DijkstraEra where accountsToUMap = conwayAccountsToUMap +class + ConwayEraTest era => + DijkstraEraTest era + instance ShelleyEraTest DijkstraEra instance AllegraEraTest DijkstraEra @@ -33,3 +39,5 @@ instance AlonzoEraTest DijkstraEra instance BabbageEraTest DijkstraEra instance ConwayEraTest DijkstraEra + +instance DijkstraEraTest DijkstraEra diff --git a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Examples.hs b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Examples.hs index a423babfd91..4fe969d9063 100644 --- a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Examples.hs +++ b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Examples.hs @@ -19,6 +19,7 @@ import Cardano.Ledger.Conway.Rules (ConwayDELEG, ConwayDelegPredFailure (..), Co import Cardano.Ledger.Dijkstra (DijkstraEra) import Cardano.Ledger.Dijkstra.Scripts (DijkstraPlutusPurpose (..)) import Cardano.Ledger.Dijkstra.TxBody (TxBody (..)) +import Cardano.Ledger.Dijkstra.TxCert import Cardano.Ledger.Mary.Value (MaryValue (..)) import Cardano.Ledger.Plutus.Data ( Datum (..), @@ -44,7 +45,6 @@ import Test.Cardano.Ledger.Alonzo.Examples ( mkLedgerExamples, ) import Test.Cardano.Ledger.Babbage.Examples (exampleBabbageNewEpochState, exampleCollateralOutput) -import Test.Cardano.Ledger.Conway.Examples (exampleConwayCerts) import Test.Cardano.Ledger.Core.KeyPair (mkAddr) import Test.Cardano.Ledger.Core.Utils (mkDummySafeHash) import Test.Cardano.Ledger.Dijkstra.Era () @@ -53,6 +53,7 @@ import Test.Cardano.Ledger.Mary.Examples (exampleMultiAssetValue) import Test.Cardano.Ledger.Shelley.Examples ( LedgerExamples (..), examplePayKey, + examplePoolParams, exampleStakeKey, keyToCredential, mkKeyHash, @@ -91,7 +92,7 @@ exampleTxBodyDijkstra = ) (SJust $ mkSized (eraProtVerHigh @DijkstraEra) exampleCollateralOutput) -- collateral return (SJust $ Coin 8675309) -- collateral tot - exampleConwayCerts + exampleDijkstraCerts ( Withdrawals $ Map.singleton (RewardAccount Testnet (keyToCredential exampleStakeKey)) @@ -110,3 +111,9 @@ exampleTxBodyDijkstra = mempty where MaryValue _ exampleMultiAsset = exampleMultiAssetValue 3 + +exampleDijkstraCerts :: OSet.OSet (DijkstraTxCert era) +exampleDijkstraCerts = + OSet.fromList -- TODO should I add the new certs here? + [ DijkstraTxCertPool (RegPool examplePoolParams) + ] diff --git a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Imp.hs b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Imp.hs new file mode 100644 index 00000000000..96661f3b9c6 --- /dev/null +++ b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/Imp.hs @@ -0,0 +1,63 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeOperators #-} +{-# OPTIONS_GHC -Wno-orphans #-} + +module Test.Cardano.Ledger.Dijkstra.Imp where + +import Cardano.Ledger.Alonzo.Plutus.Context +import Cardano.Ledger.Alonzo.Rules +import Cardano.Ledger.Babbage.Rules +import Cardano.Ledger.Babbage.TxInfo +import Cardano.Ledger.BaseTypes +import Cardano.Ledger.Conway.Rules +import Cardano.Ledger.Conway.TxInfo +import Cardano.Ledger.Dijkstra (DijkstraEra) +import Cardano.Ledger.Dijkstra.Core +import Cardano.Ledger.Shelley.API +import Cardano.Ledger.Shelley.Rules +import Data.Typeable (Typeable) +import Test.Cardano.Ledger.Common +import qualified Test.Cardano.Ledger.Conway.Imp as ConwayImp +import Test.Cardano.Ledger.Dijkstra.ImpTest + +spec :: + forall era. + ( DijkstraEraImp era + , EraSpecificSpec era + , Inject (BabbageContextError era) (ContextError era) + , Inject (ConwayContextError era) (ContextError era) + , InjectRuleFailure "LEDGER" ConwayGovPredFailure era + , InjectRuleFailure "LEDGER" ConwayCertsPredFailure era + , InjectRuleFailure "LEDGER" BabbageUtxoPredFailure era + , InjectRuleFailure "LEDGER" BabbageUtxowPredFailure era + , InjectRuleFailure "LEDGER" AlonzoUtxoPredFailure era + , InjectRuleFailure "LEDGER" AlonzoUtxosPredFailure era + , InjectRuleFailure "LEDGER" AlonzoUtxowPredFailure era + , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era + , InjectRuleFailure "LEDGER" ShelleyUtxoPredFailure era + , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era + , InjectRuleFailure "LEDGER" ConwayDelegPredFailure era + , InjectRuleFailure "LEDGER" ConwayGovCertPredFailure era + , InjectRuleFailure "LEDGER" ConwayLedgerPredFailure era + , InjectRuleFailure "LEDGER" ConwayUtxoPredFailure era + , InjectRuleFailure "LEDGER" ConwayUtxowPredFailure era + , InjectRuleFailure "BBODY" ConwayBbodyPredFailure era + , InjectRuleEvent "TICK" ConwayEpochEvent era + , Event (EraRule "EPOCH" era) ~ ConwayEpochEvent era + , Event (EraRule "NEWEPOCH" era) ~ ConwayNewEpochEvent era + , Event (EraRule "HARDFORK" era) ~ ConwayHardForkEvent era + , ApplyTx era + , NFData (Event (EraRule "ENACT" era)) + , ToExpr (Event (EraRule "ENACT" era)) + , Eq (Event (EraRule "ENACT" era)) + , Typeable (Event (EraRule "ENACT" era)) + , ToExpr (Event (EraRule "BBODY" era)) + ) => + Spec +spec = ConwayImp.spec @era + +instance EraSpecificSpec DijkstraEra diff --git a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/ImpTest.hs b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/ImpTest.hs index d86d5b2c9e1..9142221bd38 100644 --- a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/ImpTest.hs +++ b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/ImpTest.hs @@ -3,11 +3,13 @@ {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableSuperClasses #-} {-# OPTIONS_GHC -Wno-orphans #-} module Test.Cardano.Ledger.Dijkstra.ImpTest ( module Test.Cardano.Ledger.Conway.ImpTest, exampleDijkstraGenesis, + DijkstraEraImp, ) where import Cardano.Ledger.BaseTypes ( @@ -34,7 +36,7 @@ import qualified Cardano.Ledger.Shelley.Rules as Shelley import Data.Maybe (fromJust) import Lens.Micro ((%~), (&)) import Test.Cardano.Ledger.Conway.ImpTest -import Test.Cardano.Ledger.Dijkstra.Era () +import Test.Cardano.Ledger.Dijkstra.Era instance ShelleyEraImp DijkstraEra where initGenesis = pure exampleDijkstraGenesis @@ -64,6 +66,14 @@ instance AlonzoEraImp DijkstraEra where instance ConwayEraImp DijkstraEra +class + ( ConwayEraImp era + , DijkstraEraTest era + ) => + DijkstraEraImp era + +instance DijkstraEraImp DijkstraEra + -- Partial implementation used for checking predicate failures instance InjectRuleFailure "LEDGER" ShelleyDelegPredFailure DijkstraEra where injectFailure = ConwayCertsFailure . injectFailure diff --git a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs index 6d00ec395de..b205ec937a3 100644 --- a/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs +++ b/eras/dijkstra/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs @@ -14,6 +14,7 @@ import Cardano.Ledger.Dijkstra.Core (EraTx (..), EraTxBody (..), PlutusScript) import Cardano.Ledger.Dijkstra.PParams (DijkstraPParams) import Cardano.Ledger.Dijkstra.Scripts (DijkstraPlutusPurpose) import Cardano.Ledger.Dijkstra.TxBody (DijkstraTxBodyRaw) +import Cardano.Ledger.Dijkstra.TxCert import Data.Functor.Identity (Identity) import Test.Cardano.Ledger.Conway.TreeDiff (ToExpr) @@ -32,3 +33,7 @@ instance ToExpr DijkstraTxBodyRaw instance ToExpr (TxBody DijkstraEra) instance ToExpr (Tx DijkstraEra) + +instance ToExpr DijkstraDelegCert + +instance ToExpr (DijkstraTxCert era) diff --git a/eras/mary/impl/CHANGELOG.md b/eras/mary/impl/CHANGELOG.md index 9db0ce5471d..2eb4ebf951f 100644 --- a/eras/mary/impl/CHANGELOG.md +++ b/eras/mary/impl/CHANGELOG.md @@ -13,6 +13,7 @@ ### `testlib` +* Added `EraSpecificSpec MaryEra` instance * Added `Examples` module with: `ledgerExamples`, `exampleMultiAssetValue` * Added `Arbitrary` instance for `TransitionConfig MaryEra` * Added `Era` module with `MaryEraTest` class diff --git a/eras/mary/impl/testlib/Test/Cardano/Ledger/Mary/Imp.hs b/eras/mary/impl/testlib/Test/Cardano/Ledger/Mary/Imp.hs index 67db4a9e6fe..ca1e0a4aa84 100644 --- a/eras/mary/impl/testlib/Test/Cardano/Ledger/Mary/Imp.hs +++ b/eras/mary/impl/testlib/Test/Cardano/Ledger/Mary/Imp.hs @@ -4,9 +4,11 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} +{-# OPTIONS_GHC -Wno-orphans #-} module Test.Cardano.Ledger.Mary.Imp (spec) where +import Cardano.Ledger.Mary (MaryEra) import Cardano.Ledger.Mary.Core import Cardano.Ledger.Shelley.Rules ( ShelleyPoolPredFailure, @@ -17,10 +19,12 @@ import qualified Test.Cardano.Ledger.Allegra.Imp as AllegraImp import Test.Cardano.Ledger.Imp.Common import qualified Test.Cardano.Ledger.Mary.Imp.UtxoSpec as Utxo import Test.Cardano.Ledger.Mary.ImpTest +import qualified Test.Cardano.Ledger.Shelley.Imp as ShelleyImp spec :: forall era. ( MaryEraImp era + , EraSpecificSpec era , InjectRuleFailure "LEDGER" ShelleyUtxoPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era @@ -31,3 +35,6 @@ spec = do describe "MaryImpSpec" $ withEachEraVersion @era $ Utxo.spec + +instance EraSpecificSpec MaryEra where + eraSpecificSpec = ShelleyImp.shelleyEraSpecificSpec diff --git a/eras/shelley/impl/CHANGELOG.md b/eras/shelley/impl/CHANGELOG.md index d5b5baf7caa..2334fcdcf28 100644 --- a/eras/shelley/impl/CHANGELOG.md +++ b/eras/shelley/impl/CHANGELOG.md @@ -91,6 +91,13 @@ ### `testlib` +* Added `EraSpecificSpec ShelleyEra` instance +* Added `EraSpecificSpec` class +* Removed `ShelleyEraTxCert` from `ShelleyEraImp`, so added `ShelleyEraTxCert` constraint to: + * `registerStakeCredential` + * `delegateStake` + * `registerRewardAccount` + * `registerPool` * Added `withEachEraVersion` * Added `Examples` module with: `LedgerExamples`, `ledgerExamples`, `mkLedgerExamples`, `exampleCerts`,`exampleWithdrawals`, `exampleAuxDataMap`, `exampleNonMyopicRewards`, `exampleCoin`, `examplePayKey`, `exampleStakeKey`, `exampleNewEpochState`, `examplePoolDistr`, `examplePoolParams`, `exampleTxIns`, `exampleProposedPPUpdates`, `exampleByronAddress`, `testShelleyGenesis`, `keyToCredential`, `mkDSIGNKeyPair`, `mkKeyHash`, `mkScriptHash`, `mkWitnessesPreAlonzo`, `seedFromByte`, `seedFromWords` * Add `nativeAlwaysFails`, `nativeAlwaysSucceeds` diff --git a/eras/shelley/impl/src/Cardano/Ledger/Shelley/Rules/Pool.hs b/eras/shelley/impl/src/Cardano/Ledger/Shelley/Rules/Pool.hs index 4c7175f20d6..5d362c6a8c4 100644 --- a/eras/shelley/impl/src/Cardano/Ledger/Shelley/Rules/Pool.hs +++ b/eras/shelley/impl/src/Cardano/Ledger/Shelley/Rules/Pool.hs @@ -124,7 +124,7 @@ instance NoThunks (ShelleyPoolPredFailure era) instance NFData (ShelleyPoolPredFailure era) -instance (ShelleyEraTxCert era, EraPParams era) => STS (ShelleyPOOL era) where +instance EraPParams era => STS (ShelleyPOOL era) where type State (ShelleyPOOL era) = PState era type Signal (ShelleyPOOL era) = PoolCert diff --git a/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/Imp.hs b/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/Imp.hs index dd7406e0430..db0361cc03f 100644 --- a/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/Imp.hs +++ b/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/Imp.hs @@ -3,15 +3,18 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} +{-# OPTIONS_GHC -Wno-orphans #-} -module Test.Cardano.Ledger.Shelley.Imp (spec) where +module Test.Cardano.Ledger.Shelley.Imp (spec, shelleyEraSpecificSpec) where import Cardano.Ledger.Core +import Cardano.Ledger.Shelley (ShelleyEra) import Cardano.Ledger.Shelley.Rules ( ShelleyPoolPredFailure, ShelleyUtxoPredFailure, ShelleyUtxowPredFailure, ) +import Cardano.Ledger.Shelley.TxCert (ShelleyEraTxCert) import Test.Cardano.Ledger.Imp.Common import qualified Test.Cardano.Ledger.Shelley.Imp.EpochSpec as Epoch import qualified Test.Cardano.Ledger.Shelley.Imp.LedgerSpec as Ledger @@ -24,12 +27,14 @@ import qualified Test.Cardano.Ledger.Shelley.UnitTests.InstantStakeTest as Insta spec :: forall era. ( ShelleyEraImp era + , EraSpecificSpec era , InjectRuleFailure "LEDGER" ShelleyUtxoPredFailure era , InjectRuleFailure "LEDGER" ShelleyUtxowPredFailure era , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era ) => Spec spec = do + describe "Era specific tests" . withEachEraVersion @era $ eraSpecificSpec describe "ShelleyImpSpec" $ withEachEraVersion @era $ do Epoch.spec Ledger.spec @@ -38,3 +43,17 @@ spec = do Utxo.spec describe "ShelleyPureTests" $ do Instant.spec @era + +shelleyEraSpecificSpec :: + ( ShelleyEraImp era + , ShelleyEraTxCert era + , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era + ) => + SpecWith (ImpInit (LedgerSpec era)) +shelleyEraSpecificSpec = do + describe "Shelley era specific Imp spec" $ + describe "Certificates without deposits" $ do + describe "POOL" Pool.shelleyEraSpecificSpec + +instance EraSpecificSpec ShelleyEra where + eraSpecificSpec = shelleyEraSpecificSpec diff --git a/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/Imp/PoolSpec.hs b/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/Imp/PoolSpec.hs index bbd985d6c5b..6420baf48fd 100644 --- a/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/Imp/PoolSpec.hs +++ b/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/Imp/PoolSpec.hs @@ -5,7 +5,7 @@ {-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} -module Test.Cardano.Ledger.Shelley.Imp.PoolSpec (spec) where +module Test.Cardano.Ledger.Shelley.Imp.PoolSpec (spec, shelleyEraSpecificSpec) where import Cardano.Crypto.Hash.Class (sizeHash) import Cardano.Ledger.Address (RewardAccount (..)) @@ -15,7 +15,8 @@ import Cardano.Ledger.Core import Cardano.Ledger.Credential (Credential (..)) import Cardano.Ledger.Shelley.LedgerState import Cardano.Ledger.Shelley.Rules (ShelleyPoolPredFailure (..)) -import Cardano.Ledger.State (PoolMetadata (..), ppCostL, ppMetadataL, ppVrfL, spsVrf) +import Cardano.Ledger.Shelley.TxCert (ShelleyEraTxCert) +import Cardano.Ledger.State (PoolMetadata (..), PoolParams, ppCostL, ppMetadataL, ppVrfL, spsVrf) import qualified Data.Map.Strict as Map import Data.Proxy import Lens.Micro @@ -31,16 +32,6 @@ spec :: SpecWith (ImpInit (LedgerSpec era)) spec = describe "POOL" $ do describe "Register and re-register pools" $ do - it "register a pool with too low cost" $ do - (kh, vrf) <- (,) <$> freshKeyHash <*> freshKeyHashVRF - minPoolCost <- getsPParams ppMinPoolCostL - tooLowCost <- Coin <$> choose (0, unCoin minPoolCost) - let pps = (\p -> p & ppCostL .~ tooLowCost) <$> poolParams kh vrf - registerPoolTx <$> pps >>= \tx -> - submitFailingTx - tx - [injectFailure $ StakePoolCostTooLowPOOL $ Mismatch tooLowCost minPoolCost] - it "register a pool with a reward account having the wrong network id" $ do pv <- getsPParams ppProtocolVersionL rewardCredential <- KeyHashObj <$> freshKeyHash @@ -58,6 +49,31 @@ spec = describe "POOL" $ do else submitFailingTx tx [injectFailure $ WrongNetworkPOOL (Mismatch Mainnet Testnet) kh] + describe "Retiring pools" $ do + it "retire an unregistered pool" $ do + khNew <- freshKeyHash + retirePoolTx khNew (EpochInterval 10) >>= \tx -> + submitFailingTx tx [injectFailure $ StakePoolNotRegisteredOnKeyPOOL khNew] + +shelleyEraSpecificSpec :: + forall era. + ( ShelleyEraImp era + , ShelleyEraTxCert era + , InjectRuleFailure "LEDGER" ShelleyPoolPredFailure era + ) => + SpecWith (ImpInit (LedgerSpec era)) +shelleyEraSpecificSpec = describe "POOL" $ do + describe "Register and re-register pools" $ do + it "register a pool with too low cost" $ do + (kh, vrf) <- (,) <$> freshKeyHash <*> freshKeyHashVRF + minPoolCost <- getsPParams ppMinPoolCostL + tooLowCost <- Coin <$> choose (0, unCoin minPoolCost) + let pps = (\p -> p & ppCostL .~ tooLowCost) <$> poolParams kh vrf + registerPoolTx <$> pps >>= \tx -> + submitFailingTx + tx + [injectFailure $ StakePoolCostTooLowPOOL $ Mismatch tooLowCost minPoolCost] + it "register a pool with too big metadata" $ do pv <- getsPParams ppProtocolVersionL let maxMetadataSize = sizeHash (Proxy :: Proxy HASH) @@ -197,11 +213,6 @@ spec = describe "POOL" $ do submitFailingTx tx [injectFailure $ VRFKeyHashAlreadyRegistered khNew vrf] describe "Retiring pools" $ do - it "retire an unregistered pool" $ do - khNew <- freshKeyHash - retirePoolTx khNew (EpochInterval 10) >>= \tx -> - submitFailingTx tx [injectFailure $ StakePoolNotRegisteredOnKeyPOOL khNew] - it "retire a pool with too high a retirement epoch" $ do (kh, _) <- registerNewPool maxRetireInterval <- getsPParams ppEMaxL @@ -322,15 +333,6 @@ spec = describe "POOL" $ do registerPoolTx <$> poolParams kh vrf >>= submitTx_ expectPool kh (Just vrf) pure (kh, vrf) - registerPoolTx pps = - mkBasicTx mkBasicTxBody - & bodyTxL . certsTxBodyL .~ [RegPoolTxCert pps] - retirePoolTx kh retirementInterval = do - curEpochNo <- getsNES nesELL - let retirement = addEpochInterval curEpochNo retirementInterval - pure $ - mkBasicTx mkBasicTxBody - & bodyTxL . certsTxBodyL .~ [RetirePoolTxCert kh retirement] expectPool poolKh mbVrf = do pps <- psStakePools <$> getPState spsVrf <$> Map.lookup poolKh pps `shouldBe` mbVrf @@ -349,3 +351,17 @@ spec = describe "POOL" $ do pps <- registerRewardAccount >>= freshPoolParams kh pure $ pps & ppVrfL .~ vrf getPState = getsNES @era $ nesEsL . esLStateL . lsCertStateL . certPStateL + +registerPoolTx :: ShelleyEraImp era => PoolParams -> Tx era +registerPoolTx pps = + mkBasicTx mkBasicTxBody + & bodyTxL . certsTxBodyL .~ [RegPoolTxCert pps] + +retirePoolTx :: + ShelleyEraImp era => KeyHash 'StakePool -> EpochInterval -> ImpM (LedgerSpec era) (Tx era) +retirePoolTx kh retirementInterval = do + curEpochNo <- getsNES nesELL + let retirement = addEpochInterval curEpochNo retirementInterval + pure $ + mkBasicTx mkBasicTxBody + & bodyTxL . certsTxBodyL .~ [RetirePoolTxCert kh retirement] diff --git a/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/ImpTest.hs b/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/ImpTest.hs index 7ae5f08b7c0..4aa7a35ef81 100644 --- a/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/ImpTest.hs +++ b/eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/ImpTest.hs @@ -24,6 +24,7 @@ module Test.Cardano.Ledger.Shelley.ImpTest ( ImpTestM, LedgerSpec, + EraSpecificSpec (..), SomeSTSEvent (..), ImpTestState, ImpTestEnv (..), @@ -299,6 +300,10 @@ instance ShelleyEraImp era => ImpSpec (LedgerSpec era) where -- number of the current era impPrepAction = passTick +class EraTest era => EraSpecificSpec era where + eraSpecificSpec :: SpecWith (ImpInit (LedgerSpec era)) + eraSpecificSpec = pure () + data SomeSTSEvent era = forall (rule :: Symbol). ( Typeable (Event (EraRule rule era)) @@ -390,8 +395,7 @@ impEventsL :: Lens' (ImpTestState era) [SomeSTSEvent era] impEventsL = lens impEvents (\x y -> x {impEvents = y}) class - ( ShelleyEraTxCert era - , ShelleyEraTest era + ( ShelleyEraTest era , -- For BBODY rule STS (EraRule "BBODY" era) , BaseM (EraRule "BBODY" era) ~ ShelleyBase @@ -1466,6 +1470,7 @@ registerStakeCredential :: forall era. ( HasCallStack , ShelleyEraImp era + , ShelleyEraTxCert era ) => Credential 'Staking -> ImpTestM era RewardAccount @@ -1478,7 +1483,9 @@ registerStakeCredential cred = do pure $ RewardAccount networkId cred delegateStake :: - ShelleyEraImp era => + ( ShelleyEraImp era + , ShelleyEraTxCert era + ) => Credential 'Staking -> KeyHash 'StakePool -> ImpTestM era () @@ -1493,6 +1500,7 @@ registerRewardAccount :: forall era. ( HasCallStack , ShelleyEraImp era + , ShelleyEraTxCert era ) => ImpTestM era RewardAccount registerRewardAccount = do @@ -1532,7 +1540,9 @@ freshPoolParams khPool rewardAccount = do } registerPool :: - ShelleyEraImp era => + ( ShelleyEraImp era + , ShelleyEraTxCert era + ) => KeyHash 'StakePool -> ImpTestM era () registerPool khPool = registerRewardAccount >>= registerPoolWithRewardAccount khPool diff --git a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rules/Pool.hs b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rules/Pool.hs index f83f9b05edc..388370bdf57 100644 --- a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rules/Pool.hs +++ b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rules/Pool.hs @@ -13,7 +13,6 @@ module Test.Cardano.Ledger.Shelley.Rules.Pool ( import Cardano.Ledger.BaseTypes (EpochInterval (..)) import Cardano.Ledger.Block (bheader) import Cardano.Ledger.Core -import Cardano.Ledger.Shelley.Core import Cardano.Ledger.Shelley.LedgerState ( NewEpochState (..), curPParamsEpochStateL, @@ -82,9 +81,7 @@ tests = -- | Check that a `RetirePool` certificate properly marks a stake pool for -- retirement. poolRetirement :: - ( ChainProperty era - , ShelleyEraTxBody era - ) => + ChainProperty era => SourceSignalTarget (CHAIN era) -> Property poolRetirement SourceSignalTarget {source = chainSt, signal = block} = @@ -99,9 +96,7 @@ poolRetirement SourceSignalTarget {source = chainSt, signal = block} = -- | Check that a newly registered pool key is registered and not -- in the retiring map. poolRegistration :: - ( ChainProperty era - , ShelleyEraTxBody era - ) => + ChainProperty era => SourceSignalTarget (CHAIN era) -> Property poolRegistration (SourceSignalTarget {source = chainSt, signal = block}) = @@ -113,9 +108,7 @@ poolRegistration (SourceSignalTarget {source = chainSt, signal = block}) = -- | Assert that PState maps are in sync with each other after each `Signal -- POOL` transition. poolStateIsInternallyConsistent :: - ( ChainProperty era - , ShelleyEraTxBody era - ) => + ChainProperty era => SourceSignalTarget (CHAIN era) -> Property poolStateIsInternallyConsistent (SourceSignalTarget {source = chainSt, signal = block}) = diff --git a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rules/TestChain.hs b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rules/TestChain.hs index 5addda6fcbd..fe6e9465967 100644 --- a/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rules/TestChain.hs +++ b/eras/shelley/test-suite/src/Test/Cardano/Ledger/Shelley/Rules/TestChain.hs @@ -188,9 +188,7 @@ ledgerTraceFromBlockWithRestrictedUTxO chainSt block = -- | Reconstruct a POOL trace from the transactions in a Block and ChainState poolTraceFromBlock :: forall era. - ( ChainProperty era - , ShelleyEraTxBody era - ) => + ChainProperty era => ChainState era -> Block (BHeader MockCrypto) era -> (ChainState era, Trace (ShelleyPOOL era)) diff --git a/libs/cardano-ledger-api/src/Cardano/Ledger/Api/Era.hs b/libs/cardano-ledger-api/src/Cardano/Ledger/Api/Era.hs index a954d721a4b..202f335a1f4 100644 --- a/libs/cardano-ledger-api/src/Cardano/Ledger/Api/Era.hs +++ b/libs/cardano-ledger-api/src/Cardano/Ledger/Api/Era.hs @@ -88,6 +88,7 @@ import Cardano.Ledger.Credential (Credential (..)) import Cardano.Ledger.Dijkstra (DijkstraEra) import Cardano.Ledger.Dijkstra.Tx (Tx (..)) import Cardano.Ledger.Dijkstra.TxBody (TxBody (..), upgradeProposals) +import Cardano.Ledger.Dijkstra.TxCert (DijkstraTxCertUpgradeError) import Cardano.Ledger.Keys (HasKeyRole (..)) import Cardano.Ledger.Mary (MaryEra, TxBody (..)) import Cardano.Ledger.Mary.TxBody (MaryEraTxBody (..)) @@ -558,8 +559,12 @@ instance EraApi ConwayEra where , txrdmrs = upgradeRedeemers (txrdmrs atw) } +newtype DijkstraTxBodyUpgradeError = DTBUETxCert DijkstraTxCertUpgradeError + deriving (Eq, Show) + instance EraApi DijkstraEra where type TxUpgradeError DijkstraEra = TxBodyUpgradeError DijkstraEra + type TxBodyUpgradeError DijkstraEra = DijkstraTxBodyUpgradeError upgradeTx (MkConwayTx (AlonzoTx b w valid aux)) = fmap MkDijkstraTx $ AlonzoTx @@ -569,11 +574,12 @@ instance EraApi DijkstraEra where <*> pure (fmap upgradeTxAuxData aux) upgradeTxBody ConwayTxBody {..} = do + certs <- traverse (left DTBUETxCert . upgradeTxCert) $ OSet.toStrictSeq ctbCerts pure $ DijkstraTxBody { dtbSpendInputs = ctbSpendInputs , dtbOutputs = unsafeMapSized upgradeTxOut <$> ctbOutputs - , dtbCerts = OSet.mapL coerce ctbCerts + , dtbCerts = OSet.fromStrictSeq certs , dtbWithdrawals = ctbWithdrawals , dtbTxfee = ctbTxfee , dtbVldt = ctbVldt diff --git a/libs/cardano-ledger-api/test/Test/Cardano/Ledger/Api/State/Imp/QuerySpec.hs b/libs/cardano-ledger-api/test/Test/Cardano/Ledger/Api/State/Imp/QuerySpec.hs index 4d5f3eebdb2..80eb431ef2e 100644 --- a/libs/cardano-ledger-api/test/Test/Cardano/Ledger/Api/State/Imp/QuerySpec.hs +++ b/libs/cardano-ledger-api/test/Test/Cardano/Ledger/Api/State/Imp/QuerySpec.hs @@ -204,12 +204,12 @@ spec = do kh <- freshKeyHash let cred = KeyHashObj kh - _ <- registerStakeCredential cred + _ <- registerStakeCredentialWithDeposit cred _ <- delegateToDRep cred (Coin 2_000_000) DRepAlwaysAbstain kh2 <- freshKeyHash let cred2 = KeyHashObj kh2 - _ <- registerStakeCredential cred2 + _ <- registerStakeCredentialWithDeposit cred2 _ <- delegateToDRep cred2 (Coin 3_000_000) DRepAlwaysNoConfidence let realDRepCred = DRepCredential credDrep