Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs reorg #257

Merged
merged 5 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions docs/chialisp-concepts/condition-morphing.md
Original file line number Diff line number Diff line change
@@ -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).
86 changes: 86 additions & 0 deletions docs/chialisp-concepts/currying.md
Original file line number Diff line number Diff line change
@@ -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).
101 changes: 101 additions & 0 deletions docs/chialisp-concepts/inner-puzzles.md
Original file line number Diff line number Diff line change
@@ -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).
58 changes: 58 additions & 0 deletions docs/chialisp-primer/bls-signatures.md
Original file line number Diff line number Diff line change
@@ -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)!
Loading
Loading