diff --git a/doc/docusaurus/docs/working-with-scripts/script-purposes.md b/doc/docusaurus/docs/working-with-scripts/script-purposes.md new file mode 100644 index 00000000000..a89c4209e95 --- /dev/null +++ b/doc/docusaurus/docs/working-with-scripts/script-purposes.md @@ -0,0 +1,80 @@ +--- +sidebar_position: 2 +--- + +# Script Purposes + +One of the arguments every Plutus script receives is the script context, containing information about the transaction the script is validating. +One of the fields of script context is the script purpose. +Since a transaction may do multiple things, each of which is validated by a separate script, the script purpose informs a script what exactly it is supposed to validate. + +Plutus V1 and V2 share the same [`ScriptPurpose`](https://plutus.cardano.intersectmbo.org/haddock/master/plutus-ledger-api/PlutusLedgerApi-V1-Contexts.html#t:ScriptPurpose) type with four variants: spending, minting, rewarding and certifying. +Plutus V3's [`ScriptPurpose`](https://plutus.cardano.intersectmbo.org/haddock/master/plutus-ledger-api/PlutusLedgerApi-V3-Contexts.html#t:ScriptPurpose) has two additional variants: voting and proposing. +Next we go over and explain all these different script purposes. + +## Spending + +A spending script validates the spending of a UTXO. +A UTXO can have either a public key address or a script address. +To spend a UTXO with a script address, the script whose hash matches the script address must be included in the transaction (either directly, or as a reference script), and is executed to validate it. + +The script can make the decision based on the datum attached in the UTXO being spent, if any (datum is mandatory for Plutus V1 and V2, i.e., a UTXO with a Plutus V1 or V2 script address but without a datum cannot be spent; datum is optional for Plutus V3), the redeemer included in the transaction, as well as other fields of the transaction. + +The `Spending` constructor of `ScriptPurpose` includes a `TxOutRef` field that references the UTXO the script is validating, which is also one of the UTXOs the transaction attempts to spend. + +## Minting + +Minting scripts, sometimes also referred to as minting policies, are used to approve or reject minting of new assets. + +In Cardano, we can uniquely identify an asset by its `CurrencySymbol` and `TokenName`. +If a transaction attempts to mint some new assets, then for each unique `CurrencySymbol` in the new assets, the script whose hash matches the `CurrencySymbol` must be included in the transaction, and is executed to validate the minting of that `CurrencySymbol`. +This is the reason why the `Minting` constructor of `ScriptPurpose` contains a `CurrencySymbol` field. + +A minting script should pay attention to the fact that the transaction may attempt to mint multiple assets with the same `CurrencySymbol` but different `TokenNames`. +In general all these assets with the same `CurrencySymbol` should be checked. + +## Rewarding + +As previously stated, a UTXO's address can be either a public key address or a script address. +Both kinds of addresses can optionally have a staking credential. +A UTXO may contain Ada, and the Ada it contains can be delegated to an SPO to earn staking rewards. +Staking rewards are deposited into a reward account[^1] corresponding to the staking credential. + +A staking credential can contain either a public key hash or a script hash. +To withdraw rewards from a reward account corresponding to a staking credential that contains a script hash, the script with that particular hash must be included in the transaction, and is executed to validate the withdrawal. + +The script might set conditions on reward distribution, such as ensuring that any withdrawal are deposited into one of the designated addresses. + +## Certifying + +A certifying script can validate a number of certificate-related transactions, such as: (1) registering a staking credential, and in doing so, creating a reward account associated with the staking credential; (2) de-registering a staking credential, and in doing so, terminating the reward account; (3) delegating a staking credential to a particular delegatee. + +In all these cases, if the staking credential in question contains a script hash (as opposed to a public key hash), the script with that hash must be included in the transaction, and is executed to validate the action. + +Such a script may, for instance, check that certain signatures be provided for registration, de-registration and delegation, or that the delegatee must be among the allowed delegatees. + +## Voting + +A voting script validates votes cast by a Delegated Representative (DRep) or a constitutional committee member (CCM) in a transaction. +A DRep or a CCM can be associated with a script hash. +If a transaction contains one or more votes from a DRep or a constitution committee member associated with a script hash, the script with that hash must be included in the transaction, and is executed to approve or reject the vote. + +## Proposing + +A proposing script, also known as constitution script or guardrail script, validates two kinds of [governance actions](https://plutus.cardano.intersectmbo.org/haddock/master/plutus-ledger-api/PlutusLedgerApi-V3-Contexts.html#t:ScriptContext): `ParameterChange` and `TreasuryWithdrawals`. + +There is a key distinction between proposing scripts and other kinds of scripts: proposing scripts are not written by regular users. +At any given point in time, there is exactly one active proposing script being used by the entire chain. +This proposing script must be included in transactions that propose `ParameterChange` or `TreasuryWithdrawals`. +The ledger enforces that no other proposing script is accepted. +The proposing script is updated only when there is a change to the constitution, via the `NewConstitution` governance action. + +Note that what the proposing script decides is whether the _proposal_ of a governance action is allowed to go through, rather than whether the governance action will be enacted. +After a proposal goes through, it will need to meet the appropriate criteria (such as gathering enough votes from consitution committee members, DReps and/or SPOs) in order to be enacted. + +--- + +[^1]: Reward accounts are distinct from UTXOs, and are more akin to accounts in account-based blockchains. +They are used for accumulating staking rewards, rather than using UTXOs, in order to avoid creating a large number of UTXOs with tiny values. +Reward accounts are special on Cardano and cannot be created arbitrarily. +Each reward account is associated with a staking credential, and is created automatically when the staking credential is registered. diff --git a/doc/docusaurus/docs/working-with-scripts/writing-basic-minting-policies.md b/doc/docusaurus/docs/working-with-scripts/writing-basic-minting-policies.md deleted file mode 100644 index fe74ede8090..00000000000 --- a/doc/docusaurus/docs/working-with-scripts/writing-basic-minting-policies.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -sidebar_position: 10 ---- - -# Writing basic minting policies - -[Minting policy scripts](../reference/glossary.md#minting-policy-script) are the programs that can be used to control the minting of new assets on the chain. -Minting policy scripts are much like [validator scripts](../reference/glossary.md#validator-script), and they are written similarly, so please review [Writing basic validator scripts](writing-basic-validator-scripts.md) before reading this topic. - -## Minting policy arguments - -Minting policies, like validators, receive some information from the validating node: - -- The [redeemer](../reference/glossary.md#redeemer), which is some script-specific data specified by the party performing the minting. -- The [script context](../reference/glossary.md#script-context), which contains a representation of the spending transaction, as well as the hash of the minting policy which is currently being run. - -The minting policy is a function which receives these two inputs as *arguments*. The validating node is responsible for passing them in and running the minting policy. -As with validator scripts, the arguments are passed encoded as `PlutusCore.Data.Data`. - -## Plutus script context versions - -Minting policies have access to the [script context](../reference/glossary.md#script-context) as their second argument. -Each version of Plutus minting policy scripts are differentiated only by their `ScriptContext` argument. - -> See this example from the file `MustSpendScriptOutput.hs` (lines 340 to 422) showing code addressing [Versioned Policies for both Plutus V1 and Plutus V2](https://github.com/IntersectMBO/plutus-apps/blob/05e394fb6188abbbe827ff8a51a24541a6386422/plutus-contract/test/Spec/TxConstraints/MustSpendScriptOutput.hs#L340-L422). - -Minting policies tend to be particularly interested in the `mint` field, since the point of a minting policy is to control which tokens are minted. - -It is also important for a minting policy to look at the tokens in the `mint` field that use its own currency symbol i.e. policy hash. -Note that checking only a specific token name is usually not correct. -The minting policy must check for correct minting (or lack there of) of all token names under its currency symbol. -This requires the policy to refer to its own hash—fortunately this is provided for us in the script context of a minting policy. - -## Writing minting policies - -Here is an example that puts this together to make a simple policy that allows anyone to mint the token so long as they do it one token at a time. -To begin with, we'll write a version that works with structured types. - - - -However, scripts are actually given their arguments as type `Data`, and must signal failure with `error`, so we need to wrap up our typed version to use it on-chain. - - - -## Other policy examples - -Probably the simplest useful policy is one that requires a specific key to have signed the transaction in order to do any minting. -This gives the key holder total control over the supply, but this is often sufficient for asset types where there is a centralized authority. - - - -> :pushpin: **NOTE** -> -> We don't need to check that this transaction actually mints any of our asset type: the ledger rules ensure that the minting policy will only be run if some of that asset is being minted. - diff --git a/doc/docusaurus/docs/working-with-scripts/writing-basic-validator-scripts.md b/doc/docusaurus/docs/working-with-scripts/writing-basic-validator-scripts.md deleted file mode 100644 index 46e2b0f1b0d..00000000000 --- a/doc/docusaurus/docs/working-with-scripts/writing-basic-validator-scripts.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -sidebar_position: 5 ---- - -# Writing basic validator scripts - -[Validator scripts](../reference/glossary.md#validator-script) are the programs that can be used to lock transaction outputs on the chain. -Validator scripts are [Plutus Core](../reference/glossary.md#plutus-core) programs, but we can use [Plutus Tx](../reference/glossary.md#plutus-tx) to write them easily in Haskell. -Please review [Writing Plutus Tx programs](../using-plutus-tx/writing-plutus-tx-programs.md) before going through this topic. - -## Validator arguments - -Validators receive some information from the validating node: - -- The [redeemer](../reference/glossary.md#redeemer), which is some script-specific data specified by the party spending the output. -- The [datum](../reference/glossary.md#datum), which is some script-specific data specified by the party who created the output. -- The [script context](../reference/glossary.md#script-context), which contains a representation of the spending transaction, as well as the index of the input whose validator is currently being run. - -The validator is a function which receives these three inputs as *arguments*. The validating node is responsible for passing them in and running the validator. - -## The `Data` type - -But how are the validator's arguments passed? -Different scripts are going to expect different sorts of values in their datums and redeemers. - -The answer is that we pass the arguments as a *generic* structured data type `PlutusCore.Data.Data`. -`Data` is designed to make it easy to encode structured data into it, and is essentially a subset of CBOR. - -Validator scripts take three arguments of type `Data`. -Since `Data` is represented as a builtin type in Plutus Core, we use a special Haskell type `BuiltinData` rather than the underlying `Data` type. - -However, you will typically not want to use `BuiltinData` directly in your program, rather you will want to use your own datatypes. -We can easily convert to and from `BuiltinData` with the `PlutusTx.IsData.Class.ToData`, `PlutusTx.IsData.Class.FromData`, and `PlutusTx.IsData.Class.UnsafeFromData` typeclasses. -You usually don't need to write your own instances of these classes. -Instead, you can use the `unstableMakeIsData` or `makeIsDataIndexed` Template Haskell functions to generate one. - -> :pushpin: **NOTE** -> -> The `PlutusTx.IsData.Class.UnsafeFromData` class provides `unsafeFromBuiltinData`, which is the same as `fromBuiltinData`, but is faster and fails with `error` rather than returning a `Maybe`. -> We'll use `unsafeFromBuiltinData` in this tutorial, but sometimes the other version is useful. - - - -## Signaling failure - -The most important thing that a validator can do is *fail*. -This indicates that the attempt to spend the output is invalid and that transaction validation should fail. -A validator succeeds if it does not explicitly fail. -The actual value returned by the validator is irrelevant. - -How does a validator fail? -It does so by using the `PlutusTx.Builtins.error` builtin. -Some other builtins may also trigger failure if they are used incorrectly (for example, `1/0`). - -## Validator functions - -We write validator scripts as Haskell functions, which we compile with Plutus Tx into Plutus Core. -The type of a validator function is `BuiltinData -> BuiltinData -> BuiltinData -> ()`, that is, a function which takes three arguments of type `BuiltinData`, and returns a value of type `()` ("unit" or "the empty tuple" -- since the return type doesn't matter we just pick something trivial). - -Here are two examples of simple validators that always succeed and always fail, respectively: - - - -If we want to write a validator that uses types other than `BuiltinData`, we'll need to use the functions from `PlutusTx.IsData.Class.FromData` to decode them. -Importantly, `unsafeFromBuiltinData` can fail: in our example, if the `BuiltinData` in the second argument is *not* a correctly encoded `Date`, then it will fail the whole validation with `error`, which is usually what we want if we have bad arguments. - -> :red_circle: **Important** -> -> Unfortunately, there's no way to provide failure diagnostics when a validator fails on chain—it just fails. -> However, since transaction validation is entirely deterministic, you'll always be informed of this before you submit the transaction to the chain, so you can debug it locally using `traceError`. - -Here's an example that uses our date types to check whether the date which was provided is less than the stored limit in the datum. - - - -## Plutus script context versions - -Validators have access to the [script context](../reference/glossary.md#script-context) as their third argument. -Each version of Plutus validators are differentiated only by their `ScriptContext` argument. - -> See this example from the file `MustSpendScriptOutput.hs` (lines 340 to 422) showing code addressing [Versioned Policies for both Plutus V1 and Plutus V2](https://github.com/IntersectMBO/plutus-apps/blob/05e394fb6188abbbe827ff8a51a24541a6386422/plutus-contract/test/Spec/TxConstraints/MustSpendScriptOutput.hs#L340-L422). - -The script context gives validators a great deal of power, because it allows them to inspect other inputs and outputs of the current transaction. -For example, here is a validator that will only accept the transaction if a particular payment is made as part of it. - - - -This makes use of some useful functions for working with script contexts.