Skip to content

Commit

Permalink
Update Plutarch dependency to use the PlutusV3 stable release (#9)
Browse files Browse the repository at this point in the history
* release

* inprogress

* fix build issues due to new type system
  • Loading branch information
colll78 authored Feb 1, 2025
1 parent b58d989 commit 508ee6c
Show file tree
Hide file tree
Showing 20 changed files with 412 additions and 339 deletions.
4 changes: 2 additions & 2 deletions DesignDocument.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Modules like `Plutarch.Core.List` provide functions such as `pelemAtFast'` to ac
### 4. `Plutarch.Core.Eval` (`Eval.hs`)
- **Purpose**: Evaluating and serializing Plutarch terms.

### 5. `Plutarch.Core.FieldBinds` (`FieldBinds.hs`)
- **Purpose**: abstractions for handling field bindings in records.
### 5. `Plutarch.Core.Integrity` (`Integrity.hs`)
- **Purpose**: Utilities for verifying the correctness of the BuiltinData encoding of various types.

### 6. `Plutarch.Core.List` (`List.hs`)
- **Purpose**: Specialized high efficiency list operations.
Expand Down
2 changes: 1 addition & 1 deletion cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ packages:
source-repository-package
type: git
location: https://github.com/Plutonomicon/plutarch-plutus
tag: 8cc0a4ca3ed494a79fe019c72173b369cd26cb84
tag: fd7d1c1fc173542f952f19272554027183659dd6
subdir:
.
plutarch-ledger-api
Expand Down
8 changes: 4 additions & 4 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
};

plutarch = {
url = "github:Plutonomicon/plutarch-plutus/8cc0a4ca3ed494a79fe019c72173b369cd26cb84";
url = "github:Plutonomicon/plutarch-plutus/fd7d1c1fc173542f952f19272554027183659dd6";
};
};

Expand Down
2 changes: 2 additions & 0 deletions hie.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ cradle:
cabal:
- path: "./"
component: "plutarch-onchain-lib:plutarch-onchain-lib"
- path: "./"
component: "plutarch-onchain-lib:plutarch-onchain-lib-tests"
plugins:
eval:
globalOn: true
Expand Down
2 changes: 1 addition & 1 deletion nix/project.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

let
sha256map = {
"https://github.com/Plutonomicon/plutarch-plutus"."8cc0a4ca3ed494a79fe019c72173b369cd26cb84" = "sha256-zQ0qv9e3Gy6Myn8wx+geJtCL5L2qJlpruSbWmrgyLOE=";
"https://github.com/Plutonomicon/plutarch-plutus"."fd7d1c1fc173542f952f19272554027183659dd6" = "sha256-lU2JF9KYvzEPfVLHdLkrM1hTTuc9NYi2hQPFnLDm2d8=";
};

modules = [{ }];
Expand Down
52 changes: 52 additions & 0 deletions src/plutarch-onchain-lib/lib/Plutarch/Core/Context.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module Plutarch.Core.Context (
paddressCredential, ptxOutAddress, ptxOutCredential, ptxOutValue, ptxInInfoResolved, ptxInInfoOutRef, pscriptContextTxInfo, ptxInfoSignatories) where

import Plutarch.Prelude ( Term, pmatch, PAsData, PBuiltinList )
import Plutarch.LedgerApi.V3
( AmountGuarantees(Positive),
PValue,
PAddress(paddress'credential),
PCredential,
PTxOut(ptxOut'value, ptxOut'address),
PTxInInfo(ptxInInfo'outRef, ptxInInfo'resolved),
PTxOutRef, PScriptContext, PTxInfo, pscriptContext'txInfo, PPubKeyHash, ptxInfo'signatories )
import qualified Plutarch.LedgerApi.AssocMap as AssocMap

paddressCredential :: Term s PAddress -> Term s PCredential
paddressCredential addr =
pmatch addr $ \addr' ->
paddress'credential addr'

ptxOutAddress :: Term s PTxOut -> Term s PAddress
ptxOutAddress =
flip pmatch $ \txo ->
ptxOut'address txo

ptxOutCredential :: Term s PTxOut -> Term s PCredential
ptxOutCredential =
paddressCredential . ptxOutAddress

ptxOutValue :: Term s PTxOut -> Term s (PAsData (PValue 'AssocMap.Sorted 'Positive))
ptxOutValue =
flip pmatch $ \txo ->
ptxOut'value txo

ptxInInfoResolved :: Term s PTxInInfo -> Term s PTxOut
ptxInInfoResolved txInInfo =
pmatch txInInfo $ \txInInfo' ->
ptxInInfo'resolved txInInfo'

ptxInInfoOutRef :: Term s PTxInInfo -> Term s PTxOutRef
ptxInInfoOutRef txInInfo =
pmatch txInInfo $ \txInInfo' ->
ptxInInfo'outRef txInInfo'

pscriptContextTxInfo :: Term s PScriptContext -> Term s PTxInfo
pscriptContextTxInfo ctx =
pmatch ctx $ \ctx' ->
pscriptContext'txInfo ctx'

ptxInfoSignatories :: Term s PTxInfo -> Term s (PAsData (PBuiltinList (PAsData PPubKeyHash)))
ptxInfoSignatories =
flip pmatch $ \txInfo ->
ptxInfo'signatories txInfo
73 changes: 0 additions & 73 deletions src/plutarch-onchain-lib/lib/Plutarch/Core/FieldBinds.hs

This file was deleted.

42 changes: 42 additions & 0 deletions src/plutarch-onchain-lib/lib/Plutarch/Core/Integrity.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{-# LANGUAGE OverloadedStrings #-}

module Plutarch.Core.Integrity (
pisScriptCredential,
pisPubKeyCredential,
pdeserializeCredential,
) where

import Plutarch.Core.List
import Plutarch.Prelude
import Plutarch.LedgerApi.V3 (PCredential)

-- | Check that a data-encoded Credential is a ScriptCredential.
-- This does not guarantee that the data-encoded term is structurally a valid Credential.
-- So this should only be used if the data-encoded term is known to be a Credential.
-- If the term is obtained from relevant fields of the ScriptContext or TxInfo, then this check is safe
-- because the ledger guarantees the structural validity of the Credential.
pisScriptCredential :: Term s (PAsData PCredential) -> Term s PBool
pisScriptCredential cred = (pfstBuiltin # (pasConstr # pforgetData cred)) #== 1

-- | Check if the provided data-encoded Credential is a PubKeyCredential.
-- This does not guarantee that the data-encoded term is structurally a valid Credential.
-- So this should only be used if the data-encoded term is known to be a Credential.
-- If the term is obtained from relevant fields of the ScriptContext or TxInfo, then this check is safe
-- because the ledger guarantees the structural validity of the Credential.
pisPubKeyCredential :: Term s (PAsData PCredential) -> Term s PBool
pisPubKeyCredential cred = (pfstBuiltin # (pasConstr # pforgetData cred)) #== 0

-- | Check if the provided data-encoded term has the expected builtin data representation of a credential.
pdeserializeCredential :: Term s (PAsData PCredential) -> Term s (PAsData PCredential)
pdeserializeCredential term =
plet (pasConstr # pforgetData term) $ \constrPair ->
plet (pfstBuiltin # constrPair) $ \constrIdx ->
pif (plengthBS # (pasByteStr # (pheadSingleton # (psndBuiltin # constrPair))) #== 28)
(
pcond
[ ( constrIdx #== 0 , term)
, ( constrIdx #== 1 , term)
]
(ptraceInfoError "Invalid credential")
)
perror
2 changes: 1 addition & 1 deletion src/plutarch-onchain-lib/lib/Plutarch/Core/PByteString.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import Plutarch.Prelude
-- | Checks if a tokenName is prefixed by a certain ByteString
pisPrefixedWith :: ClosedTerm (PTokenName :--> PByteString :--> PBool)
pisPrefixedWith = plam $ \tn prefix ->
pmatch (pto tn) $ \(PDataNewtype tnBS) -> pisPrefixOf # prefix # pfromData tnBS
pisPrefixOf # prefix # pto tn

-- | Checks if the first ByteString is a prefix of the second
pisPrefixOf :: ClosedTerm (PByteString :--> PByteString :--> PBool)
Expand Down
66 changes: 36 additions & 30 deletions src/plutarch-onchain-lib/lib/Plutarch/Core/Time.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ module Plutarch.Core.Time (
pvalidityRangeStart,
pvalidityRangeEnd,
ptoCustomFiniteRangeH,
pisFinite
pisFinite,
) where

import GHC.Generics (Generic)
import Plutarch.Core.Data (pnonew)
import Plutarch.LedgerApi.V3 (PExtended (PFinite), PInterval (..),
PLowerBound (PLowerBound), PPosixTime (..),
PUpperBound (PUpperBound))
PUpperBound (PUpperBound), unPPosixTime)
import Plutarch.Monadic qualified as P
import Plutarch.Prelude
import Plutarch.Unsafe (punsafeCoerce)

type PPosixTimeRange = PInterval PPosixTime

Expand All @@ -37,50 +37,56 @@ instance DerivePlutusType PPosixFiniteRange where
-- Errors if the provided time range is not finite.
ptoFiniteRange :: Term s (PPosixTimeRange :--> PPosixFiniteRange)
ptoFiniteRange = phoistAcyclic $ plam $ \timeRange -> P.do
timeRangeF <- pletFields @'["from", "to"] timeRange
PLowerBound lb <- pmatch timeRangeF.from
PFinite ((pfield @"_0" #) -> start) <- pmatch (pfield @"_0" # lb)
PUpperBound ub <- pmatch timeRangeF.to
PFinite ((pfield @"_0" #) -> end) <- pmatch (pfield @"_0" # ub)
pcon $ PPosixFiniteRange { from = start, to = end }
PInterval lowerBound upperBound <- pmatch timeRange
PLowerBound lb _ <- pmatch lowerBound
PFinite start <- pmatch lb
PUpperBound ub _ <- pmatch upperBound
PFinite end <- pmatch ub
pcon $ PPosixFiniteRange { from = pfromData start, to = pfromData end }

-- | Get the start time of a 'PPosixTimeRange'.
-- Errors if the start time is not finite.
pvalidityRangeStart :: Term s (PPosixTimeRange :--> PAsData PInteger)
pvalidityRangeStart = phoistAcyclic $ plam $ \timeRange -> P.do
PInterval ((pfield @"from" #) -> startTime) <- pmatch timeRange
PLowerBound lb <- pmatch startTime
PFinite ((pfield @"_0" #) -> posixTime) <- pmatch (pfield @"_0" # lb)
pmatch posixTime $ \(PPosixTime pt) -> pmatch pt $ \(PDataNewtype t) -> t
interval <- pmatch timeRange
let startTime = pinteral'from interval
--PInterval ((pfield @"from" #) -> startTime) <- pmatch timeRange
PLowerBound lb _ <- pmatch startTime
PFinite posixTime <- pmatch lb
punsafeCoerce $ pto posixTime

-- | Get the end time of a 'PPosixTimeRange'.
-- Errors if the end time is not finite.
pvalidityRangeEnd :: Term s (PPosixTimeRange :--> PAsData PInteger)
pvalidityRangeEnd = phoistAcyclic $ plam $ \timeRange -> P.do
PInterval ((pfield @"to" #) -> to_) <- pmatch timeRange
PUpperBound ub <- pmatch to_
PFinite ((pfield @"_0" #) -> posixTime) <- pmatch (pfield @"_0" # ub)
pmatch posixTime $ \(PPosixTime pt) -> pmatch pt $ \(PDataNewtype t) -> t
interval <- pmatch timeRange
let to_ = pinteral'to interval
PUpperBound ub _ <- pmatch to_
PFinite posixTime <- pmatch ub
punsafeCoerce $ pto posixTime

-- | Extract the start and end times from a 'PPosixTimeRange' as Integers
-- and return them as a pair via CPS.
-- Errors if the start or end time is not finite.
ptoCustomFiniteRangeH :: Term s PPosixTimeRange -> TermCont @r s (Term s PInteger, Term s PInteger)
ptoCustomFiniteRangeH timeRange = do
timeRangeF <- pletFieldsC @'["from", "to"] timeRange
PLowerBound lb <- pmatchC timeRangeF.from
PFinite ((pfield @"_0" #) -> start) <- pmatchC (pfield @"_0" # lb)
PUpperBound ub <- pmatchC timeRangeF.to
PFinite ((pfield @"_0" #) -> end) <- pmatchC (pfield @"_0" # ub)
pure (pnonew $ pfromData start, pnonew $ pfromData end)
(PInterval from_ to_) <- pmatchC timeRange
PLowerBound lb _ <- pmatchC from_
PFinite (pfromData -> start) <- pmatchC lb
PUpperBound ub _ <- pmatchC to_
PFinite (pfromData -> end) <- pmatchC ub
pure (unPPosixTime start, unPPosixTime end)

-- | Check if a 'PPosixTimeRange' is finite.
pisFinite :: Term s (PInterval PPosixTime :--> PBool)
pisFinite = plam $ \i ->
let isFiniteFrom = pmatch (pfield @"_0" # (pfield @"from" # i)) $ \case
PFinite _ -> pconstant True
_ -> pconstant False
isFiniteTo = pmatch (pfield @"_0" # (pfield @"to" # i)) $ \case
PFinite _ -> pconstant True
_ -> pconstant False
in pand' # isFiniteFrom # isFiniteTo
pmatch i $ \(PInterval start' end') ->
pmatch start' $ \(PLowerBound start _) ->
pmatch end' $ \(PUpperBound end _) ->
let isFiniteFrom = pmatch start $ \case
PFinite _ -> pconstant True
_ -> pconstant False
isFiniteTo = pmatch end $ \case
PFinite _ -> pconstant True
_ -> pconstant False
in pand' # isFiniteFrom # isFiniteTo
Loading

0 comments on commit 508ee6c

Please sign in to comment.