2
2
{-# LANGUAGE DataKinds #-}
3
3
{-# LANGUAGE FlexibleContexts #-}
4
4
{-# LANGUAGE GADTs #-}
5
+ {-# LANGUAGE NamedFieldPuns #-}
5
6
{-# LANGUAGE OverloadedLists #-}
6
7
{-# LANGUAGE OverloadedStrings #-}
7
8
{-# LANGUAGE RankNTypes #-}
11
12
module Test.Cardano.Ledger.Alonzo.Imp.UtxosSpec (spec ) where
12
13
13
14
import Cardano.Ledger.Alonzo.Core
14
- import Cardano.Ledger.Alonzo.Plutus.Evaluate (CollectError (NoCostModel ))
15
+ import Cardano.Ledger.Alonzo.Plutus.Evaluate (
16
+ CollectError (NoCostModel ),
17
+ TransactionScriptFailure (RedeemerPointsToUnknownScriptHash ),
18
+ evalTxExUnits ,
19
+ )
15
20
import Cardano.Ledger.Alonzo.Rules (
16
21
AlonzoUtxosPredFailure (.. ),
17
22
TagMismatchDescription (.. ),
18
23
)
19
- import Cardano.Ledger.Alonzo.Scripts (eraLanguages )
24
+ import Cardano.Ledger.Alonzo.Scripts (ExUnits ( .. ), eraLanguages )
20
25
import Cardano.Ledger.Alonzo.TxWits (unRedeemersL )
26
+ import Cardano.Ledger.BaseTypes (Globals (.. ), StrictMaybe (.. ))
21
27
import Cardano.Ledger.Plutus.Data (Data (.. ))
22
28
import Cardano.Ledger.Plutus.Language (hashPlutusScript , withSLanguage )
23
29
import Cardano.Ledger.Shelley.LedgerState (curPParamsEpochStateL , nesEsL )
30
+ import Control.Monad.Reader (asks )
31
+ import Data.Either (isLeft )
32
+ import qualified Data.Map.Merge.Strict as Map
24
33
import qualified Data.Map.Strict as Map
25
34
import qualified Data.Set as Set
26
- import Lens.Micro ((&) , (.~) , (<>~) )
35
+ import Lens.Micro (set , (%~) , (&) , (.~) , (<>~) , (^.) , _2 )
36
+ import Lens.Micro.Mtl (use )
27
37
import qualified PlutusLedgerApi.Common as P
38
+ import qualified PlutusLedgerApi.V1 as PV1
28
39
import Test.Cardano.Ledger.Alonzo.ImpTest
29
40
import Test.Cardano.Ledger.Imp.Common
30
41
import Test.Cardano.Ledger.Plutus.Examples (
@@ -44,8 +55,8 @@ spec ::
44
55
SpecWith (ImpInit (LedgerSpec era ))
45
56
spec = describe " UTXOS" $
46
57
forM_ (eraLanguages @ era ) $ \ lang ->
47
- withSLanguage lang $ \ slang ->
48
- describe ( show lang) $ do
58
+ describe ( show lang) $
59
+ withSLanguage lang $ \ slang -> do
49
60
let redeemerSameAsDatumHash = hashPlutusScript $ redeemerSameAsDatum slang
50
61
alwaysSucceedsWithDatumHash = hashPlutusScript $ alwaysSucceedsWithDatum slang
51
62
@@ -56,6 +67,57 @@ spec = describe "UTXOS" $
56
67
, (" inputsOutputsAreNotEmptyWithDatum" , inputsOutputsAreNotEmptyWithDatum)
57
68
]
58
69
70
+ describe " ExUnits" $ do
71
+ it " Calculate ExUnits" $ do
72
+ let
73
+ overrideExUnits tx = do
74
+ pp <- getsNES $ nesEsL . curPParamsEpochStateL
75
+ utxo <- getUTxO
76
+ Globals {epochInfo, systemStart} <- use impGlobalsL
77
+ purposeUnits <-
78
+ either (fail . show ) pure . sequence $
79
+ evalTxExUnits pp tx utxo epochInfo systemStart
80
+ pure $ tx & witsTxL . rdmrsTxWitsL . unRedeemersL %~ spliceUnits purposeUnits
81
+ spliceUnits =
82
+ Map. merge
83
+ Map. dropMissing -- Ignore purposes not already in the redeemers
84
+ Map. preserveMissing -- Don't touch purposes not being updated
85
+ (Map. zipWithMatched $ \ _ -> set _2) -- Replace the units, keep the datum
86
+ redoAddrWits = updateAddrTxWits . (witsTxL . addrTxWitsL .~ mempty )
87
+
88
+ txIn <- produceScript alwaysSucceedsWithDatumHash
89
+ withPostFixup (overrideExUnits >=> fixupPPHash >=> redoAddrWits) $
90
+ submitTx_ $
91
+ mkBasicTx mkBasicTxBody & bodyTxL . inputsTxBodyL .~ [txIn]
92
+
93
+ it " Attempt to calculate ExUnits with an invalid tx" $ do
94
+ txIn <- produceScript alwaysSucceedsWithDatumHash
95
+ let tx = mkBasicTx mkBasicTxBody & bodyTxL . inputsTxBodyL .~ [txIn]
96
+
97
+ txFixed <- (tx & ) =<< asks iteFixup
98
+ logToExpr txFixed
99
+
100
+ let
101
+ twiddleIx (SJust (SpendingPurpose (AsIx 0 ))) = SpendingPurpose (AsIx 1 )
102
+ twiddleIx _ = SpendingPurpose (AsIx 0 )
103
+ badPurpose =
104
+ twiddleIx $
105
+ redeemerPointer (txFixed ^. bodyTxL) (SpendingPurpose $ AsItem txIn)
106
+ du = (Data $ PV1. I 42 , ExUnits 5000 5000 )
107
+ txBorked =
108
+ txFixed
109
+ & witsTxL . rdmrsTxWitsL . unRedeemersL %~ Map. insert badPurpose du
110
+ logToExpr txBorked
111
+
112
+ pp <- getsNES $ nesEsL . curPParamsEpochStateL
113
+ utxo <- getUTxO
114
+ Globals {epochInfo, systemStart} <- use impGlobalsL
115
+ let report = evalTxExUnits pp txBorked utxo epochInfo systemStart
116
+ logToExpr report
117
+
118
+ Map. filter isLeft report
119
+ `shouldBe` Map. singleton badPurpose (Left (RedeemerPointsToUnknownScriptHash badPurpose))
120
+
59
121
describe " Spending scripts with a Datum" $ do
60
122
forM_ scripts $ \ (name, script) -> do
61
123
it name $ do
0 commit comments