Skip to content

Commit

Permalink
Renamed RunPlutus, completed ValidateScript, evalScripts.
Browse files Browse the repository at this point in the history
Renamed module Caradano.Ledger.Alonzo.RunPlutus to Caradano.Ledger.Alonzo.PlutusScriptApi.
Completed the ValidateScript instance for Alonzo, and the evalScripts function.
Cleaned up the Utxos modue, that was way over constrained.
  • Loading branch information
TimSheard committed Mar 25, 2021
1 parent 730a9cb commit db1ab81
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 243 deletions.
2 changes: 1 addition & 1 deletion alonzo/impl/cardano-ledger-alonzo.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ library
Cardano.Ledger.Alonzo
Cardano.Ledger.Alonzo.Data
Cardano.Ledger.Alonzo.FakePlutus
Cardano.Ledger.Alonzo.RunPlutus
Cardano.Ledger.Alonzo.PlutusScriptApi
Cardano.Ledger.Alonzo.Language
Cardano.Ledger.Alonzo.PParams
Cardano.Ledger.Alonzo.Rules.Utxo
Expand Down
18 changes: 12 additions & 6 deletions alonzo/impl/src/Cardano/Ledger/Alonzo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import Cardano.Ledger.Alonzo.PParams (PParams, PParams' (..), PParamsUpdate, upd
import qualified Cardano.Ledger.Alonzo.Rules.Utxo as Alonzo (AlonzoUTXO)
import qualified Cardano.Ledger.Alonzo.Rules.Utxos as Alonzo (UTXOS)
import qualified Cardano.Ledger.Alonzo.Rules.Utxow as Alonzo (AlonzoUTXOW)
import Cardano.Ledger.Alonzo.Scripts (Script, isPlutusScript)
import Cardano.Ledger.Alonzo.Tx (Tx)
import Cardano.Ledger.Alonzo.TxBody (TxBody, TxOut)
import Cardano.Ledger.Alonzo.Scripts (Script (..), isPlutusScript)
import Cardano.Ledger.Alonzo.Tx (Tx, body', wits')
import Cardano.Ledger.Alonzo.TxBody (TxBody, TxOut, vldt')
import Cardano.Ledger.Alonzo.TxWitness (TxWitness (txwitsVKey'))
import Cardano.Ledger.AuxiliaryData (AuxiliaryDataHash (..), ValidateAuxiliaryData (..))
import qualified Cardano.Ledger.Core as Core
import qualified Cardano.Ledger.Crypto as CC
Expand All @@ -29,8 +30,10 @@ import Cardano.Ledger.Shelley.Constraints
UsesTxOut (..),
UsesValue,
)
import Cardano.Ledger.ShelleyMA.Timelocks (evalTimelock)
import Control.State.Transition.Extended (STUB)
import qualified Control.State.Transition.Extended as STS
import qualified Data.Set as Set
import Data.Typeable (Typeable)
import qualified Shelley.Spec.Ledger.API as API
import qualified Shelley.Spec.Ledger.BaseTypes as Shelley
Expand All @@ -46,6 +49,7 @@ import qualified Shelley.Spec.Ledger.STS.Snap as Shelley
import qualified Shelley.Spec.Ledger.STS.Tick as Shelley
import qualified Shelley.Spec.Ledger.STS.Upec as Shelley
import qualified Shelley.Spec.Ledger.Tx as Shelley
import Shelley.Spec.Ledger.TxBody (witKeyHash)

-- | The Alonzo era
data AlonzoEra c
Expand All @@ -62,9 +66,11 @@ instance (CC.Crypto c) => Shelley.ValidateScript (AlonzoEra c) where
if isPlutusScript script
then "\x01"
else nativeMultiSigTag -- "\x00"
validateScript = error "TODO: implement validateScript"

-- hashScript x = ... We use the default method for hashScript
validateScript (NativeScript timelock) tx = evalTimelock vhks (vldt' (body' tx)) timelock
where
vhks = Set.map witKeyHash (txwitsVKey' (wits' tx))
validateScript (PlutusScript _) _tx = False -- Plutus scripts are stripped out an run in function evalScripts
-- hashScript x = ... We use the default method for hashScript

instance
( CC.Crypto c
Expand Down
212 changes: 212 additions & 0 deletions alonzo/impl/src/Cardano/Ledger/Alonzo/PlutusScriptApi.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

module Cardano.Ledger.Alonzo.PlutusScriptApi
( -- Figure 8
getData,
collectNNScriptInputs,
evalScripts,
-- Figure 12
scriptsNeeded,
checkScriptData,
language,
)
where

import Cardano.Ledger.Alonzo.Data (getPlutusData)
import Cardano.Ledger.Alonzo.Language (Language (..))
import Cardano.Ledger.Alonzo.Scripts (CostModel, ExUnits (..))
import qualified Cardano.Ledger.Alonzo.Scripts as AlonzoScript (Script (..))
import Cardano.Ledger.Alonzo.Tx
( Data,
DataHash,
ScriptPurpose (..),
Tx (..),
body',
getValidatorHash,
indexedRdmrs,
txdats',
wits',
)
import qualified Cardano.Ledger.Alonzo.TxBody as Alonzo (TxBody (..), TxOut (..), vldt')
import Cardano.Ledger.Alonzo.TxInfo (evalPlutusScript, valContext)
import Cardano.Ledger.Alonzo.TxWitness (TxWitness (txwitsVKey'), txscripts')
import qualified Cardano.Ledger.Core as Core
import Cardano.Ledger.Era (Crypto, Era, ValidateScript (..))
import Cardano.Ledger.Mary.Value (PolicyID (..))
import qualified Cardano.Ledger.Mary.Value as Mary (Value (..))
import Cardano.Ledger.ShelleyMA.Timelocks (evalTimelock)
import Data.List (foldl')
import qualified Data.Map as Map
import Data.Maybe (isJust, maybeToList)
import Data.Sequence.Strict (StrictSeq)
import Data.Set (Set)
import qualified Data.Set as Set
import GHC.Records (HasField (..))
import Shelley.Spec.Ledger.BaseTypes (StrictMaybe (..))
import Shelley.Spec.Ledger.Credential (Credential (ScriptHashObj))
import Shelley.Spec.Ledger.Delegation.Certificates (DCert (..))
import Shelley.Spec.Ledger.Scripts (ScriptHash (..))
import Shelley.Spec.Ledger.TxBody
( DelegCert (..),
Delegation (..),
TxIn (..),
Wdrl (..),
getRwdCred,
witKeyHash,
)
import Shelley.Spec.Ledger.UTxO (UTxO (..))

-- ===============================================================
-- From the specification, Figure 8 "Scripts and their Arguments"
-- ===============================================================

getData ::
forall era.
( HasField "datahash" (Core.TxOut era) (StrictMaybe (DataHash (Crypto era)))
) =>
Tx era ->
UTxO era ->
ScriptPurpose (Crypto era) ->
[Data era]
getData tx (UTxO m) sp = case sp of
Minting _policyid -> []
Rewarding _rewaccnt -> []
Certifying _dcert -> []
Spending txin ->
-- Only the Spending ScriptPurpose contains Data
case Map.lookup txin m of
Nothing -> []
Just txout ->
case getField @"datahash" txout of
SNothing -> []
SJust hash ->
case Map.lookup hash (txdats' (getField @"wits" tx)) of
Nothing -> []
Just d -> [d]

collectNNScriptInputs ::
( Era era,
Core.Script era ~ AlonzoScript.Script era,
Core.TxOut era ~ Alonzo.TxOut era,
Core.TxBody era ~ Alonzo.TxBody era,
Core.Value era ~ Mary.Value (Crypto era),
HasField "datahash" (Core.TxOut era) (StrictMaybe (DataHash (Crypto era))),
HasField "_costmdls" (Core.PParams era) (Map.Map Language CostModel),
HasField "wdrls" (Core.TxBody era) (Wdrl (Crypto era)),
HasField "certs" (Core.TxBody era) (StrictSeq (DCert (Crypto era))),
HasField "inputs" (Core.TxBody era) (Set (TxIn (Crypto era)))
) =>
Core.PParams era ->
Tx era ->
UTxO era ->
[(AlonzoScript.Script era, [Data era], ExUnits, CostModel)]
collectNNScriptInputs pp tx utxo =
[ (script, d : (valContext utxo tx sp ++ getData tx utxo sp), eu, cost)
| (sp, scripthash) <- scriptsNeeded utxo tx, -- TODO, IN specification ORDER IS WRONG
(d, eu) <- maybeToList (indexedRdmrs tx sp),
script <- -- onlytwoPhaseScripts tx scripthash
maybeToList (Map.lookup scripthash (txscripts' (getField @"wits" tx))),
cost <- maybeToList (Map.lookup PlutusV1 (getField @"_costmdls" pp))
]

language :: Era era => AlonzoScript.Script era -> Maybe Language
language (AlonzoScript.PlutusScript _) = Just PlutusV1
language (AlonzoScript.NativeScript _) = Nothing

evalScripts ::
forall era.
( Era era,
Alonzo.TxBody era ~ Core.TxBody era
) =>
Tx era ->
[(AlonzoScript.Script era, [Data era], ExUnits, CostModel)] ->
Bool
evalScripts _tx [] = True
evalScripts tx ((AlonzoScript.NativeScript timelock, _, _, _) : rest) =
evalTimelock vhks (Alonzo.vldt' (body' tx)) timelock && evalScripts tx rest
where
vhks = Set.map witKeyHash (txwitsVKey' (wits' tx))
evalScripts tx ((AlonzoScript.PlutusScript pscript, ds, units, cost) : rest) =
evalPlutusScript cost units pscript (map getPlutusData ds) && evalScripts tx rest

-- ===================================================================
-- From Specification, Figure 12 "UTXOW helper functions"

-- This is called checkRedeemers in the Speicifcation
checkScriptData ::
forall era.
( ValidateScript era,
HasField "datahash" (Core.TxOut era) (StrictMaybe (DataHash (Crypto era))),
HasField "inputs" (Core.TxBody era) (Set (TxIn (Crypto era))),
HasField "wdrls" (Core.TxBody era) (Wdrl (Crypto era)),
HasField "certs" (Core.TxBody era) (StrictSeq (DCert (Crypto era)))
) =>
Tx era ->
UTxO era ->
(ScriptPurpose (Crypto era), ScriptHash (Crypto era)) ->
Bool
checkScriptData tx utxo (sp, _h) = any ok scripts
where
scripts = txscripts' (getField @"wits" tx)
isSpending (Spending _) = True
isSpending _ = False
ok s =
isNativeScript @era s
|| ( isJust (indexedRdmrs tx sp)
&& (not (isSpending sp) || not (null (getData tx utxo sp)))
)

-- THE SPEC CALLS FOR A SET, BUT THAT NEEDS A BUNCH OF ORD INSTANCES (DCert)
scriptsNeeded ::
forall era.
( Era era,
HasField "inputs" (Core.TxBody era) (Set (TxIn (Crypto era))),
HasField "wdrls" (Core.TxBody era) (Wdrl (Crypto era)),
HasField "certs" (Core.TxBody era) (StrictSeq (DCert (Crypto era)))
) =>
UTxO era ->
Tx era ->
[(ScriptPurpose (Crypto era), ScriptHash (Crypto era))]
scriptsNeeded (UTxO utxomap) tx = spend ++ reward ++ cert ++ minted
where
txb = body' tx
!spend = foldl' accum [] (getField @"inputs" txb)
where
accum !ans !i =
case Map.lookup i utxomap of
Nothing -> ans
Just txout ->
case getValidatorHash (getField @"address" txout) of
Nothing -> ans
Just hash -> (Spending i, hash) : ans

!reward = foldl' accum [] (Map.keys m2)
where
(Wdrl m2) = getField @"wdrls" txb
accum !ans !accnt = case getRwdCred accnt of -- TODO IS THIS RIGHT?
(ScriptHashObj hash) -> (Rewarding accnt, hash) : ans
_ -> ans

!cert = foldl addOnlyCwitness [] (getField @"certs" txb)

!minted = foldr (\hash ans -> (Minting (PolicyID hash), hash) : ans) [] valuePolicyHashes
where
valuePolicyHashes = getField @"minted" txb

-- We only find certificate witnesses in Delegating and Deregistration DCerts
-- that have ScriptHashObj credentials.
addOnlyCwitness ::
[(ScriptPurpose crypto, ScriptHash crypto)] ->
DCert crypto ->
[(ScriptPurpose crypto, ScriptHash crypto)]
addOnlyCwitness !ans (DCertDeleg c@(DeRegKey (ScriptHashObj hk))) =
(Certifying $ DCertDeleg c, hk) : ans
addOnlyCwitness !ans (DCertDeleg c@(Delegate (Delegation (ScriptHashObj hk) _dpool))) =
(Certifying $ DCertDeleg c, hk) : ans
addOnlyCwitness !ans _ = ans
35 changes: 23 additions & 12 deletions alonzo/impl/src/Cardano/Ledger/Alonzo/Rules/Utxos.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,22 @@ module Cardano.Ledger.Alonzo.Rules.Utxos where

import Cardano.Binary (FromCBOR (..), ToCBOR (..))
import Cardano.Ledger.Alonzo.Language (Language)
import Cardano.Ledger.Alonzo.PlutusScriptApi (collectNNScriptInputs, evalScripts)
import Cardano.Ledger.Alonzo.Scripts (Script)
import Cardano.Ledger.Alonzo.Tx
( CostModel,
DataHash,
IsValidating (..),
Tx (..),
txbody,
txins,
txouts,
)
import qualified Cardano.Ledger.Alonzo.TxBody as Alonzo
import qualified Cardano.Ledger.Core as Core
import Cardano.Ledger.Era (Crypto, Era)
import Cardano.Ledger.Shelley.Constraints
import Cardano.Ledger.Mary.Value (Value)
import Cardano.Ledger.Shelley.Constraints (PParamsDelta)
import qualified Cardano.Ledger.Val as Val
import Control.Iterate.SetAlgebra (eval, (∪), (⋪), (◁))
import Control.State.Transition.Extended
Expand Down Expand Up @@ -50,16 +60,16 @@ data UTXOS era
instance
forall era.
( Era era,
UsesAuxiliary era,
UsesTxBody era,
UsesTxOut era,
UsesValue era,
UsesPParams era,
Eq (Core.PParams era),
Show (Core.PParams era),
Show (PParamsDelta era),
Eq (PParamsDelta era),
Embed (Core.EraRule "PPUP" era) (UTXOS era),
Environment (Core.EraRule "PPUP" era) ~ PPUPEnv era,
State (Core.EraRule "PPUP" era) ~ PPUPState era,
Signal (Core.EraRule "PPUP" era) ~ Maybe (Update era),
Core.Script era ~ Script era,
Core.Value era ~ Value (Crypto era),
Core.TxOut era ~ Alonzo.TxOut era,
Core.TxBody era ~ Alonzo.TxBody era,
HasField "_keyDeposit" (Core.PParams era) Coin,
Expand All @@ -79,13 +89,15 @@ instance

utxosTransition ::
forall era.
( UsesTxOut era,
( Era era,
Core.Script era ~ Script era,
Environment (Core.EraRule "PPUP" era) ~ PPUPEnv era,
State (Core.EraRule "PPUP" era) ~ PPUPState era,
Signal (Core.EraRule "PPUP" era) ~ Maybe (Update era),
Embed (Core.EraRule "PPUP" era) (UTXOS era),
Core.TxOut era ~ Alonzo.TxOut era,
Core.Value era ~ Value (Crypto era),
Core.TxBody era ~ Alonzo.TxBody era,
HasField "inputs" (Core.TxBody era) (Set (TxIn (Crypto era))),
HasField "update" (Core.TxBody era) (StrictMaybe (Update era)),
HasField "certs" (Core.TxBody era) (StrictSeq (DCert (Crypto era))),
Expand All @@ -100,14 +112,15 @@ utxosTransition ::
utxosTransition =
judgmentContext >>= \(TRC (UtxoEnv _ pp _ _, UTxOState utxo _ _ _, tx)) ->
let sLst = collectNNScriptInputs pp tx utxo
scriptEvalResult = evalScripts @era sLst
scriptEvalResult = evalScripts @era tx sLst
in if scriptEvalResult
then scriptsValidateTransition
else scriptsNotValidateTransition

scriptsValidateTransition ::
forall era.
( UsesTxOut era,
( Show (Core.Value era), -- Arises because of the use of (∪) from SetAlgebra, needs Show to report errors.
Era era,
Environment (Core.EraRule "PPUP" era) ~ PPUPEnv era,
State (Core.EraRule "PPUP" era) ~ PPUPState era,
Signal (Core.EraRule "PPUP" era) ~ Maybe (Update era),
Expand Down Expand Up @@ -153,7 +166,7 @@ scriptsValidateTransition = do

scriptsNotValidateTransition ::
forall era.
( UsesTxOut era,
( Era era,
HasField "txinputs_fee" (Core.TxBody era) (Set (TxIn (Crypto era)))
) =>
TransitionRule (UTXOS era)
Expand Down Expand Up @@ -200,14 +213,12 @@ instance

deriving stock instance
( Shelley.TransUTxOState Show era,
TransValue Show era,
Show (PredicateFailure (Core.EraRule "PPUP" era))
) =>
Show (UtxosPredicateFailure era)

deriving stock instance
( Shelley.TransUTxOState Eq era,
TransValue Eq era,
Eq (PredicateFailure (Core.EraRule "PPUP" era))
) =>
Eq (UtxosPredicateFailure era)
Expand Down
4 changes: 1 addition & 3 deletions alonzo/impl/src/Cardano/Ledger/Alonzo/Rules/Utxow.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,15 @@ module Cardano.Ledger.Alonzo.Rules.Utxow where
import Cardano.Binary (FromCBOR (..), ToCBOR (..))
import Cardano.Ledger.Alonzo.Data (Data, DataHash)
import Cardano.Ledger.Alonzo.PParams (PParams)
import Cardano.Ledger.Alonzo.PlutusScriptApi (checkScriptData, language, scriptsNeeded)
import Cardano.Ledger.Alonzo.Rules.Utxo (AlonzoUTXO)
import qualified Cardano.Ledger.Alonzo.Rules.Utxo as Alonzo (UtxoPredicateFailure)
import Cardano.Ledger.Alonzo.Scripts (Script)
import Cardano.Ledger.Alonzo.Tx
( ScriptPurpose,
Tx,
checkScriptData,
hashWitnessPPData,
isNonNativeScriptAddress,
language,
scriptsNeeded,
wits',
)
import Cardano.Ledger.Alonzo.TxBody (WitnessPPDataHash)
Expand Down
Loading

0 comments on commit db1ab81

Please sign in to comment.