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

Rename and rewrite "Upgrading to Vasil and Plutus script addresses" #6533

Merged
merged 3 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 1 addition & 4 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
:toc: left
:reproducible:

image:https://img.shields.io/matrix/plutus-core%3Amatrix.org[link=https://matrix.to/#/#plutus-core:matrix.org]

== Introduction

Plutus Core is the scripting language embedded in the Cardano ledger and forms the basis of the Plutus Platform, an application development platform for developing distributed applications using the Cardano blockchain.
Expand Down Expand Up @@ -70,7 +68,6 @@ The documentation for the metatheory can be found https://plutus.cardano.interse

== Licensing

You are free to copy, modify, and distribute this software under the terms of the Apache 2.0 license.
You are free to copy, modify, and distribute this software under the terms of the Apache 2.0 license.

See the link:./LICENSE[LICENSE] and link:./NOTICE[NOTICE] files for details.

57 changes: 28 additions & 29 deletions doc/docusaurus/docs/delve-deeper/common-weaknesses.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 20
sidebar_position: 30
---

# Common weaknesses
Expand All @@ -12,77 +12,77 @@ Suppose we have a validator V that implements a typical "atomic swap" or "escrow

> This output can only be spent if, in the same transaction, there is an output sending the agreed-upon payment (encoded in the output's datum) to A.

Now suppose that A and B have two swaps in progress, one for a token T1 at the price of 10 Ada, and one for a token T2 at the same price.
Now suppose that A and B have two swaps in progress, one for a token T1 at the price of 10 Ada, and one for a token T2 at the same price.
That means that there will exist two outputs, both locked by V.

Now B constructs a transaction which spends both outputs, and creates one output addressed to A with 10 Ada (taking T1 and T2 for himself).

![Double satisfaction](../../static/img/double-satisfaction.png)
_A diagram showing the transaction setup for the double satisfaction of two swaps._

A naive implementation of V will just check that the transaction has *an* output to A with 10 Ada in it, and then be satisfied.
But this allows B to "double satisfy" the two validators, because they will both see the same output and be satisfied.
A naive implementation of V will just check that the transaction has *an* output to A with 10 Ada in it, and then be satisfied.
But this allows B to "double satisfy" the two validators, because they will both see the same output and be satisfied.
The end result is that B can get away with paying only 10 Ada to A, even though B's true liability to A is 20 Ada.

### What is going wrong here?

It is difficult to say exactly what is going wrong here.
It is difficult to say exactly what is going wrong here.
Neither validator's expectations are explicitly being violated.

One way of looking at it is that this is a consequence of the fact that validators only *validate*, rather than *doing* things.
In a model like Ethereum's, where smart contracts *make transfers*, then two smart contracts would simply make two transfers, and there would be no problem.
One way of looking at it is that this is a consequence of the fact that validators only *validate*, rather than *doing* things.
In a model like Ethereum's, where smart contracts *make transfers*, then two smart contracts would simply make two transfers, and there would be no problem.
But in the EUTXO model all a validator can do is try to ascertain whether its wishes have been carried out, which in this case is ambiguous.

Following this metaphor, we can see how the same problem could arise in the real world.
Following this metaphor, we can see how the same problem could arise in the real world.
Suppose that two tax auditors from two different departments come to visit you in turn to see if you've paid your taxes.
You come up with a clever scheme to confuse them.
Your tax liability to both departments is $10, so you make a single payment to the tax office's bank account for $10.
When the auditors arrive, you show them your books, containing the payment to the tax office.
You come up with a clever scheme to confuse them.
Your tax liability to both departments is $10, so you make a single payment to the tax office's bank account for $10.
When the auditors arrive, you show them your books, containing the payment to the tax office.
They both leave satisfied.

How do we solve this problem in the real world?
Well, the two tax offices might have different bank accounts, but more likely they would simply require you to use two different payment references.
That way, the payment that each auditor expect to see is unique, so they know it's for them.
We can do something similar in the EUTXO model.
How do we solve this problem in the real world?
Well, the two tax offices might have different bank accounts, but more likely they would simply require you to use two different payment references.
That way, the payment that each auditor expect to see is unique, so they know it's for them.
We can do something similar in the EUTXO model.
See the section on [Unique outputs](#unique-outputs) below.

### Risks

This is a serious problem for many kinds of application.
This is a serious problem for many kinds of application.
Any application that makes payments to specific parties needs to ensure that those payments are correctly identified and don't overlap with other payments.

### Solutions

It's possible that a solution will be developed that makes this weakness easier to avoid.
It's possible that a solution will be developed that makes this weakness easier to avoid.
In the meantime, there are workarounds that developers can use.

#### **Unique outputs**

The simplest workaround is to ensure that the outputs which your scripts care about are unique.
The simplest workaround is to ensure that the outputs which your scripts care about are unique.
This prevents them being confused with other outputs.

In the swap example, if A had used a different key hashes as their payment addresses in each, then one output could not have satisfied both validators, since each one would want an output addressed to a different key hash.

It is not too difficult to use unique outputs.
For payments to users, wallets typically already generate unique key hashes for every payment received.
It is not too difficult to use unique outputs.
For payments to users, wallets typically already generate unique key hashes for every payment received.
For payments to script addresses it is a bit more complicated, and applications may wish to include the equivalent of a "payment reference" in the datum to keep things unique.

#### **Ban other scripts**

A more draconian workaround is for your script to insist that it runs in a transaction which is running no other scripts, so there is no risk of confusion.
A more draconian workaround is for your script to insist that it runs in a transaction which is running no other scripts, so there is no risk of confusion.
Note that it is not enough to consider just validator scripts, minting and reward scripts must also be banned.

However, this prevents even benign usage of multiple scripts in one transaction, which stops people from designing interesting interactions, and may force users to break up transactions unnecessarily.

## Hard limits

Many resources on Cardano are limited in some fashion.
Many resources on Cardano are limited in some fashion.
At a high level, limits can be enforced in two ways:

- *Hard limits*: these are limits which cannot be breached. Typically, these are implemented with specific thresholds, where exceeding the threshold causes a hard failure.
- *Soft limits*: these are limits which *can* be breached, but where there is a significant disincentive to do so. One way of implementing a soft limit is to have sharply increasing costs to using the resource beyond the soft limit.

Hard limits are clear, easy to specify, and provide hard guarantees for the protocol, but they have the disadvantage that there is no way to evade the limit.
Hard limits are clear, easy to specify, and provide hard guarantees for the protocol, but they have the disadvantage that there is no way to evade the limit.
This means that there is a discontinuity at the limit: beforehand you can always do more by paying more, but after the limit there is nothing you can do.

Currently, these resources on Cardano have hard limits:
Expand All @@ -92,7 +92,7 @@ Currently, these resources on Cardano have hard limits:
- UTXO size
- Script execution units

If an application *requires* a transaction that exceeds one of these limits, then the application will be stuck unless the limit is increased or removed.
If an application *requires* a transaction that exceeds one of these limits, then the application will be stuck unless the limit is increased or removed.
This is most common when scripts are involved, since a script can require a very particular shape of transaction, regardless of whether this exceeds limits.

Examples:
Expand All @@ -103,7 +103,7 @@ Examples:

### Risks

This is typically an issue for applications that work with user-supplied data, or data that can grow in an unbounded way over time.
This is typically an issue for applications that work with user-supplied data, or data that can grow in an unbounded way over time.
This can result in data which itself becomes large, or which requires a large amount of resources to process.

For example:
Expand All @@ -121,18 +121,18 @@ In the meantime, there are some approaches that developers can use to reduce the

- **Careful testing**

It is important to test as many of the execution paths of your application as possible.
It is important to test as many of the execution paths of your application as possible.
This is important for correctness, but also to ensure that there are no unexpected cases where script resource usage spikes.

- **Bounding data usage**

Carefully consider whether your application may rely on unbounded data, and try to avoid that.
Carefully consider whether your application may rely on unbounded data, and try to avoid that.
For example, if your application needs to manage a large quantity of assets, try to split them across multiple UTXOs instead of relying on a single UTXO to hold them all.

- **Providing datums when creating outputs**

Datum size issues are most likely to be discovered when an output is spent, because the datum is provided only as a hash on the output.
Insisting that the datum is provided in the transaction that creates the output can reveal that it is too big earlier in the process, allowing another path to be taken.
Insisting that the datum is provided in the transaction that creates the output can reveal that it is too big earlier in the process, allowing another path to be taken.
Depending on the application, this may still prevent it from progressing, if there is only one way to move forwards.

If [CIP-32](https://cips.cardano.org/cips/cip32/) is implemented, this can be done conveniently by using inline datums, although that also risks hitting the output size limit.
Expand All @@ -142,4 +142,3 @@ If [CIP-32](https://cips.cardano.org/cips/cip32/) is implemented, this can be do
If [CIP-33](https://cips.cardano.org/cips/cip33/) is implemented, then the contribution of scripts to transaction size can be massively reduced by using a reference script instead of including the entire script.

<!-- Verify that CIP-32 and CIP-33 have already been implemented, and update statements above as appropriate. -->

27 changes: 27 additions & 0 deletions doc/docusaurus/docs/delve-deeper/understanding-script-hashes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
sidebar_position: 20
---

# Understanding Script Hashes

Script hashes are a core concept and play a vital role on Cardano.
Performing an action on Cardano that involves scripts, such as spending a script UTXO or minting tokens, requires the script with a specific hash to be executed and satisfied.
The cryptographic security of script hashes makes it effectively impossible to manufacture a script that matches a given hash, ensuring the integrity of the blockchain.
A solid understanding of script hashes is essential for DApp development.

## Changing ledger language versions leads to changed script hashes

The ledger language version of a script is part of its hash, so the exact same UPLC program will have different hashes when used as a Plutus V1, V2 or V3 script.
This means, for example, you can't supply a Plutus V3 script when performing an action that requires a Plutus V1 or V2 script, as the hash won't match.

## Changing Plutus Tx compiler versions may lead to changed script hashes

Different Plutus Tx compiler versions may compile and optimize the same Plutus Tx code differently, leading to different UPLC programs and, therefore, different script hashes.

Additionally, the version of GHC can affect the resulting UPLC program and script hashes.
While the Plutus Tx compiler currently supports only one major GHC version, different minor GHC versions may lead to slightly different UPLC programs.

If you plan to use your script in the future, the best approach is to save the compiled script in a blueprint file.
For further information, refer to [Producing a Plutus contract blueprint](../working-with-scripts/producing-a-blueprint.md).

If you wish to compile your Plutus Tx code again in the future while ensuring the script hash remains unchanged, consider using Nix to lock the versions of all dependencies by pinning to a specific version of nixpkgs.

This file was deleted.