Plutus.V1.Ledger.Api

  • 1. 📜 Overview

  • 2. 🔧 Compiler Options, Language Extensions, and Imports

  • 3. 🗄️ Data Structures and Type Synonyms

    • 3.1 🔤 SerializedScript (type)

    • 3.2 📊 LedgerPlutusVersion (data)

    • 3.3 🔢 ProtocolVersion (data)

    • 3.4 🧪 EvaluationError (data)

    • 3.5 🔄 VerboseMode (data)

    • 3.6 🔧 DefaultMachineParameters (type)

    • 3.7 🏗️ ScriptForExecution (newtype)

    • 3.8 🏗️ EvaluationContext (data)

  • 4. ⚙️ Core Functions

    • 4.1 📜 builtinsIntroducedIn

    • 4.2 🔍 builtinsAvailableIn

    • 4.3 🛠️ scriptCBORDecoder

    • 4.4 ✅ isScriptWellFormed

    • 4.5 ⚙️ mkTermToEvaluate

    • 4.6 🔄 unliftingModeIn

    • 4.7 🔧 toMachineParameters

    • 4.8 🛠️ mkMachineParametersFor

    • 4.9 🏗️ mkEvaluationContext

    • 4.10 ✔️ assertWellFormedCostModelParams

    • 4.11 🚀 evaluateScriptRestricting

    • 4.12 🚨 evaluateScriptCounting

  • 5. 🤝 Typeclass Instances

  • 6. 📚 Glossary


1 📜 Overview

This module, Plutus.ApiCommon, provides common types and functions shared across the Plutus ledger API:

  • Configures GHC simplifier ticks to support heavy optimization.

  • Defines key type synonyms (SerializedScript, LogOutput) and data types (LedgerPlutusVersion, ProtocolVersion, etc.).

  • Manages builtin availability by protocol version.

  • Implements script decoding, well‐formedness checks, and evaluation under cost constraints.

  • Builds and caches evaluation contexts for different unlifting modes.

Throughout, you’ll see examples of type, data, and newtype definitions, plus helper functions marked INLINABLE or INLINE for on-chain performance.


2 🔧 Compiler Options, Language Extensions, and Imports

-- Increase simplifier ticks for heavy optimization
{-# OPTIONS_GHC -fsimpl-tick-factor=200 #-}

module Plutus.ApiCommon where

import PlutusCore as Plutus hiding (Version)
import PlutusCore as ScriptPlutus (Version)
import PlutusCore.Data as Plutus
import PlutusCore.Evaluation.Machine.CostModelInterface as Plutus
import PlutusCore.Evaluation.Machine.ExBudget as Plutus
import PlutusCore.Evaluation.Machine.MachineParameters as Plutus
import PlutusCore.MkPlc qualified as UPLC
import UntypedPlutusCore qualified as UPLC
import UntypedPlutusCore.Check.Scope qualified as UPLC
import UntypedPlutusCore.Evaluation.Machine.Cek qualified as UPLC

import Codec.CBOR.Decoding qualified as CBOR
import Codec.CBOR.Extras
import Codec.CBOR.Read qualified as CBOR
import Control.DeepSeq
import Control.Monad.Except
import Control.Monad.Writer
import Data.Bifunctor
import Data.ByteString.Lazy (fromStrict)
import Data.ByteString.Short
import Data.Coerce
import Data.Either
import Data.Foldable (fold)
import Data.Map qualified as Map
import Data.Set qualified as Set
import Data.Text
import Data.Tuple
import GHC.Exts (inline)
import GHC.Generics
import NoThunks.Class
import PlutusCore.Pretty
import PlutusPrelude (through)
import Prettyprinter
  • OPTIONS_GHC: raises the simplifier tick budget to avoid running out during optimization of large modules.

  • No explicit LANGUAGE pragmas beyond INLINE/INLINABLE pragmas used on functions.

  • Heavy use of qualified imports (UPLC, CBOR) to avoid name clashes.


3 🗄️ Data Structures and Type Synonyms

3.1 🔤 SerializedScript (type)

-- | Scripts to the ledger are serialised bytestrings.
type SerializedScript = ShortByteString
  • Inputs/Outputs: Exactly ShortByteString, renamed for clarity.

  • Example Usage:

    let raw :: SerializedScript = toShort someLazyBS

3.2 📊 LedgerPlutusVersion (data)

data LedgerPlutusVersion = PlutusV1 | PlutusV2
  deriving stock (Eq, Ord)
  • Constructors: PlutusV1, PlutusV2

  • Example:

    let lv = PlutusV2

3.3 🔢 ProtocolVersion (data)

data ProtocolVersion = ProtocolVersion { pvMajor :: Int, pvMinor :: Int }
  deriving stock (Show, Eq)
  • Fields:

    • pvMajor: major version (e.g., 7)

    • pvMinor: minor version (e.g., 0)

  • Example:

    let pv = ProtocolVersion 7 0

3.4 🧪 EvaluationError (data)

data EvaluationError
  = CekError (UPLC.CekEvaluationException NamedDeBruijn DefaultUni DefaultFun)
  | DeBruijnError FreeVariableError
  | CodecError CBOR.DeserialiseFailure
  | IncompatibleVersionError (ScriptPlutus.Version ())
  | CostModelParameterMismatch
  deriving stock (Show, Eq)
  • Variants: several error kinds when decoding or evaluating.

  • Example:

    let err = CodecError someFailure

3.5 🔄 VerboseMode (data)

data VerboseMode = Verbose | Quiet
  deriving stock (Eq)
  • Use: toggles logging in evaluation functions.

  • Example:

    let mode = Verbose

3.6 🔧 DefaultMachineParameters (type)

type DefaultMachineParameters = MachineParameters CekMachineCosts UPLC.CekValue DefaultUni DefaultFun
  • Alias: for the CEK evaluator’s parameter bundle.

3.7 🏗️ ScriptForExecution (newtype)

newtype ScriptForExecution = ScriptForExecution (UPLC.Program UPLC.NamedDeBruijn DefaultUni DefaultFun ())
  • Wraps: a UPLC program specialized for execution.

  • Example:

    let exec = ScriptForExecution someProgram

3.8 🏗️ EvaluationContext (data)

data EvaluationContext = EvaluationContext
  { machineParametersImmediate :: DefaultMachineParameters
  , machineParametersDeferred  :: DefaultMachineParameters
  }
  deriving stock Generic
  deriving anyclass (NFData, NoThunks)
  • Fields: separate parameter sets for immediate and deferred unlifting.

  • Example:

    let ctx = EvaluationContext params1 params2

4 ⚙️ Core Functions

4.1 📜 builtinsIntroducedIn

builtinsIntroducedIn :: Map.Map (LedgerPlutusVersion, ProtocolVersion) (Set.Set DefaultFun)
builtinsIntroducedIn = Map.fromList [ ... ]
  • Inputs: none (constant map)

  • Processing: maps version to built‐in set

  • Output: map of introduced builtins

  • Example:

    Map.lookup (PlutusV1, ProtocolVersion 5 0) builtinsIntroducedIn

4.2 🔍 builtinsAvailableIn

builtinsAvailableIn :: LedgerPlutusVersion -> ProtocolVersion -> Set.Set DefaultFun
builtinsAvailableIn thisLv thisPv = fold $ Map.elems $
  Map.takeWhileAntitone builtinAvailableIn builtinsIntroducedIn
  where
    builtinAvailableIn (lv',pv') = lv' <= thisLv && pv' <= thisPv
  • Inputs: ledger version, protocol version

  • Processing: filters map entries <= inputs, folds sets

  • Output: available builtins set

  • Example:

    builtinsAvailableIn PlutusV2 (ProtocolVersion 7 0)

4.3 🛠️ scriptCBORDecoder

scriptCBORDecoder :: LedgerPlutusVersion -> ProtocolVersion -> CBOR.Decoder s ScriptForExecution
scriptCBORDecoder lv pv =
  let availableBuiltins = builtinsAvailableIn lv pv
      flatDecoder = UPLC.decodeProgram (`Set.member` availableBuiltins)
  in do
    p <- decodeViaFlat flatDecoder
    pure $ coerce p
  • Inputs: versions

  • Processing: builds flat decoder with correct builtins, decodes to ScriptForExecution

  • Output: CBOR.Decoder s ScriptForExecution

  • Example:

    CBOR.deserialiseFromBytes (scriptCBORDecoder PlutusV1 (ProtocolVersion 5 0)) bytes

4.4 ✅ isScriptWellFormed

isScriptWellFormed :: LedgerPlutusVersion -> ProtocolVersion -> SerializedScript -> Bool
isScriptWellFormed lv pv = isRight . CBOR.deserialiseFromBytes (scriptCBORDecoder lv pv) . fromStrict . fromShort
  • Inputs: versions, raw bytes

  • Processing: attempt decode, wrap isRight

  • Output: Bool

  • Example:

    isScriptWellFormed PlutusV2 (ProtocolVersion 7 0) rawScript

4.5 ⚙️ mkTermToEvaluate

mkTermToEvaluate
  :: MonadError EvaluationError m
  => LedgerPlutusVersion -> ProtocolVersion -> SerializedScript -> [Plutus.Data] -> m (UPLC.Term ...)
  • Inputs: versions, serialized script, data args

  • Processing: decode via scriptCBORDecoder, check version tag, apply constants, scope‐check

  • Output: UPLC term ready for CEK machine

  • Example:

    runExceptT $ mkTermToEvaluate PlutusV1 v1 raw args

4.6 🔄 unliftingModeIn

unliftingModeIn :: ProtocolVersion -> UnliftingMode
unliftingModeIn pv = if pv >= ProtocolVersion 7 0 then UnliftingDeferred else UnliftingImmediate
  • Inputs: protocol version

  • Processing: simple comparison

  • Output: UnliftingMode

  • Example:

    unliftingModeIn (ProtocolVersion 6 0) == UnliftingImmediate

4.7 🔧 toMachineParameters

toMachineParameters :: ProtocolVersion -> EvaluationContext -> DefaultMachineParameters
toMachineParameters pv = case unliftingModeIn pv of
  UnliftingImmediate -> machineParametersImmediate
  UnliftingDeferred  -> machineParametersDeferred
  • Inputs: protocol version, context

  • Processing: selects field

  • Output: parameters

  • Example:

    toMachineParameters vctxPV ctx

4.8 🛠️ mkMachineParametersFor

mkMachineParametersFor
  :: MonadError CostModelApplyError m
  => UnliftingMode -> Plutus.CostModelParams -> m DefaultMachineParameters
mkMachineParametersFor unlMode newCMP =
  inline Plutus.mkMachineParameters unlMode <$> Plutus.applyCostModelParams ...
{-# INLINE mkMachineParametersFor #-}
  • Inputs: unlifting mode, cost model params

  • Processing: apply and inline mkMachineParameters

  • Output: DefaultMachineParameters

4.9 🏗️ mkEvaluationContext

mkEvaluationContext :: MonadError CostModelApplyError m => Plutus.CostModelParams -> m EvaluationContext
mkEvaluationContext newCMP = EvaluationContext
  <$> inline mkMachineParametersFor UnliftingImmediate newCMP
  <*> inline mkMachineParametersFor UnliftingDeferred newCMP
  • Inputs: cost model params

  • Processing: builds both parameter sets

  • Output: EvaluationContext

4.10 ✔️ assertWellFormedCostModelParams

assertWellFormedCostModelParams :: MonadError CostModelApplyError m => Plutus.CostModelParams -> m ()
assertWellFormedCostModelParams = void . Plutus.applyCostModelParams Plutus.defaultCekCostModel
  • Inputs: cost model params

  • Processing: checks default cost model

  • Output: () or error

4.11 🚀 evaluateScriptRestricting

evaluateScriptRestricting
  :: LedgerPlutusVersion -> ProtocolVersion -> VerboseMode -> EvaluationContext -> ExBudget -> SerializedScript -> [Plutus.Data]
  -> (LogOutput, Either EvaluationError ExBudget)
  • Inputs: versions, verbosity, context, budget, script, args

  • Processing: mkTermToEvaluate, run CEK with restricting budget, collect logs

  • Output: logs and either error or remaining budget

  • Example:

    evaluateScriptRestricting PlutusV2 v7 Verbose ctx budget raw args

4.12 🚨 evaluateScriptCounting

evaluateScriptCounting
  :: LedgerPlutusVersion -> ProtocolVersion -> VerboseMode -> EvaluationContext -> SerializedScript -> [Plutus.Data]
  -> (LogOutput, Either EvaluationError ExBudget)
  • Inputs: versions, verbosity, context, script, args

  • Processing: mkTermToEvaluate, run CEK in counting mode, collect logs

  • Output: logs and either error or budget used


5 🤝 Typeclass Instances

instance Ord ProtocolVersion where
  compare (ProtocolVersion maj min) (ProtocolVersion maj' min') = compare maj maj' <> compare min min'
  • Explicit Ord implementation matching derived ordering.

instance Pretty ProtocolVersion where
  pretty (ProtocolVersion mj mn) = pretty mj <> "." <> pretty mn
  • Renders version as "7.0".

instance Pretty EvaluationError where
  pretty (CekError e)      = prettyClassicDef e
  pretty (DeBruijnError e) = pretty e
  pretty (CodecError e)    = viaShow e
  pretty (IncompatibleVersionError v) = "Unsupported version:" <+> pretty v
  pretty CostModelParameterMismatch = "Cost model parameters mismatch"
  • Human‐readable error messages via Prettyprinter.


6 📚 Glossary

  • ShortByteString: compact bytestring optimized for short data.

  • CBOR Decoder: parser for CBOR‐encoded data.

  • ExBudget: resource budget for script execution.

  • CEK machine: abstract machine implementing Plutus Core evaluation.

  • UnliftingMode: strategy for converting on‐chain constants back to Haskell.

  • INLINE / INLINABLE: pragmas guiding GHC inlining for performance.

  • NoThunks: class preventing unexpected thunks in data.

  • CostModelParams: map from builtin costs to integer values.

  • MonadError: monad supporting error‐throwing and catching.

Last updated