diff --git a/README.adoc b/README.adoc index ef30ea1c2bd..b3dc4e72880 100644 --- a/README.adoc +++ b/README.adoc @@ -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. @@ -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. - diff --git a/doc/docusaurus/docs/delve-deeper/common-weaknesses.md b/doc/docusaurus/docs/delve-deeper/common-weaknesses.md index e39a2f92991..3e5696eab0c 100644 --- a/doc/docusaurus/docs/delve-deeper/common-weaknesses.md +++ b/doc/docusaurus/docs/delve-deeper/common-weaknesses.md @@ -1,5 +1,5 @@ --- -sidebar_position: 20 +sidebar_position: 30 --- # Common weaknesses @@ -12,7 +12,7 @@ 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). @@ -20,69 +20,69 @@ Now B constructs a transaction which spends both outputs, and creates one output ![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: @@ -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: @@ -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: @@ -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. @@ -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. - diff --git a/doc/docusaurus/docs/delve-deeper/understanding-script-hashes.md b/doc/docusaurus/docs/delve-deeper/understanding-script-hashes.md new file mode 100644 index 00000000000..59c9d04a1a4 --- /dev/null +++ b/doc/docusaurus/docs/delve-deeper/understanding-script-hashes.md @@ -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. diff --git a/doc/docusaurus/docs/delve-deeper/upgrade-vasil-plutus-script-addresses.md b/doc/docusaurus/docs/delve-deeper/upgrade-vasil-plutus-script-addresses.md deleted file mode 100644 index 0393f7c5f4d..00000000000 --- a/doc/docusaurus/docs/delve-deeper/upgrade-vasil-plutus-script-addresses.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -sidebar_position: 30 ---- - -# Upgrading to Vasil and Plutus script addresses - -## A Plutus V2 script will not have the same hash value as a Plutus V1 script - -DApp developers might expect that when doing a migration from `PlutusV1` scripts to `PlutusV2` scripts, the same source code, when recompiled, will generate the same hash value of that script address. -However, it is impossible for a compiled `PlutusV2` script to have the same script hash and address as a compiled `PlutusV1` script. - -Using the exact same script with different language versions will result in different hashes. -The exact same script (as in `UPLC.Program`) can be used as a `PlutusV1` script or a `PlutusV2` script, and since the language version is part of the hash, the two hashes will be different. - -## A Plutus V1 script will not necessarily have the same hash value when recompiled with a later version of the Plutus Compiler - -Suppose you write your Haskell source code (Plutus Tx), compile it into Plutus Core code (PLC), generate its hash value, then use it in a transaction. -If you don't save your compiled code, and then decide to use the same script in the future, you would have to recompile it. -This could result in a different hash value of the script address even without upgrading from `PlutusV1` to `PlutusV2` scripts. -This is because the hash is computed based on the output of the compiled code. - -Given Plutus compiler version changes, changes in the dependencies, and multiple other improvements, it is expected that the hash value of the script address will change after the source code is recompiled. - -## When to export and save the output of a compiled script - -Once you expect that you will not modify the on-chain part of your application and you don't want the hash value of your script address to change, the best way to keep it the same is to save the output of your final compiled Plutus Core code (PLC) to a blueprint file. - -For details on how to export scripts as blueprints, please see [Producing a Plutus contract blueprint](../working-with-scripts/producing-a-blueprint.md). -