From 91c0493ebf0bc92089504e071dcbc234aac16bc2 Mon Sep 17 00:00:00 2001 From: Ziyang Liu Date: Thu, 14 Mar 2024 12:36:27 -0700 Subject: [PATCH 1/9] CIP-0069 | add Datum to ScriptContext --- CIP-0069/README.md | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/CIP-0069/README.md b/CIP-0069/README.md index aaf4df638..739bc3e12 100644 --- a/CIP-0069/README.md +++ b/CIP-0069/README.md @@ -41,12 +41,29 @@ This primarily manifests in the ability to use a single validator for both minti All the script purposes have a form of `Redeemer -> ScriptContext -> a` except the `Spending` one. It has the following form: `Datum -> Redeemer -> ScriptContext -> a`. This is enforced by the Cardano ledger. -We modify the general signature to be `ScriptArgs -> ScriptContext -> a`. +We make the following modification: + +- The signature of all scripts will be `Redeemer -> ScriptContext -> a`. +- The `ScriptPurpose` type is modified such that the `Spending` variant contains a `Datum`: + +```hs +data ScriptPurpose + = ... + | Spending TxOutRef Datum + ... +``` + +- A new data type `ScriptIdentifier` is created. + It is identical to the original `ScriptPurpose` and is used in the `txInfoRedeemers` map to uniquely identify a script within a transaction. ```hs -data ScriptArgs = - RedeemerOnly Redeemer - | RedeemerAndDatum Redeemer Datum +data ScriptIdentifier + = MintingScript CurrencySymbol + | SpendingScript TxOutRef + | RewardingScript Credential + | CertifyingScript Integer TxCert + | VotingScript Voter + | ProposingScript Integer ProposalProcedure ``` ## Rationale: how does this CIP achieve its goals? From 21c26706336b4f1d571881e637dae9922f12049f Mon Sep 17 00:00:00 2001 From: Ziyang Liu Date: Mon, 18 Mar 2024 17:21:04 -0700 Subject: [PATCH 2/9] Maybe Datum --- CIP-0069/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CIP-0069/README.md b/CIP-0069/README.md index 739bc3e12..ce8c51e85 100644 --- a/CIP-0069/README.md +++ b/CIP-0069/README.md @@ -44,15 +44,17 @@ It has the following form: `Datum -> Redeemer -> ScriptContext -> a`. This is en We make the following modification: - The signature of all scripts will be `Redeemer -> ScriptContext -> a`. -- The `ScriptPurpose` type is modified such that the `Spending` variant contains a `Datum`: +- The `ScriptPurpose` type is modified such that the `Spending` variant contains an optional `Datum`: ```hs data ScriptPurpose = ... - | Spending TxOutRef Datum + | Spending TxOutRef (Maybe Datum) ... ``` +The `Datum` is optional, which will enable us to allow executing spending scripts without a datum. + - A new data type `ScriptIdentifier` is created. It is identical to the original `ScriptPurpose` and is used in the `txInfoRedeemers` map to uniquely identify a script within a transaction. From 39005ff0db811116d39b759169ae58baa4b2da97 Mon Sep 17 00:00:00 2001 From: microproofs Date: Fri, 19 Apr 2024 16:08:24 -0400 Subject: [PATCH 3/9] Push up new specification that changes Plutus scripts to take in 1 argument --- CIP-0069/README.md | 71 +++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/CIP-0069/README.md b/CIP-0069/README.md index ce8c51e85..d64cf33df 100644 --- a/CIP-0069/README.md +++ b/CIP-0069/README.md @@ -22,6 +22,8 @@ The exact change would be to have every validator take as argument the redeemer ## Motivation: why is this CIP necessary? +### Multi-purpose Scripts + As it stands the scripts being made on cardano often suffer this problem, and the tokens usually are made to be able to be minted at any time. This leads to further checks being made on the frontend and further fragilitiy of the systems we create. When a mutual dependency arises we are forced to choose which script gets to statically know what's the hash of the other, and which has to be provided 'during runtime'. - Use Case 1: Minting validator checks datum given to spending validator. The spending validator requires the token be present as witness of the datum's correctness. @@ -30,43 +32,46 @@ As it stands the scripts being made on cardano often suffer this problem, and th - Use Case 3 (taken from Minswap's Dex V1): NFT is minted for the same reason as above. It allows a minting policy to later mint LP tokens with that unique id token name. -We see a similar pattern repeating over and over again as witnessed by dapp developers and auditors alike. By allowing the multi-purpose policies (spending and any other) we increase the security of Cardano by giving us more confidence and allowing to design protocols that have their architecture driven by Cardano's features, not limited by Cardano's language. +We see a similar pattern repeating over and over again as witnessed by dapp developers and auditors alike. By allowing the multi-purpose scripts (spending and any other) we increase the security of Cardano by giving us more confidence and allowing to design protocols that have their architecture driven by Cardano's features, not limited by Cardano's language. This primarily manifests in the ability to use a single validator for both minting and spending but the proposed solution makes it possible to use one validator for any and all purposes at once. -## Specification +### No Datum Spend Purpose -### Removing the datum argument +One of the major footguns of Plutus scripts is if a user sends to the script with a wrong or missing datum. This has happened in the case of the Nami wallet having a bug that caused the wrong address to be chosen. There are other instances of user error where they send from a CEX to a script address. A wrong datum can be handled by the Plutus scripts themselves by having an alternative execution branch if type does not match the expected datum type. But in the case of no datum the script is not run and fails in phase 1 validation. The other motivation of this CIP is to be able to create spend scripts that can handle the no datum case. -All the script purposes have a form of `Redeemer -> ScriptContext -> a` except the `Spending` one. -It has the following form: `Datum -> Redeemer -> ScriptContext -> a`. This is enforced by the Cardano ledger. +I see three major use cases when it comes to running spend scripts without datums: -We make the following modification: +- Use Case 1: A script that acts as a wallet for users. By having no datum spending the user can send directly from exchanges or have friends send to their smart contract wallet with no datum needed. -- The signature of all scripts will be `Redeemer -> ScriptContext -> a`. -- The `ScriptPurpose` type is modified such that the `Spending` variant contains an optional `Datum`: +- Use Case 2: As a DAO treasury. The funds in this script would be controlled by a DAO and anyone can donate/contribute to the DAO without a datum. -```hs -data ScriptPurpose - = ... - | Spending TxOutRef (Maybe Datum) - ... -``` +- Use Case 3: Allow dApp protocols to have a claim or withdraw mechanism (similar to Ethereum for tokens sent to a contract without call) for claiming tokens sent without a datum. -The `Datum` is optional, which will enable us to allow executing spending scripts without a datum. +I'd be remiss if I didn't mention CIP-0112 which has been expanded to improve native script capabilities to provide an alternative solution for use case 1 and 2. But for use case 3, CIP-0112 does not enable a "claim or withdraw mechanism" for contracts. -- A new data type `ScriptIdentifier` is created. - It is identical to the original `ScriptPurpose` and is used in the `txInfoRedeemers` map to uniquely identify a script within a transaction. +## Specification + +### Removing the datum argument -```hs -data ScriptIdentifier - = MintingScript CurrencySymbol - | SpendingScript TxOutRef - | RewardingScript Credential - | CertifyingScript Integer TxCert - | VotingScript Voter - | ProposingScript Integer ProposalProcedure +All the script purposes have a form of ```Redeemer -> ScriptContext -> a``` except the Spending one. It has the following form: ```Datum -> Redeemer -> ScriptContext -> a```. This is enforced by the Cardano ledger. + +We propose to make the following modification: + +The signature of all scripts will be ```ScriptContext -> a```. +The ScriptContext type is now a union type with a variant for each script purpose. +``` +data ScriptContext + = Minting TxInfo Redeemer CurrencySymbol + | Spending TxInfo Redeemer (Maybe Datum) TxOutRef + | Rewarding TxInfo Redeemer Credential + | Certifying TxInfo Redeemer Integer TxCert + | Voting TxInfo Redeemer Voter + | Proposing TxInfo Redeemer Integer ProposalProcedure ``` +The Datum is optional, which will enable us to allow the execution of spending scripts without a datum. + +The ScriptPurpose type is left the same used in the Redeemers Map is left the same. ## Rationale: how does this CIP achieve its goals? @@ -74,6 +79,9 @@ Unifying of the script signature is a very elegant solution to the problem, stre Given that accessing the datum is almost always made by a spending script, it makes sense to introduce that argument back to the `ScriptPurpose` that now plays a more important role. It begs the question if it should be added as an argument to all validators, to further emphasize that fact. + +This CIP turns all scripts into 1 arg scripts with a Script Context union type for each purpose. + ## Backwards compatibility This change is not backwards compatible; it must be introduced in a new Plutus language version. @@ -87,7 +95,18 @@ Node code must be modified. ### Implementation Plan -None. +The Cardano Ledger and Cardano Plutus teams would need to implement this in following repositories: + IntersectMBO/plutus + IntersectMBO/cardano-ledger + +The following languages that compile to uplc would need to update to support the new ScriptContext argument that +is passed in for the next Plutus Version: +Aiken +Helios +Opshin +Plu-ts +Plutarch +Scalus ## Copyright From 7296a6a57d418f1cd00b18c9f1acff280d268e8a Mon Sep 17 00:00:00 2001 From: microproofs Date: Fri, 19 Apr 2024 16:22:00 -0400 Subject: [PATCH 4/9] Add one more line about the relaxing the ledger rule --- CIP-0069/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CIP-0069/README.md b/CIP-0069/README.md index d64cf33df..46963d85a 100644 --- a/CIP-0069/README.md +++ b/CIP-0069/README.md @@ -69,10 +69,14 @@ data ScriptContext | Voting TxInfo Redeemer Voter | Proposing TxInfo Redeemer Integer ProposalProcedure ``` -The Datum is optional, which will enable us to allow the execution of spending scripts without a datum. +The Datum is optional, which will enable us to allow the execution of spending scripts without a datum. +One more change will be needed on the ledger side in order to make the Datum optional for spending scripts. +The ledger UTXOW rule needs to be relaxed, this ledger rule checks if a utxo has an existing datum if the address's payment credential is a phase 2 validation script. The ScriptPurpose type is left the same used in the Redeemers Map is left the same. + + ## Rationale: how does this CIP achieve its goals? Unifying of the script signature is a very elegant solution to the problem, streamlining the experience of developing on cardano. From 048158b2b7ea94d9970286fb9f1bd01efb27efeb Mon Sep 17 00:00:00 2001 From: microproofs Date: Fri, 19 Apr 2024 16:22:38 -0400 Subject: [PATCH 5/9] typo fix --- CIP-0069/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CIP-0069/README.md b/CIP-0069/README.md index 46963d85a..01a1175a8 100644 --- a/CIP-0069/README.md +++ b/CIP-0069/README.md @@ -73,7 +73,7 @@ The Datum is optional, which will enable us to allow the execution of spending s One more change will be needed on the ledger side in order to make the Datum optional for spending scripts. The ledger UTXOW rule needs to be relaxed, this ledger rule checks if a utxo has an existing datum if the address's payment credential is a phase 2 validation script. -The ScriptPurpose type is left the same used in the Redeemers Map is left the same. +The ScriptPurpose type used in the Redeemers Map is left the same. From a8ae5271b777e26a61de52c47073fcd58e96d17a Mon Sep 17 00:00:00 2001 From: Kasey <49739331+MicroProofs@users.noreply.github.com> Date: Fri, 19 Apr 2024 23:33:49 -0400 Subject: [PATCH 6/9] Update CIP-0069/README.md -- ScriptContext type Co-authored-by: Alexey Kuleshevich --- CIP-0069/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CIP-0069/README.md b/CIP-0069/README.md index 01a1175a8..2e656e212 100644 --- a/CIP-0069/README.md +++ b/CIP-0069/README.md @@ -62,12 +62,12 @@ The signature of all scripts will be ```ScriptContext -> a```. The ScriptContext type is now a union type with a variant for each script purpose. ``` data ScriptContext - = Minting TxInfo Redeemer CurrencySymbol - | Spending TxInfo Redeemer (Maybe Datum) TxOutRef - | Rewarding TxInfo Redeemer Credential - | Certifying TxInfo Redeemer Integer TxCert - | Voting TxInfo Redeemer Voter - | Proposing TxInfo Redeemer Integer ProposalProcedure + = SpendingContext TxInfo Redeemer (Maybe Datum) TxOutRef + | MintingContext TxInfo Redeemer CurrencySymbol + | CertifyingContext TxInfo Redeemer Integer TxCert + | RewardingContext TxInfo Redeemer Credential + | VotingContext TxInfo Redeemer Voter + | ProposingContext TxInfo Redeemer Integer ProposalProcedure ``` The Datum is optional, which will enable us to allow the execution of spending scripts without a datum. One more change will be needed on the ledger side in order to make the Datum optional for spending scripts. From 2b85ccd800e5537bdf4397f213e7b129908af021 Mon Sep 17 00:00:00 2001 From: Kasey <49739331+MicroProofs@users.noreply.github.com> Date: Fri, 19 Apr 2024 23:34:29 -0400 Subject: [PATCH 7/9] Update CIP-0069/README.md -- Remove old paragraph Co-authored-by: Alexey Kuleshevich --- CIP-0069/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CIP-0069/README.md b/CIP-0069/README.md index 2e656e212..c950d849b 100644 --- a/CIP-0069/README.md +++ b/CIP-0069/README.md @@ -80,7 +80,6 @@ The ScriptPurpose type used in the Redeemers Map is left the same. ## Rationale: how does this CIP achieve its goals? Unifying of the script signature is a very elegant solution to the problem, streamlining the experience of developing on cardano. -Given that accessing the datum is almost always made by a spending script, it makes sense to introduce that argument back to the `ScriptPurpose` that now plays a more important role. It begs the question if it should be added as an argument to all validators, to further emphasize that fact. From 2d9e392019a3e94c3cf250471325c4c89d8de861 Mon Sep 17 00:00:00 2001 From: microproofs Date: Tue, 30 Apr 2024 12:37:04 -0400 Subject: [PATCH 8/9] update type structure --- CIP-0069/README.md | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/CIP-0069/README.md b/CIP-0069/README.md index c950d849b..4d223afa6 100644 --- a/CIP-0069/README.md +++ b/CIP-0069/README.md @@ -59,15 +59,28 @@ All the script purposes have a form of ```Redeemer -> ScriptContext -> a``` exce We propose to make the following modification: The signature of all scripts will be ```ScriptContext -> a```. -The ScriptContext type is now a union type with a variant for each script purpose. +The ScriptInfo type is a union type with a variant for each script purpose. ``` -data ScriptContext - = SpendingContext TxInfo Redeemer (Maybe Datum) TxOutRef - | MintingContext TxInfo Redeemer CurrencySymbol - | CertifyingContext TxInfo Redeemer Integer TxCert - | RewardingContext TxInfo Redeemer Credential - | VotingContext TxInfo Redeemer Voter - | ProposingContext TxInfo Redeemer Integer ProposalProcedure +data ScriptContext = ScriptContext + { scriptContextTxInfo :: TxInfo + , scriptContextScriptInfo :: ScriptInfo + } + +data ScriptInfo + = MintingScript V2.CurrencySymbol Redeemer + | SpendingScript V3.TxOutRef (Maybe Datum) Redeemer + | RewardingScript V2.Credential Redeemer + | CertifyingScript + Haskell.Integer + -- ^ 0-based index of the given `TxCert` in `txInfoTxCerts` + TxCert + Redeemer + | VotingScript Voter Redeemer + | ProposingScript + Haskell.Integer + -- ^ 0-based index of the given `ProposalProcedure` in `txInfoProposalProcedures` + ProposalProcedure + Redeemer ``` The Datum is optional, which will enable us to allow the execution of spending scripts without a datum. One more change will be needed on the ledger side in order to make the Datum optional for spending scripts. From ffc4c8d1f21026f288a26c14ec46f7e0e10d0258 Mon Sep 17 00:00:00 2001 From: Ziyang Liu Date: Wed, 5 Jun 2024 11:38:55 -0700 Subject: [PATCH 9/9] factor out redeemer --- CIP-0069/README.md | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/CIP-0069/README.md b/CIP-0069/README.md index 4d223afa6..6cc23fd7e 100644 --- a/CIP-0069/README.md +++ b/CIP-0069/README.md @@ -38,7 +38,7 @@ This primarily manifests in the ability to use a single validator for both minti ### No Datum Spend Purpose -One of the major footguns of Plutus scripts is if a user sends to the script with a wrong or missing datum. This has happened in the case of the Nami wallet having a bug that caused the wrong address to be chosen. There are other instances of user error where they send from a CEX to a script address. A wrong datum can be handled by the Plutus scripts themselves by having an alternative execution branch if type does not match the expected datum type. But in the case of no datum the script is not run and fails in phase 1 validation. The other motivation of this CIP is to be able to create spend scripts that can handle the no datum case. +One of the major footguns of Plutus scripts is if a user sends to the script with a wrong or missing datum. This has happened in the case of the Nami wallet having a bug that caused the wrong address to be chosen. There are other instances of user error where they send from a CEX to a script address. A wrong datum can be handled by the Plutus scripts themselves by having an alternative execution branch if type does not match the expected datum type. But in the case of no datum the script is not run and fails in phase 1 validation. The other motivation of this CIP is to be able to create spend scripts that can handle the no datum case. I see three major use cases when it comes to running spend scripts without datums: @@ -59,35 +59,43 @@ All the script purposes have a form of ```Redeemer -> ScriptContext -> a``` exce We propose to make the following modification: The signature of all scripts will be ```ScriptContext -> a```. -The ScriptInfo type is a union type with a variant for each script purpose. -``` +The `ScriptInfo` type is a union type with a variant for each script purpose. +It is the same as `ScriptPurpose`, except for the additional optional datum in spending scripts. + +```haskell +-- | The context that the currently-executing script can access. data ScriptContext = ScriptContext - { scriptContextTxInfo :: TxInfo + { scriptContextTxInfo :: TxInfo + -- ^ information about the transaction the currently-executing script is included in + , scriptContextRedeemer :: V2.Redeemer + -- ^ Redeemer for the currently-executing script , scriptContextScriptInfo :: ScriptInfo + -- ^ the purpose of the currently-executing script, along with information associated + -- with the purpose } +-- | Like `ScriptPurpose` but with an optional datum for spending scripts. data ScriptInfo - = MintingScript V2.CurrencySymbol Redeemer - | SpendingScript V3.TxOutRef (Maybe Datum) Redeemer - | RewardingScript V2.Credential Redeemer + = MintingScript V2.CurrencySymbol + | SpendingScript V3.TxOutRef (Haskell.Maybe V2.Datum) + | RewardingScript V2.Credential | CertifyingScript Haskell.Integer -- ^ 0-based index of the given `TxCert` in `txInfoTxCerts` TxCert - Redeemer - | VotingScript Voter Redeemer + | VotingScript Voter | ProposingScript Haskell.Integer -- ^ 0-based index of the given `ProposalProcedure` in `txInfoProposalProcedures` ProposalProcedure - Redeemer ``` -The Datum is optional, which will enable us to allow the execution of spending scripts without a datum. + +The datum in `SpendingScript` is optional, which will allow the execution of spending scripts without a datum. One more change will be needed on the ledger side in order to make the Datum optional for spending scripts. The ledger UTXOW rule needs to be relaxed, this ledger rule checks if a utxo has an existing datum if the address's payment credential is a phase 2 validation script. The ScriptPurpose type used in the Redeemers Map is left the same. - +It is used to uniquely identify a Plutus script within a transaction. ## Rationale: how does this CIP achieve its goals? @@ -115,7 +123,7 @@ The Cardano Ledger and Cardano Plutus teams would need to implement this in foll IntersectMBO/plutus IntersectMBO/cardano-ledger -The following languages that compile to uplc would need to update to support the new ScriptContext argument that +The following languages that compile to uplc would need to update to support the new ScriptContext argument that is passed in for the next Plutus Version: Aiken Helios