-
Notifications
You must be signed in to change notification settings - Fork 482
Tool to dump cost model parameters in order expected by ledger #7171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
9c4146e
Add executable to dump cost model parameters
kwxm 3e1c8ea
Change some imports
kwxm b6d23a9
Add a description of what the program does and is for
kwxm c11e843
Add comment about default option
kwxm 6958287
Update help text
kwxm ff5fb7a
Amend output format
kwxm e58a9ab
Update comment
kwxm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
140 changes: 140 additions & 0 deletions
140
plutus-ledger-api/exe/dump-cost-model-parameters/Main.hs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| {-# LANGUAGE AllowAmbiguousTypes #-} | ||
| {-# LANGUAGE LambdaCase #-} | ||
| {-# LANGUAGE TypeApplications #-} | ||
|
|
||
| module Main (main) | ||
| where | ||
|
|
||
| import Parsers (Format (..), WhichLL (..), parseDumpOptions) | ||
|
|
||
| import PlutusCore qualified as PLC | ||
| import PlutusCore.Builtin qualified as PLC | ||
| import PlutusCore.Default.Builtins qualified as PLC | ||
| import PlutusCore.Evaluation.Machine.ExBudgetingDefaults qualified as PLC | ||
|
|
||
| import PlutusLedgerApi.Common (IsParamName, PlutusLedgerLanguage (..), showParamName) | ||
| import PlutusLedgerApi.V1 qualified as V1 | ||
| import PlutusLedgerApi.V2 qualified as V2 | ||
| import PlutusLedgerApi.V3 qualified as V3 | ||
|
|
||
| import Data.Aeson qualified as A (Object, ToJSON, Value (Array, Number)) | ||
| import Data.Aeson.Encode.Pretty (encodePretty) | ||
| import Data.Aeson.Key qualified as K (fromString) | ||
| import Data.Aeson.KeyMap qualified as KM (KeyMap, singleton) | ||
| import Data.ByteString.Lazy (putStr) | ||
| import Data.Int (Int64) | ||
| import Data.List.Extra (enumerate) | ||
| import Data.Map qualified as Map (lookup) | ||
| import Data.Text (Text) | ||
| import Data.Vector qualified as V (fromList) | ||
| import Options.Applicative (execParser) | ||
| import Text.Printf (printf) | ||
|
|
||
| {- | This executable prints out the cost model parameters according to the various | ||
| `PlutusLedgerApi.V<n>.ParamName types`. These determine both the cost model | ||
| parameters included in the protocol parameters (and hence which Plutus | ||
| builtins are available to each Plutus ledger language version) and the order | ||
| in which they occur. The protocol parameters and the ledger both treat the | ||
| cost model parameters as ordered lists of integers and know nothing about | ||
| the names of the parameters (see | ||
| `cardano-ledger/libs/cardano-ledger-core/src/Cardano/Ledger/Plutus/CostModels.hs` | ||
| for how the ledger (and also cardano-api and cardano-cli) deals with cost | ||
| models), and the `ParamName` types provide the link between the lists of | ||
| parameters and the complex structure used to represent a cost model in | ||
| Plutus Core. New cost models (possibly enabling new builtins) are | ||
| propagated to the chain by protocol updates which update the cost model | ||
| parameters, and this executable produces lists of cost model parameters in a | ||
| form suitable for inclusion in the protocol parameters, and so can be helpful | ||
| when we need to propose new parameters for use on the chain, and to check | ||
| that the on-chain parameters are as expected. Note that this code deals | ||
| only with the cost model parameters in the current state of the `plutus` | ||
| repository, which may differ from those on the chain: specifically, the cost | ||
| model parameters dealt with by this code will often be those which are | ||
| expected to come into effect at the next hard fork and hence will be ahead | ||
| of those currently in use for new script executions on the chain. The exact | ||
| structure of the cost model used by a particular ledger language is | ||
| determined by a _semantic variant_ which depends on both the ledger language | ||
| and the protocol version (see the `mkEvaluationContext` functions in the | ||
| various `EvaluationContext` files), and this code will need to be updated | ||
| if, for example, a new Plutus Ledger language is added or the structure of | ||
| the cost model used by an existing ledger language changes. | ||
| -} | ||
|
|
||
| -- Mapping of LL versions to semantic versions and parameter names for *the | ||
| -- current state of the repository*. This MUST be updated if the mappings in | ||
| -- the PlutusLedgerApi.V<n>.EvaluationContext modules are changed. | ||
| infoFor :: PlutusLedgerLanguage -> (PLC.BuiltinSemanticsVariant PLC.DefaultFun, [Text]) | ||
| infoFor = | ||
| let paramNames :: forall a . IsParamName a => [Text] | ||
| paramNames = fmap showParamName $ enumerate @a | ||
| in \case | ||
| PlutusV1 -> (PLC.DefaultFunSemanticsVariantB, paramNames @V1.ParamName) | ||
| PlutusV2 -> (PLC.DefaultFunSemanticsVariantB, paramNames @V2.ParamName) | ||
| PlutusV3 -> (PLC.DefaultFunSemanticsVariantC, paramNames @V3.ParamName) | ||
|
|
||
| -- Return the current cost model parameters for a given LL version in the form | ||
| -- of a list of (name, value) pairs ordered by name according to the relevant | ||
| -- `ParamName` type. | ||
| getParamsFor :: PlutusLedgerLanguage -> [(Text, Int64)] | ||
| getParamsFor ll = | ||
| let (semvar, paramNames) = infoFor ll | ||
| params = | ||
| case PLC.defaultCostModelParamsForVariant semvar of | ||
| Nothing -> error $ "Can't find default cost model parameters for " | ||
| ++ show semvar | ||
| Just p -> p | ||
| lookupParam name = | ||
| case Map.lookup name params of | ||
| Nothing -> error $ "No entry for " ++ show name | ||
| ++ " in cost model for semantic variant " | ||
| ++ show semvar | ||
| Just n -> (name, n) | ||
| in fmap lookupParam paramNames | ||
|
|
||
| -- A couple of convenience functions for dealing with JSON. | ||
| mkObject :: String -> v -> KM.KeyMap v | ||
| mkObject k v = KM.singleton (K.fromString k) v | ||
|
|
||
| putJSON :: A.ToJSON a => a -> IO () | ||
| putJSON = Data.ByteString.Lazy.putStr . encodePretty | ||
|
|
||
| -- Return the cost model parameters for a given LL in the form of a JSON object | ||
| -- containing the LL version and an array of parameter values. This is the same | ||
| -- format that cardano-cli uses to render the protocol parameters. Cost model | ||
| -- parameter names are not included in the protocol parameters: they used to be, | ||
| -- but not any more. | ||
| getParamsAsJSON :: PlutusLedgerLanguage -> A.Object | ||
| getParamsAsJSON ll = | ||
| let params = getParamsFor ll | ||
| entries = A.Array $ V.fromList $ fmap (\(_,v) -> A.Number $ fromIntegral v) params | ||
| in mkObject (show ll) entries | ||
|
|
||
| printParameters :: Format -> PlutusLedgerLanguage -> IO () | ||
| printParameters fmt ll = | ||
| case fmt of | ||
| Untagged -> do | ||
| printf "%s:\n" $ show ll | ||
| mapM_ (\(_,val) -> printf " %-d\n" val) $ getParamsFor ll | ||
| printf "\n" | ||
| Tagged -> do | ||
| printf "%s:\n" $ show ll | ||
| mapM_ (\(name,val) -> printf " %-12d -- %s\n" val name) $ getParamsFor ll | ||
| printf "\n" | ||
| JSON -> putJSON $ getParamsAsJSON ll | ||
|
|
||
| -- Print the cost model parameters for all ledger languages. For JSON we have | ||
| -- to create a single object containing parameters for all ledger language | ||
| -- versions and print that; for the other formats we just print them all out in | ||
| -- sequence. | ||
| printAll :: Format -> IO () | ||
| printAll fmt = | ||
| case fmt of | ||
| JSON -> putJSON $ mkObject "costModels" $ mconcat (fmap getParamsAsJSON enumerate) | ||
| _ -> mapM_ (printParameters fmt) enumerate | ||
|
|
||
| main :: IO () | ||
| main = do | ||
| (lls, fmt) <- execParser parseDumpOptions | ||
| case lls of | ||
| One ll -> printParameters fmt ll | ||
| All -> printAll fmt |
57 changes: 57 additions & 0 deletions
57
plutus-ledger-api/exe/dump-cost-model-parameters/Parsers.hs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| {-# LANGUAGE LambdaCase #-} | ||
|
|
||
| module Parsers (Format(..), WhichLL(..), parseDumpOptions) | ||
| where | ||
|
|
||
| import Options.Applicative | ||
| import PlutusLedgerApi.Common.Versions (PlutusLedgerLanguage (..)) | ||
|
|
||
| data WhichLL = | ||
| One PlutusLedgerLanguage -- Print parameters for a single LL. | ||
| | All -- Print parameters for all LLs. | ||
| deriving stock (Show) | ||
|
|
||
| parseVersion :: ReadM WhichLL | ||
| parseVersion = eitherReader $ \case | ||
| "1" -> Right $ One PlutusV1 | ||
| "2" -> Right $ One PlutusV2 | ||
| "3" -> Right $ One PlutusV3 | ||
| s -> Left $ "Unknown ledger language version: " ++ s | ||
|
|
||
| whichll :: Parser WhichLL | ||
| whichll = | ||
| option parseVersion | ||
| (short 'V' <> | ||
| metavar "N" <> | ||
| help "Print parameters for PlutusV<N> only" | ||
| ) | ||
| <|> flag All All | ||
| -- This makes `All` the default: if the previous parser fails then we | ||
| -- arrive here and it returns `All` whether or not the option is | ||
| -- present on the command line. | ||
| (short 'a' <> | ||
| long "all" <> | ||
| help "Print parameters for all Plutus ledger language versions (default)" | ||
| ) | ||
|
|
||
| data Format = Untagged | Tagged | JSON | ||
| deriving stock (Show) | ||
|
|
||
| format :: Parser Format | ||
| format = | ||
| flag' Untagged (short 'u' <> long "untagged" <> help "Print parameter values only") | ||
| <|> flag' Tagged (short 't' <> long "tagged" <> help "Print parameter values and names") | ||
| <|> flag JSON JSON (short 'j' <> long "json" <> help "Print parameters in JSON format (default)") | ||
|
|
||
| dumpOptions :: Parser (WhichLL, Format) | ||
| dumpOptions = (,) <$> whichll <*> format | ||
|
|
||
| parseDumpOptions :: ParserInfo (WhichLL, Format) | ||
| parseDumpOptions = | ||
| info (dumpOptions <**> helper) | ||
| (fullDesc <> | ||
| progDesc ("Print the current (and possibly undeployed) cost model parameters " | ||
| ++ " in the plutus repository in the order used in the protocol parameters.\n" | ||
| ++ "The purpose of this tool is to help with the deployment and verification " | ||
| ++ "of updated cost model parameters: it MUST be kept up to date with the " | ||
| ++ "`mkEvaluationContext` functions in plututus-ledger-api.")) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation is inconsistent across newly added files,
do you mind applying Fourmolu to all the Haskell code in this PR?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done that, but then stylish-haskell changed some of it back when I committed the changes. Specifically, it lined up the
->s in case expressions and also the-#}s at the end of the pragmas at the start. I like both of those better than what Fourmolu does, but you might object!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure but I think that also Fourmolu aligned
let ... in ...like thisand stylish-haskell changed it back to
The first one looks a bit strange to me but I see why it's done it. It's a pity that
letandindon't have the same number of letters...