In this lesson, we'll talk about why you might want to nest puzzles and how to set them up.
- Functions: Learn how to define and execute functions in Chialisp.
- Nesting Puzzles: Understand the use of nesting puzzles in Chialisp.
Expand for the full script
All puzzles result in the output of a condition that tells a blockchain what to do with a coin that it's wrapped in. Inner puzzles can be thought of as a coin within a coin where the result is a condition that is passed to the outer puzzle which executes it.
One specific use for this functionality is if you wanted to use a generic inner puzzle and wrap it in an outer puzzle that verifies a signature. The outer puzzle can be a sort of template that you can pass in any generic inner puzzle and it will be signature protected by the outer puzzle. Let's create this exact outer puzzle template.
We're going to define a module, and for our parameters we'll have a
PUBLIC_KEY that we'll curry in later, an
INNER_PUZZLE that we'll also curry in, and then the
inner_solution. We'll include the
condition_codes.clib library file and the
sha256tree.clib library file as well. Then, we're going to define a new function.
We'll call this
calculate_output and in the parameters we'll have our
inner_solution, and the
conditions that we'll execute. In a combine statement, we'll have the standard signature verification that we used in the previous video. (
(defun calculate_output (PUBLIC_KEY inner_solution conditions) (c (list AGG_SIG_MET PUBLIC_KEY (sha256tree inner_solution)) conditions)))
For the message that we're verifying, we'll be verifying the
inner_solution and then we'll return the
conditions. Now that we've defined our new function, we'll call it with
calculate_output, provide the
PUBLIC_KEY and the
inner_solution, and then we'll use the
apply operator or
a on our
INNER_PUZZLE, providing the
calculate_output PUBLIC_KEY inner_solution (a INNER_PUZZLE inner_solution))
apply operator is how you execute some code. So the
INNER_PUZZLE will be executed with the
inner_solution. So this puzzle will first evaluate the inner puzzle with the
(a INNER_PUZZLE inner_solution)) method, and use the result as the condition for our
This function requires a signature of the
inner_solution to pass. Now let's write the inner puzzle. For this puzzle, we're going to use a condition called
ASSERT_HEIGHT_RELATIVE, which specifies when a coin can be spent, based on the number of blocks passed since coin creation. We'll define a module and in our parameters, we'll curry in the
REQUIRED_BLOCKS. This will be a number of blocks that have to pass before the coin can be spent.
Then, we'll have our
conditions. We'll include the
condition_codes.clib library again, and then we'll define a statement that uses the
ASSERT_HEIGHT_RELATIVE condition on the
REQUIRED_BLOCKS that we curried in, and then we'll return the
All right, now we have both our inner puzzle and our outer puzzle. Let's curry in the needed values. First we'll get our public key with
chia keys show, and then we'll curry the block value into the inner puzzle with
cdv clsp curry inner-puzzle.clsp -a and specify the number of blocks that we want to pass.
In this case, we'll use
20. We can now curry this result, along with our public key, into the outer puzzle with
cdv clsp curry outer-puzzle.clsp -a, enter our public key,
-a and in quotes we'll paste the compiled inner puzzle.
Now that we have our final compiled puzzle, we can go ahead and create a coin using the process that we covered in the last video. Once the coin has been created, we can create our solution for this coin. First we get our wallet address and
decode it. We'll use this in our desired solution. Again, we'll be using the
CREATE_COIN condition signified by the code
Note that I'm nesting the solution in four (4) sets of parentheses. This is because the outer puzzle parameters list is passed in wrapped with parentheses as is the inner solution. In the inner puzzle, we have another set of parentheses for the list of conditions, and each condition is also wrapped.
It's important to understand the structure of the puzzle to make sure that the solution you provide is structured properly. Now we'll add the encoded solution into our spend bundle where we already have the coin info and puzzle reveal from coin creation. Next, we'll get our signature using the method we outlined in the previous video. We'll hash our solution and concatenate it with the coin ID and genesis challenge.
Now we can sign the resulting message with
chia keys sign and copy the signature into our spend bundle, being sure to append
0x to signify that it's a value. Now run
cdv rpc pushtx spendbundle.json.
If the number of blocks is not yet passed, it will have a pending status. If successful, we can look up the coin record again and see that the spent block index is more than 20 blocks later than the confirmed block index. In this video, we learned how inner puzzles work and how they interact with outer puzzles. Thanks so much for watching, catch you next time.
- More Parentheses: It's important to take note of where your solutions are going to be used in your puzzle and wrap them in the appropriate amount of parentheses. This can be counter-intuitive as the parentheses can seem unecessary at first glance.
What operator is used to evaluate a puzzle within another puzzle?
Answer (expand when ready to see the answer)
apply operator. (
(a INNER_PUZZLE inner_solution)
What does the
ASSERT_HEIGHT_RELATIVE condition check for?
Answer (expand when ready to see the answer)
ASSERT_HEIGHT_RELATIVE checks for how many blocks have passed since coin creation. It allows the resolution of a puzzle after a predefined number of blocks have passed.
Runnable Chialisp and clvm plugins
For information on using these plugins please refer to the academy overview
- General chialisp concepts: overviews of currying, inner puzzles, and morphing conditions.
- Guided chialisp walkthroughs: guides for installation, creating smart coins, and working with BLS signatures.
- Chialisp detailed documentation: detailed information on all aspects of chialisp.
- Support in discord: for further support join our discord server and ask in the #chialisp or #support channels.