-
Notifications
You must be signed in to change notification settings - Fork 377
CIP-0172? | Self-Usable Transaction Outputs #1135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
890f163
b03fee5
0e01420
ff72346
34b7c27
2b5e04f
cd2b8d3
405f1a7
63ea4c1
44110be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,119 @@ | ||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||
| CIP: 172 | ||||||||||||||||||||||||||||||
| Title: Self-Usable Transaction Outputs | ||||||||||||||||||||||||||||||
| Status: Proposed | ||||||||||||||||||||||||||||||
| Category: Ledger | ||||||||||||||||||||||||||||||
| Authors: | ||||||||||||||||||||||||||||||
| - Carlos Tomé Cortiñas <carlos.tome-cortinas@iohk.io> | ||||||||||||||||||||||||||||||
| Implementors: | ||||||||||||||||||||||||||||||
| Discussions: | ||||||||||||||||||||||||||||||
| Created: 2026-01-15 | ||||||||||||||||||||||||||||||
| License: CC-BY-4.0 | ||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Abstract | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| We propose to allow transactions to reference scripts and data present on their | ||||||||||||||||||||||||||||||
| own outputs during validation. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Motivation: Why is this CIP necessary? | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Transaction outputs carry scripts (via reference scripts) and/or data (via | ||||||||||||||||||||||||||||||
| inline datum). However, the Cardano Ledger currently enforces a restriction | ||||||||||||||||||||||||||||||
| that prevents a transaction from satisfying its validation requirements using | ||||||||||||||||||||||||||||||
| scripts and data contained within its own outputs. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| This restriction creates a specific inefficiency: if a transaction produces an | ||||||||||||||||||||||||||||||
| output containing a script or datum that is also required to validate that same | ||||||||||||||||||||||||||||||
| transaction, the transaction cannot utilize the copy present in the output. | ||||||||||||||||||||||||||||||
| Instead, the transaction must provide a redundant copy of the same script or | ||||||||||||||||||||||||||||||
| data (e.g., in the transaction witnesses). This forced redundancy increases | ||||||||||||||||||||||||||||||
| transaction size, and thus transaction fees, directly inflating the costs | ||||||||||||||||||||||||||||||
| incurred by users. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| In combination with the upcoming feature of [nested transactions](https://github.com/cardano-foundation/CIPs/blob/master/CIP-0118/README.md), in the | ||||||||||||||||||||||||||||||
| Dijkstra era, the current restriction imposes a strict constraint in how | ||||||||||||||||||||||||||||||
| scripts and/or data can be shared within a batch. Specifically, without this | ||||||||||||||||||||||||||||||
| proposal, scripts and/or data produced in transaction outputs are only | ||||||||||||||||||||||||||||||
| accessible to subsequent sub-transactions (via reference inputs). This forces | ||||||||||||||||||||||||||||||
| transaction builders to artificially order transactions or to provide redundant | ||||||||||||||||||||||||||||||
| copies of the same script or data (e.g., if two sub-transactions mutually | ||||||||||||||||||||||||||||||
| depend on each other's script and/or data). | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The key idea of this CIP is to remove this restriction, allowing transactions | ||||||||||||||||||||||||||||||
rphair marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||
| to reference their own outputs for validation purposes. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Use cases | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### Stateful dApps | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Even for simple dApps consisting of a single script, currently deploying these | ||||||||||||||||||||||||||||||
| dApps on Cardano requires multiple transactions. The minimal workflow for such | ||||||||||||||||||||||||||||||
| a stateful dApp requires (1) deploying the dApp's script in the UTxO and (2) | ||||||||||||||||||||||||||||||
| referencing this script (via reference inputs) to mint the relevant state | ||||||||||||||||||||||||||||||
| tokens. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| With the proposed changes, such applications could be deployed in a single | ||||||||||||||||||||||||||||||
| transaction, which simultaneously produces the reference script UTxO's and | ||||||||||||||||||||||||||||||
| mints the state token. This eliminates the need for submitting multiple | ||||||||||||||||||||||||||||||
| transactions, thereby reducing costs, while at the same time improving the | ||||||||||||||||||||||||||||||
| developer's experience. | ||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is a reference script at all needed in this use case? This exact annoyance could guide a dApp developer to not use reference scripts, but just include the script in the witness set of the transaction that mints the tokens. Thus, only incurring a transaction fee and not require the additional deposit for the reference script in the output (which grows the utxo state, that must be paid).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comparing to just including the witness set, adding a script to the UTxO will require the user to lock up the funds in the form of minUtxO, so that is the motivating factor against it. Which means the only reason why a user would want to do this instead of just using a script in witnesses is for further reuse. So, this statement is incorrect: "not require the additional deposit for the reference script" There is still deposit for including a script in the output.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The point is that the script that is used to deploy the initial state tokens will of-course be reused. IE. A DEX pool script (minting policy and spending validator multi-validator). Right now you need to deploy reference scripts, and create the pool in two separate txs. You could just mint the tokens providing pool script as witness and then deploy reference scripts after but that's still two txs.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then, it was just not clear to me as a reader that this example is not an isolated usage, but the optimization of combined publishing scripts as reference + the first usage in the same transaction. The example was helpful and I suggest it should be added to the CIP / existing examples be made more concrete.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @carlostome I think adding such an example would help make the proposal more "user friendly" - which has been important for other CIPs to keep people aware of best-practice design patterns. |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### Nested transactions: order-agnostic script sharing across a batch | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The nested transactions CIP specifies that scripts are to be shared among all | ||||||||||||||||||||||||||||||
| sub- and top-level transactions within a batch (see [CIP-0118 > Changes to Transaction | ||||||||||||||||||||||||||||||
| Validity](https://github.com/carlostome/CIPs/tree/master/CIP-0118#changes-to-transaction-validity)). | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| With the current restriction, this requirement can only be partially achieved | ||||||||||||||||||||||||||||||
| by sharing scripts either (1) from transaction witnesses or (2) via reference | ||||||||||||||||||||||||||||||
| inputs that point to outputs of sub-transactions in the same batch which have | ||||||||||||||||||||||||||||||
| already been applied to the UTxO state. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| With the proposed change in this CIP, the requirement can be achieved allowing | ||||||||||||||||||||||||||||||
| scripts to be shared directly from transaction outputs, regardless of which | ||||||||||||||||||||||||||||||
| sub- or top-level transaction they appear in. This eliminates the dependency on | ||||||||||||||||||||||||||||||
| processing order and enables more flexible script sharing within the batch. | ||||||||||||||||||||||||||||||
rphair marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Specification | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| There is an [Agda | ||||||||||||||||||||||||||||||
| specification](https://github.com/IntersectMBO/formal-ledger-specifications/tree/carlos/usable-outputs) | ||||||||||||||||||||||||||||||
| prototype of the proposed changes (for Conway). | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Changes to the Ledger logic | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - The function `txscripts` needs to be modified to include scripts from `txouts`. | ||||||||||||||||||||||||||||||
| - The function `getDatum` needs to be modified to include data from `txouts`. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Rationale: How does this CIP achieve its goals? | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The current ledger logic prohibits transactions from accessing their own | ||||||||||||||||||||||||||||||
| outputs during validation. However, this restriction comes at the cost of | ||||||||||||||||||||||||||||||
| redundancy when the same script or datum serves dual purposes: being included | ||||||||||||||||||||||||||||||
| in an output for future use and being required for current validation. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| This CIP achieves its goal by relaxing this restriction so that validation may | ||||||||||||||||||||||||||||||
| reference scripts and data committed in the transaction body’s outputs, which | ||||||||||||||||||||||||||||||
| removes the need to carry duplicate copies in witnesses and reduces transaction | ||||||||||||||||||||||||||||||
| size and fees. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
rphair marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||
| ### Backward compatibility | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The changes proposed in this CIP break backward compatibility of Plutus scripts | ||||||||||||||||||||||||||||||
| whose logic depends on the script being part of the outputs of the transaction | ||||||||||||||||||||||||||||||
| being validated. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Path to Active | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Acceptance Criteria | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - Fully implemented in Cardano node | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Implementation Plan | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - TODO | ||||||||||||||||||||||||||||||
|
Comment on lines
+109
to
+115
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I used https://github.com/carlostome/CIPs/tree/master/CIP-0118#implementation-plan as a template:
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p.s. I can also see (somehow missed before) in the original comment the current uncertainty about implementation in Conway vs. Dijkstra... understandably this would still be |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Copyright | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| This CIP is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode). | ||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow the argument of re-using inlined data.
If a transaction wants to spend an output that carries inlined data, that data would already be in the utxo set and thus the creating tx paid for it. For "normal" datum use, there would only be a datumhash on the utxo and the spending transaction provides the preimage in the witness set. This data resolves across any spent inputs that are parameterized by the same data (hash). I don't know how this evolves for nested transactions but I would expect it to allow re-use of hashed data. For other validation purposes, there is no datum in the context.
So, what exactly motivates the sketched change of
getDatumin the agda spec?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do agree with this point, since datums are not reusable from reference inputs either. This change alone would lead to strange semantic where datum from outputs created can be reused throughout a transaction, while ones specified in inputs and reference inputs cannot. If we are to make such a change it would require its own CIP. However, I vaguely remember discussing this point long time ago with some folks that actually write DApps and their argument against was that it is very rare that a script requires the same data and it is usually fairly small anyways.
I think it would be worthwhile analyzing the chain and see whether there could actually be some space savings if we were to add such feature of inline datums being shared throughout a transaction.