Add commentary about sign_coin_spends and p2_delegated_puzzle_or_hidden_puzzle (#9452)

This commit is contained in:
arty
2022-01-10 21:00:24 -08:00
committed by GitHub
parent e498a406a0
commit 8610ab704a
2 changed files with 59 additions and 0 deletions
@@ -12,6 +12,48 @@ If the hidden puzzle path is taken, the hidden puzzle and original public key wi
which proves that it was hidden there in the first place.
This roughly corresponds to bitcoin's taproot.
Note:
p2_delegated_puzzle_or_hidden_puzzle is essentially the "standard coin" in chia.
DEFAULT_HIDDEN_PUZZLE_HASH from this puzzle is used with
calculate_synthetic_secret_key in the wallet's standard pk_to_sk finder.
This is important because it allows sign_coin_spends to function properly via the
following mechanism:
- A 'standard coin' coin exists in the blockchain with some puzzle hash.
- The user's wallet contains a primary sk/pk pair which are used to derive to one
level a set of auxiliary sk/pk pairs which are used for specific coins. these
can be used for signing in AGG_SIG_ME but the standard coin uses key further
derived from one of these via calculate_synthetic_secret_key as described in
https://chialisp.com/docs/standard_transaction . Therefore when a wallet needs
to find a secret key for signing based on a public key, it needs to try repeating
this derivation as well and see if the G1Element (pk) associated with any of the
derived secret keys matches the pk requested by the coin.
- Python code previously appeared which was written like:
delegated_puzzle_solution = Program.to((1, condition_args))
solutions = Program.to([[], delgated_puzzle_solution, []])
In context, delegated_puzzle_solution here is any *chialisp program*, here one
simply quoting a list of conditions, and the following argument is the arguments
to this program, which here are unused. Secondly, the actual arguments to the
p2_delegated_puzzle_or_hidden_puzzle are given. The first argument determines
wehther a hidden or revealed puzzle is used. If the puzzle is hidden, then what
is required is a signature given a specific syntheic key since the key cannot be
derived inline without the puzzle. In that case, the first arguemnt is this key.
In most cases, the puzzle will be revealed and this argument will be the nil object,
() (represented here by an empty python list).
The second and third arguments are a chialisp program and its corresponding
arguments, which will be run inside the standard coin puzzle. This interacts with
sign_coin_spend in that the AGG_SIG_ME condition added by the inner puzzle asks the
surrounding system to provide a signature over the provided program with a synthetic
key whose derivation is within. Any wallets which intend to use standard coins in
this way must try to resolve a public key to a secret key via this derivation.
"""
import hashlib
from typing import Union
+17
View File
@@ -15,6 +15,23 @@ async def sign_coin_spends(
additional_data: bytes,
max_cost: int,
) -> SpendBundle:
"""
Sign_coin_spends runs the puzzle code with the given argument and searches the
result for an AGG_SIG_ME condition, which it attempts to sign by requesting a
matching PrivateKey corresponding with the given G1Element (public key) specified
in the resulting condition output.
It's important to note that as mentioned in the documentation about the standard
spend that the public key presented to the secret_key_for_public_key_f function
provided to sign_coin_spends must be prepared to do the key derivations required
by the coin types it's allowed to spend (at least the derivation of the standard
spend as done by calculate_synthetic_secret_key with DEFAULT_PUZZLE_HASH).
If a coin performed a different key derivation, the pk presented to this function
would be similarly alien, and would need to be tried against the first stage
derived keys (those returned by master_sk_to_wallet_sk from the ['sk'] member of
wallet rpc's get_private_key method).
"""
signatures: List[blspy.G2Element] = []
pk_list: List[blspy.G1Element] = []
msg_list: List[bytes] = []