diff --git a/docs/chialisp-concepts/condition-morphing.md b/docs/chialisp-concepts/condition-morphing.md new file mode 100644 index 00000000..17c58e76 --- /dev/null +++ b/docs/chialisp-concepts/condition-morphing.md @@ -0,0 +1,136 @@ +--- +slug: /chialisp-condition-morphing +title: Condition Morphing +--- + +You've seen how you can use inner puzzles to output conditions and append them to the output of the outer puzzle. However, sometimes you want to change the output of the inner puzzle to enforce certain rules. This is called **condition morphing**. + +An example of this is the singleton - every coin that its inner puzzle creates which has an odd output, is turned into an inner puzzle of itself. It changes the puzzle in the condition to the singleton with the original puzzle as its new inner puzzle. This can be a bit confusing to think about, but it allows for many things such as keeping track of state. + +## Example + +Let's try a simpler example of condition morphing that doubles the amount of created coins. + +Write the following in a file named `coin-doubler.clsp`: + +```chialisp title="coin-double.clsp" +; Using the dot here means that the inner solution is the rest of the parameters. This avoids the need to nest parentheses. +(mod (INNER_PUZZLE . inner_solution) + + ; Doubles the amount of CREATE_COIN conditions. + (defun morph-condition (condition) + + ; Checks if the opcode is 51, which is CREATE_COIN. + (if (= (f condition) 51) + + ; Create a new condition similar to the original. + (list + ; It's still the same opcode. + 51 + + ; The second value, the puzzle hash, is also the same. + (f (r condition)) + + ; The third value, the amount, is doubled. + (* (f (r (r condition))) 2) + ) + + ; If it's not the right opcode, leave it untouched. + condition + ) + ) + + ; Goes through every condition and morphs it. + (defun morph-conditions (conditions) + + ; If there are conditions left in the list. + (if (l conditions) + (c + ; Morph the first condition. + (morph-condition (f conditions)) + + ; Then morph the rest and form a list. + (morph-conditions (r conditions)) + ) + + ; Otherwise, the output has ended. + () + ) + ) + + ; Morph the conditions output from the inner puzzle. + (morph-conditions (a INNER_PUZZLE inner_solution)) +) +``` + +Make sure you read the comments and understand it fully before continuing. + +### Inner Puzzle + +Now we need an inner puzzle to morph the conditions of. + +Write the following in a file named `any-with-signature.clsp`: + +```chialisp title="any-with-signature.clsp" +(mod (PUBLIC_KEY conditions) + (include condition_codes.clib) + (include sha256tree.clib) + + (c + (list AGG_SIG_ME PUBLIC_KEY (sha256tree conditions)) + conditions + ) +) +``` + +Retrieve the libraries used in this example: + +```bash +cdv clsp retrieve condition_codes sha256tree +``` + +:::info +Similarly to [the example in the Inner Puzzles guide](/chialisp-inner-puzzles#inner-puzzle), this allows the spender to pick any conditions. However, it also requires a signature. It's essentially the inner and outer puzzle from that example combined. +::: + +### Public Key + +You can refer to the [signature guide](/chialisp-bls-signatures) to learn about key pairs and how to use your wallet to sign messages. We will be using similar steps here to get the derived public key. + +Run this to get the derived public key: + +```bash +chia keys derive child-key --derive-from-hd-path "m/12381/8444/2/0" +``` + +You will use this public key in the next step. + +### Currying + +Now, we will wrap this inner puzzle in the outer puzzle we wrote previously. This will require the spend to be signed by a given key, and any coins created will have double the amount. + +First, run this command to get the compiled form of the inner puzzle: + +```bash +run -i include any-with-signature.clsp +``` + +Yes, the output is just `2`. + +You can run this command to curry in the public key previously calculated and the inner puzzle: + +```bash +cdv clsp curry coin-doubler.clsp -a "0xPublicKey" -a 2 +``` + +That should produce an output similar to this: + +```chialisp +(a (q 2 (q 2 6 (c 2 (c (a 5 7) ()))) (c (q (a (i (= 9 (q . 51)) (q 4 (q . 51) (c 21 (c (* 45 (q . 2)) ()))) (q . 5)) 1) 2 (i (l 5) (q 4 (a 4 (c 2 (c 9 ()))) (a 6 (c 2 (c 13 ())))) ()) 1) 1)) (c (q . 0xPublicKey) (c (q 2 (q 4 (c 4 (c 5 (c (a 6 (c 2 (c 11 ()))) ()))) 11) (c (q 50 2 (i (l 5) (q 11 (q . 2) (a 6 (c 2 (c 9 ()))) (a 6 (c 2 (c 13 ())))) (q 11 (q . 1) 5)) 1) 1)) 1))) +``` + +Now the inner puzzle and outer puzzle have been combined together. + +## Conclusion + +This combined puzzle would allow you to spend coins created with it with your public key, but any create coin conditions would have their amounts doubled in the output. Feel free to ask questions you may have on our [Discord](https://discord.gg/chia). diff --git a/docs/chialisp-concepts/currying.md b/docs/chialisp-concepts/currying.md new file mode 100644 index 00000000..b9e5aaa5 --- /dev/null +++ b/docs/chialisp-concepts/currying.md @@ -0,0 +1,86 @@ +--- +slug: /chialisp-currying +title: Currying +--- + +When you are writing puzzles in Chialisp you may want to have certain parameters decided before the coins are created. This is called **currying**. It allows puzzles to be reused but have different content and produce a different hash. + +An example of this is the standard transaction puzzle. One of its parameters is the `SYNTHETIC_PUBLIC_KEY`, which is unique for each address in your wallet. It represents a synthetic child key of your root public key. As such, the puzzle has to be changed for every address. This would be tedious to do without currying, since it allows the original puzzle (also known as the mod) to be used as a template. + +## Example + +We're going to write a simple example to try currying on the command line. + +Write this in a file named `multiply.clsp`: + +```chialisp title="multiply.clsp" +(mod (first second) + (* first second) +) +``` + +### Currying + +Now, we are going to make an instance of this program that will set the value of the parameter `first` to `2`. This will effectively turn this program from a multiplier to a doubler. + +You can curry it like this: + +```bash +cdv clsp curry multiply.clsp -a 2 +``` + +Which should produce the following curried result: + +```chialisp +(a (q 18 2 5) (c (q . 2) 1)) +``` + +:::info +This is no longer in Chialisp form, but rather has been compiled to CLVM. You don't need to understand how this works or be able to read it, but only be aware that it does what was mentioned before. +::: + +You can now run this curried CLVM, and include the value to be doubled as the second parameter, like so: + +```bash +brun "(a (q 18 2 5) (c (q . 2) 1))" "(5)" +``` + +It should output twice the value of `5`: + +```chialisp +10 +``` + +### Reuse + +The real use of currying comes from the fact that you can curry it again with a new value: + +```bash +cdv clsp curry multiply.clsp -a 5 +``` + +Which should produce the following curried result: + +```chialisp +(a (q 18 2 5) (c (q . 5) 1)) +``` + +This will do the same thing as the previous curried program, except it will multiply by `5` instead of by `2`. + +## Convention + +In the previous example, we curried a value into a program, but the program did not declare that this was required. However, often times (especially with puzzles), you will be required to curry the value beforehand to use it properly. To indicate that a parameter is meant to be curried in, you write it in `SCREAMING_SNAKE_CASE`. + +Let's rewrite the previous example with this convention: + +```chialisp title="multiply.clsp" +(mod (FIRST second) + (* FIRST second) +) +``` + +Writing parameters like this doesn't change anything in how they function, but rather how they are expected to be used. This convention makes it clear that you _need_ to specify the value of it before creating coins with it on-chain. + +## Conclusion + +This is very useful for writing reusable and composable puzzles in Chialisp. It is also commonly used in tandem with [inner puzzles](/chialisp-inner-puzzles). However, currying can be a pretty confusing topic, so if you have any further questions, feel free to ask them on our [Discord](https://discord.gg/chia). diff --git a/docs/chialisp-concepts/inner-puzzles.md b/docs/chialisp-concepts/inner-puzzles.md new file mode 100644 index 00000000..46763db2 --- /dev/null +++ b/docs/chialisp-concepts/inner-puzzles.md @@ -0,0 +1,101 @@ +--- +slug: /chialisp-inner-puzzles +title: Inner Puzzles +--- + +Sometimes you want the behavior of your puzzles to be composable, so that you can reuse code in multiple ways. An example of this is the [Chia Asset Token](/cats) puzzle, which allows you to specify an **inner puzzle**. + +This allows the outer puzzle to enforce certain rules on how it can be spent, while the inner puzzle can do whatever it wants within those rules. In this case, the CAT enforces that it maintains a constant amount in mojos, while the inner puzzle (typically the [Standard Transaction primitive](/standard-transactions/)) decides how it can be spent. + +This is typically used in combination with a variety of other concepts, which we will talk about later. However, for the purpose of this guide and to make it easier to follow, we will provide a simple example that only incorporates currying and inner puzzles. + +## Example + +We're going to write a simple example to try inner puzzles on the command line. + +Write this in a file named `require-signature.clsp`: + +```chialisp title="require-signature.clsp" +; Using the dot here means that the inner solution is the rest of the parameters. This avoids the need to nest parentheses. +(mod (PUBLIC_KEY INNER_PUZZLE . inner_solution) + (include condition_codes.clib) + (include sha256tree.clib) + + (c + (list AGG_SIG_ME PUBLIC_KEY (sha256tree inner_solution)) + (a INNER_PUZZLE inner_solution) + ) +) +``` + +Retrieve the libraries used in this example: + +```bash +cdv clsp retrieve condition_codes sha256tree +``` + +First, note that `PUBLIC_KEY` and `INNER_PUZZLE` are both all caps. Because of this you can tell that they are meant to be [curried](/chialisp-currying) in before used as a puzzle. + +The `c` operator creates a cons pair with two values. Here, it is essentially prepending the `AGG_SIG_ME` condition to the output of the inner puzzle. + +The `a` operator executes a program with its parameters. Here, it is used to run the curried inner puzzle with the inner solution passed in during the spend. It outputs a list of conditions which will get appended to the first condition. + +The `AGG_SIG_ME` condition will verify the `PUBLIC_KEY` signed the message, which is the tree hash of the inner solution. + +### Inner Puzzle + +Next, we need to write the inner puzzle that will be curried into the example. + +Write this in a file named `any-conditions.clsp`: + +```chialisp title="any-conditions.clsp" +(mod (conditions) + conditions +) +``` + +:::info +This is an exceedingly simple puzzle that just returns any conditions passed into the solution. It is insecure on its own, as it allows anyone to spend it however they want. +::: + +### Public Key + +You can refer to the [BLS Signatures guide](/chialisp-bls-signatures) to learn about key pairs and how to use your wallet to sign messages. We will be using similar steps here to get the derived public key. + +Run this to get the derived public key: + +```bash +chia keys derive child-key --derive-from-hd-path "m/12381/8444/2/0" +``` + +You will use this public key in the next step. + +### Currying + +Now, we will wrap this inner puzzle in the outer puzzle we wrote previously. This will require the spend to be signed by a given key, which effectively secures the inner puzzle so that only you can spend it, instead of anyone. + +First, run this command to get the compiled form of the inner puzzle: + +```bash +run any-conditions.clsp +``` + +Yes, the output is just `2`. + +You can run this command to curry in the public key previously calculated and the inner puzzle: + +```bash +cdv clsp curry require-signature.clsp -a "0xPublicKey" -a 2 +``` + +That should produce an output similar to this: + +```chialisp +(a (q 2 (q 4 (c 4 (c 5 (c (a 6 (c 2 (c 15 ()))) ()))) (a 11 15)) (c (q 50 2 (i (l 5) (q 11 (q . 2) (a 6 (c 2 (c 9 ()))) (a 6 (c 2 (c 13 ())))) (q 11 (q . 1) 5)) 1) 1)) (c (q . 0xPublicKey) (c (q . 2) 1))) +``` + +Now the inner puzzle and outer puzzle have been combined. + +## Conclusion + +The concept of inner puzzles allows for the composition of puzzles. This is commonly used in the wallet, where CATs, DIDs, and NFTs wrap the standard transaction. That way they have the ability to be transferred, yet also have their own set of rules that control their use. If you have any questions about inner puzzles, feel free to ask on our [Discord](https://discord.gg/chia). diff --git a/docs/chialisp-primer/bls-signatures.md b/docs/chialisp-primer/bls-signatures.md new file mode 100644 index 00000000..feff33ca --- /dev/null +++ b/docs/chialisp-primer/bls-signatures.md @@ -0,0 +1,58 @@ +--- +slug: /chialisp-bls-signatures +title: 5. BLS Signatures +--- + +When creating a spend bundle previously, we have left the `aggregated_signature` field set to the default value of `c0` followed by 190 zeros. This value indicates that there are no signatures. We will detail what signatures are, and how you can use them on the blockchain. + +Chia uses a specific kind of signature called a [BLS Signature](https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html). It's a form of elliptic curve cryptography. + +One helpful feature of BLS signatures is that they can be non-interactively aggregated. You can take a signature from a party you don't trust, and combine it with another signature to produce a single signature that verifies the combination of all of the messages they were signing. + +## Digital Signatures + +A [digital signature](https://en.wikipedia.org/wiki/Digital_signature) is a cryptographically secure way to check the author of a message. It is quite similar to written signatures. + +To create a signature, first you need a [key pair](https://en.wikipedia.org/wiki/Public-key_cryptography) that consists of a private key and its corresponding public key. The private key is used to sign messages, whereas the public key is used to verify the signature created for the message. + +## Example + +:::danger +Your private key should _never_ be shared with anyone other than yourself unless you are fine with them having complete control over the wallet it is for, as well as signing messages on your behalf. The same is true for the mnemonic seed phrase used to generate the key pair. +::: + +The first thing you need to do is find the fingerprint of the wallet you are going to be using for message signing. + +You can use the following command to do this: + +```bash +chia keys show +``` + +:::info +You are not going to be using the root key pair itself to sign messages, but rather a child key derived from it. The `hd_path` represents the path used for deriving the child key from the root. + +The `12381` is specific to BLS signatures, whereas `8444` is specific to Chia. Wallets use the index `2`, and finally the last value is just the key index, starting at `0`. + +You will not need to change the value in this guide, but you can tweak the last value if you want. +::: + +You can now sign messages using this key pair like so: + +```bash +chia keys sign --fingerprint "FingerPrint" --hd_path "m/12381/8444/2/0" --message "Message" +``` + +It will show you the derived public key and signature based on the path and message specified. + +You can use those values to verify that the signature is correct like this: + +```bash +chia keys verify --public_key "PublicKey" --signature "Signature" --message "Message" +``` + +If the result is `True`, it is valid. Otherwise, either the public key, signature, or message is incorrect. + +## Conclusion + +This was just a primer on BLS signatures, and in practice it can be a bit more complicated. They will be put to good use in future guides, and it's a good idea to understand how they work before you dive into them. If you have any questions about BLS signature, feel free to ask on our [Discord](https://discord.gg/chia)! diff --git a/docs/chialisp-primer/first-smart-coin.md b/docs/chialisp-primer/first-smart-coin.md new file mode 100644 index 00000000..58934b52 --- /dev/null +++ b/docs/chialisp-primer/first-smart-coin.md @@ -0,0 +1,186 @@ +--- +slug: /chialisp-first-smart-coin +title: 4. First Smart Coin +--- + +By now, you should understand what Chialisp is and how you can use it to write programs and modules that can be run on the command-line. In this guide, we are going to write a simple **puzzle**, use it to lock a **coin** with a password, and finally spend it. This example is insecure for a variety of reasons which will be explained after, but it's a good tool for learning how smart coins work. + +## Prerequisites + +The previous guide detailed how to set up the testnet. You will need to follow it to continue. + +:::tip +While this guide can be followed on the command-line like the first, we recommend writing more complicated Chialisp programs like this one that you plan on reusing in a text editor of your choice, then using the command-line to compile it and use the RPC commands. +::: + +## Password Puzzle + +Write the following Chialisp code in a file named `password.clsp`: + +```chialisp title="password.clsp" +;;; This puzzle locks coins with a password. +;;; It should not be used for production purposes. +;;; Use a password that has no meaning to you, preferably random. + +(mod ( + PASSWORD_HASH ; This is the sha256 hash of the password. + + password ; This is the original password used in the password hash. + conditions ; An arbitrary list of conditions to output. + ) + + ; If the hash of the password matches, + (if (= (sha256 password) PASSWORD_HASH) + ; Output the conditions list. + conditions + + ; Otherwise, throw an error. + (x) + ) +) +``` + +1. The puzzle takes in a **curried in** value `PASSWORD_HASH`. +2. The solution takes in the `password` and desired `conditions`. +3. If the hash of the password matches the curried in value, output the `conditions`. +4. Otherwise, throw an error to prevent the spend from occurring. + +## Puzzles + +We've mentioned previously that Chialisp can be used to write puzzles, but you may be wondering what exactly a puzzle is. A puzzle is a special module that is used to lock a coin with a set of rules. These rules affect how and when they can be spent, and what happens when they are. + +### Currying + +Currying can be thought of as defining the value of function parameters before it is called. This is usually used with modules to allow the same puzzle to be reused for multiple different scenarios. + +In this example, the curried in `PASSWORD_HASH` represents the hash of the password that is required to spend the coin. Not every instance of this puzzle will have the same password, so we create a parameter and curry the value when we actually make an instance of this puzzle. + +### Conditions + +A condition consists of a condition number followed by its arguments. They can do a variety of things, from the creation of new coins and requiring other spends to happen at the same time, to various assertions related to the state of the blockchain. + +A complete list of conditions can be found on the [Conditions page](/conditions), but we will only be using one in this tutorial: condition `51`, or `CREATE_COIN`, creates a new coin with the given `puzzle_hash` and `amount` if the spend is valid. It is used to send money to another puzzle hash (which is analogous to an address). + +## Coins + +Everything on the Chia Blockchain, including the standard transactions used to move money between wallets, is a coin. Coins are identified by their id, which is just a [sha256 hashed](https://en.wikipedia.org/wiki/Cryptographic_hash_function) representation of the following three components: + +- `parent_coin_id`, which is the id of the coin that created this one. +- `puzzle_hash`, which is the hash of the puzzle used to spend the coin. +- `amount`, which is the amount of money locked with the coin, in mojos (a trillionth of an XCH). + +Multiple coins can have the same puzzle hash, and a coin can create multiple children. The only limitation is that no two coins can have the same parent, puzzle hash, and amount, as their ids would be the same. + +A coin can be spent by revealing its puzzle and providing a solution. The solution is then passed to its puzzle, which outputs a list of conditions. + +## Putting it Together + +We will now use these concepts and the `password.clsp` file you just wrote to create and spend a coin. + +### Creating the Coin + +:::danger +Don't use a password that you use or plan to use for anything else, as this is not a secure smart coin. The most ideal choice for this is any number of random characters of your choice, such as `x7h2dDkE`. Just write it down for later. +::: + +The first step is to curry the puzzle with the password's hash and get the puzzle hash and puzzle reveal: + +```bash +opc -H "$(cdv clsp curry password.clsp --args "$(run "(sha256 'password')")")" +opc "$(cdv clsp curry password.clsp --args "$(run "(sha256 'password')")")" +``` + +Write down both values this produces, the first one being the puzzle hash, and the second being the puzzle reveal. + +You can convert the puzzle hash to an address and send funds to it like so: + +```bash +cdv encode --prefix txch "PuzzleHash" +chia wallet send --amount 0.01 --fee 0.00005 --address "txch1Address" +``` + +This will send 10 billion mojos with a fee of 100 million mojos (the current recommended amount to get the transaction to go through quickly) to the address you specify, therefore creating your coin! + +### Spending the Coin + +There's only one thing left to do, which is to spend the coin that we just created. We are going to be using a few RPC calls to do this. + +First, we need to find the coin that we just created by its puzzle hash: + +```bash +cdv rpc coinrecords --only-unspent --by puzzlehash "PuzzleHash" +``` + +Take note of the values in the `coin` object in the output. + +Get the puzzle hash of your wallet address: + +```bash +chia wallet get_address +cdv decode "txch1WalletAddress" +``` + +:::caution +Make sure you put the `0x` prefix in front of the wallet's puzzle hash in this command. It isn't required for the other commands, but in this case it will compile as a string without it, which you don't want. +::: + +Then, get the solution in hex, with the password and your wallet puzzle hash: + +```bash +opc "('password' ((51 0xWalletPuzzleHash 9900000000)))" +``` + +This will produce a solution with the password that will create a new coin with the amount minus a fee of 100 million mojos. A coin will go back to your wallet when you spend the coin with this solution. + +We will not be using an aggregated signature for the spend bundle, so we will specify the signature equivalent of zero. Just paste the long value in the below spend bundle. + +Use the coin information you gathered with the `coinrecords` command, the `puzzle_reveal` from the first `opc` command you ran, and the `solution` from the second. + +Write the following in a file named `spendbundle.json`: + +```json title="spendbundle.json" +{ + "coin_spends": [ + { + "coin": { + "amount": 10000000000, + "parent_coin_info": "0xParentCoinInfo", + "puzzle_hash": "0xPuzzleHash" + }, + "puzzle_reveal": "PuzzleReveal", + "solution": "Solution" + } + ], + "aggregated_signature": "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +} +``` + +Finally, run the following command to push the transaction to the Testnet: + +```bash +cdv rpc pushtx spendbundle.json +``` + +If all went well, this should spend the coin! Otherwise, retrace your steps carefully to try to find what went wrong. If you still can't figure it out, don't hesitate to ask us on our join our [Discord](https://discord.gg/chia) and ask in the #chialisp channel and we will answer as soon as we can. + +## Potential Questions + +Here are some questions you may have had when creating and spending the coin. + +### Why Allow Arbitrary Conditions? + +We allow any conditions to be passed in the solution. While you might think that for this example we would only need to create a single coin, this allows us to reserve network fees, or to enable more complicated functionality later such as interacting with other spends. In this example, we will only use the create coin condition in this list. + +### Why are Password Coins Insecure? + +When you spend one or more coins, the puzzle and its solution go into the [mempool](https://docs.chia.net/mempool) until the block is inevitably farmed. This means that anyone can read the password in plain text during this time, or after the coin is spent. + +A simple solution to that would be to use a new random password every time you create a coin. However, a malicious farmer can actually change the solution to spends however they would like before adding it to their block. In doing so, they could change where the money will go in order to steal the coin. + +While there are other ways, the most common solution to that is to simply require a [digital signature](https://en.wikipedia.org/wiki/BLS_digital_signature) instead of a password. This is a cryptographically secure way of ensuring that the solution is not tampered with. If it is, the spend will no longer be valid. We will worry about this in a future guide, so you can safely ignore this concept for now. + +So, while a password example is a good idea for learning and testing purposes, it is certainly not feasible for real-world use. + +## Conclusion + +This is only scratching the surface of what's possible to do with smart coins on the Chia Blockchain. But it's a good foundation of understanding for more complicated examples to come. Every guide in this series builds off of the others, so make sure to take a break to let it soak in, and refresh your memory on concepts that you need to when you come back. We're looking forward to the awesome things you will build with this technology! diff --git a/docs/chialisp-primer/intro.md b/docs/chialisp-primer/intro.md new file mode 100644 index 00000000..c0a0891f --- /dev/null +++ b/docs/chialisp-primer/intro.md @@ -0,0 +1,73 @@ +--- +slug: /chialisp-primer/intro +title: 1. Intro to Chialisp +--- + +[Chialisp](https://chialisp.com) is a language based on [Lisp]() that is used on the Chia blockchain to dictate how and when [coins](https://docs.chia.net/coin-set-intro) can be spent. It's designed to be as simple and efficient as possible, but still provide broad functionality and [Turing Completeness](https://en.wikipedia.org/wiki/Turing_completeness). + +Throughout this guide you will learn the basics of Chialisp, and by the end you should have the skills required to write working programs using it. No prior knowledge of Lisp is required. + +## Installation + +You can follow the [Chia Dev Tools installation guide](https://github.com/Chia-Network/chia-dev-tools/#install) to install and use Chia Dev Tools. You will be using these tools and a simple text editor of your choice to write and run snippets of code. + +Once you have it set up, run the following command: + +```bash +run "test" +``` + +The `run` command compiles Chialisp code. In this case, we are compiling a simple string to make sure it is installed properly. + +If it is working correctly, it should output `"test"`. You can now follow along with any of the code in the coming sections. + +## Atoms + +An **atom** can represent an integer, string, or hexadecimal number. However, the difference is only known before the code is compiled, and every atom is stored directly as bytes. + +For example, these atoms all have the same value: + +| Representation | Example | Description | +| -------------- | ------- | ----------------------------------- | +| Symbol | `A` | Names and operators | +| String | `"A"` | Used to represent text | +| Integer | `65` | Whole numbers, positive or negative | +| Hexadecimal | `0x41` | Raw byte representation | + +If you are interested in learning more about how atoms are represented, see the [CLVM](/clvm) guide. + +## Lists + +A **list** is a nested chain of [cons pairs](https://en.wikipedia.org/wiki/Cons) used to represent a set of values, which are also either atoms or lists. While you can manually create these pairs, and it is a good thing to know how to do, we will focus on the higher-level concept of lists for now, since they are easier to use and more practical. + +The first item in an unquoted list is the operator, and the rest are its operands. The same goes for functions or macros and their arguments. If you want to express a list of values, you either have to use the `list` operator or quote the list. + +This creates a list of values: + +```bash +run '(list 1 2 3)' +``` + +And here is an operator: + +```bash +run '(+ 2 3)' +``` + +As you can see, just about everything in this language is based on lists, hence the name Lisp (an abbreviation for List Processor). You can see a full list of built-in [operators](/operators). + +## Example + +Lets try a more complex example: + +```bash +run '(* (if (> 3 2) 10 5) 10)' +``` + +If 3 is greater than 2, it's 10, otherwise 5. Then multiply it by 10. The result here is as you would expect, 100. + +## Conclusion + +Hopefully this guide has been a good introduction into the world of Chialisp. There is a lot more to learn, but this is the foundation that everything else is built on top of. + +If you really want to get started with using it, the best way is to try out these examples yourself, and play around a little yourself. Feel free to ask questions on our [Discord](https://discord.gg/chia) that come up along the way. We are always happy to help you learn. diff --git a/docs/chialisp-primer/testnet-setup.md b/docs/chialisp-primer/testnet-setup.md new file mode 100644 index 00000000..14e01624 --- /dev/null +++ b/docs/chialisp-primer/testnet-setup.md @@ -0,0 +1,47 @@ +--- +slug: /chialisp-testnet-setup +title: 3. Testnet Setup +--- + +If you haven't already, you will need to [clone the Chia Blockchain repository](https://github.com/Chia-Network/chia-blockchain), then follow the below steps to set it up and configure it for the testnet. + +## Setup + +:::tip +If you are using Windows, we recommend PowerShell, and you may need to replace forward slashes `/` with backslashes `\`. +::: + +1. Open the `chia-blockchain` folder in a command prompt of your choice. +2. Set the environment variable `CHIA_ROOT` to `~/.chia/testnet`. +3. Run `./Install.ps1` on Windows or `./install.sh` on MacOS or Linux. +4. Run `. ./activate` to use the Python virtual environment. +5. Run `chia init` to setup and configure Chia. +6. Run `chia keys generate` to prepare the wallet keys. +7. Run `chia configure -t true` to use the Testnet. +8. Download the [Testnet database](https://download.chia.net/testnet11/blockchain_v2_testnet11.sqlite.gz) and place it in the `~/.chia/testnet11/db` folder. +9. Finally, run `chia start node` to start the full node. + +## Faucet + +Now you can set up the wallet and use a faucet to receive Testnet coins to use in the upcoming guides. + +1. Run `chia start wallet` to start the wallet. +2. Run `chia wallet get_address` to get the next wallet address. +3. Go to the [Testnet faucet](https://testnet11-faucet.chia.net) and give it your address. +4. Wait a minute or two and run `chia wallet show` to check your balance. + +## Peers + +If you were previously running on mainnet, you will have a list of mainnet peers stored in the following file: + +``` +~/.chia/mainnet/db/peers.dat +``` + +Be sure to **rename or delete** this file when you convert your system to running on testnet. If you do not do this, your system will eventually drop its mainnet peers and add new testnet peers, but this could take a long time. + +One way to speed up the peer discovery process even more is to run the [add-nodes bash script](https://github.com/wallentx/farm-and-ranch-supply-depot/blob/main/bin/extra/add-nodes). Note that this script won't work on Windows. Your mileage also may vary on Linux and MacOS. + +## Conclusion + +You should now be ready to use the Testnet to create and spend smart coins. As always, if you ran into any issues while setting up the Testnet, feel free to ask for support on our [Discord](https://discord.gg/chia). diff --git a/docs/chialisp-primer/using-modules.md b/docs/chialisp-primer/using-modules.md new file mode 100644 index 00000000..75a30e90 --- /dev/null +++ b/docs/chialisp-primer/using-modules.md @@ -0,0 +1,116 @@ +--- +slug: /chialisp-using-modules +title: 2. Using Modules +--- + +Up to this point, you have written single expressions and evaluated them on the command-line. However, sometimes you want to split your code into multiple functions or include common libraries. In order to do things like that, you will need to understand what modules are. + +## Modules + +The `mod` operator creates a context for converting the usage of constants into a single expression. + +:::note +Functions inside the module will not have direct access to the solution, so values you need access to will need to be passed in as a function parameter manually. + +In other words, there is no concept of [scope](). +::: + +This module will add two arbitrary values together: + +```chialisp +(mod (first second) + (+ first second) +) +``` + +And this is an example of defining a constant and a function, followed by their usage: + +```chialisp +;;; Raises the number by one order of magnitude. + +(mod (value) + ; Defines a constant value with a name. + (defconstant ORDER_OF_MAGNITUDE 10) + + ; Defines a function that can be called with a value. + (defun raise_magnitude (value) + (* value ORDER_OF_MAGNITUDE) + ) + + ; Calls the previously defined function. + (raise_magnitude value) +) +``` + +1. The module takes in a `value` parameter. +2. `ORDER_OF_MAGNITUDE` is defined as 10. +3. The `raise_magnitude` function takes in a `value` parameter (this is different from the `value` defined as a module parameter). +4. Returns the `value` function parameter multiplied by the `ORDER_OF_MAGNITUDE`. +5. Calls the function with the module parameter `value`. + +## Example + +By now you have seen how some aspects of the language work, and we can use these concepts to write and run a simple Chialisp program. We will write a module that calculates the factorial of a number using [recursion](https://en.wikipedia.org/wiki/Recursion). + +Put this in a file named `factorial.clsp`: + +```chialisp title="factorial.clsp" +;;; Calculates a factorial recursively. +;;; f(n) = n * f(n - 1) +;;; f(n) = n if n <= 2 + +(mod (number) + ; Defines the factorial function. + (defun factorial (number) + (if (> number 1) + (* number (factorial (- number 1))) + 1 + ) + ) + + ; Calls the function with the number provided. + (factorial number) +) +``` + +Run this example with the following command: + +```bash +brun "$(run factorial.clsp)" "(5)" +``` + +It will compile it and run the result with a solution where `number` is 5. The result of this should be the factorial of that number, which is 120. There were a few new operators used in these examples. For more information, you should refer to the [operator reference](/operators). Below is a detailed explanation of how this works. + +1. The module takes in a `number` parameter. +2. The `factorial` function also takes in a `number` parameter. +3. If the number is greater than 2, returns the number times the previous factorial. +4. Otherwise, returns the number itself. +5. Call the recursive function with the `number` module parameter. + +We can visualize this function with the input 5 as follows: + +```chialisp +(factorial 5) +(* 5 (factorial 4)) +(* 5 (* 4 (factorial 3))) +(* 5 (* 4 (* 3 (factorial 2)))) +(* 5 (* 4 (* 3 (* 2 (factorial 1))))) +(* 5 (* 4 (* 3 (* 2 1)))) +``` + +Which then simplifies like this: + +```chialisp +(* 5 (* 4 (* 3 2))) +(* 5 (* 4 6)) +(* 5 24) +120 +``` + +Everything that would normally be written using iteration in an imperative language, for example array modification, is instead written using recursion in Chialisp. It can be hard to understand at first, but eventually it will make more and more sense. + +## Conclusion + +Modules allow you to use functional programming in Chialisp, which makes writing it feel more natural. It also allows you to reuse your code and express it in a more clear way. + +If you have any questions about modules, or anything else, remember to come ask questions on our [Discord](https://discord.gg/chia). diff --git a/docs/commands.md b/docs/commands.md index a2c97086..de0a011a 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -55,7 +55,7 @@ You can also use `-i` instead of `--include` if you prefer. ### Curry -You can [curry](https://docs.chia.net/guides/chialisp-currying) values into your program like this: +You can [curry](/chialisp-currying) values into your program like this: ```bash cdv clsp curry program.clsp --args '0xCAFEF00D' --args '(hello there)' diff --git a/docs/common_issues.md b/docs/common_issues.md index 69026c65..f362acec 100644 --- a/docs/common_issues.md +++ b/docs/common_issues.md @@ -38,7 +38,7 @@ The problem with this puzzle is that whoever farms the coin will see the `passwo ### How to avoid -Password coins are easy to create, so they are often used in training materials (see [our documentation](https://docs.chia.net/guides/chialisp-first-smart-coin/#password-puzzle) for more info). However, coins locked with a password (and nothing else) are not secure. Instead, use announcements and the `AGG_SIG_ME` condition to secure your coins, as explained in the [standard transaction puzzle](https://chialisp.com/standard-transactions/). +Password coins are easy to create, so they are often used in training materials (see [our documentation](/chialisp-first-smart-coin/#password-puzzle) for more info). However, coins locked with a password (and nothing else) are not secure. Instead, use announcements and the `AGG_SIG_ME` condition to secure your coins, as explained in the [standard transaction puzzle](/standard-transactions/). Also keep in mind that a farmer can attempt to modify a coin's solution as it is being spent. If modifying any of the conditions from your coin's solution would result in the solution remaining valid, then you should assume the farmer will do exactly this. @@ -185,7 +185,7 @@ Note that Replace By Fee cannot be used for spend bundle splitting. The spend bu ### How to avoid -If your spend bundle would be vulnerable to being split in a malicious way, you can link all coin spends together with [announcements](https://docs.chia.net/conditions#assert-coin-announcement). This will ensure that the spend bundle must remain intact when spent. +If your spend bundle would be vulnerable to being split in a malicious way, you can link all coin spends together with [announcements](/conditions#assert-coin-announcement). This will ensure that the spend bundle must remain intact when spent. --- diff --git a/docs/conditions.md b/docs/conditions.md new file mode 100644 index 00000000..001fd694 --- /dev/null +++ b/docs/conditions.md @@ -0,0 +1,635 @@ +--- +slug: /conditions +title: Conditions +--- + +When a coin is spent, its puzzle is executed on the Chialisp Virtual Machine (CLVM). If the program does not fail, it returns a list of conditions. These conditions determine what the outcome of the spend is, and whether or not the spend is valid. + +Puzzles have no access to the outside world, or even to blockchain parameters like block height. Therefore, to interact with the outside environment, they return a list of conditions, each of which must be valid in order for the spend itself to be valid. + +There are two kinds of conditions. Some require something to be true (such as time passing) in order for the spend to be valid. And others cause something to happen if the spend is valid (such as the creation of new coins). + +## Condition List {#list} + +:::warning + +Be vigilant when using `ASSERT_MY_COIN_ID` as a shortcut for validating the parent coin ID, puzzle hash, and amount. If they are passed into the solution separately, then validated all at once by hashing them together, it is possible to shift the bytes to the left or right and manipulate the values. + +You are recommended to use the `coinid` operator when computing coin IDs. This operator was introduced with [CHIP-11](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md). It verifies that hashes are indeed 32 bytes in length, at no extra CLVM cost versus verifying the parent ID, puzzle hash, and amount individually. The `coinid` operator, as well as the other CHIP-11 operators, are described on the [operators page](/operators#chip-0011-operators). + +::: + +:::warning + +`ASSERT_COIN_ANNOUNCEMENT` and `ASSERT_PUZZLE_ANNOUNCEMENT` should typically only be used in a puzzle's _solution_, and not in the puzzle itself. This is especially important when using `ASSERT_COIN_ANNOUNCEMENT`, because it refers to a specific coin. + +To illustrate the danger, let's say `coin A` uses this condition in its puzzle, and it asserts a coin announcement from `coin B`. +In this case, `coin A` requires `coin B` to be spent in the same block as it is spent. +If `coin B` is spent before `coin A`, then `coin A` can _never_ be spent. + +However, if this condition is instead used in the _solution_ for `coin A`, and `coin B` has already been spent, then `coin A` can still be spent later, albeit with a different solution. + +It is somewhat less dangerous to use `ASSERT_PUZZLE_ANNOUNCEMENT` in a coin's puzzle because it only relies on a coin with a specific puzzle, and many such coins might exist. +However, it is still best practice to only use this condition in a coin's solution. + +::: + +### 1 `REMARK` {#remark} + +Format: `(1)` + +This condition is always considered valid by the mempool. + +This condition has no parameters. + +--- + +### 43 `AGG_SIG_PARENT` {#agg-sig-parent} + +:::info +This condition is part of [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md), and will be available at block height 5,496,000. +::: + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) of 1,200,000. +::: + +Format: `(43 public_key message)` + +Verifies a signature for a given message which is concatenated with the following values: + +- The parent coin id of the coin being spent. +- The domain string, `sha256(genesis_id + 43)`. + +The following parameters are expected: + +| Name | Type | +| ------------ | --------- | +| `public_key` | G1Element | +| `message` | Bytes | + +--- + +### 44 `AGG_SIG_PUZZLE` {#agg-sig-puzzle} + +:::info +This condition is part of [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md), and will be available at block height 5,496,000. +::: + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) of 1,200,000. +::: + +Format: `(44 public_key message)` + +Verifies a signature for a given message which is concatenated with the following values: + +- The puzzle hash of the coin being spent. +- The domain string, `sha256(genesis_id + 44)`. + +The following parameters are expected: + +| Name | Type | +| ------------ | --------- | +| `public_key` | G1Element | +| `message` | Bytes | + +--- + +### 45 `AGG_SIG_AMOUNT` {#agg-sig-amount} + +:::info +This condition is part of [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md), and will be available at block height 5,496,000. +::: + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) of 1,200,000. +::: + +Format: `(45 public_key message)` + +Verifies a signature for a given message which is concatenated with the following values: + +- The amount of the coin being spent. +- The domain string, `sha256(genesis_id + 45)`. + +The following parameters are expected: + +| Name | Type | +| ------------ | --------- | +| `public_key` | G1Element | +| `message` | Bytes | + +--- + +### 46 `AGG_SIG_PUZZLE_AMOUNT` {#agg-sig-puzzle-amount} + +:::info +This condition is part of [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md), and will be available at block height 5,496,000. +::: + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) of 1,200,000. +::: + +Format: `(46 public_key message)` + +Verifies a signature for a given message which is concatenated with the following values: + +- The puzzle hash of the coin being spent. +- The amount of the coin being spent. +- The domain string, `sha256(genesis_id + 46)`. + +The following parameters are expected: + +| Name | Type | +| ------------ | --------- | +| `public_key` | G1Element | +| `message` | Bytes | + +--- + +### 47 `AGG_SIG_PARENT_AMOUNT` {#agg-sig-parent-amount} + +:::info +This condition is part of [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md), and will be available at block height 5,496,000. +::: + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) of 1,200,000. +::: + +Format: `(47 public_key message)` + +Verifies a signature for a given message which is concatenated with the following values: + +- The parent coin id of the coin being spent. +- The amount of the coin being spent. +- The domain string, `sha256(genesis_id + 47)`. + +The following parameters are expected: + +| Name | Type | +| ------------ | --------- | +| `public_key` | G1Element | +| `message` | Bytes | + +--- + +### 48 `AGG_SIG_PARENT_PUZZLE` {#agg-sig-parent-puzzle} + +:::info +This condition is part of [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md), and will be available at block height 5,496,000. +::: + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) of 1,200,000. +::: + +Format: `(48 public_key message)` + +Verifies a signature for a given message which is concatenated with the following values: + +- The parent coin id of the coin being spent. +- The puzzle hash of the coin being spent. +- The domain string, `sha256(genesis_id + 48)`. + +The following parameters are expected: + +| Name | Type | +| ------------ | --------- | +| `public_key` | G1Element | +| `message` | Bytes | + +--- + +### 49 `AGG_SIG_UNSAFE` {#agg-sig-unsafe} + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) of 1,200,000. +::: + +Format: `(49 public_key message)` + +Verifies a signature for a given message. For [security reasons](https://github.com/Chia-Network/post-mortem/blob/main/2023-05/2023-05-08-AGG_SIG_UNSAFE-can-mimic-AGG_SIG_ME-condition.md), domain strings are not permitted at the end of `AGG_SIG_UNSAFE` messages. + +The following parameters are expected: + +| Name | Type | +| ------------ | --------- | +| `public_key` | G1Element | +| `message` | Bytes | + +--- + +### 50 `AGG_SIG_ME` {#agg-sig-me} + +:::tip +In most cases, `AGG_SIG_ME` is the recommended condition for requiring signatures. Signatures created for a specific coin spend will only be valid for that exact coin, which prevents an attacker from reusing the signature for other spends. +::: + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) of 1,200,000. +::: + +Format: `(50 public_key message)` + +Verifies a signature for a given message which is concatenated with the following values: + +- The id of the coin being spent. +- The domain string, `genesis_id`. + +The following parameters are expected: + +| Name | Type | +| ------------ | --------- | +| `public_key` | G1Element | +| `message` | Bytes | + +--- + +### 51 `CREATE_COIN` {#create-coin} + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) of 1,800,000. +::: + +Format: `(51 puzzle_hash amount (...memos)?)` + +Creates a new coin output with a given puzzle hash and amount. This coin is its parent. + +For more information on the `memos` parameter, see the section on [Memos and Hinting](#memos). + +The following parameters are expected: + +| Name | Type | +| -------------------- | ------------ | +| `puzzle_hash` | Bytes32 | +| `amount` | Unsigned Int | +| `memos` _(optional)_ | Bytes32 List | + +--- + +### 52 `RESERVE_FEE` {#reserve-fee} + +Format: `(52 amount)` + +Requires that the total amount remaining in the transaction after all outputs have been created is no less than the reserved fee amount. + +The following parameters are expected: + +| Name | Type | +| -------- | ------------ | +| `amount` | Unsigned Int | + +--- + +### 60 `CREATE_COIN_ANNOUNCEMENT` {#create-coin-announcement} + +Format: `(60 message)` + +Creates an announcement of a given message, tied to this coin's id. For more details, see the section on [Announcements](#announcements). + +The following parameters are expected: + +| Name | Type | +| --------- | ----- | +| `message` | Bytes | + +--- + +### 61 `ASSERT_COIN_ANNOUNCEMENT` {#assert-coin-announcement} + +Format: `(61 announcement_id)` + +Asserts an announcement with a given id, which is calculated as `sha256(coin_id + message)`. For more details, see the section on [Announcements](#announcements). + +The following parameters are expected: + +| Name | Type | +| ----------------- | ------- | +| `announcement_id` | Bytes32 | + +--- + +### 62 `CREATE_PUZZLE_ANNOUNCEMENT` {#create-puzzle-announcement} + +Format: `(62 message)` + +Creates an announcement of a given message, tied to this coin's puzzle hash. For more details, see the section on [Announcements](#announcements). + +The following parameters are expected: + +| Name | Type | +| --------- | ----- | +| `message` | Bytes | + +--- + +### 63 `ASSERT_PUZZLE_ANNOUNCEMENT` {#assert-puzzle-announcement} + +Format: `(63 announcement_id)` + +Asserts an announcement with a given id, which is calculated as `sha256(puzzle_hash + message)`. For more details, see the section on [Announcements](#announcements). + +The following parameters are expected: + +| Name | Type | +| ----------------- | ------- | +| `announcement_id` | Bytes32 | + +--- + +### 64 `ASSERT_CONCURRENT_SPEND` {#assert-concurrent-spend} + +Format: `(64 coin_id)` + +Asserts that this coin is spent within the same block as the spend of a given coin. + +The following parameters are expected: + +| Name | Type | +| --------- | ------- | +| `coin_id` | Bytes32 | + +--- + +### 65 `ASSERT_CONCURRENT_PUZZLE` {#assert-concurrent-puzzle} + +Format: `(65 puzzle_hash)` + +Asserts that this coin is in the same block as the spend of another coin with a given puzzle hash. + +The following parameters are expected: + +| Name | Type | +| ------------- | ------- | +| `puzzle_hash` | Bytes32 | + +--- + +### 70 `ASSERT_MY_COIN_ID` {#assert-my-coin-id} + +Format: `(70 coin_id)` + +Asserts that id of this coin matches a given value. + +The following parameters are expected: + +| Name | Type | +| --------- | ------- | +| `coin_id` | Bytes32 | + +--- + +### 71 `ASSERT_MY_PARENT_ID` {#assert-my-parent-id} + +Format: `(71 parent_id)` + +Asserts that the parent id of this coin matches a given value. + +The following parameters are expected: + +| Name | Type | +| ----------- | ------- | +| `parent_id` | Bytes32 | + +--- + +### 72 `ASSERT_MY_PUZZLE_HASH` {#assert-my-puzzle-hash} + +Format: `(72 puzzle_hash)` + +Asserts that the puzzle hash of this coin matches a given value. + +The following parameters are expected: + +| Name | Type | +| ------------- | ------- | +| `puzzle_hash` | Bytes32 | + +--- + +### 73 `ASSERT_MY_AMOUNT` {#assert-my-amount} + +Format: `(73 amount)` + +Asserts that the amount of this coin matches a given value. + +The following parameters are expected: + +| Name | Type | +| -------- | ------------ | +| `amount` | Unsigned Int | + +--- + +### 74 `ASSERT_MY_BIRTH_SECONDS` {#assert-my-birth-seconds} + +Format: `(74 seconds)` + +Asserts that this coin was created at a given timestamp. + +The following parameters are expected: + +| Name | Type | +| --------- | ------------ | +| `seconds` | Unsigned Int | + +--- + +### 75 `ASSERT_MY_BIRTH_HEIGHT` {#assert-my-birth-height} + +Format: `(75 block_height)` + +Asserts that this coin was created at a given block height. + +The following parameters are expected: + +| Name | Type | +| -------------- | ------------ | +| `block_height` | Unsigned Int | + +--- + +### 76 `ASSERT_EPHEMERAL` {#assert-ephemeral} + +Format: `(76)` + +Asserts that this coin was created within the current block. + +This condition has no parameters. + +--- + +### 80 `ASSERT_SECONDS_RELATIVE` {#assert-seconds-relative} + +Format: `(80 seconds_passed)` + +Asserts that the previous transaction block was created at least a given number of seconds after this coin was created. + +The following parameters are expected: + +| Name | Type | +| ---------------- | ------------ | +| `seconds_passed` | Unsigned Int | + +--- + +### 81 `ASSERT_SECONDS_ABSOLUTE` {#assert-seconds-absolute} + +Format: `(81 seconds)` + +Asserts that the previous transaction block was created at at least a given timestamp, in seconds. + +The following parameters are expected: + +| Name | Type | +| --------- | ------------ | +| `seconds` | Unsigned Int | + +--- + +### 82 `ASSERT_HEIGHT_RELATIVE` {#assert-height-relative} + +Format: `(82 block_height_passed)` + +Asserts that the previous transaction block was created at least a given number of blocks after this coin was created. + +The following parameters are expected: + +| Name | Type | +| --------------------- | ------------ | +| `block_height_passed` | Unsigned Int | + +--- + +### 83 `ASSERT_HEIGHT_ABSOLUTE` {#assert-height-absolute} + +Format: `(83 block_height)` + +Asserts that the previous transaction block was created at at least a given height. + +The following parameters are expected: + +| Name | Type | +| -------------- | ------------ | +| `block_height` | Unsigned Int | + +--- + +### 84 `ASSERT_BEFORE_SECONDS_RELATIVE` {#assert-before-seconds-relative} + +Format: `(84 seconds_passed)` + +Asserts that the previous transaction block was created before a given number of seconds after this coin was created. + +The following parameters are expected: + +| Name | Type | +| ---------------- | ------------ | +| `seconds_passed` | Unsigned Int | + +--- + +### 85 `ASSERT_BEFORE_SECONDS_ABSOLUTE` {#assert-before-seconds-absolute} + +Format: `(85 seconds)` + +Asserts that the previous transaction block was created before a given timestamp, in seconds. + +The following parameters are expected: + +| Name | Type | +| --------- | ------------ | +| `seconds` | Unsigned Int | + +--- + +### 86 `ASSERT_BEFORE_HEIGHT_RELATIVE` {#assert-before-height-relative} + +Format: `(86 block_height_passed)` + +Asserts that the previous transaction block was created before a given number of blocks after this coin was created. + +The following parameters are expected: + +| Name | Type | +| --------------------- | ------------ | +| `block_height_passed` | Unsigned Int | + +--- + +### 87 `ASSERT_BEFORE_HEIGHT_ABSOLUTE` {#assert-before-height-absolute} + +Format: `(87 block_height)` + +Asserts that the previous transaction block was created before a given height. + +The following parameters are expected: + +| Name | Type | +| -------------- | ------------ | +| `block_height` | Unsigned Int | + +--- + +### 90 `SOFTFORK` {#softfork} + +:::info +This condition is part of [CHIP-0011](https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0011.md), and will be available at block height 5,496,000. +::: + +:::note +This condition adds an additional [CLVM cost](https://docs.chia.net/coin-set-costs/) equal to whatever the value of the first argument is. +::: + +Format: `(90 cost ...args)` + +Allows future conditions with non-zero CLVM costs to be added as soft forks. This functionality was previously only possible as a hard fork. + +The cost of the condition is specified in ten-thousands, and further arguments are not specified (the soft-forked condition defines these). The reason to scale the cost by 10,000 is to make the argument smaller. For example, a cost of 100 in this condition would equate to an actual cost of 1 million (1,000,000). The cost argument is two bytes, with a maximum size of 65,535 (an actual cost of 655,350,000). + +The following parameters are expected: + +| Name | Type | +| --------- | ------------ | +| `cost` | Unsigned Int | +| `...args` | Any | + +## Memos and Hinting {#memos} + +When a coin uses one or more outer puzzles that change their puzzle hash, it's challenging for wallets to know which coins they have the ability to spend. The memos field allows you to hint the inner puzzle hash of created coins, which consequently lets the wallet know that the coin belongs to it. Coins can be looked up by the inner puzzle hash rather than the outer puzzle hash. + +The `CREATE_COIN` condition is defined as a list containing the opcode `51` and the following arguments: + +```chialisp +; The third parameter is optional. +(51 puzzle_hash amount (...memos)) +``` + +The `memos` parameter is an optional list, which must be null terminated. + +If `memos` is present, and the first memo is exactly 32 bytes long, it's used as the hint and the rest of the list are memos. Otherwise, values in the entire list are memos. + +As an example, the following inner solution for the [standard transaction](/standard-transactions) would create an unhinted coin: + +```chialisp +(() (q . ((51 target_puzzle_hash amount))) ()) +``` + +The following solution would instead create a coin with the hint matching the inner puzzle hash: + +```chialisp +(() (q . ((51 target_puzzle_hash amount (target_puzzle_hash)))) ()) +``` + +This `CREATE_COIN` condition creates the same coin as before, but now it specifies the hint with which the receiving wallet can look up to find this coin. + +Hints are only necessary for outer puzzles, of which the inner puzzle hash matches the hint. For example, coins using the standard transaction itself with no outer puzzle do not need a hint. + +## Announcements + +Announcements are ephemeral, meaning that they don't last forever. They can only be asserted within the block they are created. Their purpose is to ensure multiple coins are spent together, either for fees, verification, or as a security measure. + +For coin announcements, the id is the `coin_id` and `message` sha256 hashed together. Likewise, for puzzle announcements, it's the `puzzle_hash` and `message` sha256 hashed together. diff --git a/docs/costs.md b/docs/costs.md index 9b8cc4c7..54a0b150 100644 --- a/docs/costs.md +++ b/docs/costs.md @@ -64,7 +64,7 @@ Additionally, there is a cost of 10 per byte of memory allocated in the return v ## Conditions -More information on the costs associated with conditions can be found on the [Conditions page](https://docs.chia.net/conditions#costs) of the Chia docs. +More information on the costs associated with conditions can be found on the [Conditions page](/conditions#costs) of the Chia docs. ## Evaluating Cost diff --git a/docs/intro.md b/docs/intro.md index 8abf3623..10da1c0f 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -58,4 +58,4 @@ New features are listed in detail [here](/modern-chialisp). ## Getting Started -If you'd like to get started learning and using Chialisp, you can start with the [Intro to Chialisp](https://docs.chia.net/guides) guide. Throughout this series, you will write programs in the language, create smart coins on the Chia blockchain, and spend them on the command-line. +If you'd like to get started learning and using Chialisp, you can start with the [Intro to Chialisp](/chialisp-primer/intro) guide. Throughout this series, you will write programs in the language, create smart coins on the Chia blockchain, and spend them on the command-line. diff --git a/docs/optimization.md b/docs/optimization.md index 0a12728a..6200ebcd 100644 --- a/docs/optimization.md +++ b/docs/optimization.md @@ -10,7 +10,7 @@ It is possible to optimize the cost of your programs by making certain changes a ## Conditions -Check out the [full conditions list](https://docs.chia.net/conditions/#list) for detailed information on conditions and their use. +Check out the [full conditions list](/conditions/#list) for detailed information on conditions and their use. If you are writing a puzzle for the Chia blockchain, minimize the number of spends and conditions used. Specifically, the `CREATE_COIN`, `AGG_SIG_ME`, and `AGG_SIG_UNSAFE` conditions have a massive cost associated with them. This is because they are an expensive operation to perform on the node. diff --git a/docs/primitives/cats.md b/docs/primitives/cats.md index 08c0228c..08d98a78 100644 --- a/docs/primitives/cats.md +++ b/docs/primitives/cats.md @@ -5,7 +5,7 @@ slug: /cats Chia Asset Tokens are fungible tokens that are issued on the Chia blockchain. The CAT puzzle ensures that the supply of a specific CAT never changes unless the rules of issuance specific to that CAT are followed. These are enforced using a separate Chialisp program called the [Token and Asset Issuance Limitations (TAIL)](#tail). -Aside from the TAIL, there is also an [inner puzzle](https://docs.chia.net/guides/chialisp-inner-puzzles) that the CAT wraps around. The inner puzzle controls the ownership of the specific coin, and when the coin is spent, the new puzzle is wrapped in the CAT again. Typically, you wrap the [standard transaction](/standard-transactions) so that you can send CATs to Chia wallet addresses. +Aside from the TAIL, there is also an [inner puzzle](/chialisp-inner-puzzles) that the CAT wraps around. The inner puzzle controls the ownership of the specific coin, and when the coin is spent, the new puzzle is wrapped in the CAT again. Typically, you wrap the [standard transaction](/standard-transactions) so that you can send CATs to Chia wallet addresses. :::note diff --git a/docusaurus.config.js b/docusaurus.config.js index 1b9cc06c..2df37e15 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -22,20 +22,26 @@ module.exports = { }, items: [ { - href: 'https://chia.net', - label: 'Chia.net', + href: 'https://docs.chia.net', + label: 'Chia Docs', position: 'left', }, { - href: 'https://github.com/Chia-Network/chialisp-web', - label: 'GitHub', + href: 'https://docs.chia.net/academy-home/', + label: 'Chia Academy', position: 'left', }, { - href: 'https://docs.chia.net', - label: 'Chia Docs', - position: 'left', + href: 'https://chia.net', + label: 'Chia.net', + position: 'right', + }, + { + href: 'https://github.com/Chia-Network/', + label: 'GitHub', + position: 'right', }, + ], }, footer: { diff --git a/sidebars.js b/sidebars.js index 31e6d375..bf8efd2d 100644 --- a/sidebars.js +++ b/sidebars.js @@ -1,17 +1,52 @@ module.exports = { someSidebar: [ + 'intro', { - type: 'link', - label: 'Learn Chialisp', - href: 'https://docs.chia.net/guides', + type: 'category', + label: 'Chialisp Primer', + collapsible: true, + collapsed: true, + link: { + type: 'generated-index', + slug: '/chialisp-primer', + title: 'Chialisp Primer', + description: + 'This guide will teach you the basics of Chialisp, a smart coin language used on the Chia blockchain. You will learn the skills required to write basic programs that can dictate how and when coins (including XCH) can be spent.', + }, + items: [ + 'chialisp-primer/intro', + 'chialisp-primer/using-modules', + 'chialisp-primer/testnet-setup', + 'chialisp-primer/first-smart-coin', + 'chialisp-primer/bls-signatures', + ], }, - 'intro', + { + type: 'category', + label: 'Chialisp Concepts', + collapsible: true, + collapsed: true, + link: { + type: 'generated-index', + slug: '/chialisp-concepts', + title: 'Chialisp Concepts', + description: + 'This guide introduces some key Chialisp concepts. Understanding these concepts will enable you to write Chialisp programs more easily.', + }, + items: [ + 'chialisp-concepts/currying', + 'chialisp-concepts/inner-puzzles', + 'chialisp-concepts/condition-morphing', + ], + }, + 'commands', 'syntax', 'modern-chialisp', 'operators', 'examples', 'costs', + 'conditions', 'optimization', 'common_issues', 'debugging',