Skip to content

Commit 2e71a80

Browse files
committed
Review changes
1 parent 4b34a06 commit 2e71a80

File tree

1 file changed

+56
-2
lines changed

1 file changed

+56
-2
lines changed

docs/ADR-10-cardano-api-script-witness-api.md

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,35 @@ data Witnessable thing era where
7373
=> Voter -> Witnessable Voter era
7474
WitProposal :: L.ConwayEraScript era => Proposal -> Witnessable Proposal era
7575

76+
instance Ord (Witnessable thing era) where
77+
compare a b =
78+
case (a, b) of
79+
(WitTxIn txinA, WitTxIn txinB) -> compare txinA txinB
80+
(WitTxCert (certA, _), WitTxCert (certB, _)) -> compare certA certB
81+
(WitMint mintA, WitMint mintB) -> compare mintA mintB
82+
(WitWithdrawal (stakeAddrA, _), WitWithdrawal (stakeAddrB, _)) -> compare stakeAddrA stakeAddrB
83+
(WitVote voterA, WitVote voterB) -> compare voterA voterB
84+
(WitProposal propA, WitProposal propB) -> compare propA propB
85+
86+
type Mint = (PolicyId, AssetName, Quantity)
87+
88+
type Withdrawal = (StakeAddress, L.Coin)
89+
90+
type Cert = (AnyCertificate, StakeCredential)
91+
92+
type Voter = Api.AnyVoter
93+
94+
type Proposal = Api.AnyProposal
95+
96+
7697
data AnyWitness era where
7798
AnyKeyWitness :: AnyWitness era
7899
AnySimpleScriptWitness :: SimpleScriptOrReferenceInput era -> AnyWitness era
79100
AnyPlutusScriptWitness :: PlutusScriptWitness lang purpose era -> AnyWitness era
80101
```
81102

103+
NB: See `class GetPlutusScriptPurpose` to understand the purpose of the ledger constraints in `Witnessable thing era` constructor.
104+
82105
And the upshot is once we have `[(Witnessable thing era, AnyWitness era)]` these can be uniformly treated to construct the redeemer pointer map (`Redeemers era`):
83106

84107
```haskell
@@ -96,6 +119,16 @@ getTxScriptWitnessesRequirements
96119
-> TxScriptWitnessRequirements (ShelleyLedgerEra era)
97120
getTxScriptWitnessesRequirements eon wits =
98121
obtainMonoidConstraint eon $ mconcat $ map (getTxScriptWitnessRequirements eon) wits
122+
123+
124+
obtainMonoidConstraint
125+
:: AlonzoEraOnwards era
126+
-> (Monoid (TxScriptWitnessRequirements (ShelleyLedgerEra era)) => a)
127+
-> a
128+
obtainMonoidConstraint eon = case eon of
129+
AlonzoEraOnwardsAlonzo -> id
130+
AlonzoEraOnwardsBabbage -> id
131+
AlonzoEraOnwardsConway -> id
99132
```
100133

101134
## New `IndexedPlutusScriptWitness` types
@@ -112,7 +145,7 @@ data IndexedPlutusScriptWitness witnessable (lang :: L.Language) (purpose :: Plu
112145
```
113146

114147
We do away with `cardano-api`'s `ScriptWitnessIndex` and directly use `cardano-ledger`'s `PlutusPurpose AsIx era` which is essentially the same thing.
115-
The benefit here is we get to use ledger type classes to calculate the index of the plutus script witness thing we are interested in:
148+
The benefit here is we get to use ledger type classes to produce the index of the plutus script witness thing we are interested in:
116149

117150
```haskell
118151
class GetPlutusScriptPurpose era where
@@ -130,6 +163,8 @@ instance GetPlutusScriptPurpose era where
130163
toPlutusScriptPurpose index WitProposal{} = L.mkProposingPurpose (L.AsIx index)
131164
```
132165

166+
The ledger constraints in the `Witnessable thing era` data constructors allow us to directly construct the script witness index (`PlutusPurpose AsIx era`) with the `toPlutusScriptPurpose` class method. We no longer have to use the old api's `ScriptWitnessIndex` which is eventually converted into a `PlutusPurpose AsIx era`. This approach is more direct.
167+
133168
This ultimately allows us to collapse all of the different index calculation functions into a single function:
134169

135170
```haskell
@@ -148,7 +183,10 @@ createIndexedPlutusScriptWitnesses witnessableThings =
148183
[ AnyIndexedPlutusScriptWitness $ createIndexedPlutusScriptWitness index thing sWit
149184
| (index, (thing, AnyPlutusScriptWitness sWit)) <- zip [0 ..] witnessableThings
150185
]
186+
where
187+
enforceOrdering = List.sortBy (compare `on` fst)
151188
```
189+
152190
## New `PlutusScriptInEra` type
153191

154192

@@ -157,7 +195,23 @@ data PlutusScriptInEra (lang :: L.Language) era where
157195
PlutusScriptInEra :: PlutusRunnable lang -> PlutusScriptInEra lang era
158196
```
159197

160-
Why PlutusRunnable? Mainly for deserialization benefits. The deserialization of this type looks at the major protocol version and the script language to determine if indeed the script is runnable.
198+
Why PlutusRunnable? Mainly for deserialization benefits. The deserialization of this type looks at the major protocol version and the script language to determine if indeed the script is runnable. This is the decode CBOR instance in `cardano-ledger`:
199+
200+
```haskell
201+
instance PlutusLanguage l => DecCBOR (PlutusRunnable l) where
202+
decCBOR = do
203+
plutus <- decCBOR
204+
pv <- getDecoderVersion
205+
either (fail . show) pure $ decodePlutusRunnable pv plutus
206+
```
207+
`decodePlutusRunnable` eventually calls a deserialization function in the `plutus` repo which will fail if
208+
the plutus script version you are using is not available in a given era.
209+
210+
A ficticious example: The plutus team introduces PlutusV4. This plutus script version can only be used in the era after Conway (Conway + 1).
211+
However a user tries to use a PlutusV4 script in Conway. Because we use `PlutusRunnable` to represent our plutus scripts we would get a deserialization error.
212+
If we stuck with `ShortByteString` to represent plutus scripts, the error would only occur at transaction submission or when using `transaction build`.
213+
This is a small QOL improvement as now if your script deserializes at least you know it's valid for a particular era.
214+
161215

162216
## New `PlutusScriptDatum` type
163217

0 commit comments

Comments
 (0)