Skip to content
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

CPS-0004? | Spending Script Redundant Execution #418

Closed
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5504768
Added the CPS README with a possible solution
Dec 20, 2022
803e0bf
Capitalized parts of Title in yaml
fallen-icarus Dec 20, 2022
3a04f25
grammar
fallen-icarus Dec 20, 2022
f4a519f
Changed the category to plutus
fallen-icarus Dec 20, 2022
d632850
Updated the readme
Jan 7, 2023
7816bf8
Added suggestion about possible low level representation for Maybe Datum
Jan 7, 2023
823fb16
Added more to low level suggestion
fallen-icarus Jan 7, 2023
c8d916d
Edited `Maybe Datum` low level representation section.
Jan 8, 2023
7b142f8
Added comment about hardcoding into plutus.
Jan 8, 2023
e4010db
Added haddock documentation supporting possible use for negative de b…
Jan 8, 2023
acd3162
Added more comments.
Jan 8, 2023
9ffb99e
Spelling
fallen-icarus Jan 8, 2023
57235ea
Replaced low-level spec with simpler one
Jan 9, 2023
3f9cb9d
Added comment to abstract
fallen-icarus Jan 9, 2023
59135d2
Removed High-level adjective
fallen-icarus Jan 9, 2023
9939892
Added specification in terms of Data too
Jan 9, 2023
0fd5b1a
Removed proposed solution and cut down on extraneous info in examples.
Jan 17, 2023
60be8b5
Merge branch 'cardano-foundation:master' into full-eUTxO-potential
fallen-icarus Jan 17, 2023
068bbd8
Capitalized UTxO
Jan 17, 2023
cd657fd
Edits
Jan 17, 2023
6a7f67a
Replaced problem example with an easy to understand scenario. + edits
Jan 18, 2023
40b37c4
Edited multisig use case
Jan 18, 2023
fd604a3
Broke equation over multiple lines
Jan 18, 2023
f9cc61c
Fixed equation
Jan 18, 2023
808c528
removed period in equation
Jan 18, 2023
0618887
Removed multisig use case until confirmed. Edits.
Jan 19, 2023
b4946f2
Added comments about simple scripts
Jan 19, 2023
6571789
Merge branch 'cardano-foundation:master' into full-eUTxO-potential
fallen-icarus Jan 23, 2023
64f1061
added missing space
Jan 23, 2023
7f9f238
fixating CPS number to facilitate incoming references
rphair Apr 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions CPS-????/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
CPS: 4
Title: Spending Script Redundant Executions
Status: Open
Category: Plutus
Authors:
- fallen-icarus <modern.daidalos@gmail.com>
Proposed Solutions: []
Discussions:
- https://github.com/cardano-foundation/CIPs/issues/417
Created: 2022-12-20
---
# CPS-XXXX: Spending Script Redundant Executions

## Abstract
Plutus spendings scripts are currently executed once for every UTxO being consumed from the script's address. However, there are use cases where the validity of the transaction depends on the transaction as a whole and not on any individual UTxO. The eUTxO model allows a spending script to see the entire transaction context which means it is already possible to create scripts that validate based on the transaction as a whole. As of now, spending scripts that do this are forced to be executed once per UTxO even if these extra executions are completely redundant. Not only does this waste computational resources, but it can also result in the transaction fee growing quickly based on the number of UTxOs being consumed from the relevant script address. There is a technique that can be used to minimize this limitation but it has its own drawbacks.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, there are use cases where the validity of the transaction depends on the transaction as a whole and not on any individual UTxO.

Perhaps it's clearer to say that they don't depend on any details of which UTXO is being spent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fallen-icarus what technique can be used already to minimise this drawback?

Copy link
Author

@fallen-icarus fallen-icarus Apr 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matiwinnetou The Current Alternative lays it out. In a nut shell, since you can make a plutus staking script execute only once for a given transaction, you off-load the heavy computation to that script. Then the spending plutus script just checks if the staking script was executed in the tx.

The idea is similar to what is being discussed in #309.


## Problem
Imagine a scenario where Alice would like to trustlessly swap assets with Bob. An atomic swap contract is used and any UTxOs that are to be swapped contain an inline datum of an asking price. Here is a table to represent all of Alice's available UTxOs to swap (at the atomic swap script address):

|UTxO ID| Asking Price|Amount|
|--|--|--|
| 1 | 1.5 DUST/ADA | 10 ADA |
| 2 | 2 DUST/ADA | 20 ADA |
| 3 | 1 DUST/ADA | 5 ADA |

If Bob wants to swap his DUST for Alice's ADA, he will need to satisfy Alice's asking price. As an example, if he wants to take all 10 ADA from UTxO 1, he will need to deposit 15 DUST to Alice's atomic swap address in the same transaction that consumes UTxO 1.

But what if he wants to swap his DUST for 25 ADA? That would require using at least two of Alice's UTxOs. Doing this is trivial for the atomic swap contract because it validates based off of the transaction as a whole:

``` Txt
The value being deposited to the swap address must be >=
the value withdrawn from the swap address *
the weighted average asking price of all UTxOs being spent from the swap address
```

This brings us to the problem: **there is currently no way to efficiently use a plutus spending script that validates based off of the transaction as a whole**. (These scripts will be called *transaction level spending scripts* for the rest of this CPS). With the current design of Cardano, if Bob consumed UTxO 2 and UTxO 3 in the same transaction to satisfy his desire for 25 ADA, the atomic swap contract will be executed twice. Since the transaction context doesn't change between executions, the second execution is completely redundant.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the transaction context doesn't change between executions, the second execution is completely redundant

Do you mean "script context"? The script context does change, in that it contains information about which script is executing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I specifically mean the TxInfo part of the ScriptContext.


Any time a developer creates a transaction level spending script, it will be redundantly executed for every additional UTxO consumed from the corresponding script address. These redundant executions are a waste of scarce resources and result in much higher fees for end users. Not only that, but the inability to efficiently use these transaction level spending scripts significantly handicaps the use of the eUTxO model. The eUTxO model already allows for creating such spending scripts; developers are just unable to properly use them.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure you've quite argued that it's a significant handicap :)


### The Current Alternative
The alternative involves taking advantage of the fact that staking scripts do not suffer from the same limitation as spending scripts.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the explanation for why this works is wrong. Staking scripts do get information about what script is running and do get redeemers.

The reason this works is because you get all your spending scripts to coordinate on delegating to a single other script execution. You could do exactly this trick with another spending script: spend an additional UTXO locked with a script that does the "real work", and have all the other UTXO spending scripts just assert that that script is being spent in the transaction. Same effect!

Copy link
Author

@fallen-icarus fallen-icarus Feb 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your reason does not account for everything in the actual implementation. Using another spending script was discussed here. It is not a viable solution because it creates a bottleneck problem: you are only as concurrent as the number of utxos available at the spending script being delegated to. This bottleneck problem does not exist for staking scripts since no utxos are needed to force execution of the script.

Edit: wrong comment

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Staking scripts do get information about what script is running and do get redeemers.

As I said here, I do not believe having a redeemer or info about what script is running is an issue. In fact, I think removing access about which script is currently running is a major problem because it is a major part of securing certain dapp designs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is not that it's a workaround, my point is that your explanation for why it works is wrong.


> Given a [spending] script **s**, you can turn it into a [spending] script **s'** that checks that 0 ADA is withdrawn from a [staking] script **s''** with the same logic as **s**. This is a transformation that is valid for any [spending] script. -- @L-as

In a nut shell, you use a staking script **AS** a spending script. The transaction level logic would be in the staking script. Meanwhile, the spending script just checks that both the required staking script is executed AND 0 ADA is withdrawn from the rewards address within the transaction. The withdrawal of the 0 ADA is necessary to force the staking script to be executed.

The only requirement to use this technique is that the script address must have been created using the `s'` spending script and the `s''` staking script. The staking address DOES NOT need to actually have rewards or even be delegated/registered for this technique to work.

With this method, the main computation is only executed once no matter how many UTxOs are spent from the script address.

#### The Drawbacks

1. This technique now means that everything requires two plutus scripts instead of just one. While the spending script can be made extremely small, this doesn't change the fact that two are now needed.
2. This technique DOES NOT stop the redundant executions; the spending script will still redundantly check if the required staking script was executed. This technique just minimizes the cost of the redundant executions by moving the heavy computation into a script that is only executed once per transaction.
3. This is not the intended use for staking scripts.

### Simple Scripts
I tried to test Cardano simple scripts to determine if this problem also impacts them. However, given that simple scripts are so small, it was hard to tell from just looking at the transaction fee. Since the interface for using Cardano simple scripts is the same as for using plutus scripts, I have to assume that this problem also impacts simple scripts.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's quite likely that it does affect them.


If simple scripts are indeed impacted by this problem, the above technique would not work for them. The technique only works for plutus scripts.

## Use Cases
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see a lot more detail here, of the level that there is for the swap example. At the moment it looks to me like there is one convincing usecase, which isn't much.

Any time a spending script's validation depends on the entire transaction and not on any particular UTxO.

1. P2P Atomic Swaps - within one transaction, the value entering the swap address must be some proportion of the value leaving the swap address
Copy link
Collaborator

@rphair rphair Mar 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be fair to ask for a more detailed explanation of the P2P Atomic Swaps use case? This may be naïve (and I'm not technically capable of joining the debate of the proposal particulars) but if a treatment of this issue is helpful in implementing atomic swaps on Cardano, then I believe this use case should be covered in detail in the document... to progress this CPS and any CIP that facilitates that treatment.

I'm trying to get more reviewers based on interest in the Atomic Swap idea as you've described it on GitHub. If in agreement with what I've said above, I also think this repository should be linked from the CPS itself. Here is what I posted about fallen-icarus/cardano-swaps (please correct me if I've described the issue inaccurately or naïvely) in the Cardano MBO on Matrix:

I've been watching this concept develop from #418 and I don't think third party reviewers have been giving it enough credit, or even enough attention. I don't know every technical underpinning of every current & proposed DEX on Cardano but in the meantime this idea seems unique to me. I do wish I could do more to promote this idea since my own technical shortcomings make it impossible for me to convincingly push ahead any proposed standards that would be required to make this happen. I can only hope key people at IOG, CF, and Cardano dev agencies can take a serious look at how significant it would be for the industry & Cardano's own marketplace to support a true non-custodial DEX. 😯

https://matrix.to/#/!QvtUklhUfmEuCBIexz:matrix.org/$lU0OwYOAQXpNYVFJl1I33YPhhQ_wH14Jzu5etQP9Drk?via=matrix.adamantium.online&via=matrix.org&via=forum.balanceanalytics.io

Copy link
Author

@fallen-icarus fallen-icarus Mar 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be fair to ask for a more detailed explanation of the P2P Atomic Swaps use case?

I fully intend to do this. However, I believe these redundant executions impact all distributed dapp designs, not just atomic swaps. In addition to this, I think people are underestimating the usefulness of atomic swaps; I believe you can slightly alter the logic from cardano-swaps to create a distributed p2p lending protocol. To prove it, I am currently working on a p2p lending proof-of-concept that does this. I have already finished the on-chain code for it; I just need to finish the helper cli program and the documentation. I hope to be done with it within a week or two. After that, I have an idea of how to create a distributed DAO where users maintain custody and delegation control while still enabling the DAO to spend funds from user wallets when certain conditions are met (such as a multisig). Again, it uses a similar design to cardano-swaps. The DAO design is pretty simple and I should hopefully finish it within a week or two of starting it.

All of the proof-of-concepts are impacted by the redundant executions. I would like to finish both the p2p lending and the distributed DAO implementations so that I can really emphasize why this problem should be fixed. I intend to link all three proof-of-concepts in the CPS once done. I appreciate your helping to spread the word and I agree that (until zhekson1's recent tweet) the design was not being taken seriously enough, although, I understand why since this idea is coming from an unknown community member. If there is enough of a demand, I can look to rewrite the CPS before finishing the other proof-of-concepts. I could possibly still explain the p2p lending design and the DAO design, just without being able to point to working prototypes.

2. P2P Lending - within one transaction, the amount borrowed must be some proportion of the amount posted as collateral. Likewise, the amount of collateral reclaimed depends on how much of the loan is repaid.
3. DAOs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is far too loose. It seems false for many examples that I can think of? In particular, any application that relies on the script knowing its own address relies on the ability to know which script is executing.

4. (Assuming simple scripts also suffer from this problem) Multisig
5. (Assuming simple scripts also suffer from this problem) Time Locking

## Goals
1. Stop redundantly executing transaction level spending scripts.
2. Do not remove the option to allow script execution per UTxO. There are still use cases where the script should validate based off individual UTxOs. Also, there could be cases where this option is more efficient than having to traverse the transaction's context to get the relevant datum. An example of this latter case is when only one UTxO is consumed from a script address.
3. Try to use the ledger as is. The way scripts are stored onchain should not change unless absolutely necessary.
4. Try to leave the developer experience as untouched as possible. We don't want to make developers re-learn plutus.
5. Do not add too much new overhead to already resource constrained plutus scripts.

## Open Questions
1. Would this require a hardfork?
2. Would this require a new version of plutus?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The answer to both of these questions is almost certainly yes.