1
1
{-# LANGUAGE GADTs #-}
2
+ {-# LANGUAGE NamedFieldPuns #-}
2
3
{-# LANGUAGE RankNTypes #-}
3
4
{-# LANGUAGE ScopedTypeVariables #-}
4
5
5
6
-- | This module provides convenience functions when dealing with Plutus scripts.
6
- -- It currently only supports PlutusV1 script & cost model.
7
7
module Cardano.TxGenerator.Setup.Plutus
8
8
( readPlutusScript
9
9
, preExecutePlutusScript
10
10
)
11
11
where
12
- import Control.Monad.Writer (runWriter )
13
12
14
- import Data.Map.Strict (Map )
15
- import qualified Data.Map.Strict as Map
16
- import Data.Text (Text )
13
+ import Data.Bifunctor (bimap )
14
+ import Data.Map.Strict as Map (lookup , toAscList )
17
15
18
16
import Control.Monad.Trans.Except
19
17
import Control.Monad.Trans.Except.Extra
18
+ import Control.Monad.Writer (runWriter )
20
19
21
20
import Cardano.CLI.Shelley.Run.Read (readFileScriptInAnyLang )
22
21
@@ -31,6 +30,9 @@ import qualified PlutusLedgerApi.V2 as PlutusV2
31
30
import Cardano.TxGenerator.Types
32
31
33
32
33
+ type ProtocolVersion = (Int , Int )
34
+
35
+
34
36
readPlutusScript :: FilePath -> IO (Either TxGenError ScriptInAnyLang )
35
37
readPlutusScript fp
36
38
= runExceptT $ do
@@ -46,37 +48,46 @@ preExecutePlutusScript ::
46
48
-> ScriptData
47
49
-> ScriptRedeemer
48
50
-> Either TxGenError ExecutionUnits
49
- preExecutePlutusScript protocolParameters script@ (ScriptInAnyLang scriptLang _) datum redeemer
51
+ preExecutePlutusScript
52
+ ProtocolParameters {protocolParamCostModels, protocolParamProtocolVersion}
53
+ script@ (ScriptInAnyLang scriptLang _)
54
+ datum
55
+ redeemer
50
56
= runExcept $ do
57
+ costModel <- hoistMaybe (TxGenError $ " preExecutePlutusScript: cost model unavailable for: " ++ show scriptLang) $
58
+ case script of
59
+ ScriptInAnyLang _ (PlutusScript lang _) ->
60
+ AnyPlutusScriptVersion lang `Map.lookup` protocolParamCostModels
61
+ _ ->
62
+ Nothing
63
+
51
64
case script of
52
65
ScriptInAnyLang (PlutusScriptLanguage PlutusScriptV1 ) script' ->
53
- hoistEither $ preExecutePlutusV1 protocolParameters script' datum redeemer
66
+ hoistEither $ preExecutePlutusV1 protocolVersion script' datum redeemer costModel
54
67
ScriptInAnyLang (PlutusScriptLanguage PlutusScriptV2 ) script' ->
55
- hoistEither $ preExecutePlutusV2 protocolParameters script' datum redeemer
68
+ hoistEither $ preExecutePlutusV2 protocolVersion script' datum redeemer costModel
56
69
_ ->
57
70
throwE $ TxGenError $ " preExecutePlutusScript: script not supported: " ++ show scriptLang
71
+ where
72
+ protocolVersion :: ProtocolVersion
73
+ protocolVersion = bimap fromIntegral fromIntegral protocolParamProtocolVersion
58
74
59
75
preExecutePlutusV1 ::
60
- ProtocolParameters
76
+ ProtocolVersion
61
77
-> Script PlutusScriptV1
62
78
-> ScriptData
63
79
-> ScriptRedeemer
80
+ -> CostModel
64
81
-> Either TxGenError ExecutionUnits
65
- preExecutePlutusV1 protocolParameters (PlutusScript _ (PlutusScriptSerialised script)) datum redeemer
66
- = fst $ -- for now, we discard warnings (:: PlutusCore.Evaluation.Machine.CostModelInterface.CostModelApplyWarn)
67
- runWriter $ runExceptT go
82
+ preExecutePlutusV1 protocolVersion_ (PlutusScript _ (PlutusScriptSerialised script)) datum redeemer costModel
83
+ = fst $ runWriter $ runExceptT go -- for now, we discard warnings (:: PlutusCore.Evaluation.Machine.CostModelInterface.CostModelApplyWarn)
68
84
where
85
+ protocolVersion = uncurry PlutusV1. ProtocolVersion protocolVersion_
69
86
go
70
87
= do
71
- CostModel costModel <- hoistMaybe (TxGenError " preExecutePlutusScript: costModel unavailable" ) $
72
- AnyPlutusScriptVersion PlutusScriptV1 `Map.lookup` protocolParamCostModels protocolParameters
73
88
evaluationContext <- firstExceptT PlutusError $
74
89
PlutusV1. mkEvaluationContext (flattenCostModel costModel)
75
90
76
- let
77
- (majVer, minVer) = protocolParamProtocolVersion protocolParameters
78
- protocolVersion = PlutusV1. ProtocolVersion (fromIntegral majVer) (fromIntegral minVer)
79
-
80
91
exBudget <- firstExceptT PlutusError $
81
92
hoistEither $
82
93
snd $ PlutusV1. evaluateScriptCounting protocolVersion PlutusV1. Verbose evaluationContext script
@@ -85,7 +96,7 @@ preExecutePlutusV1 protocolParameters (PlutusScript _ (PlutusScriptSerialised sc
85
96
, PlutusV1. toData dummyContext
86
97
]
87
98
88
- x <- hoistMaybe (TxGenError " preExecutePlutusScript : could not convert to execution units" ) $
99
+ x <- hoistMaybe (TxGenError " preExecutePlutusV1 : could not convert to execution units" ) $
89
100
exBudgetToExUnits exBudget
90
101
return $ fromAlonzoExUnits x
91
102
@@ -110,26 +121,21 @@ preExecutePlutusV1 protocolParameters (PlutusScript _ (PlutusScriptSerialised sc
110
121
}
111
122
112
123
preExecutePlutusV2 ::
113
- ProtocolParameters
124
+ ProtocolVersion
114
125
-> Script PlutusScriptV2
115
126
-> ScriptData
116
127
-> ScriptRedeemer
128
+ -> CostModel
117
129
-> Either TxGenError ExecutionUnits
118
- preExecutePlutusV2 protocolParameters (PlutusScript _ (PlutusScriptSerialised script)) datum redeemer
119
- = fst $ -- for now, we discard warnings (:: PlutusCore.Evaluation.Machine.CostModelInterface.CostModelApplyWarn)
120
- runWriter $ runExceptT go
130
+ preExecutePlutusV2 protocolVersion_ (PlutusScript _ (PlutusScriptSerialised script)) datum redeemer costModel
131
+ = fst $ runWriter $ runExceptT go -- for now, we discard warnings (:: PlutusCore.Evaluation.Machine.CostModelInterface.CostModelApplyWarn)
121
132
where
133
+ protocolVersion = uncurry PlutusV2. ProtocolVersion protocolVersion_
122
134
go
123
135
= do
124
- CostModel costModel <- hoistMaybe (TxGenError " preExecutePlutusScript: costModel unavailable" ) $
125
- AnyPlutusScriptVersion PlutusScriptV1 `Map.lookup` protocolParamCostModels protocolParameters
126
136
evaluationContext <- firstExceptT PlutusError $
127
137
PlutusV2. mkEvaluationContext (flattenCostModel costModel)
128
138
129
- let
130
- (majVer, minVer) = protocolParamProtocolVersion protocolParameters
131
- protocolVersion = PlutusV2. ProtocolVersion (fromIntegral majVer) (fromIntegral minVer)
132
-
133
139
exBudget <- firstExceptT PlutusError $
134
140
hoistEither $
135
141
snd $ PlutusV2. evaluateScriptCounting protocolVersion PlutusV2. Verbose evaluationContext script
@@ -138,7 +144,7 @@ preExecutePlutusV2 protocolParameters (PlutusScript _ (PlutusScriptSerialised sc
138
144
, PlutusV2. toData dummyContext
139
145
]
140
146
141
- x <- hoistMaybe (TxGenError " preExecutePlutusScript : could not convert to execution units" ) $
147
+ x <- hoistMaybe (TxGenError " preExecutePlutusV2 : could not convert to execution units" ) $
142
148
exBudgetToExUnits exBudget
143
149
return $ fromAlonzoExUnits x
144
150
@@ -164,9 +170,11 @@ preExecutePlutusV2 protocolParameters (PlutusScript _ (PlutusScriptSerialised sc
164
170
, PlutusV2. txInfoRedeemers = PlutusV2. fromList []
165
171
}
166
172
167
- -- This is an incredibly bad idea. The order of the output list is inportant , but:
173
+ -- The order of the output list is important , but:
168
174
-- * This way of flattening it is not guaranteed to always be correct.
169
175
-- * There is no way to ensure that the list remains in the correct order.
170
- -- IMO, the `[Integer]` should *NEVER* have been exposed from `ledger`.
171
- flattenCostModel :: Map Text Integer -> [Integer ]
172
- flattenCostModel = map snd . Map. toAscList
176
+ -- However, we're bound to the type `Cardano.Api.ProtocolParameters.CostModel` which
177
+ -- might be changed from a key-value map to something providing stronger guarantees.
178
+ flattenCostModel :: CostModel -> [Integer ]
179
+ flattenCostModel (CostModel cm)
180
+ = snd <$> Map. toAscList cm
0 commit comments