From 0916da6594609b811e31c1f666638d15c8bd7381 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 27 Mar 2020 15:13:13 +0000 Subject: BIP-0341: Replace notion of is_negated with parity bit --- bip-0341.mediawiki | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/bip-0341.mediawiki b/bip-0341.mediawiki index 6472430..564071f 100644 --- a/bip-0341.mediawiki +++ b/bip-0341.mediawiki @@ -59,7 +59,7 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to [[bip-0340.mediawiki#design|BIP340]]. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y oddness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the signature and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the parity of the public key's Y coordinate, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the signature and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' (see the next subsection). * If there are at least two witness elements left, script path spending is used: @@ -168,8 +168,8 @@ Alice will not be able to notice the script path, but Mallory can unilaterally s '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the Python3 algorithms below. These algorithms take advantage of helper functions from the [bip-0340/referency.py BIP340 reference code] for integer conversion, point multiplication, and tagged hashes. First, we define taproot_tweak_pubkey for 32-byte [[bip-0340.mediawiki|BIP340]] public key arrays. -In addition to the tweaked public key byte array, the function returns a boolean indicating whether the public key represents the tweaked point or its negation. -This will be required for spending the output with a script path. +The function returns a bit indicating the tweaked public key's Y coordinate as well as the public key byte array. +The parity bit will be required for spending the output with a script path. In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key. For any byte string h it holds that taproot_tweak_pubkey(pubkey_gen(seckey), h)[0] == pubkey_gen(taproot_tweak_seckey(seckey, h)). @@ -179,8 +179,7 @@ def taproot_tweak_pubkey(pubkey, h): if t >= SECP256K1_ORDER: raise ValueError Q = point_add(lift_x_even_y(int_from_bytes(pubkey)), point_mul(G, t)) - is_negated = not has_even_y(Q) - return bytes_from_int(x(Q)), is_negated + return 0 if has_even_y(Q) else 1, bytes_from_int(x(Q)) def taproot_tweak_seckey(seckey0, h): P = point_mul(G, int_from_bytes(seckey0)) @@ -226,7 +225,7 @@ def taproot_output_script(internal_pubkey, script_tree): To spend this output using script ''D'', the control block would contain the following data in this order: - + The TapTweak would then be computed as described [[bip-0341.mediawiki#script-validation-rules|above]] like so: @@ -258,9 +257,8 @@ This function returns the witness stack necessary and a sighash fun def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - _, is_negated = taproot_tweak_pubkey(internal_pubkey, h) - output_pubkey_tag = 0 if is_negated else 1 - pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey + output_pubkey_y_parity, _ = taproot_tweak_pubkey(internal_pubkey, h) + pubkey_data = bytes([output_pubkey_y_parity + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] -- cgit v1.2.3