From 6357ff36a450523eb9aa8540753ef608d5057d0c Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Thu, 5 Mar 2026 10:04:34 -0500 Subject: [PATCH 01/41] nit: mark bitcoind dependent sign tests --- testing/test_sign.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testing/test_sign.py b/testing/test_sign.py index 8e05141d5..8c24bf3dc 100644 --- a/testing/test_sign.py +++ b/testing/test_sign.py @@ -956,6 +956,7 @@ def test_change_p2sh_p2wpkh(start_sign, end_sign, check_against_bitcoind, use_re end_sign(True) +@pytest.mark.bitcoind def test_wrong_p2sh_p2wpkh(bitcoind, start_sign, end_sign, bitcoind_d_sim_watch, cap_story): sim = bitcoind_d_sim_watch sim_addr = sim.getnewaddress("", "bech32") @@ -1734,6 +1735,7 @@ def make_spend(amount): @pytest.mark.parametrize('addr_fmt', ADDR_STYLES_SINGLE) @pytest.mark.parametrize('num_ins', [1, 17]) @pytest.mark.parametrize('num_outs', [1, 17]) +@pytest.mark.bitcoind def test_txid_calc(num_ins, fake_txn, try_sign, dev, decode_with_bitcoind, cap_story, txid_from_export_prompt, press_cancel, num_outs, addr_fmt): # verify correct txid for transactions is being calculated @@ -3722,6 +3724,7 @@ def random_nLockTime_test_cases(num=10): (1748671747, "2025-05-31 06:09:07"), *random_nLockTime_test_cases() ]) +@pytest.mark.bitcoind def test_timelocks_visualize(start_sign, end_sign, dev, bitcoind, use_regtest, bitcoind_d_sim_watch, nLockTime, sim_root_dir): # - works on simulator and connected USB real-device @@ -3778,6 +3781,7 @@ def test_timelocks_visualize(start_sign, end_sign, dev, bitcoind, use_regtest, @pytest.mark.parametrize('in_out', [(4,1),(2,2),(2,1)]) @pytest.mark.parametrize('partial', [False, True]) +@pytest.mark.bitcoind def test_base64_psbt_qr(in_out, partial, scan_a_qr, readback_bbqr, goto_home, use_regtest, cap_story, fake_txn, dev, decode_psbt_with_bitcoind, decode_with_bitcoind, From a5554b6690032f9a796a8bcfb1261e02f1e721ea Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 29 Jul 2026 14:34:58 -0400 Subject: [PATCH 02/41] bump submodule version external/ckcc-protocol - Add bip375 and bip376 constants external/libngu - Expose ec_pubkey_combine - Expose ec_pubkey_tweak_mul - Add bip352_encode update libngu --- external/ckcc-protocol | 2 +- external/libngu | 2 +- external/micropython | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/external/ckcc-protocol b/external/ckcc-protocol index 650c54b52..dec724e2a 160000 --- a/external/ckcc-protocol +++ b/external/ckcc-protocol @@ -1 +1 @@ -Subproject commit 650c54b5215a7cfe077cd02bb83c884aa984d32c +Subproject commit dec724e2a645cecbfad0d8c7d68a03fdda0722ff diff --git a/external/libngu b/external/libngu index ff4db2c3b..0ca8db37a 160000 --- a/external/libngu +++ b/external/libngu @@ -1 +1 @@ -Subproject commit ff4db2c3b6d3f02eb31ff2b020a4c1502a76d70b +Subproject commit 0ca8db37a6a588d31143f891518bd39ce4d37a5f diff --git a/external/micropython b/external/micropython index 3d227feca..4107246f8 160000 --- a/external/micropython +++ b/external/micropython @@ -1 +1 @@ -Subproject commit 3d227feca2b5067fbd024a30d7118cf148d0d3df +Subproject commit 4107246f8a080807b62c3b4838e71e812ea68b6f From 7e8481b2d5139bdd2d0fee9512148cc5a04241ec Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:38:21 -0500 Subject: [PATCH 03/41] BIP-352: implement Silent Payments cryptographic primitives Add bip352 crypto primitives / helpers Add bip352 tagged hashes --- shared/precomp_tag_hash.py | 10 ++- shared/silentpayments.py | 142 +++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 shared/silentpayments.py diff --git a/shared/precomp_tag_hash.py b/shared/precomp_tag_hash.py index ecded264c..e67812955 100644 --- a/shared/precomp_tag_hash.py +++ b/shared/precomp_tag_hash.py @@ -13,4 +13,12 @@ # BIP-322 # single sha256 of b'BIP0322-signed-message' -BIP322_TAG_HASH = b'te\x84\xa1\x87/\xa1\x00AUN\xff\xa08\xd6\x12IB\xddy\xb4\xe5\x8aL\xda\x18N\x13\xdb\xe6,I' \ No newline at end of file +BIP322_TAG_HASH = b'te\x84\xa1\x87/\xa1\x00AUN\xff\xa08\xd6\x12IB\xddy\xb4\xe5\x8aL\xda\x18N\x13\xdb\xe6,I' + +# BIP-352 tag hashes +# SHA256(BIP0352/SharedSecret) +BIP352_SHARED_SECRET_TAG_H = b'\x9fm\x80\x11X\x1e\xb6-r\xe6\x13`L3\r\xca*\x0b\xd3I\xe2JF\xd9\xa2\xef$\xb9\xa9\x8fA\xbd' +# SHA256(BIP0352/Inputs) +BIP352_INPUTS_TAG_H = b'\x1e{\x96\xeb\x16\nh\x81\x9f\x97vKC\xd5\xd7~fY\xd7Xw\x9dC\xa8\xa7u_[\xe4Z~3' +# SHA256(BIP0352/Label) +BIP352_LABEL_TAG_H = b'\x03I\x19F5\xc2\xd0>b\xd4\x13\xba\x8c\xcdQ\x98\x91\x90\x17\xa1\xe9\x9c\xbei\x1fZ4\xa9\x93w\xe0\x95' diff --git a/shared/silentpayments.py b/shared/silentpayments.py new file mode 100644 index 000000000..f917ad657 --- /dev/null +++ b/shared/silentpayments.py @@ -0,0 +1,142 @@ +# (c) Copyright 2024 by Coinkite Inc. This file is covered by license found in COPYING-CC. +# +# silentpayments.py - BIP-352/BIP-375 +# +# Consolidates cryptographic primitives and PSBT handling logic for Silent Payments +# +import ngu +from precomp_tag_hash import BIP352_SHARED_SECRET_TAG_H, BIP352_INPUTS_TAG_H + +G = ngu.secp256k1.generator() +SECP256K1_ORDER = ngu.secp256k1.curve_order_int() + +# ----------------------------------------------------------------------------- +# Silent Payments Cryptographic Primitives +# ----------------------------------------------------------------------------- + + +def _combine_pubkeys(pubkeys): + """ + Combine a list of public keys into a single public key + + Args: + pubkeys: List of public keys to combine (33-byte compressed) + + Returns: + bytes: Combined public key (33-byte compressed) + """ + if len(pubkeys) == 1: + return pubkeys[0] + return ngu.secp256k1.ec_pubkey_combine(pubkeys) + + +def _compute_ecdh_share(a_sum_bytes, B_scan_bytes): + """ + Compute ECDH share (partial shared secret) + + Formula: ecdh_share = a_sum * B_scan + + Args: + a_sum_bytes: Combined private key (32-byte scalar) + B_scan_bytes: Scan public key (33-byte compressed) + + Returns: + bytes: ECDH share point (33-byte compressed) + """ + return ngu.secp256k1.ec_pubkey_tweak_mul(B_scan_bytes, a_sum_bytes) + + +def _compute_input_hash(outpoints, A_sum_bytes): + """ + Compute BIP-352 input hash + + Formula: input_hash = hash_BIP0352/Inputs(smallest_outpoint || A_sum) + + Args: + outpoints: List of (txid, vout) tuples, where txid is 32-byte and vout is 4-byte little-endian + A_sum_bytes: Sum of all eligible input public keys (33-byte compressed) + + Returns: + bytes: Input hash (32-byte scalar) + """ + smallest = min(outpoints, key=lambda x: x[0] + x[1]) + msg = smallest[0] + smallest[1] + A_sum_bytes + input_hash_bytes = ngu.hash.sha256t(BIP352_INPUTS_TAG_H, msg, True) + input_hash_int = int.from_bytes(input_hash_bytes, "big") + if not (0 < input_hash_int < SECP256K1_ORDER): + raise ValueError("Invalid input hash: not in valid scalar range") + return input_hash_int.to_bytes(32, "big") + + +def _compute_shared_secret_tweak(shared_secret_bytes, k): + """ + Compute BIP-352 shared secret tweak + + Formula: t_k = hash_BIP0352/SharedSecret(serP(shared_secret) || ser_32(k)) + + Args: + shared_secret_bytes: Shared secret point (33-byte compressed) + k: Output index per scan key group (int) + + Returns: + bytes: Shared secret tweak (32-byte scalar) + """ + msg = shared_secret_bytes + k.to_bytes(4, "big") + tweak_bytes = ngu.hash.sha256t(BIP352_SHARED_SECRET_TAG_H, msg, True) + tweak_int = int.from_bytes(tweak_bytes, "big") + if not (0 < tweak_int < SECP256K1_ORDER): + raise ValueError("Invalid shared secret tweak: not in valid scalar range") + return tweak_int.to_bytes(32, "big") + + +def _compute_silent_payment_output_script(outpoints, A_sum_bytes, ecdh_share_bytes, B_spend_bytes, k): + """ + Compute the P2TR scriptPubKey for silent payment + + Formula: P_k = B_spend + t_k * G + + Args: + outpoints: List of (txid, vout) tuples from eligible inputs + A_sum_bytes: Sum of eligible input public keys (33-byte compressed) + ecdh_share_bytes: ECDH share point (33-byte compressed) + B_spend_bytes: Recipient spend public key (33-byte compressed) + k: Output index per scan key group (int) + + Returns: + bytes: P2TR scriptPubKey (OP_1 <32-byte x-only pubkey>) + """ + input_hash_bytes = _compute_input_hash(outpoints, A_sum_bytes) + shared_secret_bytes = ngu.secp256k1.ec_pubkey_tweak_mul(ecdh_share_bytes, input_hash_bytes) + tweak_bytes = _compute_shared_secret_tweak(shared_secret_bytes, k) + # Derive output pubkey: P_k = B_spend + t_k * G + tweak_point = ngu.secp256k1.ec_pubkey_tweak_mul(G, tweak_bytes) + output_pubkey = ngu.secp256k1.ec_pubkey_combine([B_spend_bytes, tweak_point]) + x_only = output_pubkey[1:] + return b"\x51\x20" + x_only + + +# ----------------------------------------------------------------------------- +# Input Eligibility +# ----------------------------------------------------------------------------- + + +def _is_p2pkh(spk): + # OP_DUP OP_HASH160 OP_PUSHBYTES_20 <20 bytes> OP_EQUALVERIFY OP_CHECKSIG + return ( + len(spk) == 25 and spk[0] == 0x76 and spk[1] == 0xA9 and spk[2] == 0x14 and spk[-2] == 0x88 and spk[-1] == 0xAC + ) + + +def _is_p2wpkh(spk): + # OP_0 OP_PUSHBYTES_20 <20 bytes> + return len(spk) == 22 and spk[0] == 0x00 and spk[1] == 0x14 + + +def _is_p2tr(spk): + # OP_1 OP_PUSHBYTES_32 <32 bytes> + return len(spk) == 34 and spk[0] == 0x51 and spk[1] == 0x20 + + +def _is_p2sh(spk): + # OP_HASH160 OP_PUSHBYTES_20 <20 bytes> OP_EQUAL + return len(spk) == 23 and spk[0] == 0xA9 and spk[1] == 0x14 and spk[-1] == 0x87 From 0ef0dec8379fccfca2212e7d0f7eb6881ad4d8ae Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:38:42 -0500 Subject: [PATCH 04/41] BIP-374: implement DLEQ proof generation and verification Add bip374 tagged hashes Add dleq bip374 reference generate_dleq_proof, verify_dleq_proof functions --- shared/dleq.py | 157 +++++++++++++++++++++++++++++++++++++ shared/precomp_tag_hash.py | 8 ++ 2 files changed, 165 insertions(+) create mode 100644 shared/dleq.py diff --git a/shared/dleq.py b/shared/dleq.py new file mode 100644 index 000000000..b3f8c6f8c --- /dev/null +++ b/shared/dleq.py @@ -0,0 +1,157 @@ +# (c) Copyright 2024 by Coinkite Inc. This file is covered by license found in COPYING-CC. +# +# dleq.py - DLEQ (Discrete Logarithm Equality) proofs for BIP-374 +# +# Implements non-interactive zero-knowledge proofs that prove: +# log_G(A) = log_B(C) +# where: +# - G is the secp256k1 generator +# - A = a*G (sender's public key) +# - B = (recipient's scan public key) +# - C = a*B (ECDH share point) +# +# This proves the ECDH computation is correct without revealing the private key +# +import ngu +from precomp_tag_hash import DLEQ_TAG_AUX_H, DLEQ_TAG_NONCE_H, DLEQ_TAG_CHALLENGE_H + +G = ngu.secp256k1.generator() +SECP256K1_ORDER = ngu.secp256k1.curve_order_int() + + +def xor_bytes(a, b): + """XOR two byte strings of equal length""" + return bytes(x ^ y for x, y in zip(a, b)) + + +def dleq_challenge(A, B, C, R1, R2, m=None, _G=None): + """Compute DLEQ challenge using BIP-374 tagged hash""" + + # BIP-374: e = TaggedHash("BIP0374/challenge", cbytes(A) || cbytes(B) || cbytes(C) || cbytes(G) || cbytes(R1) || cbytes(R2) || m) + challenge_input = A + B + C + _G + R1 + R2 + if m is not None: + challenge_input += m + + challenge_hash = ngu.hash.sha256t(DLEQ_TAG_CHALLENGE_H, challenge_input, True) + return int.from_bytes(challenge_hash, "big") + + +def generate_dleq_proof(a_sum, B_scan, aux_rand=None, m=None): + """ + Generate DLEQ proof (BIP-374) + + Args: + a_sum: Input private key a (32-byte scalar) + B_scan: Scan public key B (33-byte compressed) + aux_rand: Auxiliary randomness r (32-byte or None) + m: Optional message (32-byte or None) + + Returns: + bytes: DLEQ proof (64-byte: e || s) + + Raises: + ValueError: If inputs are invalid + """ + a_sum_int = int.from_bytes(a_sum, "big") + if not (0 < a_sum_int < SECP256K1_ORDER): + raise ValueError("Invalid input private key: not in valid scalar range") + + # Compute public key A = a*G + A_bytes = ngu.secp256k1.ec_pubkey_tweak_mul(G, a_sum) + + # Compute ECDH share C = a*B + C_bytes = ngu.secp256k1.ec_pubkey_tweak_mul(B_scan, a_sum) + + if aux_rand is None: + aux_rand = ngu.random.bytes(32) + else: + if len(aux_rand) != 32: + raise ValueError("aux_rand must be 32 bytes") + + # t = a XOR TaggedHash("BIP0374/aux", r) + aux_hash = ngu.hash.sha256t(DLEQ_TAG_AUX_H, aux_rand, True) + del aux_rand + t = xor_bytes(a_sum, aux_hash) + + # rand = TaggedHash("BIP0374/nonce", t || A || C || m) + nonce_input = t + A_bytes + C_bytes + if m is not None: + nonce_input += m + rand = ngu.hash.sha256t(DLEQ_TAG_NONCE_H, nonce_input, True) + + # k = int(rand) mod n + k = int.from_bytes(rand, "big") % SECP256K1_ORDER + if k == 0: + raise ValueError("Generated nonce k is zero") + + # R1 = k*G, R2 = k*B + k_bytes = k.to_bytes(32, "big") + R1_bytes = ngu.secp256k1.ec_pubkey_tweak_mul(G, k_bytes) + R2_bytes = ngu.secp256k1.ec_pubkey_tweak_mul(B_scan, k_bytes) + + # e = TaggedHash("BIP0374/challenge", A || B || C || G || R1 || R2 || m) + e = dleq_challenge(A_bytes, B_scan, C_bytes, R1_bytes, R2_bytes, m, _G=G) + + # s = (k + e*a) mod n + s = (k + e * a_sum_int) % SECP256K1_ORDER + + # proof = e || s + proof = e.to_bytes(32, "big") + s.to_bytes(32, "big") + + # Verify the proof before returning (sanity check) + if not verify_dleq_proof(A_bytes, B_scan, C_bytes, proof, m): + raise ValueError("Generated proof failed verification (internal error)") + return proof + + +def verify_dleq_proof(A_sum_bytes, B_scan_bytes, ecdh_share_bytes, proof, m=None): + """ + Verify DLEQ proof (BIP-374) + + Args: + A_sum_bytes: Input public key A (33-byte compressed) + B_scan_bytes: Scan public key B (33-byte compressed) + ecdh_share_bytes: ECDH share point C (33-byte compressed) + proof: DLEQ proof (64-byte: e || s) + m: Optional message (32-byte or None) + + Returns: + bool: True if proof is valid, False otherwise + """ + if len(proof) != 64: + return False + if m is not None and len(m) != 32: + return False + + e_bytes = proof[:32] + s_bytes = proof[32:] + + s = int.from_bytes(s_bytes, "big") + if not (0 < s < SECP256K1_ORDER): + return False + + # Reconstruct R1 = s*G - e*A + # We compute this as s*G + (-e)*A using point negation + sG = ngu.secp256k1.ec_pubkey_tweak_mul(G, s_bytes) + eA = ngu.secp256k1.ec_pubkey_tweak_mul(A_sum_bytes, e_bytes) + + # Negate eA by flipping the y-coordinate (change 02<->03 prefix) + eA_neg = bytearray(eA) + eA_neg[0] = 0x03 if eA[0] == 0x02 else 0x02 + R1_bytes = ngu.secp256k1.ec_pubkey_combine([sG, bytes(eA_neg)]) + + # Reconstruct R2 = s*B - e*C + sB = ngu.secp256k1.ec_pubkey_tweak_mul(B_scan_bytes, s_bytes) + eC = ngu.secp256k1.ec_pubkey_tweak_mul(ecdh_share_bytes, e_bytes) + + # Negate eC + eC_neg = bytearray(eC) + eC_neg[0] = 0x03 if eC[0] == 0x02 else 0x02 + R2_bytes = ngu.secp256k1.ec_pubkey_combine([sB, bytes(eC_neg)]) + + # Recompute challenge e' + e_check = dleq_challenge(A_sum_bytes, B_scan_bytes, ecdh_share_bytes, R1_bytes, R2_bytes, m, _G=G) + + # Verify e == e' + e = int.from_bytes(e_bytes, "big") + return e == e_check diff --git a/shared/precomp_tag_hash.py b/shared/precomp_tag_hash.py index e67812955..c38eca6ab 100644 --- a/shared/precomp_tag_hash.py +++ b/shared/precomp_tag_hash.py @@ -22,3 +22,11 @@ BIP352_INPUTS_TAG_H = b'\x1e{\x96\xeb\x16\nh\x81\x9f\x97vKC\xd5\xd7~fY\xd7Xw\x9dC\xa8\xa7u_[\xe4Z~3' # SHA256(BIP0352/Label) BIP352_LABEL_TAG_H = b'\x03I\x19F5\xc2\xd0>b\xd4\x13\xba\x8c\xcdQ\x98\x91\x90\x17\xa1\xe9\x9c\xbei\x1fZ4\xa9\x93w\xe0\x95' + +# BIP-374 DLEQ proof tag hashes +# SHA256(BIP0374/aux) +DLEQ_TAG_AUX_H = b'\xfc\xe2u Date: Thu, 19 Mar 2026 14:08:45 -0400 Subject: [PATCH 05/41] SP: add SilentPaymentsMixin Extend psbt handling with silent payment specific functions Incorporate validation functions from bip375 test vectors - psbt_structure, input_eligibility, ecdh_coverage Add private key derivation helper functions --- shared/silentpayments.py | 522 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 522 insertions(+) diff --git a/shared/silentpayments.py b/shared/silentpayments.py index f917ad657..a3000f66c 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -5,9 +5,16 @@ # Consolidates cryptographic primitives and PSBT handling logic for Silent Payments # import ngu +from dleq import generate_dleq_proof, verify_dleq_proof +from exceptions import FatalPSBTIssue from precomp_tag_hash import BIP352_SHARED_SECRET_TAG_H, BIP352_INPUTS_TAG_H +from serializations import SIGHASH_ALL, SIGHASH_DEFAULT +from ubinascii import unhexlify as a2b_hex +from utils import keypath_to_str G = ngu.secp256k1.generator() +# BIP-341 NUMS point (Nothing Up My Sleeve) - x-only (32-byte) +NUMS_H = a2b_hex("50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0") SECP256K1_ORDER = ngu.secp256k1.curve_order_int() # ----------------------------------------------------------------------------- @@ -140,3 +147,518 @@ def _is_p2tr(spk): def _is_p2sh(spk): # OP_HASH160 OP_PUSHBYTES_20 <20 bytes> OP_EQUAL return len(spk) == 23 and spk[0] == 0xA9 and spk[1] == 0x14 and spk[-1] == 0x87 + + +# ----------------------------------------------------------------------------- +# PSBT Mixin +# ----------------------------------------------------------------------------- + + +class SilentPaymentsMixin: + """ + Mixin class for psbtObject to handle Silent Payments logic + + This class assumes it is mixed into psbtObject and has access to psbt as self + """ + + def _process_silent_payments(self, sv): + """ + Core SP workflow: validate, compute shares, compute scripts + + Returns: + bool: True if output scripts were computed + """ + if not self.has_silent_payment_outputs(): + return + self._validate_psbt_structure() + self._validate_input_eligibility() + self._validate_ecdh_coverage() + + if not self._compute_and_store_proof_entries(sv): + return False + + if self._is_ecdh_coverage_complete(): + self._compute_silent_payment_output_scripts() + return True + return False + + # ----------------------------------------------------------------------------- + # Input Helper Functions + # ----------------------------------------------------------------------------- + + def _get_ecdh_and_pubkey(self, scan_key): + """ + Get combined ECDH share and summed pubkey for a given scan key + + Returns: + tuple: (ecdh_share_bytes, summed_pubkey_bytes) or (None, None) + """ + # Global share: return ECDH share directly, sum all eligible input pubkeys + if self.sp_global_ecdh_shares and scan_key in self.sp_global_ecdh_shares: + ecdh_share = self.sp_global_ecdh_shares[scan_key] + pubkeys = [] + for inp in self.inputs: + if self._is_input_eligible(inp): + pk = self._pubkey_from_input(inp) + if pk: + pubkeys.append(pk) + if pubkeys: + return ecdh_share, _combine_pubkeys(pubkeys) + + # Per-input shares: combine EDCH shares and sum all eligible input pubkeys + combined_ecdh = None + pubkeys = [] + for inp in self.inputs: + if inp.sp_ecdh_shares and scan_key in inp.sp_ecdh_shares: + share = inp.sp_ecdh_shares[scan_key] + if combined_ecdh is None: + combined_ecdh = share + else: + combined_ecdh = ngu.secp256k1.ec_pubkey_combine([combined_ecdh, share]) + pk = self._pubkey_from_input(inp) + if pk: + pubkeys.append(pk) + + if combined_ecdh and pubkeys: + return combined_ecdh, _combine_pubkeys(pubkeys) + return None, None + + def _is_input_eligible(self, input): + """Check if input is eligible for silent payments per BIP-352""" + spk = input.utxo_spk + if not spk: + return False + + if not (_is_p2pkh(spk) or _is_p2wpkh(spk) or _is_p2tr(spk) or _is_p2sh(spk)): + return False + + if _is_p2tr(spk): + if input.taproot_internal_key: + tap_ik = self.get(input.taproot_internal_key) + if tap_ik == NUMS_H: + return False + + if _is_p2sh(spk): + if input.redeem_script: + rs = self.get(input.redeem_script) + if not _is_p2wpkh(rs): + return False + else: + return False + return True + + def _pubkey_from_input(self, input): + """ + Extract the contributing public key from an input + + Note: + P2TR: use PSBT_IN_WITNESS_UTXO to fetch x-only compressed pubkey + non-taproot: use BIP32 derivation pubkey from subpaths + + Returns: + bytes: Input public key (33-byte compressed) or None if not found + """ + spk = input.utxo_spk + if spk and _is_p2tr(spk): + return b"\x02" + spk[2:34] + if input.subpaths: + for pk_coords, _ in input.subpaths: + pk = self.get(pk_coords) + if len(pk) == 33: + return pk + return None + + # ----------------------------------------------------------------------------- + # Validation Functions + # ----------------------------------------------------------------------------- + + def _is_ecdh_coverage_complete(self): + """ + Check if all eligible inputs have ECDH shares for all scan keys + + Returns: + bool: True if coverage is complete + False if any eligible input is missing a share for any scan key + """ + scan_keys = self._get_silent_payment_scan_keys() + if not scan_keys: + return True + + for scan_key in scan_keys: + if self.sp_global_ecdh_shares and scan_key in self.sp_global_ecdh_shares: + continue + # Check per-input: every eligible input must have a share + for inp in self.inputs: + if self._is_input_eligible(inp): + if not inp.sp_ecdh_shares or scan_key not in inp.sp_ecdh_shares: + return False + return True + + def _validate_psbt_structure(self): + """ + Validate PSBT structure requirements for silent payments + + Raises FatalPSBTIssue if any structural requirements are violated + """ + for i, outp in enumerate(self.outputs): + has_sp_info = bool(outp.sp_v0_info) + has_sp_label = bool(outp.sp_v0_label) + has_script = bool(outp.script and self.get(outp.script)) + + # Output must have script or SP info + if not has_script and not has_sp_info: + raise FatalPSBTIssue("Output #%d must have either PSBT_OUT_SCRIPT or PSBT_OUT_SP_V0_INFO" % i) + + if has_sp_label and not has_sp_info: + raise FatalPSBTIssue("Output #%d has SP label but missing SP_V0_INFO" % i) + + if has_sp_info: + if len(outp.sp_v0_info) != 66: + raise FatalPSBTIssue( + "Output #%d SP_V0_INFO wrong size (%d bytes, expected 66)" % (i, len(outp.sp_v0_info)) + ) + + # Validate ECDH share sizes (33 bytes) and DLEQ proof sizes (64 bytes) + if self.sp_global_ecdh_shares: + for _, share in self.sp_global_ecdh_shares.items(): + if len(share) != 33: + raise FatalPSBTIssue("Global ECDH share wrong size (%d bytes, expected 33)" % len(share)) + + if self.sp_global_dleq_proofs: + for _, proof in self.sp_global_dleq_proofs.items(): + if len(proof) != 64: + raise FatalPSBTIssue("Global DLEQ proof wrong size (%d bytes, expected 64)" % len(proof)) + + for i, inp in enumerate(self.inputs): + if inp.sp_ecdh_shares: + for _, share in inp.sp_ecdh_shares.items(): + if len(share) != 33: + raise FatalPSBTIssue( + "Input #%d ECDH share wrong size (%d bytes, expected 33)" % (i, len(share)) + ) + if inp.sp_dleq_proofs: + for _, proof in inp.sp_dleq_proofs.items(): + if len(proof) != 64: + raise FatalPSBTIssue( + "Input #%d DLEQ proof wrong size (%d bytes, expected 64)" % (i, len(proof)) + ) + + # TX_MODIFIABLE must be cleared when output scripts are finalized + for outp in self.outputs: + if outp.sp_v0_info and outp.script: + if self.txn_modifiable is not None and self.txn_modifiable != 0: + raise FatalPSBTIssue("TX_MODIFIABLE not cleared but SP output script is set") + + def _validate_input_eligibility(self): + """ + Validate input constraints for silent payments (BIP-375) + + Raises FatalPSBTIssue if any input constraints are violated + """ + for i, inp in enumerate(self.inputs): + if not inp.utxo_spk: + continue + + spk = inp.utxo_spk + # No segwit v>1 inputs when SP outputs present + if len(spk) >= 2 and 0x52 <= spk[0] <= 0x60: + witness_version = spk[0] - 0x50 + raise FatalPSBTIssue( + "BIP-375 violation: Input #%d spends Segwit v%d output. " + "Silent payment outputs cannot be mixed with Segwit v>1 inputs." % (i, witness_version) + ) + + # SIGHASH_ALL required when SP outputs present + if inp.sighash is not None and inp.sighash not in ( + SIGHASH_ALL, + SIGHASH_DEFAULT, + ): + raise FatalPSBTIssue( + "BIP-375 violation: Input #%d uses sighash 0x%x. " + "Silent payments require SIGHASH_ALL." % (i, inp.sighash) + ) + + def _validate_ecdh_coverage(self): + """ + Validate ECDH share coverage and DLEQ proof correctness (BIP-375) + + Raises FatalPSBTIssue if any ECDH share / DLEQ requirements are violated + """ + scan_keys = self._get_silent_payment_scan_keys() + if not scan_keys: + return + + for scan_key in scan_keys: + has_global = self.sp_global_ecdh_shares and scan_key in self.sp_global_ecdh_shares + has_input = any(inp.sp_ecdh_shares and scan_key in inp.sp_ecdh_shares for inp in self.inputs) + + # Check if any output with this scan pk has a computed script + scan_key_has_script = any( + outp.sp_v0_info and outp.sp_v0_info[:33] == scan_key and outp.script for outp in self.outputs + ) + + if scan_key_has_script and not has_global and not has_input: + raise FatalPSBTIssue("SP output script set but no ECDH share for scan key") + + # Verify global DLEQ proof + if has_global: + if not self.sp_global_dleq_proofs or scan_key not in self.sp_global_dleq_proofs: + raise FatalPSBTIssue("Global ECDH share missing DLEQ proof") + + ecdh_share = self.sp_global_ecdh_shares[scan_key] + proof = self.sp_global_dleq_proofs[scan_key] + + # Sum all eligible input pubkeys + pubkeys = [] + for inp in self.inputs: + if not self._is_input_eligible(inp): + continue + pk = self._pubkey_from_input(inp) + if pk: + pubkeys.append(pk) + if not pubkeys: + raise FatalPSBTIssue("No public keys found for DLEQ verification") + combined_pk = _combine_pubkeys(pubkeys) + + if not verify_dleq_proof(combined_pk, scan_key, ecdh_share, proof): + raise FatalPSBTIssue("Global DLEQ proof verification failed") + + # Verify per-input coverage and DLEQ proofs + if not has_global: + for i, inp in enumerate(self.inputs): + eligible = self._is_input_eligible(inp) + has_share = inp.sp_ecdh_shares and scan_key in inp.sp_ecdh_shares + + if not eligible and has_share: + raise FatalPSBTIssue("Input #%d has ECDH share but is ineligible" % i) + if eligible and not has_share and scan_key_has_script: + raise FatalPSBTIssue("Eligible input #%d missing ECDH share" % i) + + if has_share: + if not inp.sp_dleq_proofs or scan_key not in inp.sp_dleq_proofs: + raise FatalPSBTIssue("Input #%d ECDH share missing DLEQ proof" % i) + + pk = self._pubkey_from_input(inp) + if not pk: + raise FatalPSBTIssue("Input #%d missing public key for DLEQ verification" % i) + + ecdh_share = inp.sp_ecdh_shares[scan_key] + proof = inp.sp_dleq_proofs[scan_key] + if not verify_dleq_proof(pk, scan_key, ecdh_share, proof): + raise FatalPSBTIssue("Input #%d DLEQ proof verification failed" % i) + + # ----------------------------------------------------------------------------- + # Modify PSBT Field Functions + # ----------------------------------------------------------------------------- + + def _compute_and_store_proof_entries(self, sv): + """ + Compute proof entries (ECDH shares and DLEQ proofs) for our inputs, store in PSBT fields + + Notes: + Sets self.sp_all_inputs_ours for callers + + Returns: + bool: True if shares were computed + False if we have no signable inputs + """ + # Collect per-input private keys for eligible inputs we own + # Track foreign ownership: if _derive_input_privkey returns None for an input + # that has derivation paths, that input belongs to another signer + has_foreign = False + input_material = [] # list of (inp, privkey_int) + for inp in self.inputs: + if not inp.sp_idxs or not self._is_input_eligible(inp): + continue + + input_sk = self._derive_input_privkey(inp, sv) + if input_sk: + input_material.append((inp, input_sk)) + elif inp.taproot_subpaths or inp.subpaths: + has_foreign = True + + # Detect foreign eligible inputs (different XFP, no sp_idxs) + if not has_foreign: + for inp in self.inputs: + if inp.sp_idxs: + continue + if self._is_input_eligible(inp) and self._pubkey_from_input(inp): + has_foreign = True + break + + if not input_material: + return False + + self.sp_all_inputs_ours = not has_foreign + all_inputs_ours = self.sp_all_inputs_ours + + scan_keys = self._get_silent_payment_scan_keys() + if not scan_keys: + return False + + for scan_key in scan_keys: + if all_inputs_ours: + # Single-signer: combine all input private keys, one global ECDH share and DLEQ proofs + combined_sk = 0 + for _, input_sk in input_material: + input_sk_int = int.from_bytes(input_sk, "big") + combined_sk = (combined_sk + input_sk_int) % SECP256K1_ORDER + + self.sp_global_ecdh_shares = self.sp_global_ecdh_shares or {} + self.sp_global_dleq_proofs = self.sp_global_dleq_proofs or {} + self._store_proof_entry(combined_sk.to_bytes(32, "big"), scan_key, self.sp_global_ecdh_shares, self.sp_global_dleq_proofs) + else: + # Multi-signer: per-input ECDH shares and DLEQ proofs for owned inputs + for inp, input_sk in input_material: + inp.sp_ecdh_shares = inp.sp_ecdh_shares or {} + inp.sp_dleq_proofs = inp.sp_dleq_proofs or {} + self._store_proof_entry(input_sk, scan_key, inp.sp_ecdh_shares, inp.sp_dleq_proofs) + return True + + def _compute_silent_payment_output_scripts(self): + """ + Compute and set the scriptPubKey for each silent payment output + + Note: All validations "must" be done before calling this function + + No return value; modifies self.outputs in-place + """ + outpoints = self._get_outpoints() + + # Track k per scan key + scan_key_k = {} + + for out_idx, outp in enumerate(self.outputs): + if not outp.sp_v0_info: + continue + + scan_key = outp.sp_v0_info[:33] + B_spend = outp.sp_v0_info[33:66] + k = scan_key_k.get(scan_key, 0) + + ecdh_share, summed_pubkey = self._get_ecdh_and_pubkey(scan_key) + if not ecdh_share or not summed_pubkey: + raise FatalPSBTIssue("Missing ECDH share for output #%d" % out_idx) + + outp.script = _compute_silent_payment_output_script(outpoints, summed_pubkey, ecdh_share, B_spend, k) + scan_key_k[scan_key] = k + 1 + + def _store_proof_entry(self, sk, scan_key, shares, proofs): + """ + Store a proof entry (ECDH share and DLEQ proof) for scan key if not already present + + Raises FatalPSBTIssue if the existing entry is incomplete or its ECDH share is not from our key + """ + if scan_key not in shares and scan_key not in proofs: + shares[scan_key] = _compute_ecdh_share(sk, scan_key) + proofs[scan_key] = generate_dleq_proof(sk, scan_key) + return + + if scan_key not in shares or scan_key not in proofs: + raise FatalPSBTIssue("Proof entry must have both ECDH share and DLEQ proof") + if shares[scan_key] != _compute_ecdh_share(sk, scan_key): + raise FatalPSBTIssue("Existing ECDH share does not match our key") + + # ----------------------------------------------------------------------------- + # Utility Functions + # ----------------------------------------------------------------------------- + + def has_silent_payment_outputs(self): + """ + Check if PSBT contains any silent payment outputs + + Returns: + bool: True if any output has PSBT_OUT_SP_V0_INFO field + """ + for outp in self.outputs: + if outp.sp_v0_info: + return True + return False + + def _get_outpoints(self): + """ + Get a list of outpoints (txid, vout) for all inputs + + Returns: + list: Outpoints as (txid, vout) tuples + """ + outpoints = [] + for inp in self.inputs: + if inp.previous_txid and inp.prevout_idx is not None: + outpoints.append((self.get(inp.previous_txid), self.get(inp.prevout_idx))) + else: + raise FatalPSBTIssue("Missing outpoint for silent payment input") + if not outpoints: + raise FatalPSBTIssue("Did not find any outpoints") + return outpoints + + def _get_silent_payment_scan_keys(self): + """ + Extract unique scan keys from silent payment outputs + + Returns: + list: Unique scan public keys (33-byte compressed) + """ + scan_keys = set() + for outp in self.outputs: + if outp.sp_v0_info: + scan_key = outp.sp_v0_info[:33] + scan_keys.add(scan_key) + return list(scan_keys) + + # ----------------------------------------------------------------------------- + # Key Derivation Functions + # ----------------------------------------------------------------------------- + + def _derive_input_privkey(self, input, sv): + """ + Derive the contributing private key for an eligible input + + Note: + For taproot inputs, uses the internal key's derivation path (ik_idx), XFP-checked + For non-taproot inputs, uses the first matching BIP32 derivation path + + Returns: + bytes: Derived private key as (32-byte scalar) or None if not eligible + """ + # TODO: BIP-376 sp_spend_derivation should go here + spk = input.utxo_spk + if spk and _is_p2tr(spk): + if input.ik_idx is not None and input.taproot_subpaths: + _, path_coords = input.taproot_subpaths[input.ik_idx] + xfp_path = self.parse_xfp_path(path_coords[2]) + if xfp_path[0] == self.my_xfp: + return self._path_to_privkey(xfp_path, sv) + else: + for xfp_path in self._iter_input_xfp_paths(input): + if xfp_path[0] == self.my_xfp: + return self._path_to_privkey(xfp_path, sv) + return None + + def _iter_input_xfp_paths(self, input): + """ + Iterate over all BIP32 derivation paths for an input, yielding parsed xfp_path tuples + + Note: + For taproot inputs, yields paths from taproot_subpaths (path_coords[2]) + For non-taproot inputs, yields paths from subpaths (path_coords) + + Returns: + generator: Parsed xfp_path tuples for all derivation paths in the input + """ + if input.taproot_subpaths: + for _, path_coords in input.taproot_subpaths: + yield self.parse_xfp_path(path_coords[2]) + elif input.subpaths: + for _, path_coords in input.subpaths: + yield self.parse_xfp_path(path_coords) + + def _path_to_privkey(self, xfp_path, sv): + """ + Derive private key from a parsed xfp_path tuple + + Returns: + bytes: Derived private key (32-byte scalar) + """ + node = sv.derive_path(keypath_to_str(xfp_path, skip=1), register=False) + return node.privkey() From 2dbd95d3a6f53488604e6943b72de3428c93edba Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Sun, 8 Mar 2026 12:34:33 -0400 Subject: [PATCH 06/41] fix: (psbt v2) structural changes Only store key_data for short_values - remove key_type Only serialize PSBT_OUT_SCRIPT if self.script has a value Adjust v2 script assert to not required if sp_v0_info is present --- shared/psbt.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/shared/psbt.py b/shared/psbt.py index 8a5cf644a..e16b2ac2c 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -295,7 +295,8 @@ def parse(self, fd): # storing offset and length only! Mostly. if kt in self.short_values: actual = fd.read(vs) - self.store(kt, bytes(key), actual) + # only store key data for short_values + self.store(kt, bytes(key[1:]), actual) else: # skip actual data for now # TODO: could this be stored more compactly? @@ -554,7 +555,8 @@ def serialize(self, out_fd, is_v2): wr(PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS, v, k) if is_v2: - wr(PSBT_OUT_SCRIPT, self.script) + if self.script is not None: + wr(PSBT_OUT_SCRIPT, self.script) wr(PSBT_OUT_AMOUNT, self.amount) if self.proprietary: @@ -1955,7 +1957,11 @@ async def validate(self): if self.is_v2: # v2 requires inclusion assert o.amount is not None - assert o.script + # Silent Payments: if not spending to silent payment then script must be provided + if not o.sp_v0_info: + assert o.script, "v2 script required when not silent payment output" + if o.amount == 0 and o.script == b'\x6a': + null_data_op_return = True else: # v0 requires exclusion assert o.amount is None From 1d2dcb17cd695444b2e6dfbc16fd31d95555b9da Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Fri, 20 Mar 2026 14:29:11 -0400 Subject: [PATCH 07/41] fix: (usb_test) Unify local and globals dict to single namespace Provides silent payments testing framework with access to MockPSBT --- shared/usb_test_commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shared/usb_test_commands.py b/shared/usb_test_commands.py index 4747bf8e8..b76d6a96c 100644 --- a/shared/usb_test_commands.py +++ b/shared/usb_test_commands.py @@ -33,7 +33,9 @@ def do_usb_command(cmd, args): if cmd == 'EXEC': RV = uio.BytesIO() - exec(str(args, 'utf8'), None, dict(RV=RV)) + ns = globals().copy() + ns['RV'] = RV + exec(str(args, 'utf8'), ns) return b'biny' + RV.getvalue() except BaseException as exc: From ad74ac36a093a533a84b76d61388ebcc8afb793b Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:49:15 -0500 Subject: [PATCH 08/41] BIP-375: add test vectors Use devtest/verify_sp_outputs.py for simulator testing Add testing/test_bip375_vectors.py and testing/bip375_test_vectors.json - Correct input eligibility ecdh share assumptions Add devtest/unit_silentpayments.py to perform unit testing via simulator Mirror psbt fields in testing/psbt.py --- shared/silentpayments.py | 115 +- testing/bip375_test_vectors.json | 1766 ++++++++++++++++++++++++ testing/devtest/unit_silentpayments.py | 608 ++++++++ testing/devtest/verify_sp_outputs.py | 208 +++ testing/psbt.py | 50 + testing/sp_helpers.py | 289 ++++ testing/test_bip375_vectors.py | 236 ++++ 7 files changed, 3256 insertions(+), 16 deletions(-) create mode 100644 testing/bip375_test_vectors.json create mode 100644 testing/devtest/unit_silentpayments.py create mode 100644 testing/devtest/verify_sp_outputs.py create mode 100644 testing/sp_helpers.py create mode 100644 testing/test_bip375_vectors.py diff --git a/shared/silentpayments.py b/shared/silentpayments.py index a3000f66c..031d7fd76 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -4,6 +4,7 @@ # # Consolidates cryptographic primitives and PSBT handling logic for Silent Payments # +import chains import ngu from dleq import generate_dleq_proof, verify_dleq_proof from exceptions import FatalPSBTIssue @@ -17,6 +18,7 @@ NUMS_H = a2b_hex("50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0") SECP256K1_ORDER = ngu.secp256k1.curve_order_int() + # ----------------------------------------------------------------------------- # Silent Payments Cryptographic Primitives # ----------------------------------------------------------------------------- @@ -115,13 +117,86 @@ def _compute_silent_payment_output_script(outpoints, A_sum_bytes, ecdh_share_byt input_hash_bytes = _compute_input_hash(outpoints, A_sum_bytes) shared_secret_bytes = ngu.secp256k1.ec_pubkey_tweak_mul(ecdh_share_bytes, input_hash_bytes) tweak_bytes = _compute_shared_secret_tweak(shared_secret_bytes, k) - # Derive output pubkey: P_k = B_spend + t_k * G - tweak_point = ngu.secp256k1.ec_pubkey_tweak_mul(G, tweak_bytes) - output_pubkey = ngu.secp256k1.ec_pubkey_combine([B_spend_bytes, tweak_point]) - x_only = output_pubkey[1:] + x_only = _compute_silent_payment_spending_xonly(B_spend_bytes, tweak_bytes) return b"\x51\x20" + x_only +def _compute_silent_payment_spending_privkey(b_spend_bytes, sp_tweak_bytes): + """ + Compute private key for spending a silent payment output + + Formula: d_k = (b_spend + sp_tweak) mod n + + Note: sp_tweak = combined tweak (shared secret + label if applicable) + + Args: + b_spend_bytes: Base spend private key (32-byte scalar) + sp_tweak_bytes: Tweak from PSBT_IN_SP_TWEAK (32-byte scalar) + + Returns: + bytes: Tweaked spending private key normalized to even Y (32-byte scalar) + + Raises: + ValueError: If sp_tweak or spending_privkey is invalid + """ + sp_tweak_int = int.from_bytes(sp_tweak_bytes, "big") + b_spend_int = int.from_bytes(b_spend_bytes, "big") + if not (0 < b_spend_int < SECP256K1_ORDER): + raise ValueError("Invalid spend private key: not in valid scalar range") + if not (0 < sp_tweak_int < SECP256K1_ORDER): + raise ValueError("Invalid tweak: not in valid scalar range") + spending_sk = (b_spend_int + sp_tweak_int) % SECP256K1_ORDER + if spending_sk == 0: + raise ValueError("Invalid computed spend key: result is zero") + return _negate_if_odd_y(spending_sk.to_bytes(32, "big")) + + +def _compute_silent_payment_spending_xonly(B_spend_bytes, sp_tweak_bytes): + """ + Compute x-only pubkey for spending a silent payment output + + Formula: P_k = B_spend + sp_tweak * G + + Args: + B_spend_bytes: Recipient spend public key (33-byte compressed) + sp_tweak_bytes: SP tweak (32-byte scalar) + + Returns: + bytes: x-only public key (32-byte) + """ + tweak_point = ngu.secp256k1.ec_pubkey_tweak_mul(G, sp_tweak_bytes) + output_pubkey = ngu.secp256k1.ec_pubkey_combine([B_spend_bytes, tweak_point]) + return output_pubkey[1:] + + +def _negate_if_odd_y(privkey): + """ + Normalize a private key so its corresponding public key has even Y (0x02 prefix) + + Returns: + bytes: normalized private key (32-byte scalar) + """ + pubkey = ngu.secp256k1.ec_pubkey_tweak_mul(G, privkey) + if pubkey[0] == 0x03: + privkey = (SECP256K1_ORDER - int.from_bytes(privkey, "big")).to_bytes(32, "big") + return privkey + + +def _sum_privkeys(privkeys): + """ + Sum list of private key (32-byte scalars) + + Returns: + bytes: summed private key (32-byte scalar) + """ + total = 0 + for sk in privkeys: + total = (total + int.from_bytes(sk, "big")) % SECP256K1_ORDER + if total == 0: + raise ValueError("Invalid private key sum: result is zero") + return total.to_bytes(32, "big") + + # ----------------------------------------------------------------------------- # Input Eligibility # ----------------------------------------------------------------------------- @@ -204,8 +279,9 @@ def _get_ecdh_and_pubkey(self, scan_key): pubkeys.append(pk) if pubkeys: return ecdh_share, _combine_pubkeys(pubkeys) + return None, None - # Per-input shares: combine EDCH shares and sum all eligible input pubkeys + # Per-input shares: combine shares and pubkeys from eligible inputs combined_ecdh = None pubkeys = [] for inp in self.inputs: @@ -215,9 +291,10 @@ def _get_ecdh_and_pubkey(self, scan_key): combined_ecdh = share else: combined_ecdh = ngu.secp256k1.ec_pubkey_combine([combined_ecdh, share]) - pk = self._pubkey_from_input(inp) - if pk: - pubkeys.append(pk) + if self._is_input_eligible(inp): + pk = self._pubkey_from_input(inp) + if pk: + pubkeys.append(pk) if combined_ecdh and pubkeys: return combined_ecdh, _combine_pubkeys(pubkeys) @@ -258,6 +335,9 @@ def _pubkey_from_input(self, input): Returns: bytes: Input public key (33-byte compressed) or None if not found """ + if not self._is_input_eligible(input): + return None + spk = input.utxo_spk if spk and _is_p2tr(spk): return b"\x02" + spk[2:34] @@ -411,8 +491,6 @@ def _validate_ecdh_coverage(self): # Sum all eligible input pubkeys pubkeys = [] for inp in self.inputs: - if not self._is_input_eligible(inp): - continue pk = self._pubkey_from_input(inp) if pk: pubkeys.append(pk) @@ -477,6 +555,7 @@ def _compute_and_store_proof_entries(self, sv): elif inp.taproot_subpaths or inp.subpaths: has_foreign = True + # FIXME: is this the right approach? cosign_xfp? # Detect foreign eligible inputs (different XFP, no sp_idxs) if not has_foreign: for inp in self.inputs: @@ -499,14 +578,11 @@ def _compute_and_store_proof_entries(self, sv): for scan_key in scan_keys: if all_inputs_ours: # Single-signer: combine all input private keys, one global ECDH share and DLEQ proofs - combined_sk = 0 - for _, input_sk in input_material: - input_sk_int = int.from_bytes(input_sk, "big") - combined_sk = (combined_sk + input_sk_int) % SECP256K1_ORDER + combined_sk = _sum_privkeys(sk for _, sk in input_material) self.sp_global_ecdh_shares = self.sp_global_ecdh_shares or {} self.sp_global_dleq_proofs = self.sp_global_dleq_proofs or {} - self._store_proof_entry(combined_sk.to_bytes(32, "big"), scan_key, self.sp_global_ecdh_shares, self.sp_global_dleq_proofs) + self._store_proof_entry(combined_sk, scan_key, self.sp_global_ecdh_shares, self.sp_global_dleq_proofs) else: # Multi-signer: per-input ECDH shares and DLEQ proofs for owned inputs for inp, input_sk in input_material: @@ -540,7 +616,14 @@ def _compute_silent_payment_output_scripts(self): if not ecdh_share or not summed_pubkey: raise FatalPSBTIssue("Missing ECDH share for output #%d" % out_idx) - outp.script = _compute_silent_payment_output_script(outpoints, summed_pubkey, ecdh_share, B_spend, k) + computed = _compute_silent_payment_output_script(outpoints, summed_pubkey, ecdh_share, B_spend, k) + + if outp.script: + existing = self.get(outp.script) if isinstance(outp.script, tuple) else outp.script + if existing != computed: + raise FatalPSBTIssue("SP output #%d: output script mismatch" % out_idx) + + outp.script = computed scan_key_k[scan_key] = k + 1 def _store_proof_entry(self, sk, scan_key, shares, proofs): diff --git a/testing/bip375_test_vectors.json b/testing/bip375_test_vectors.json new file mode 100644 index 000000000..922eeebe1 --- /dev/null +++ b/testing/bip375_test_vectors.json @@ -0,0 +1,1766 @@ +{ + "description": "BIP-375 Test Vectors", + "version": "1.1.1", + "notes": [ + "Generated by https://github.com/macgyver13/bip375-test-generator/", + "Each vector includes: base64-encoded psbt and description", + "Supplementary material (inputs, outputs, sp_proofs) is included for diagnostics and should not be used for validation", + "'checks' overrides the validation sequence, e.g. skip structure checks to test input eligibility" + ], + "invalid": [ + { + "description": "psbt structure: missing PSBT_OUT_SP_V0_INFO field when PSBT_OUT_SP_V0_LABEL set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgImjPUplZ8wrI96VHHKTGdTalHw5bForwPu1HFe3McuABCgQBAAAAAA==", + "supplementary": {} + }, + { + "description": "psbt structure: incorrect byte length for PSBT_OUT_SP_V0_INFO field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUECekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84AA=", + "supplementary": {} + }, + { + "description": "psbt structure: incorrect byte length for PSBT_IN_SP_ECDH_SHARE field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GggA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QoiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": {} + }, + { + "description": "psbt structure: incorrect byte length for PSBT_IN_SP_DLEQ field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4Gg/ihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": {} + }, + { + "description": "psbt structure: PSBT_GLOBAL_TX_MODIFIABLE field is non-zero when PSBT_OUT_SCRIPT set for sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAQABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": {} + }, + { + "description": "psbt structure: missing PSBT_OUT_SCRIPT field when sending to non-sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAA=", + "supplementary": {} + }, + { + "description": "ecdh coverage: only one ineligible P2SH multisig input when PSBT_OUT_SCRIPT set for sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiDNOBpFUI/j2cq2O34PcEoPVp2/1VqYEC2eozruYht19AEPBAAAAAABAFMCAAAAAXyoMfPUiQn+aMsOqqoR+Hc97n6McwhTN1kOJLsGOQ20AAAAAAD/////AaCGAQAAAAAAF6kU2OZohxTu7Qqi7dSJqhyjwXFwHk2HAAAAAAEER1IhAr5Ar99ismPLfe4rmF0cOP5BsZlNKwUHU0PRcsIY6rHEIQJ6R5JT0AogWhCpQ483IBm582TgqDaAC/g529KOfOa5VVKuARAE/v///wABAwiQXwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "", + "public_key": "", + "prevout_txid": "cd381a45508fe3d9cab63b7e0f704a0f569dbfd55a98102d9ea33aee621b75f4", + "prevout_index": 0, + "prevout_scriptpubkey": "a914d8e6688714eeed0aa2edd489aa1ca3c171701e4d87", + "amount": 100000, + "non_witness_utxo": "02000000017ca831f3d48909fe68cb0eaaaa11f8773dee7e8c73085337590e24bb06390db40000000000ffffffff01a08601000000000017a914d8e6688714eeed0aa2edd489aa1ca3c171701e4d8700000000", + "sequence": 4294967294, + "signed": false + } + ] + } + }, + { + "description": "ecdh coverage: missing PSBT_IN_SP_ECDH_SHARE field for input 0 when PSBT_OUT_SCRIPT set for sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBHxAnAAAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0BAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 10000, + "witness_utxo": "10270000000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637", + "dleq_proof": "f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6", + "input_index": 1 + } + ] + } + }, + { + "description": "ecdh coverage: missing PSBT_IN_SP_DLEQ field for input when PSBT_IN_SP_ECDH_SHARE set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": null, + "input_index": 0 + } + ] + } + }, + { + "description": "ecdh coverage: missing PSBT_GLOBAL_SP_DLEQ field when PSBT_GLOBAL_SP_ECDH_SHARE set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWwABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b" + } + ] + } + }, + { + "description": "ecdh coverage: invalid proof in PSBT_IN_SP_DLEQ field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAbvHreDwFl9ZoVl4787j95b7SgVKV9D4XAVEk1EXcy9rdKkne51lhePEhbl1NuRdP/dpjNON8kDEQjAjOE3TeDwABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "6ef1eb783c0597d668565e3bf3b8fde5bed2815295f43e17015124d445dccbdadd2a49dee7596178f1216e5d4db9174ffdda6334e37c9031108c08ce1374de0f", + "input_index": 0 + } + ] + } + }, + { + "description": "ecdh coverage: invalid proof in PSBT_GLOBAL_SP_DLEQ field", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQOfI/UQrlNiKKmoskrQ0ZI+gB8n+CARyozeA0LUjKETQm9iLP+6G0S1DhsRlf7t4Xi0vFL/PkYV0P+EqyCUPldkAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAJB3pqpkrBSuehqk/mjAKs4gbJ6scjSQYa52A5ALkibgIgbxQypXj44zCvC5ACVnRryfTlKqLozHkCncjnajwpSwYBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "2430479d2da1310a024d2aab8e4c7b49d76cd51f45ee8127c159b0393a675b6f75c581ebe3d0817ddaf3bb598cfd7a022f1a87ed479664f6b947a47db5941cb2" + } + ] + } + }, + { + "description": "ecdh coverage: missing PSBT_IN_BIP32_DERIVATION field for input when PSBT_IN_SP_DLEQ set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ] + } + }, + { + "description": "ecdh coverage: output 1 missing ECDH share for scan key with one input / three sp outputs (different scan keys)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9ADQMAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwIQLChkR0sISqyB9uMKxe30ZnOTzmBNgI0/SZoJhOi1JJdCIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwQPCxHVHD/ROzjgpsjvwu4Mpxdzr2dLMVHmiSFJJcS1fIFojJ4Hi3UIhabKsoa1d+k6JJfrSWNrGvG2vILnyRElEiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEDCJBfAQAAAAAAAQQiUSDTlxRqgoZbVOsSuepx1oJP6rD5KkgTf3p5OmhZazNnpAEJQgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3gPycOClYyGDtqsBB06HfmgA2wD1x8XS+vu2j5wo1IVFJAABAwgQJwAAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUIDUteMQTkAMq2RgWppf8dA2OuQnPBNcIhSZLBR8jheJewC4MTBh7chX5l8hIWnW0WRtsKEd7laESO5lpItMVSGC/gAAQMIIE4AAAAAAAABBCJRINLSQezkGFFKoY45kuyVPE1K1exwSmk+IQa6IsOwWnqDAQlCArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwAhJoHj8J6uOKjy8/7NfdVvxYbPoCjoqzP3KpD4QKbSJcAA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 200000, + "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de", + "ecdh_share": "0376892327c4e780aeeed4ce1bc92bb0122b7b7910d96f0ad5148b496f9c3e92fb", + "dleq_proof": "98f14ac45af6459ab0c84d47da5364cfb144ff90bdac732f9cabc6db000dcf1a95e3b31f7b70a04298a51b6fd4516c81d716c9954f8af10c3d59809aee2bbd38", + "input_index": 0 + }, + { + "scan_key": "02b9456157e946ef07f74b54fa09be4a7e938dcafbfb27b4b372c573c059f12ab0", + "ecdh_share": "02c2864474b084aac81f6e30ac5edf4667393ce604d808d3f499a0984e8b524974", + "dleq_proof": "f0b11d51c3fd13b38e0a6c8efc2ee0ca71773af674b3151e689214925c4b57c81688c9e078b750885a6cab286b577e93a2497eb49636b1af1b6bc82e7c911251", + "input_index": 0 + } + ] + } + }, + { + "description": "ecdh coverage: input 1 missing ECDH share for output 1 with two inputs / two sp outputs (different scan keys)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0BAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94hAnUEQAf+LQMNV3wymRzyo+deU1BCRbPL5bMFOufF8iBaIh4DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp95AOLnjgGtJvr7vxs7gZcKwZv2wCuzs8ei1sqr0fPBBeyma4KJW7Xy2yCcC63E31zv1eSccQoTQBuO1nXCpuWfYiQABAwiQXwEAAAAAAAEEIlEg9Jwu8ZtnBhG4bd7+iQzvlCaKgq4zHkb+GVHWxuNyPLEBCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRID2h4XbGT7RZU+xG4FA2NLx+jjQ6do2+77sKPojMSkyaAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 100000, + "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de", + "ecdh_share": "0376892327c4e780aeeed4ce1bc92bb0122b7b7910d96f0ad5148b496f9c3e92fb", + "dleq_proof": "98f14ac45af6459ab0c84d47da5364cfb144ff90bdac732f9cabc6db000dcf1a95e3b31f7b70a04298a51b6fd4516c81d716c9954f8af10c3d59809aee2bbd38", + "input_index": 0 + }, + { + "scan_key": "0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec", + "ecdh_share": "03091fd48039177f44d7b79e96168849c62eb3f87800c46767c50a8f38f98efd15", + "dleq_proof": "be1a723aef55e8981b99599a9bc12b38f87eba0158cc7066890f2269cade463b77341a97d29271964d01c0241cc322fd5390c29b99160f826f329365898cbf02", + "input_index": 0 + }, + { + "scan_key": "03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de", + "ecdh_share": "0275044007fe2d030d577c32991cf2a3e75e53504245b3cbe5b3053ae7c5f2205a", + "dleq_proof": "38b9e3806b49bebeefc6cee065c2b066fdb00aececf1e8b5b2aaf47cf0417b299ae0a256ed7cb6c82702eb7137d73bf579271c4284d006e3b59d70a9b967d889", + "input_index": 1 + } + ] + } + }, + { + "description": "ecdh coverage: input 1 missing ECDH share for scan key with two inputs / one sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9QwwAAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gvp1lyDkV+wkkirvfyoyj7ubONQxVT2Xo1Sbl31J6tSIBDwQAAAAAAQEfUMMAAAAAAAAWABRGM9WcrRNDR5ly4MmWkh0KXa22XSIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 50000, + "witness_utxo": "50c3000000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 50000, + "witness_utxo": "50c30000000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ] + } + }, + { + "description": "input eligibility: segwit version greater than 1 in transaction inputs with sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABZSFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHLzeIUvuENyYHLyUHbw53Vg7UwuBHFm7mpibHW/2znWAiAhKq5fCVdONB9YhvX/8y9XFuq5AwpKU3nmAWtqTULcJAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "5214229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000165214229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ] + }, + "checks": [ + "input_eligibility" + ] + }, + { + "description": "input eligibility: non-SIGHASH_ALL signature on input with sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHLzeIUvuENyYHLyUHbw53Vg7UwuBHFm7mpibHW/2znWAiAhKq5fCVdONB9YhvX/8y9XFuq5AwpKU3nmAWtqTULcJAEBAwQCAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ] + } + }, + { + "description": "output scripts: P2TR input with NUMS internal key cannot derive sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAQMEAQAAAAEQBP7///8BFyBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wCIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIHCUAAAAAAAABBCJRICdoyIruoiMiW6OthOeGNS+YKdLT6TeKOToL/1mvh83QAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_index": 0, + "prevout_scriptpubkey": "512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "amount": 10000, + "witness_utxo": "102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 9500, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51202768c88aeea223225ba3ad84e786352f9829d2d3e9378a393a0bff59af87cdd0" + } + ] + } + }, + { + "description": "output scripts: PSBT_OUT_SCRIPT does not match derived sp output", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIM3jnYsFtJb48Y8gsn0K+aMjMwngRyIZ4IE/87XTeH4pAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29" + } + ] + } + }, + { + "description": "output scripts: two sp outputs (same scan / different spend keys) not sorted lexicographically by spend key", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCID9iBcRocGpGJF8XE6u4uLmjp7/YOsdF98ByDUQxtM38AiBxWKv7gg8r9a1nRfVvwHCcmVzMrP4XCY2KobYfjJ/y/wEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgdUe4Fj1bvFSYQL5MwUaq0JUgc2e565RwbeZwjUCPk/kBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgCi4D5lDNIleEbx2x1q254/iwluzMvIXshHEAXvx9nfYYAAQMIECcAAAAAAAABBCJRIGziw1OV8XDyS20tgNCkDEb0a6S0hD9qsxGpNLMcXYTcAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA6r4Yq7amM+SU5r33DN10dpfsGsSHvCh8DGp9zgv1T27AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068028b80f994334895e11bc76c75ab6e78fe2c25bb332f217b211c4017bf1f677d86", + "script": "51207547b8163d5bbc549840be4cc146aad095207367b9eb94706de6708d408f93f9" + }, + { + "output_index": 1, + "amount": 10000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803aaf862aeda98cf92539af7dc3375d1da5fb06b121ef0a1f031a9f7382fd53dbb", + "script": "51206ce2c35395f170f24b6d2d80d0a40c46f46ba4b4843f6ab311a934b31c5d84dc" + } + ] + } + }, + { + "description": "output scripts: k values assigned to wrong output indices with three sp outputs (same scan / spend keys)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFg36hg2U7tRrGNQq+bDhHvokGogZdwwSNbSCOp8DkyCAiAQ+0/6sv7Vqmy2KAqTxHnPsE5Gyp7fF6owXNFnSiQsSQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIECcAAAAAAAABBCJRIJcUQsifBHhuCCcorhFu6rgC8/qelf2w03U6aEAgIAbeAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCBAnAAAAAAAAAQQiUSA/y66kkIf44D2d79Ory9bejAMrWD+Fpl0FeIHExEPNwAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + }, + { + "output_index": 1, + "amount": 10000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + }, + { + "output_index": 2, + "amount": 10000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + } + ] + } + } + ], + "valid": [ + { + "description": "can finalize: one P2PKH input single-signer", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIDnBDcvHz0XG2UNW/1DBK42GqVUM8DcXPZzr94cU5nx1AiBxlVpC7SBTJDIHI8TwFCXc6J9CX4NwKEy0J2z9tt6jrAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEg4UDSh7RbRs1OqvpDdwYVcLq+g9G4vJUKdKn+oJIz16YBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "522748eb17764d28ca494815ec8d49e7d30d52bc73422c7c86eb74e397057294", + "prevout_index": 0, + "prevout_scriptpubkey": "76a9141e2ad7872d329413a56df0968be338222783163b88ac", + "amount": 100000, + "non_witness_utxo": "0200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6" + } + ] + } + }, + { + "description": "can finalize: two inputs single-signer using global ECDH share", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQLTJicjNSYH6E/K92UfjS1jfgIK6obfrYDTBs1PSM/MYiIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQMZTtx+UaBipW9w58JGERbyQOgh2tzgGDp5dsdzsMKvfVOC18XhXP1EZ3nGqY60ZtEnjvLZUY5Nsi67qTZFzkrkAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAXBfzaBiZu2zKxaYZ3s39nu25F1JLr/OZWqIDufxOOtgIgPc3jI53ZBjavZPskEspB45fJWKAwd3z/nIlAucd310wBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgA4mx4K7v1/q2Ce+rAYv7AWrP8hu4EPPEjDi6ckQYDpUCIBUP7GDiVvQMR1dN/RKaCOr3rB2Xq+4x9AaZ+Hk1RhnzASIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgEz1qT1CQlbV5T3SR+8PxLDxFvC2bYK8luLunBMgHKq8BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", + "amount": 100000, + "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02d3262723352607e84fcaf7651f8d2d637e020aea86dfad80d306cd4f48cfcc62", + "dleq_proof": "c653b71f946818a95bdc39f0918445bc903a0876b738060e9e5db1dcec30abdf54e0b5f178573f5119de71aa63ad19b449e3bcb65463936c8baeea4d917392b9" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120133d6a4f509095b5794f7491fbc3f12c3c45bc2d9b60af25b8bba704c8072aaf" + } + ] + } + }, + { + "description": "can finalize: two inputs single-signer using per-input ECDH shares", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIBcF/NoGJm7bMrFphnezf2e7bkXUkuv85laogO5/E462AiA9zeMjndkGNq9k+yQSykHjl8lYoDB3fP+ciUC5x3fXTAEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgA4mx4K7v1/q2Ce+rAYv7AWrP8hu4EPPEjDi6ckQYDpUCIBUP7GDiVvQMR1dN/RKaCOr3rB2Xq+4x9AaZ+Hk1RhnzAQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDNNLO907e1EZCJ2B/xZrB3oDBKiQzpWJxUo7cz1D6bCsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEA3wAwLQqBz9rZfDEtuVuBndLOAwd894otkCxIe4LO0z3hQ30VuC12OGXXd/yUmLIOB4g+FLNhwveP2qDKmMlvMAAEDCBhzAQAAAAAAAQQiUSATPWpPUJCVtXlPdJH7w/EsPEW8LZtgryW4u6cEyAcqrwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", + "amount": 100000, + "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + }, + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "0334d2cef74eded4464227607fc59ac1de80c12a2433a56271528edccf50fa6c2b", + "dleq_proof": "37c00c0b42a073f6b65f0c4b6e56e06774b380c1df3de28b640b121ee0b3b4cf7850df456e0b5d8e1975ddff25262c8381e20f852cd870bde3f6a832a6325bcc", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120133d6a4f509095b5794f7491fbc3f12c3c45bc2d9b60af25b8bba704c8072aaf" + } + ] + } + }, + { + "description": "can finalize: two inputs / two sp outputs with mixed global and per-input ECDH shares", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQNmz8f9zgbgjtSbGzlSuNFRqPfgdf5fbdWN1o+dre7KlCIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQF6riwhtSFD+nRyflhqR+Ze2HKjQhQr8BqeL3zx0nvVAUOaStT+1sIbl54eT8B5203R/ieMXen/v9vjBYX8bBuMAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfQA0DAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEA1k6e8CREAEbpyjkwLrh7LfYN/FHJwKkX1oLzz4EFkIwCIB6+EqXx/SGW8u+11Tr+V850W5Af6ImXitWa7+FKT1A3AQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECED+9Fz2cSNWMUCJCbQUni8oXuajiKCZmkBobALngS3mUkiHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDAXaQQSHz67DeP6+avUAXjrmyGI2gYsOVbIUAX61Bz7e9AF5V1tdzaqQY0kayLg/0GJNQXek0t1JlMRkDWuMzeAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH0ANAwAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgWoJ5pshwRPECyFkwyJ7C/wGUKGJBraOMeFTy6DZR1fICICvMZkqflwTVcxLbwryDaGcIDyLEdYuR27ktF6HkEeqpAQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDpqibG5hqmVUz4XvtZFALVBuw1zkHHv4q4rfvsKDKa88iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDDSmopQLvppzVsHMb/41jdREHbWIl8upnCEut1KF59oeyhHHksl6OASTNFqyJN6dlMKzbuhSauI1KBcaMjHeczAAEDCJBfAQAAAAAAAQQiUSCA65gxi89t1hGsF6lksJFzbATK6t8ubodOXO+Gx8YFFwEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwiQXwEAAAAAAAEEIlEgELYvxakKvKAWeWHb/0zq6aoyTvssfyRmJ+i1oz3jfIQBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4A", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 200000, + "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", + "amount": 200000, + "witness_utxo": "400d030000000000160014139350117c577941a985802bb9edefc113932bc7", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "0366cfc7fdce06e08ed49b1b3952b8d151a8f7e075fe5f6dd58dd68f9dadeeca94", + "dleq_proof": "5eab8b086d4850fe9d1c9f961a91f997b61ca8d0850afc06a78bdf3c749ef54050e692b53fb5b086e5e78793f01e76d3747f89e3177a7feff6f8c1617f1b06e3" + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949", + "dleq_proof": "c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde", + "input_index": 0 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf", + "dleq_proof": "c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de733", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "512080eb98318bcf6dd611ac17a964b091736c04caeadf2e6e874e5cef86c7c60517" + }, + { + "output_index": 1, + "amount": 90000, + "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", + "script": "512010b62fc5a90abca0167961dbff4ceae9aa324efb2c7f246627e8b5a33de37c84" + } + ] + } + }, + { + "description": "can finalize: one input / one sp output with both global and per-input ECDH shares", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQCf7kMXWHHjjEVIA/9GD0o0KtIOAYslUGTTGQW1CZ84xvUKH6TWUUsCBevDvTVDP9XhDaw0o+e2PIbeaRHZAgI4AAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfQA0DAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiA3eo+fWjPY+iVcM7OSJtO88CKd+tlgRw74AWpxQvIzWAIgCBvWlIh63us2Ia9aLeTw05yxNpLQQb99vM00oysFQekBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQAATg9RmG+hyXvKQSPSMkR+J9fNDF9fAwKzGDvZfG1K//3qW2DObYl34Orq1eqJz7c2aNceU2suxyGEXG7JnB18AAQMIkF8BAAAAAAABBCJRINxNRNnjYeXnQ2V5x44lklVB4in9wVOtWYmtiuawYkx4AQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 200000, + "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e", + "dleq_proof": "27fb90c5d61c78e3115200ffd183d28d0ab4838062c9541934c6416d4267ce31bd4287e9359452c0817af0ef4d50cff578436b0d28f9ed8f21b79a447640808e" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "5120dc4d44d9e361e5e7436579c78e25925541e229fdc153ad5989ad8ae6b0624c78" + } + ] + } + }, + { + "description": "can finalize: three sp outputs (different scan keys) with multiple global ECDH shares", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEDAQYBACIHAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQLC2d9g7mmlqGYE3ZpigsIu+OLJJ22m5ZWlRj83Gq3uJCIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQLcfS7KxWiwEVF1ujzVSW/0xLbZCUItvMrrjyUvpU+L0CIHA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQJwvvXAapqFX8Y7/yvQvi1wAzyCC2FTQTyNbtpR8lobKSIIAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQOyCQr97WIHO4GBWbH8TzEfkcQyJomRYwgMBswMeSBc7wL6gFoDTN1616AYRqw1Qix5Jq7VxsYeAMqrknwsC99IiCAMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEDqQ0cOXhvjKRtIoLy1P1WVLGSGDnY177pQA8yt7XfdEo4hZpew9SO+IX7Gh1B3l8zOvFzZQ2KvG0bYA2Qr1flAIggDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAG9/lTtSioG//mwAJrk49gPxHYWR1r98hJEz+PG0QTfJHQah1UU14ZU+5yhEY5tPlUvOPjKujVS6DM8UBvwy9PwABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLg3ekbsHGTj/QlvLhIwW7hrrfzKDP2b9X3JYim55whAIgfn3H3eyoVVwXfr7/yUnqTDNSD+W+7Hun4nJ+NPvUjf0BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0iAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAPmSLe+tUsYSCQS6pacAUymDbsHD2uFsoGjAFrJrBNLYAiBw+V8k+cklbkGWlGnDUqz6yOiUMjUC6s0WPJSi42nuHwEiBgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwgAAACAAQAAAAEQBP7///8AAQMIkF8BAAAAAAABBCJRIKFPr9x+36QEQnF0sSasoOmZMTP+F+JCCurtIO9U/DjcAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCJBfAQAAAAAAAQQiUSB99fJJWUQ0FLvv6J0tqJSGSlYotoAzuSPoaGvcw96dlAEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwiQXwEAAAAAAAEEIlEgsvEqf1cMxQV4QPpjk/cfBpABQgiBgYEMNLuIdh2SlQ0BCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 500000, + "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 100000, + "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "02dc7d2ecac568b0115175ba3cd5496ff4c4b6d909422dbccaeb8f252fa54f8bd0", + "dleq_proof": "ea43470e5e1be3291b48a0bcb53f55952c64860e7635efba5003ccaded77dd128e216697b0f523be217ec687507797cccebc5cd94362af1b46d803642bd5f940" + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02c2d9df60ee69a5a86604dd9a6282c22ef8e2c9276da6e595a5463f371aadee24", + "dleq_proof": "ec8242bf7b5881cee060566c7f13cc47e4710c89a26458c20301b3031e48173bc0bea01680d3375eb5e80611ab0d508b1e49abb571b1878032aae49f0b02f7d2" + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "0270bef5c06a9a855fc63bff2bd0be2d70033c820b6153413c8d6eda51f25a1b29", + "dleq_proof": "1bdfe54ed4a2a06fff9b0009ae4e3d80fc47616475afdf21244cfe3c6d104df24741a875514d78654fb9ca1118e6d3e552f38f8caba3552e8333c501bf0cbd3f" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "5120a14fafdc7edfa404427174b126aca0e9993133fe17e2420aeaed20ef54fc38dc" + }, + { + "output_index": 1, + "amount": 90000, + "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", + "script": "51207df5f24959443414bbefe89d2da894864a5628b68033b923e8686bdcc3de9d94" + }, + { + "output_index": 2, + "amount": 90000, + "sp_v0_info": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c0", + "script": "5120b2f12a7f570cc5057840fa6393f71f06900142088181810c34bb88761d92950d" + } + ] + } + }, + { + "description": "can finalize: one P2WPKH input / two mixed outputs - labeled sp output and BIP 32 change", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCspcmETsmSLIHmcIF+My2i3RXSxdOpRiq21l5TtoKJXgIgTfMs6jgucsQ8BYQE/a5wWVHmuj3jPYM8g6lbsBg4CscBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRICJoz1KZWfMKyPelRxykxnU2pR8OWxaK8D7tRxXtzHLgAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA+qPIovitxbaze/LKBAHKHTwCkdvXAe9BRkXEmzGSz3vAQoEAQAAAAABAwhw8wUAAAAAAAEEFgAUOMGPNd2AY+OApw/+tPmP9O80gXciAgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwwAAAAAAAAAAAAAAAEA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 500000, + "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803ea8f228be2b716dacdefcb2810072874f00a476f5c07bd051917126cc64b3def", + "sp_v0_label": 1, + "script": "51202268cf529959f30ac8f7a5471ca4c67536a51f0e5b168af03eed4715edcc72e0" + }, + { + "output_index": 1, + "amount": 390000, + "script": "001438c18f35dd8063e380a70ffeb4f98ff4ef348177" + } + ] + } + }, + { + "description": "can finalize: one input / two sp outputs - output 0 has no label / output 1 uses label=0 convention for sp change", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR/gkwQAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICJa45kPVF365uoUKpN0arSqgSfjyBNY63wha08anrtiAiBl42BSGRArJQdeOVXz80zjvPKjXR4QFd1dw7/tPs81qQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts0hA84eNnXZDZkmSfqd2xH5AlSbs7AvVvbonMCgTIuMN92UIh0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts1ADolhPR9rJTbbj6kkIA2zpvjvyhciVWTVaxEuUIZbTTAuBY+m9hwp4jZqSnJp1FVaXGHWVVnb+/rJ4urf5TY31SIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIKBIDZZnnBk25au9SLqw4B/6yx7n0cnhaC8VQBaZZYXZAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA7RDRzNcY/UF5V4mirKA8xi0pqoUSS/zecNmih9U74ybAAEDCDDmAgAAAAAAAQQiUSDkKhgUiNj/9ucWH3FfXvD0fcbISAhIqtaERxvz6ljzUgEJQgJfDsGzjZmEp+ti8VvkAwIEEPFC7fTWnjY/VhWv0qa2zQLOCzIZpapd+PIc45PpYs3afVFUbaTTXDjtAYilludg8wEKBAAAAAAA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 300000, + "witness_utxo": "e093040000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd", + "ecdh_share": "03ce1e3675d90d992649fa9ddb11f902549bb3b02f56f6e89cc0a04c8b8c37dd94", + "dleq_proof": "0e89613d1f6b2536db8fa924200db3a6f8efca17225564d56b112e50865b4d302e058fa6f61c29e2366a4a7269d4555a5c61d65559dbfbfac9e2eadfe53637d5", + "input_index": 0 + }, + { + "scan_key": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568", + "ecdh_share": "025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050", + "dleq_proof": "7940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b", + "script": "5120a0480d96679c1936e5abbd48bab0e01ffacb1ee7d1c9e1682f154016996585d9" + }, + { + "output_index": 1, + "amount": 190000, + "sp_v0_info": "025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd02ce0b3219a5aa5df8f21ce393e962cdda7d51546da4d35c38ed0188a596e760f3", + "sp_v0_label": 0, + "script": "5120e42a181488d8fff6e7161f715f5ef0f47dc6c8480848aad684471bf3ea58f352" + } + ] + } + }, + { + "description": "can finalize: three sp outputs (same scan key) - output 0 uses label=1, outputs 1 and 2 uses label=2 (same spend key)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+AGgYAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFaplAuaU3aICoTcvxrXSZnHH6i4SXpbYSuzopSyB0k4AiA98iUFQysKS0I3s2sHC3R8ZpycvK7JZiE0PcjMfiNnYgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWhAeUCBnrbp8ljBWDh8CmTMFvUXx+9ECRIszqqU9OL/U3bEJHv8Fw2bJjsOPSBrZoyH6Us03ur6AKF5KwR614h1uwABAwihhgEAAAAAAAEEIlEgG/+hD9qiUCwvDJKF/grxmlD4UV47bfv1behQ2ZkBRAABCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgD1DFYje5hqzo5clspnDdC3Gaghh3s9ZG0I7DlJwcPgjQBCgQBAAAAAAEDCDLmAgAAAAAAAQQiUSCITaZwjIK5tWyYvTvm5fU4lLsb/ZC/rPiUAlVw9r1TBQEJQgKLeQ4Jh/3p8NEjmOtr4wxzdnk8ZHhloqAvLvyWDZZlaAMhk60Mh1+sUkNzgCKQCnckxhdd2smUQWWqtFeq35xPPAEKBAIAAAAAAQMIooYBAAAAAAABBCJRINKR0zkoDgyG4scIpZH46OL4ktEqfP6FELZneZtxExyGAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoAyGTrQyHX6xSQ3OAIpAKdyTGF13ayZRBZaq0V6rfnE88AQoEAgAAAAA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 400000, + "witness_utxo": "801a060000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568", + "ecdh_share": "025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050", + "dleq_proof": "7940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100001, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803d431588dee61ab3a39725b299c3742dc66a0861decf591b423b0e527070f8234", + "sp_v0_label": 1, + "script": "51201bffa10fdaa2502c2f0c9285fe0af19a50f8515e3b6dfbf56de850d999014400" + }, + { + "output_index": 1, + "amount": 190002, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c", + "sp_v0_label": 2, + "script": "5120884da6708c82b9b56c98bd3be6e5f53894bb1bfd90bfacf894025570f6bd5305" + }, + { + "output_index": 2, + "amount": 100002, + "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c", + "sp_v0_label": 2, + "script": "5120d291d339280e0c86e2c708a591f8e8e2f892d12a7cfe8510b667799b71131c86" + } + ] + } + }, + { + "description": "can finalize: two inputs using per-input ECDH shares - only eligible inputs contribute shares (P2SH excluded)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLTLcGPIp7P5Ia4ABZbNd4jlRA4dY+8e4bzsjCrJQMogIgNw2OmoWgzI3SWwuwgfMaotzFugoiSOqGCoFlHKNKDGgBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4g0iImLyaHKbt8hMVYEppdaYYYXO9TXsFJwN9g3UqSwgQBDwQAAAAAAQBTAgAAAAFA5vqmEmjxehAQHWJVNYKIKuSFi+4TNj24D98oH4Jf/AAAAAAA/////wHwSQIAAAAAABepFPRfjMomjsJuS76JkXDxOCUNfPVehwAAAAABBEdSIQKHfKAvFEBZvYLQDhs5muN094pSzvehyjfyjXiLNA0veSEDTIekSHL14fAG002IoAlZKCvUU150d8PWjDFlmR6hs5ZSrgEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCECYototkRuaocCWXPZOvsZTkIKEPOhzLOK3YLUZKiUpCgiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDCJBfAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "", + "public_key": "", + "prevout_txid": "d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204", + "prevout_index": 0, + "prevout_scriptpubkey": "a914f45f8cca268ec26e4bbe899170f138250d7cf55e87", + "amount": 150000, + "non_witness_utxo": "020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + } + ] + } + }, + { + "description": "can finalize: two inputs using global ECDH share - only eligible inputs contribute shares (P2SH excluded)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQCQwR50toTEKAk0qq45Me0nXbNUfRe6BJ8FZsDk6Z1tvdcWB6+PQgX3a87tZjP16Ai8ah+1HlmT2uUekfbWUHLIAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEAi0y3BjyKez+SGuAAWWzXeI5UQOHWPvHuG87IwqyUDKICIDcNjpqFoMyN0lsLsIHzGqLcxboKIkjqhgqBZRyjSgxoASIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///wABDiDSIiYvJocpu3yExVgSml1phhhc71NewUnA32DdSpLCBAEPBAAAAAABAFMCAAAAAUDm+qYSaPF6EBAdYlU1gogq5IWL7hM2PbgP3ygfgl/8AAAAAAD/////AfBJAgAAAAAAF6kU9F+MyiaOwm5LvomRcPE4JQ189V6HAAAAAAEER1IhAod8oC8UQFm9gtAOGzma43T3ilLO96HKN/KNeIs0DS95IQNMh6RIcvXh8AbTTYigCVkoK9RTXnR3w9aMMWWZHqGzllKuARAE/v///wABAwiQXwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "", + "public_key": "", + "prevout_txid": "d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204", + "prevout_index": 0, + "prevout_scriptpubkey": "a914f45f8cca268ec26e4bbe899170f138250d7cf55e87", + "amount": 150000, + "non_witness_utxo": "020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "2430479d2da1310a024d2aab8e4c7b49d76cd51f45ee8127c159b0393a675b6f75c581ebe3d0817ddaf3bb598cfd7a022f1a87ed479664f6b947a47db5941cb2" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + } + ] + } + }, + { + "description": "can finalize: two mixed input types - only eligible inputs contribute ECDH shares (NUMS internal key excluded)", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARAE/v///wEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0iAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAPRhsN/2Q/wKVsFSIUU2OBYiEkh+UGpZ4GnXXtHwq4T2AiBSxx6U6TEuqKkAH80mNyvnCZfdwqpinFqBFtxR9bfpogEBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgcJQAAAAAAAAEEIlEgBXZyJSSDmoybydLZc46Yu0DdLsUCO9x9p/cGI818hfsBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_index": 0, + "prevout_scriptpubkey": "512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "amount": 10000, + "witness_utxo": "102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 100000, + "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637", + "dleq_proof": "f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 9500, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51200576722524839a8c9bc9d2d9738e98bb40dd2ec5023bdc7da7f70623cd7c85fb" + } + ] + } + }, + { + "description": "can finalize: three sp outputs (same scan key) - each output has distinct k value", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEEAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+AGgYAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIA3+9XB4r8pV2yK0ze42yxF/h2HkeAgptCHRBkisr62PAiBk5vWJD0/QW3emSnGDHJiGTZyYTJ7x/r6afFC08VkHIQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIoIYBAAAAAAABBCJRID/LrqSQh/jgPZ3v06vL1t6MAytYP4WmXQV4gcTEQ83AAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCKCGAQAAAAAAAQQiUSCXFELInwR4bggnKK4Rbuq4AvP6npX9sNN1OmhAICAG3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwiQXwEAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 400000, + "witness_utxo": "801a060000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + }, + { + "output_index": 1, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + }, + { + "output_index": 2, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + }, + { + "output_index": 3, + "amount": 90000, + "script": "512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da4" + } + ] + } + }, + { + "description": "can finalize: three sp outputs (same scan key) / two regular outputs - k values assigned independently of output index", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEGAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQD333KAYwDd2+SyTNcz9TsypkayNsKUYFfeR65QOyqxaAIgTGlAW3e+2vOyB+3ll0m7o9VMRhWoi7025Ugkr3fJ5zEBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCFDDAAAAAAAAAQQiUSCcaj0jgY6CDtHQz965Y2V8jsMne32bhlx411V/Xe3WogABAwighgEAAAAAAAEEIlEgP8uupJCH+OA9ne/Tq8vW3owDK1g/haZdBXiBxMRDzcABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIUMMAAAAAAAABBCJRIHnvVoij+n/vw5InRVsfHC8IxwCHQk1qAPhMMUIayo2kAAEDCKCGAQAAAAAAAQQiUSCXFELInwR4bggnKK4Rbuq4AvP6npX9sNN1OmhAICAG3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwjILAEAAAAAAAEEIlEgb8UG+AUqn1qKqbmQ1emU9JXd7W1HusRMqs2t2NiZHNAA", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 500000, + "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + }, + { + "output_index": 1, + "amount": 50000, + "script": "51209c6a3d23818e820ed1d0cfdeb963657c8ec3277b7d9b865c78d7557f5dedd6a2" + }, + { + "output_index": 2, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + }, + { + "output_index": 3, + "amount": 50000, + "script": "512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da4" + }, + { + "output_index": 4, + "amount": 100000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + }, + { + "output_index": 5, + "amount": 77000, + "script": "51206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd0" + } + ] + } + }, + { + "description": "in progress: two P2TR inputs, neither is signed", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQMEAQAAAAEQBP7///8BFyDIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvyIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gK5A3/0HdF05VIvD0BFw/QENiMq8mANTaXJ6hPMPKtLUBDwQAAAAAAQErECcAAAAAAAAiUSBDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwEDBAEAAAABEAT+////ARcgQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsiHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEC5Xp63LAY2PsxVOgMFLl6UJlLQjVoQeqfwTFwYUQA5jciHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaED3+jgd4gs7RZxuQmxiE9QXUwjySCpE4zKEIyYk1Nr9VzKZvzrxarMCxWJjY6N9RIcH9+eh6+oGR7zNSGIDuyumAAEDCLj5AgAAAAAAAQQiUSDLH766UNBuv/tpC9qdX/Oc4vrbT87clmMu/xukHMDAewEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_index": 0, + "prevout_scriptpubkey": "5120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "amount": 100000, + "witness_utxo": "a086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "2b9037ff41dd174e5522f0f4045c3f40436232af2600d4da5c9ea13cc3cab4b5", + "prevout_index": 0, + "prevout_scriptpubkey": "512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "amount": 10000, + "witness_utxo": "102700000000000022512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + }, + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637", + "dleq_proof": "f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 195000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120cb1fbeba50d06ebffb690bda9d5ff39ce2fadb4fcedc96632eff1ba41cc0c07b" + } + ] + } + }, + { + "description": "in progress: one P2TR input / one sp output with no ECDH shares when PSBT_OUT_SCRIPT field is not set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/ARAE/v///wEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "prevout_index": 0, + "prevout_scriptpubkey": "5120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "amount": 100000, + "witness_utxo": "a086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + } + ] + } + }, + { + "description": "in progress: two inputs / one sp output, input 1 missing ECDH share when PSBT_OUT_SCRIPT field is not set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gvp1lyDkV+wkkirvfyoyj7ubONQxVT2Xo1Sbl31J6tSIBDwQAAAAAAQEf8EkCAAAAAAAWABRGM9WcrRNDR5ly4MmWkh0KXa22XSIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwhADQMAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 1, + "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", + "amount": 150000, + "witness_utxo": "f0490200000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 200000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + } + ] + } + }, + { + "description": "in progress: one input / two sp outputs, input 0 missing ECDH share for output 0 when PSBT_OUT_SCRIPT field is not set", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9ADQMAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIAAQMIkF8BAAAAAAABCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIENYHfbIefmqrcU2YN6xVrnxIr0a7KczIDvOh/zx84buAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 200000, + "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec", + "ecdh_share": "03091fd48039177f44d7b79e96168849c62eb3f87800c46767c50a8f38f98efd15", + "dleq_proof": "be1a723aef55e8981b99599a9bc12b38f87eba0158cc7066890f2269cade463b77341a97d29271964d01c0241cc322fd5390c29b99160f826f329365898cbf02", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de03f270e0a5632183b6ab01074e877e6800db00f5c7c5d2fafbb68f9c28d4854524" + }, + { + "output_index": 1, + "amount": 90000, + "sp_v0_info": "0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf8", + "script": "512043581df6c879f9aaadc53660deb156b9f122bd1aeca733203bce87fcf1f386ee" + } + ] + } + }, + { + "description": "in progress: large PSBT with nine mixed inputs / six outputs - some inputs signed", + "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQkBBQEGAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLNThMVlDzsjgXC0oPt/Sorr8CiDHHC50NMY3FUceJxgIgMZmwKWN19OdCfS+4KMjLfkHblItuYaaIKCeY8x+RIogBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQP70XPZxI1YxQIkJtBSeLyhe5qOIoJmaQGhsAueBLeZSSIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQNzctF59PYo2oLMvU5CF72wgJ8UF8mr6qNfqAXUitZVTCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMBdpBBIfPrsN4/r5q9QBeOubIYjaBiw5VshQBfrUHPt70AXlXW13NqpBjSRrIuD/QYk1Bd6TS3UmUxGQNa4zN4iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAAE4PUZhvocl7ykEj0jJEfifXzQxfXwMCsxg72XxtSv/96ltgzm2Jd+Dq6tXqic+3NmjXHlNrLschhFxuyZwdfIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxApoctTrEZ/ir3CVP3UqIiNrVKO1f3DlEfEL2LQv9Wtaz2NlCTxIDqnxN3Z4SUW1kxisKSfZFariRM+2g/QYijpwABDiC+nWXIORX7CSSKu9/KjKPu5s41DFVPZejVJuXfUnq1IgEPBAAAAAABAR+ghgEAAAAAABYAFBOTUBF8V3lBqYWAK7nt78ETkyvHIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxHMEQCIGBe6cE9y5EoaPHeTsHHUaxLRis49eXxBj+EHthVABbpAiBHqaafS5jOmNbyz3jQjoWlVWhRC3tc+65oAn9FjH5+BQEBAwQBAAAAIgYC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtwIAAAAgAEAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhA6aomxuYaplVM+F77WRQC1QbsNc5Bx7+KuK377CgymvPIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAvaue4qsmg+cnwTqtIQGIXLfLjjZ8vbsMbQEu1ooaqvwIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhArHT7S+kvDFqCOsUhfp17X3VTKeprhjQxKF9qT8ww4XVIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAw0pqKUC76ac1bBzG/+NY3URB21iJfLqZwhLrdShefaHsoRx5LJejgEkzRasiTenZTCs27oUmriNSgXGjIx3nMyIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQDNKztgQbrqkKH2spWzKJnlfLSpzl4TPa3NNozcHV/SZ4SDA5AvkBDbNdMTvJpBXBvUvp/pujnZFHoWDeDBRqEMiHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEDYQaNzrSiWuXK4z+oWNP8Uow+A2Ez9bvGIkzl7jzRsgFGcmxYaciRNDptk5UNsmM6d1OF6Byj8mXtce885zstoAAEOINBBx0LKNkRy0aGMeo6uB+bpBKnqG4XxmFJfuD7yduNDAQ8EAAAAAAEBH6CGAQAAAAAAFgAUIwf8d0yhdLQq2oFLwubkRP89gwwiAgJlXvXa8F0o0cpzuo4hEwDbK3BBZzcYPg+ow1XuTBy6xkcwRAIgKTOk1x6k+7U8mzjYjLK+bqIQKQBrzEx5rJgFGKrIYxkCICj9GcotjGhqD9CjsK6gmpqVgMw4oisFIgS+RXXwNa0/AQEDBAEAAAAiBgJlXvXa8F0o0cpzuo4hEwDbK3BBZzcYPg+ow1XuTBy6xggAAACAAgAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECED33Bv8m1nL+UMb1aiyh5xdOdQVckgu9M34afWvygm9twiHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCEDv7hiU765b1i4xGnkQs/Pn3ilQTqVQjvo5oZ2Ty+nvT8iHQOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobCEDhgSqjP8wnd30mx82b4nCaWFlh/xB22CFQPlDFTb2ZG8iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEED9LowiubZy07ueJtS22i3D8SVFWpaf2OKywbp5EHatcbOMAfkhjD1ndv2JXS8wZ0hJltheJoOQwrQz5sSyGJHxIh4DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAUt/78AlfKbHeJMnWjVSdHFS85pAEVP43/RD1yQPf7oX3utinKtqOUs2QkvUdnpC1p+TzbKBN+Y53+60TRzBbxyIeA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsQJPh5dSIi8HP4C7s+p3qFE6thPI6EPwaMBEDweVjk1J7Y0F8bEpa9FNZ/4tuF5r3OXjk1i6GLu3Soob1J45Ms0AAAQ4gUiYs1dQCvzJhbQf8Ayhqj3/nivesQR3/9BZV3cEBHm8BDwQAAAAAAQEfoIYBAAAAAAAWABRwGLzpZSiNi/DM8+DsSLbx27/lSCICAwOg9FKNJk6OlSVmNLlEFOJ0j3KWJwT+V+iwosxE0jg9SDBFAiEA2yW73RvPhQMJZj64j7uw62ETCVeF1/bVM42du8cFAycCIHmV0Cb1bqmeBz39CnlsbnT8Ye0I7NJGcM7zQNrVCueaAQEDBAEAAAAiBgMDoPRSjSZOjpUlZjS5RBTidI9ylicE/lfosKLMRNI4PQgAAACAAwAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDgCmZjHPCsTnbdVV+wwEexl7NISRHljAGVxhSo+kiicwiHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCECmAuscmThS/ggzENbaaeN9ybBd+sCbxuBtS3oEScvWOsiHQOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobCEDon2fH6U+Q/cINaaZCVS3ijX3RwZve4K0qeqC6LteBqYiHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEA4HOPBrJ/H9qUVNkViUphHaOj70BQHAjn0yxOxZ5PHTMXtZ3yKfqzBc+mI01Oj8onH4hQdt6S0FFxUmeyDfzauIh4DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAOOA0Y7ZFDb0FEGWoEqbyYxCH95UeRqyE5m2oEXVXF8CTGA5NSYJ7jAl8pwk/6S05P5Wl162EmkGALcTkVYq96SIeA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsQHMqoJV6nbLHWeOayl0BZ+8T0qNKQ8gS6cydcS1Fj3sihdp1EesW9h+WANIL5OlN/dK8OuN/2UP8NJR9/D/cZ5cAAQ4g4pjq8k/hymi0Hktrg8w9kc7ZnG541bmSz7FXcbVFcGQBDwQAAAAAAQEfoIYBAAAAAAAWABSTMrsCDLA9SetNBHEsHMCOKwbY2CICA6iRG+taSP4RnLAVCIzww6EYzwJnckSJctG3DHZKxZQSRzBEAiBr1hL2RzkhB3F8V6+V7oRzl08sMjurcHnoGRbsuQIcjgIgWlToLfcW0eQKehOGkN9w6tSjzILOEImugKMj+1/ui1UBAQMEAQAAACIGA6iRG+taSP4RnLAVCIzww6EYzwJnckSJctG3DHZKxZQSCAAAAIAEAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQK+9HOMbzJ/FySxQHmIlZzfK9GSEIlL/QQ1NbYROCcIGCIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQJ+t8HEr81+Yqtq09K6JzOjdFIgZB+RkD6/57zF29xrXSIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQPKiLzbbR9SkekMddPaYBqL0pmR6rv3+UsvOUg+OFjJoSIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQApYSScQKCC3tsrWvPsDGiOjcxKth9I/HLWoNZvi1f85tqKi/jfNDVPuNH8T5rNSV2my54nwaZy5hViOrC2vEN0iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEB3sVcjNtm9Ti9zQR649qliNaEw9ETL6wekifRHkh43SJ1x/T2yigu6o1uIw3t1eezb9s4WOHANuB38hr95zRvnIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAXQ3oon8NUogCzzNUoa9Qe88P7UGdpkHJwIB811Tgevh5C1EccF1fv2MwWrIq/gSX+s8HC1r+r87jppAFR3Z3VgABDiAXMIM+y1vgE2LXFJUiYESEIW4cexjPMT0c8VQ++F3ztgEPBAAAAAABASughgEAAAAAACJRINFVcTxSDOLYJ2FkIV1lmrYjxfcwb4ZSwXVuJoM+iG4BAQMEAQAAAAEQBP7///8BFyDRVXE8Ugzi2CdhZCFdZZq2I8X3MG+GUsF1biaDPohuASIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQJPKhWksVprePCmMvx/3xEpKfZL1N0U9npjz0+48yWiBCIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQOAK2mzYNpFhVErHPlnsYQBAibXXOW3Yud6ASi8sGjMuyIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQJAdhVQXsveqIExJQTu9vRoGiYxbvc9M1N6f9eT9GWOqSIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQI8iPeJ5ht2HkqA9nVtmIyPoaXgw66u2c2OIH+cshkgq5hoJJo0IO4NUz8K601wUjuspGvYi3UYGNGBjMq8bgpciHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAQOuBcEOQymDdsP+4dxfDQQ4n08gr0k0bUjq0yTWFdbyj8oKMYRFEw6laoYgGbLeDCY32zxBjAsHS1hUiuiyDJIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxA8FWZBzhUTQmbFZKQ5/VELLkSJiYBdKqdjByDELfLAc4rlMxdK4/fgWZ+Avt5bbDlwnh33g1BoqDnCbAURbrylgABDiDpNTLg7aOcTTnaLT+R0UUpvENfwu+5GW4l+6rEtOibgQEPBAAAAAABASughgEAAAAAACJRINAOFftian7+6FxbzmdtY2tgSJFOmjSs4LTLxEvJSAd6AQMEAQAAAAEQBP7///8BFyDQDhX7Ymp+/uhcW85nbWNrYEiRTpo0rOC0y8RLyUgHeiIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQIVP83+lq5wNj/RVCZG0wnCEyuDJVQOPdf4jjf5eWB5piIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQIPqjoMMa52ledpVG4wqngqvTH7aBuXChOqNcwh39E4ACIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQPzE/j0desB487LwOqsL3JtKQMsb/fDrWzDv4uxAYZSfCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQEMg6fYP08Km9zeqzlRsI7DH126EFZwK0onB30wPilAOUSCfKW+dfSI6HSkr1B0mb6rLG+hDvs9LcG6xXbpwKAYiHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEDkB0puyJPquAbV35p07SV+eF/zeGQ9uqeTPHgTp7X2yQyoK2JTnzmzjCxy/lz4HCKl5kH2c2RPbEhrPbV3RkRjIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAOynhLPaT8nITn3RFLyvMwrzQdDLc6PsQc1TBRYoSpHyFRNLWyh4zvOBXi2UIz4pZNGc/n8Q1pfhKIqVLWty8/AABDiC2Nou8Mwzd/p4lUO2338Fa50ysm8x9ln/oHm8n+Fl7HQEPBAAAAAABAFMCAAAAAf6hTz0WmysEANsUmWIhsxGCu56GyhaekbnHvZP5xz6IAAAAAAD/////AaCGAQAAAAAAF6kUDfEBNX9z5mWFAM9W86Ey17uK+92HAAAAAAEBIKCGAQAAAAAAF6kUDfEBNX9z5mWFAM9W86Ey17uK+92HIgICBQDxZ89mnn2sOeauzaHyjGa3jscJfu/vJdVPe+eF5/ZHMEQCIA134+usWENCsMr5fopp9YcHxKsAzK2+hsRKoYe1Zfv/AiBubgVutYtmJeL++r0axbRapqEto5ypCKEaIcY396JcMAEBAwQBAAAAAQQWABTGvIEF7G22DE2lOsNc2iBAaekOiiIGAgUA8WfPZp59rDnmrs2h8oxmt47HCX7v7yXVT3vnhef2CAAAAIAHAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQL+eEHN37Rv2yypveVslVjC0bNhIWZWWQgCJOJAMUOECCIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQJvAnsjWnWTyolDxte3432S6rM5YX9/DDRBBsWN0MvGqiIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQIGEUUMbBlE7N7LePYYFsdn+6Q2jyH36bFpd5x28jz0zCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQIgHJVFmLD7r7lRfGIuNr8aClzovIY58oH/I5C/1ehE0YwRJ/XAxd9ehLQyc7QJIRNwbng7K1nWH3VxHlDGzahoiHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAWtYFI97r/eD5DEPGFUD/pJBfbpDuWbIOiGEMiyx8gQky50ECuahrqTnREvceGJYqXVkTOGgGVVkwrn8PGBqKSIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxASrNr3WnrHNDUsK6uQD3OTbUijFujopHccl3iM4LRc20mXXvDP4NpClylYJcZ8Z6BlS1MjV4oj9DLjGQREEuAowABDiADvOulN51z2ur+Z3lysD3PfvMLfxDqqDrQS8C/ANiy9wEPBAAAAAABAFUCAAAAASo0rBsNt3qBmMHikALMR7v81u2DCWAwTSyaOrVISGtdAAAAAAD/////AaCGAQAAAAAAGXapFFab8xHmijg3Z7Q/gwQt+r5gCT7eiKwAAAAAIgIDGZ0vFV8y67FnrrDMym5a+3NAiY3xt6uZNlAPbUORkCpHMEQCIGIn/SRuyIcF32NUW0i+PRLD1KVITUtOxDRAmsuEETxaAiA8y8m0eI77f7hg2oVYqUx+TEJa11XoaOLY8Fz7RhJflwEBAwQBAAAAIgYDGZ0vFV8y67FnrrDMym5a+3NAiY3xt6uZNlAPbUORkCoIAAAAgAgAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhAvPBdbCLIHY3YWqnTme6rBoYB8lLznCAD3b1sXtSwAgtIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAvoc7ZMlmKJ/ooQQuVXqZ0ebWkAztp8smeTiZ2e7oKVWIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhAwDg/RcQ3FatfBc6qRQdcxV3AJvD3/y6hXakjnerNNlwIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAmSJWWP7eeowkN+s4Ib3J03AKvIlui23O+E4pNHt4vCsD5tozg25PQHZzkMNmRM4Bazax1UaWNUD6UdCwQH221yIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQKCUjFF9cJdsDjnKZ6vxnnIXBA2+Fyu5ZTQTPm/6OUHBZZQW9UBmK3Vh77cAZLTXGpsXtjvFY/Yw20Qi8nPg3xIiHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEDuCqplynPMxUezHCt+0q4xpPTM2upz8q3SRjDWCO3prqXYCGiBhuvKQrh376sT815g8hDU9iBgL4UPwHMcIB6RAAEDCDB1AAAAAAAAAQQiUSAa+l2IGIzvm5Gz8QArEeD56UrTmBl4xNEqBgVWTAgSMwEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwgwdQAAAAAAAAEEIlEgyr9+Sg3kJOybut1/ckLM52c+FwH0nWoZqXBV2jMrEyQBCUIDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSgDEmZYHj6EHLuU3mLqc1WDojLEyIj6bt7y7C+HB4n8HdQAAQMIIE4AAAAAAAABBCJRIEqtyeClkNIeDBnLICTycUD5sZwqEoLVDqfF9F6wP9SiAQlCAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQAkpI124g1AvPXy4aXD/+s9wqizuI15pIbVTJ2eqo+hiOAAEDCCBOAAAAAAAAAQQiUSAvpDcA6h0o/XrU3LMys+XloNjLVCWPZmHE3gN31ygE5QEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwgQJwAAAAAAAAEEIlEgUZhvruMZQ2tRs4QJwbMA9DluKzLjzJoSripL4TXab24BCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAAAQMIUMMAAAAAAAABBCJRIG/FBvgFKp9aiqm5kNXplPSV3e1tR7rETKrNrdjYmRzQAA==", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_index": 0, + "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_index": 0, + "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", + "amount": 100000, + "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 2, + "private_key": "e6db4a04e2fc29745ea1a9dcf1fed7449c8228ffe0503d8171e64126d5399800", + "public_key": "02655ef5daf05d28d1ca73ba8e211300db2b70416737183e0fa8c355ee4c1cbac6", + "prevout_txid": "d041c742ca364472d1a18c7a8eae07e6e904a9ea1b85f198525fb83ef276e343", + "prevout_index": 0, + "prevout_scriptpubkey": "00142307fc774ca174b42ada814bc2e6e444ff3d830c", + "amount": 100000, + "witness_utxo": "a0860100000000001600142307fc774ca174b42ada814bc2e6e444ff3d830c", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 3, + "private_key": "f5208ed67b0019ba4e306aff029d247931e0dfacd1fe6e69091bc6bc70a42619", + "public_key": "0303a0f4528d264e8e95256634b94414e2748f72962704fe57e8b0a2cc44d2383d", + "prevout_txid": "52262cd5d402bf32616d07fc03286a8f7fe78af7ac411dfff41655ddc1011e6f", + "prevout_index": 0, + "prevout_scriptpubkey": "00147018bce965288d8bf0ccf3e0ec48b6f1dbbfe548", + "amount": 100000, + "witness_utxo": "a0860100000000001600147018bce965288d8bf0ccf3e0ec48b6f1dbbfe548", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 4, + "private_key": "0c19c34dc1005feb5ca60104d20472f7f2f97bd4d521264618196bf71155b20a", + "public_key": "03a8911beb5a48fe119cb015088cf0c3a118cf026772448972d1b70c764ac59412", + "prevout_txid": "e298eaf24fe1ca68b41e4b6b83cc3d91ced99c6e78d5b992cfb15771b5457064", + "prevout_index": 0, + "prevout_scriptpubkey": "00149332bb020cb03d49eb4d04712c1cc08e2b06d8d8", + "amount": 100000, + "witness_utxo": "a0860100000000001600149332bb020cb03d49eb4d04712c1cc08e2b06d8d8", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 5, + "private_key": "5aaa151cbdeb566911784d166b01ce57f35993b98f96846efec1cfefcc0d8f56", + "public_key": "02d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", + "prevout_txid": "1730833ecb5be01362d7149522604484216e1c7b18cf313d1cf1543ef85df3b6", + "prevout_index": 0, + "prevout_scriptpubkey": "5120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", + "amount": 100000, + "witness_utxo": "a086010000000000225120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 6, + "private_key": "d92c1506167b3a00a21f4d90d7b5ccb4713c00194aa66f9c7deb162c467f9643", + "public_key": "02d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", + "prevout_txid": "e93532e0eda39c4d39da2d3f91d14529bc435fc2efb9196e25fbaac4b4e89b81", + "prevout_index": 0, + "prevout_scriptpubkey": "5120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", + "amount": 100000, + "witness_utxo": "a086010000000000225120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", + "sequence": 4294967294, + "signed": false + }, + { + "input_index": 7, + "private_key": "d8bc8d0e1233a97133f3573d6dceb6736e8b6d2e4839925145022ea3efdad8f8", + "public_key": "020500f167cf669e7dac39e6aecda1f28c66b78ec7097eefef25d54f7be785e7f6", + "prevout_txid": "b6368bbc330cddfe9e2550edb7dfc15ae74cac9bcc7d967fe81e6f27f8597b1d", + "prevout_index": 0, + "prevout_scriptpubkey": "a9140df101357f73e6658500cf56f3a132d7bb8afbdd87", + "amount": 100000, + "witness_utxo": "a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd87", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 8, + "private_key": "81e30f5b5d049bdf5c5bea9c3329bf57cc8b473240182a9f2a6eee07435bd54a", + "public_key": "03199d2f155f32ebb167aeb0ccca6e5afb7340898df1b7ab9936500f6d4391902a", + "prevout_txid": "03bceba5379d73daeafe677972b03dcf7ef30b7f10eaa83ad04bc0bf00d8b2f7", + "prevout_index": 0, + "prevout_scriptpubkey": "76a914569bf311e68a383767b43f83042dfabe60093ede88ac", + "amount": 100000, + "non_witness_utxo": "02000000012a34ac1b0db77a8198c1e29002cc47bbfcd6ed830960304d2c9a3ab548486b5d0000000000ffffffff01a0860100000000001976a914569bf311e68a383767b43f83042dfabe60093ede88ac00000000", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e", + "dleq_proof": "001383d4661be8725ef29048f48c911f89f5f34317d7c0c0acc60ef65f1b52bfff7a96d8339b625df83abab57aa273edcd9a35c794dacbb1c861171bb267075f", + "input_index": 0 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949", + "dleq_proof": "c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde", + "input_index": 0 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "037372d179f4f628da82ccbd4e4217bdb0809f1417c9abeaa35fa805d48ad6554c", + "dleq_proof": "a6872d4eb119fe2af70953f752a22236b54a3b57f70e511f10bd8b42ff56b5acf6365093c480ea9f13776784945b59318ac2927d915aae244cfb683f4188a3a7", + "input_index": 0 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "02f6ae7b8aac9a0f9c9f04eab484062172df2e38d9f2f6ec31b404bb5a286aabf0", + "dleq_proof": "334aced8106ebaa4287daca56cca26795f2d2a739784cf6b734da3370757f499e120c0e40be40436cd74c4ef26905706f52fa7fa6e8e76451e8583783051a843", + "input_index": 1 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf", + "dleq_proof": "c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de733", + "input_index": 1 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "02b1d3ed2fa4bc316a08eb1485fa75ed7dd54ca7a9ae18d0c4a17da93f30c385d5", + "dleq_proof": "d841a373ad2896b972b8cfea1634ff14a30f80d84cfd6ef18893397b8f346c80519c9b161a72244d0e9b64e5436c98ce9dd4e17a0728fc997b5c7bcf39cecb68", + "input_index": 1 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "03bfb86253beb96f58b8c469e442cfcf9f78a5413a95423be8e686764f2fa7bd3f", + "dleq_proof": "52dffbf0095f29b1de24c9d68d549d1c54bce6900454fe37fd10f5c903dfee85f7bad8a72ada8e52cd9092f51d9e90b5a7e4f36ca04df98e77fbad1347305bc7", + "input_index": 2 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03df706ff26d672fe50c6f56a2ca1e7174e75055c920bbd337e1a7d6bf2826f6dc", + "dleq_proof": "fd2e8c22b9b672d3bb9e26d4b6da2dc3f125455a969fd8e2b2c1ba791076ad71b38c01f9218c3d6776fd895d2f3067484996d85e268390c2b433e6c4b21891f1", + "input_index": 2 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "038604aa8cff309dddf49b1f366f89c269616587fc41db608540f9431536f6646f", + "dleq_proof": "93e1e5d4888bc1cfe02eecfa9dea144ead84f23a10fc1a301103c1e56393527b63417c6c4a5af45359ff8b6e179af73978e4d62e862eedd2a286f5278e4cb340", + "input_index": 2 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "02980bac7264e14bf820cc435b69a78df726c177eb026f1b81b52de811272f58eb", + "dleq_proof": "38e03463b6450dbd051065a812a6f2631087f7951e46ac84e66da811755717c093180e4d49827b8c097ca7093fe92d393f95a5d7ad849a41802dc4e4558abde9", + "input_index": 3 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "038029998c73c2b139db75557ec3011ec65ecd212447963006571852a3e92289cc", + "dleq_proof": "381ce3c1ac9fc7f6a51536456252984768e8fbd014070239f4cb13b16793c74cc5ed677c8a7eacc173e988d353a3f289c7e2141db7a4b4145c5499ec837f36ae", + "input_index": 3 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "03a27d9f1fa53e43f70835a6990954b78a35f747066f7b82b4a9ea82e8bb5e06a6", + "dleq_proof": "732aa0957a9db2c759e39aca5d0167ef13d2a34a43c812e9cc9d712d458f7b2285da7511eb16f61f9600d20be4e94dfdd2bc3ae37fd943fc34947dfc3fdc6797", + "input_index": 3 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "027eb7c1c4afcd7e62ab6ad3d2ba2733a3745220641f91903ebfe7bcc5dbdc6b5d", + "dleq_proof": "77b1572336d9bd4e2f73411eb8f6a96235a130f444cbeb07a489f447921e37489d71fd3db28a0bbaa35b88c37b7579ecdbf6ce1638700db81dfc86bf79cd1be7", + "input_index": 4 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02bef4738c6f327f1724b1407988959cdf2bd19210894bfd043535b61138270818", + "dleq_proof": "0a584927102820b7b6cad6bcfb031a23a37312ad87d23f1cb5a8359be2d5ff39b6a2a2fe37cd0d53ee347f13e6b3525769b2e789f0699cb985588eac2daf10dd", + "input_index": 4 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "03ca88bcdb6d1f5291e90c75d3da601a8bd29991eabbf7f94b2f39483e3858c9a1", + "dleq_proof": "5d0de8a27f0d528802cf3354a1af507bcf0fed419da641c9c0807cd754e07af8790b511c705d5fbf63305ab22afe0497facf070b5afeafcee3a6900547767756", + "input_index": 4 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "03802b69b360da4585512b1cf967b184010226d75ce5b762e77a0128bcb068ccbb", + "dleq_proof": "103ae05c10e43298376c3fee1dc5f0d04389f4f20af49346d48ead324d615d6f28fca0a318445130ea56a862019b2de0c2637db3c418c0b074b58548ae8b20c9", + "input_index": 5 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "024f2a15a4b15a6b78f0a632fc7fdf112929f64bd4dd14f67a63cf4fb8f325a204", + "dleq_proof": "8f223de27986dd8792a03d9d5b662323e8697830ebabb67363881fe72c86482ae61a09268d083b8354cfc2bad35c148eeb291af622dd460634606332af1b8297", + "input_index": 5 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "02407615505ecbdea881312504eef6f4681a26316ef73d33537a7fd793f4658ea9", + "dleq_proof": "f055990738544d099b159290e7f5442cb91226260174aa9d8c1c8310b7cb01ce2b94cc5d2b8fdf81667e02fb796db0e5c27877de0d41a2a0e709b01445baf296", + "input_index": 5 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "020faa3a0c31ae7695e769546e30aa782abd31fb681b970a13aa35cc21dfd13800", + "dleq_proof": "e4074a6ec893eab806d5df9a74ed257e785ff378643dbaa7933c7813a7b5f6c90ca82b62539f39b38c2c72fe5cf81c22a5e641f673644f6c486b3db577464463", + "input_index": 6 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02153fcdfe96ae70363fd1542646d309c2132b8325540e3dd7f88e37f9796079a6", + "dleq_proof": "4320e9f60fd3c2a6f737aace546c23b0c7d76e84159c0ad289c1df4c0f8a500e51209f296f9d7d223a1d292bd41d266faacb1be843becf4b706eb15dba702806", + "input_index": 6 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "03f313f8f475eb01e3cecbc0eaac2f726d29032c6ff7c3ad6cc3bf8bb10186527c", + "dleq_proof": "3b29e12cf693f272139f74452f2bccc2bcd07432dce8fb107354c1458a12a47c8544d2d6ca1e33bce0578b6508cf8a5934673f9fc435a5f84a22a54b5adcbcfc", + "input_index": 6 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "026f027b235a7593ca8943c6d7b7e37d92eab339617f7f0c344106c58dd0cbc6aa", + "dleq_proof": "16b58148f7baff783e4310f185503fe92417dba43b966c83a2184322cb1f20424cb9d040ae6a1aea4e7444bdc786258a975644ce1a0195564c2b9fc3c606a292", + "input_index": 7 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02fe7841cddfb46fdb2ca9bde56c9558c2d1b36121665659080224e24031438408", + "dleq_proof": "88072551662c3eebee545f188b8dafc682973a2f218e7ca07fc8e42ff57a1134630449fd703177d7a12d0c9ced024844dc1b9e0ecad67587dd5c479431b36a1a", + "input_index": 7 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "020611450c6c1944ecdecb78f61816c767fba4368f21f7e9b169779c76f23cf4cc", + "dleq_proof": "4ab36bdd69eb1cd0d4b0aeae403dce4db5228c5ba3a291dc725de23382d1736d265d7bc33f83690a5ca5609719f19e81952d4c8d5e288fd0cb8c6411104b80a3", + "input_index": 7 + }, + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "02fa1ced932598a27fa28410b955ea67479b5a4033b69f2c99e4e26767bba0a556", + "dleq_proof": "a0948c517d70976c0e39ca67abf19e7217040dbe172bb96534133e6ffa3941c1659416f540662b7561efb70064b4d71a9b17b63bc563f630db4422f273e0df12", + "input_index": 8 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "02f3c175b08b207637616aa74e67baac1a1807c94bce70800f76f5b17b52c0082d", + "dleq_proof": "99225658fede7a8c2437eb3821bdc9d3700abc896e8b6dcef84e29347b78bc2b03e6da33836e4f40767390c36644ce016b36b1d546963540fa51d0b0407db6d7", + "input_index": 8 + }, + { + "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", + "ecdh_share": "0300e0fd1710dc56ad7c173aa9141d731577009bc3dffcba8576a48e77ab34d970", + "dleq_proof": "ee0aaa65ca73ccc547b31c2b7ed2ae31a4f4ccdaea73f2add24630d608ede9aea5d808688186ebca42b877efab13f35e60f210d4f620602f850fc0731c201e91", + "input_index": 8 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 30000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "51201afa5d88188cef9b91b3f1002b11e0f9e94ad3981978c4d12a0605564c081233" + }, + { + "output_index": 1, + "amount": 30000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "5120cabf7e4a0de424ec9bbadd7f7242cce7673e1701f49d6a19a97055da332b1324" + }, + { + "output_index": 2, + "amount": 20000, + "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", + "script": "51204aadc9e0a590d21e0c19cb2024f27140f9b19c2a1282d50ea7c5f45eb03fd4a2" + }, + { + "output_index": 3, + "amount": 20000, + "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", + "script": "51202fa43700ea1d28fd7ad4dcb332b3e5e5a0d8cb54258f6661c4de0377d72804e5" + }, + { + "output_index": 4, + "amount": 10000, + "sp_v0_info": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c0", + "script": "512051986faee319436b51b38409c1b300f4396e2b32e3cc9a12ae2a4be135da6f6e" + }, + { + "output_index": 5, + "amount": 50000, + "script": "51206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd0" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/testing/devtest/unit_silentpayments.py b/testing/devtest/unit_silentpayments.py new file mode 100644 index 000000000..35955499b --- /dev/null +++ b/testing/devtest/unit_silentpayments.py @@ -0,0 +1,608 @@ +# (c) Copyright 2024 by Coinkite Inc. This file is covered by license found in COPYING-CC. +# +# Unit tests for BIP-352/BIP-375 Silent Payments implementation +# Runs inside the simulator via sim_execfile('devtest/unit_silentpayments.py') +# Success = no output; failure = assertion traceback +# +import ngu +from ubinascii import unhexlify as a2b_hex +from uhashlib import sha256 + +from dleq import generate_dleq_proof, verify_dleq_proof +from exceptions import FatalPSBTIssue +from silentpayments import ( + _compute_ecdh_share, + _compute_input_hash, + _combine_pubkeys, + _compute_shared_secret_tweak, + _compute_silent_payment_output_script, + _is_p2pkh, + _is_p2wpkh, + _is_p2tr, + _is_p2sh, + NUMS_H, + SilentPaymentsMixin, +) +from precomp_tag_hash import ( + BIP352_SHARED_SECRET_TAG_H, + BIP352_INPUTS_TAG_H, + BIP352_LABEL_TAG_H, + DLEQ_TAG_AUX_H, + DLEQ_TAG_NONCE_H, + DLEQ_TAG_CHALLENGE_H, +) +from public_constants import ( + PSBT_GLOBAL_SP_ECDH_SHARE, + PSBT_GLOBAL_SP_DLEQ, + PSBT_IN_SP_ECDH_SHARE, + PSBT_IN_SP_DLEQ, + PSBT_OUT_SP_V0_INFO, + PSBT_OUT_SP_V0_LABEL, +) + +# --------------------------------------------------------------------------- +# Constants +# --------------------------------------------------------------------------- + +TEST_PRIVKEY = a2b_hex("a5377d45114b0206f6773e231861ece8c04e13840ab007df6722a3508211c073") +TEST_PRIVKEY2 = a2b_hex("1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") +TEST_SCAN_KEY = a2b_hex("03af606abaa5e29a89b93bf971c21e46dd2797aee31273c47f979a102eb51c3629") +TEST_SPEND_KEY = a2b_hex("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5") +MY_XFP = 0x12345678 +TEST_DERIV_OURS = (MY_XFP, 44, 0, 0, 0) +FOREIGN_XFP = 0xDEADBEEF +G = ngu.secp256k1.generator() +P2WPKH_SPK = b"\x00\x14" + b"\xab" * 20 + +# --------------------------------------------------------------------------- +# BIP-352 Crypto Primitives +# --------------------------------------------------------------------------- + +# ECDH share computation +ecdh_share = _compute_ecdh_share(TEST_PRIVKEY, TEST_SCAN_KEY) +assert len(ecdh_share) == 33 +assert ecdh_share[0] in (0x02, 0x03) + +# Input hash computation (order-independent) +outpoints = [ + ( + a2b_hex("0000000000000000000000000000000000000000000000000000000000000001"), + b"\x00\x00\x00\x00", + ), + ( + a2b_hex("0000000000000000000000000000000000000000000000000000000000000002"), + b"\x00\x00\x00\x01", + ), +] +spk = a2b_hex("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798") +ih = _compute_input_hash(outpoints, spk) +assert isinstance(ih, bytes) and len(ih) == 32 +assert int.from_bytes(ih, "big") > 0 +assert _compute_input_hash(outpoints[::-1], spk) == ih + +# Shared secret tweak (different k -> different tweak) +es = a2b_hex("03ccffacf309a1570d01449966bbc0f876d23ee929e88a68968e0a606e31efcc35") +t0 = _compute_shared_secret_tweak(es, 0) +t1 = _compute_shared_secret_tweak(es, 1) +t2 = _compute_shared_secret_tweak(es, 2) +assert t0 != t1 and t1 != t2 and t0 != t2 +assert isinstance(t0, bytes) + +# --------------------------------------------------------------------------- +# Tagged Hash Constants +# --------------------------------------------------------------------------- + +assert BIP352_SHARED_SECRET_TAG_H == sha256(b"BIP0352/SharedSecret").digest() +assert BIP352_INPUTS_TAG_H == sha256(b"BIP0352/Inputs").digest() +assert BIP352_LABEL_TAG_H == sha256(b"BIP0352/Label").digest() +assert DLEQ_TAG_AUX_H == sha256(b"BIP0374/aux").digest() +assert DLEQ_TAG_NONCE_H == sha256(b"BIP0374/nonce").digest() +assert DLEQ_TAG_CHALLENGE_H == sha256(b"BIP0374/challenge").digest() + +# --------------------------------------------------------------------------- +# PSBT Field Constants (BIP-375) +# --------------------------------------------------------------------------- + +assert PSBT_GLOBAL_SP_ECDH_SHARE == 0x07 +assert PSBT_GLOBAL_SP_DLEQ == 0x08 +assert PSBT_IN_SP_ECDH_SHARE == 0x1D +assert PSBT_IN_SP_DLEQ == 0x1E +assert PSBT_OUT_SP_V0_INFO == 0x09 +assert PSBT_OUT_SP_V0_LABEL == 0x0A + +# --------------------------------------------------------------------------- +# DLEQ Proofs +# --------------------------------------------------------------------------- + +pubkey = ngu.secp256k1.ec_pubkey_tweak_mul(G, TEST_PRIVKEY) + +proof = generate_dleq_proof(TEST_PRIVKEY, TEST_SCAN_KEY) +assert len(proof) == 64 +assert verify_dleq_proof(pubkey, TEST_SCAN_KEY, ecdh_share, proof) + +# Tampered proof rejected +tampered = bytearray(proof) +tampered[0] ^= 0xFF +assert not verify_dleq_proof(pubkey, TEST_SCAN_KEY, ecdh_share, bytes(tampered)) + +# Wrong ECDH share rejected +wrong_ecdh = a2b_hex("02ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") +try: + assert not verify_dleq_proof(pubkey, TEST_SCAN_KEY, wrong_ecdh, proof) +except Exception as e: + assert isinstance(e, ValueError) + +# Deterministic with same aux_rand +p1 = generate_dleq_proof(TEST_PRIVKEY, TEST_SCAN_KEY, b"\x00" * 32) +p2 = generate_dleq_proof(TEST_PRIVKEY, TEST_SCAN_KEY, b"\x00" * 32) +assert p1 == p2 + +# --------------------------------------------------------------------------- +# Address Encoding +# --------------------------------------------------------------------------- + +sk = a2b_hex("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798") +spk2 = a2b_hex("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5") + +addr = ngu.codecs.bip352_encode("sp", sk, spk2) +assert isinstance(addr, str) and addr.startswith("sp1q") and len(addr) == 116 + +addr_tn = ngu.codecs.bip352_encode("tsp", sk, spk2) +assert addr_tn.startswith("tsp1q") and len(addr_tn) == 117 + +assert ngu.codecs.bip352_encode("sp", sk, spk2, 0) == addr + +for v in [0, 1, 15, 30, 31]: + a = ngu.codecs.bip352_encode("sp", sk, spk2, v) + assert isinstance(a, str) and a.startswith("sp1") + +for v in [32, 33, 100, -1, -10]: + try: + ngu.codecs.bip352_encode("sp", sk, spk2, v) + assert False, "Should raise for version %d" % v + except ValueError as e: + assert "version must be 0-31" in str(e) + +# Different keys -> different addresses +sk2 = a2b_hex("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5") +assert ngu.codecs.bip352_encode("sp", sk2, spk2) != addr + +spk3 = a2b_hex("021b8c93100d35bd448f4646cc4678f278351b439b52b303ea31ec97b6eda4116f") +assert ngu.codecs.bip352_encode("sp", sk, spk3) != addr + +# Invalid key sizes +for bad_hex in [ + "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ff", + "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16", + "", +]: + try: + bad_key = a2b_hex(bad_hex) if bad_hex else b"" + ngu.codecs.bip352_encode("sp", sk, bad_key) + assert False, "Should raise for bad key" + except ValueError as e: + assert "33 bytes" in str(e) + +# Uncompressed key rejected +uncompressed = a2b_hex( + "04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + "1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a" +) +try: + ngu.codecs.bip352_encode("sp", sk, uncompressed) + assert False, "Should raise for uncompressed key" +except ValueError as e: + assert "33 bytes" in str(e) + + +# --------------------------------------------------------------------------- +# Mock Infrastructure +# --------------------------------------------------------------------------- + + +class MockInput: + def __init__(self): + self.sp_idxs = None + self.sp_ecdh_shares = None + self.sp_dleq_proofs = None + self.subpaths = None + self.taproot_subpaths = None + self.previous_txid = None + self.prevout_idx = None + self.witness_utxo = None + self.taproot_internal_key = None + self.utxo_spk = None + self.ik_idx = None + self.sighash = None + self.redeem_script = None + + @property + def is_sp_spend(self): + return bool(self.sp_tweak and self.sp_spend_bip32_derivation) + + +class MockOutput: + def __init__(self): + self.sp_v0_info = None + self.sp_v0_label = None + self.script = None + + +class MockPSBT(SilentPaymentsMixin): + def __init__(self): + self.inputs = [] + self.outputs = [] + self.my_xfp = MY_XFP + self.sp_global_ecdh_shares = {} + self.sp_global_dleq_proofs = {} + + def get(self, x): + return x + + def parse_xfp_path(self, coords): + return coords + + def handle_zero_xfp(self, xfp_path, my_xfp, _): + return xfp_path + + def _path_to_privkey(self, xfp_path, sv): + return sv[xfp_path] + + +def _make_eligible_input(pk, deriv, txid, vout_bytes): + inp = MockInput() + inp.utxo_spk = P2WPKH_SPK + inp.subpaths = [(pk, deriv)] + inp.previous_txid = txid + inp.prevout_idx = vout_bytes + inp.sp_idxs = [0] + return inp + + +def _make_test_keypair(): + pk = ngu.secp256k1.ec_pubkey_tweak_mul(G, TEST_PRIVKEY) + es = _compute_ecdh_share(TEST_PRIVKEY, TEST_SCAN_KEY) + dp = generate_dleq_proof(TEST_PRIVKEY, TEST_SCAN_KEY, b"\x00" * 32) + return pk, TEST_SCAN_KEY, es, dp + + +def _make_mock_psbt_with_global_proofs(): + pk, scan_key, es, dp = _make_test_keypair() + psbt = MockPSBT() + inp = _make_eligible_input(pk, (MY_XFP, 44, 0, 0, 0), b"\x01" * 32, b"\x00\x00\x00\x00") + psbt.inputs = [inp] + outp = MockOutput() + outp.sp_v0_info = scan_key + TEST_SPEND_KEY + psbt.outputs = [outp] + psbt.sp_global_ecdh_shares = {scan_key: es} + psbt.sp_global_dleq_proofs = {scan_key: dp} + return psbt, scan_key, es, dp, pk, TEST_SPEND_KEY + + +def _make_sp_output(scan_key): + outp = MockOutput() + outp.sp_v0_info = scan_key + TEST_SPEND_KEY + return outp + + +# --------------------------------------------------------------------------- +# Mixin: ECDH Coverage +# --------------------------------------------------------------------------- + +# Global coverage complete +psbt, _, _, _, _, _ = _make_mock_psbt_with_global_proofs() +assert psbt._is_ecdh_coverage_complete() is True + +# Global missing +psbt.sp_global_ecdh_shares = {} +assert psbt._is_ecdh_coverage_complete() is False + +# Per-input coverage +pk, scan_key, es, _ = _make_test_keypair() +psbt = MockPSBT() +psbt.sp_global_ecdh_shares = {} +inp = _make_eligible_input(pk, TEST_DERIV_OURS, b"\x01" * 32, b"\x00" * 4) +inp.sp_ecdh_shares = {scan_key: es} +psbt.inputs = [inp] +psbt.outputs = [_make_sp_output(scan_key)] +assert psbt._is_ecdh_coverage_complete() is True + +# Per-input missing +inp.sp_ecdh_shares = {} +assert psbt._is_ecdh_coverage_complete() is False + +# No SP outputs: vacuously true +psbt = MockPSBT() +psbt.sp_global_ecdh_shares = {} +psbt.inputs = [MockInput()] +assert psbt._is_ecdh_coverage_complete() is True + +# --------------------------------------------------------------------------- +# Mixin: DLEQ Validation +# --------------------------------------------------------------------------- + +# Global valid proof +psbt, *_ = _make_mock_psbt_with_global_proofs() +psbt._validate_ecdh_coverage() + +# Global tampered proof +psbt, scan_key, _, dp, _, _ = _make_mock_psbt_with_global_proofs() +tampered = bytearray(dp) +tampered[0] ^= 0xFF +psbt.sp_global_dleq_proofs = {scan_key: bytes(tampered)} +try: + psbt._validate_ecdh_coverage() + assert False, "Should raise FatalPSBTIssue" +except FatalPSBTIssue: + pass + +# Global missing proof +psbt, _, _, _, _, _ = _make_mock_psbt_with_global_proofs() +psbt.sp_global_dleq_proofs = {} +try: + psbt._validate_ecdh_coverage() + assert False, "Should raise FatalPSBTIssue" +except FatalPSBTIssue: + pass + +# Per-input valid proof +pk, scan_key, es, dp = _make_test_keypair() +psbt = MockPSBT() +psbt.sp_global_ecdh_shares = {} +inp = _make_eligible_input(pk, TEST_DERIV_OURS, b"\x01" * 32, b"\x00" * 4) +inp.sp_ecdh_shares = {scan_key: es} +inp.sp_dleq_proofs = {scan_key: dp} +psbt.inputs = [inp] +outp = MockOutput() +outp.sp_v0_info = scan_key + TEST_SPEND_KEY +outp.script = b"\x51\x20" + b"\xcc" * 32 +psbt.outputs = [outp] +psbt._validate_ecdh_coverage() + +# Per-input tampered proof +pk, scan_key, es, dp = _make_test_keypair() +psbt = MockPSBT() +psbt.sp_global_ecdh_shares = {} +tampered = bytearray(dp) +tampered[0] ^= 0xFF +inp = _make_eligible_input(pk, TEST_DERIV_OURS, b"\x01" * 32, b"\x00" * 4) +inp.sp_ecdh_shares = {scan_key: es} +inp.sp_dleq_proofs = {scan_key: bytes(tampered)} +psbt.inputs = [inp] +outp = MockOutput() +outp.sp_v0_info = scan_key + TEST_SPEND_KEY +outp.script = b"\x51\x20" + b"\xcc" * 32 +psbt.outputs = [outp] +try: + psbt._validate_ecdh_coverage() + assert False, "Should raise FatalPSBTIssue" +except FatalPSBTIssue: + pass + +# --------------------------------------------------------------------------- +# Mixin: Compute and Store ECDH +# --------------------------------------------------------------------------- + +pk_ours = ngu.secp256k1.ec_pubkey_tweak_mul(G, TEST_PRIVKEY) + +# Single signer -> global +psbt = MockPSBT() +psbt.sp_global_ecdh_shares = None +psbt.sp_global_dleq_proofs = None +inp = _make_eligible_input(pk_ours, TEST_DERIV_OURS, b"\x01" * 32, b"\x00" * 4) +psbt.inputs = [inp] +outp = MockOutput() +outp.sp_v0_info = TEST_SCAN_KEY + TEST_SPEND_KEY +psbt.outputs = [outp] +sv = {TEST_DERIV_OURS: TEST_PRIVKEY} +assert psbt._compute_and_store_proof_entries(sv) is True +assert len(psbt.sp_global_ecdh_shares) == 1 +assert TEST_SCAN_KEY in psbt.sp_global_ecdh_shares +assert len(psbt.sp_global_dleq_proofs) == 1 + +# Idempotent +psbt._compute_and_store_proof_entries(sv) +assert len(psbt.sp_global_ecdh_shares) == 1 + +# Multi-signer -> per-input +psbt = MockPSBT() +inp_ours = _make_eligible_input(pk_ours, TEST_DERIV_OURS, b"\x01" * 32, b"\x00" * 4) +foreign_deriv = (FOREIGN_XFP, 44, 0, 0, 0) +inp_foreign = _make_eligible_input(b"\x02" + b"\xbb" * 32, foreign_deriv, b"\x02" * 32, b"\x01" * 4) +psbt.inputs = [inp_ours, inp_foreign] +outp = MockOutput() +outp.sp_v0_info = TEST_SCAN_KEY + TEST_SPEND_KEY +psbt.outputs = [outp] +assert psbt._compute_and_store_proof_entries(sv) is True +assert not psbt.sp_global_ecdh_shares +assert len(inp_ours.sp_ecdh_shares) == 1 +assert TEST_SCAN_KEY in inp_ours.sp_ecdh_shares + +# --------------------------------------------------------------------------- +# Mixin: Ownership +# --------------------------------------------------------------------------- + +# All owned +psbt = MockPSBT() +psbt.sp_global_ecdh_shares = None +psbt.sp_global_dleq_proofs = None +inp = _make_eligible_input(pk_ours, TEST_DERIV_OURS, b"\x01" * 32, b"\x00" * 4) +pub2 = ngu.secp256k1.ec_pubkey_tweak_mul(G, TEST_PRIVKEY2) +inp2 = _make_eligible_input(pub2, (MY_XFP, 44, 0, 0, 1), b"\x02" * 32, b"\x01\x00\x00\x00") +psbt.inputs = [inp, inp2] +outp = MockOutput() +outp.sp_v0_info = TEST_SCAN_KEY + TEST_SPEND_KEY +psbt.outputs = [outp] +psbt._compute_and_store_proof_entries( + { + TEST_DERIV_OURS: TEST_PRIVKEY, + (MY_XFP, 44, 0, 0, 1): TEST_PRIVKEY2, + } +) +assert psbt.sp_all_inputs_ours is True + +# Foreign input +psbt = MockPSBT() +inp_ours = _make_eligible_input(pk_ours, TEST_DERIV_OURS, b"\x01" * 32, b"\x00" * 4) +inp_foreign = _make_eligible_input(b"\x02" + b"\xbb" * 32, (FOREIGN_XFP, 44, 0, 0, 0), b"\x02" * 32, b"\x01" * 4) +psbt.inputs = [inp_ours, inp_foreign] +outp = MockOutput() +outp.sp_v0_info = TEST_SCAN_KEY + TEST_SPEND_KEY +psbt.outputs = [outp] +psbt._compute_and_store_proof_entries({TEST_DERIV_OURS: TEST_PRIVKEY}) +assert psbt.sp_all_inputs_ours is False + +# No signable inputs +psbt = MockPSBT() +inp = _make_eligible_input(b"\x02" + b"\xbb" * 32, (FOREIGN_XFP, 44, 0, 0, 0), b"\x01" * 32, b"\x00" * 4) +psbt.inputs = [inp] +outp = MockOutput() +outp.sp_v0_info = TEST_SCAN_KEY + TEST_SPEND_KEY +psbt.outputs = [outp] +assert psbt._compute_and_store_proof_entries({}) is False + +# --------------------------------------------------------------------------- +# Mixin: Compute Output Scripts +# --------------------------------------------------------------------------- + +# Single input, single output +psbt, scan_key, es, _, pk, spend_key = _make_mock_psbt_with_global_proofs() +psbt._compute_silent_payment_output_scripts() +outp = psbt.outputs[0] +assert outp.script is not None and len(outp.script) == 34 and outp.script[0] == 0x51 +expected = _compute_silent_payment_output_script([(b"\x01" * 32, b"\x00\x00\x00\x00")], pk, es, spend_key, 0) +assert outp.script == expected + +# Missing ECDH share +psbt, _, _, _, _, _ = _make_mock_psbt_with_global_proofs() +other_scan = a2b_hex("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798") +psbt.outputs[0].sp_v0_info = other_scan + TEST_SPEND_KEY +try: + psbt._compute_silent_payment_output_scripts() + assert False, "Should raise" +except Exception as e: + assert "Missing ECDH share" in str(e) + +# Per-input share combining +pub1 = ngu.secp256k1.ec_pubkey_tweak_mul(G, TEST_PRIVKEY) +pub2 = ngu.secp256k1.ec_pubkey_tweak_mul(G, TEST_PRIVKEY2) +share1 = _compute_ecdh_share(TEST_PRIVKEY, TEST_SCAN_KEY) +share2 = _compute_ecdh_share(TEST_PRIVKEY2, TEST_SCAN_KEY) + +psbt = MockPSBT() +psbt.sp_global_ecdh_shares = {} +inp1 = _make_eligible_input(pub1, (MY_XFP, 44, 0, 0, 0), b"\x01" * 32, b"\x00\x00\x00\x00") +inp1.sp_ecdh_shares = {TEST_SCAN_KEY: share1} +inp2 = _make_eligible_input(pub2, (MY_XFP, 44, 0, 0, 1), b"\x02" * 32, b"\x01\x00\x00\x00") +inp2.sp_ecdh_shares = {TEST_SCAN_KEY: share2} +psbt.inputs = [inp1, inp2] +outp = MockOutput() +outp.sp_v0_info = TEST_SCAN_KEY + TEST_SPEND_KEY +psbt.outputs = [outp] +psbt._compute_silent_payment_output_scripts() + +combined_share = ngu.secp256k1.ec_pubkey_combine([share1, share2]) +summed_pk = _combine_pubkeys([pub1, pub2]) +outpoints = [(b"\x01" * 32, b"\x00\x00\x00\x00"), (b"\x02" * 32, b"\x01\x00\x00\x00")] +expected = _compute_silent_payment_output_script(outpoints, summed_pk, combined_share, TEST_SPEND_KEY, 0) +assert outp.script == expected + +# k counter per scan key (skips non-SP outputs) +psbt, scan_key, es, _, pk, _ = _make_mock_psbt_with_global_proofs() +spend_key_a = a2b_hex("022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4") +spend_key_b = a2b_hex("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5") +spend_key_c = a2b_hex("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798") + +sp0 = MockOutput() +sp0.sp_v0_info = scan_key + spend_key_a +reg1 = MockOutput() +sp2 = MockOutput() +sp2.sp_v0_info = scan_key + spend_key_b +reg3 = MockOutput() +sp4 = MockOutput() +sp4.sp_v0_info = scan_key + spend_key_c +psbt.outputs = [sp0, reg1, sp2, reg3, sp4] +psbt._compute_silent_payment_output_scripts() + +ops = [(b"\x01" * 32, b"\x00\x00\x00\x00")] +spk_sum = _combine_pubkeys([pk]) +assert sp0.script == _compute_silent_payment_output_script(ops, spk_sum, es, spend_key_a, k=0) +assert sp2.script == _compute_silent_payment_output_script(ops, spk_sum, es, spend_key_b, k=1) +assert sp4.script == _compute_silent_payment_output_script(ops, spk_sum, es, spend_key_c, k=2) +assert reg1.script is None +assert reg3.script is None + +# --------------------------------------------------------------------------- +# Mixin: Simple Methods +# --------------------------------------------------------------------------- + +psbt = MockPSBT() +outp = MockOutput() +outp.sp_v0_info = b"\x02" + b"\xaa" * 32 + b"\x02" + b"\xbb" * 32 +psbt.outputs = [outp] +assert psbt.has_silent_payment_outputs() is True + +psbt = MockPSBT() +psbt.outputs = [MockOutput()] +assert psbt.has_silent_payment_outputs() is False + +# _get_silent_payment_scan_keys +psbt = MockPSBT() +scan1 = b"\x02" + b"\xaa" * 32 +scan2 = b"\x03" + b"\xbb" * 32 +o1 = MockOutput() +o1.sp_v0_info = scan1 + b"\x02" + b"\xcc" * 32 +o2 = MockOutput() +o2.sp_v0_info = scan2 + b"\x02" + b"\xdd" * 32 +o3 = MockOutput() +psbt.outputs = [o1, o2, o3] +keys = psbt._get_silent_payment_scan_keys() +assert len(keys) == 2 and set(keys) == {scan1, scan2} + +# Dedup +psbt = MockPSBT() +o1 = MockOutput() +o1.sp_v0_info = scan1 + b"\x02" + b"\xbb" * 32 +o2 = MockOutput() +o2.sp_v0_info = scan1 + b"\x02" + b"\xcc" * 32 +psbt.outputs = [o1, o2] +assert len(psbt._get_silent_payment_scan_keys()) == 1 + +# --------------------------------------------------------------------------- +# Script type predicates +# --------------------------------------------------------------------------- + +assert _is_p2wpkh(b"\x00\x14" + b"\xab" * 20) is True +assert _is_p2wpkh(b"\x00\x14" + b"\xab" * 19) is False # wrong length +assert _is_p2tr(b"\x51\x20" + b"\xcd" * 32) is True +assert _is_p2tr(b"\x51\x20" + b"\xcd" * 31) is False # wrong length +assert _is_p2pkh(b"\x76\xa9\x14" + b"\xab" * 20 + b"\x88\xac") is True +assert _is_p2pkh(b"\x76\xa9\x14" + b"\xab" * 20 + b"\x88\xad") is False # wrong suffix +assert _is_p2sh(b"\xa9\x14" + b"\xab" * 20 + b"\x87") is True +assert _is_p2sh(b"\xa9\x14" + b"\xab" * 19 + b"\x87") is False # wrong length + +# P2TR with NUMS output key is still valid P2TR shape (ineligibility is checked separately) +assert _is_p2tr(b"\x51\x20" + NUMS_H) is True + +# --------------------------------------------------------------------------- +# _combine_pubkeys edge cases +# --------------------------------------------------------------------------- + +try: + _combine_pubkeys([]) + assert False, "Should raise ValueError for empty pubkey list" +except ValueError: + pass + +# Intermediate sums should not fail if final sum is non-zero. +A = ngu.secp256k1.ec_pubkey_tweak_mul(G, (1).to_bytes(32, "big")) +neg_A = bytes([0x03 if A[0] == 0x02 else 0x02]) + A[1:] +assert _combine_pubkeys([A, neg_A, A]) == A + +# Final point-at-infinity should still fail in phase 1. +try: + _combine_pubkeys([A, neg_A]) + assert False, "Should raise ValueError for point-at-infinity" +except ValueError: + pass diff --git a/testing/devtest/verify_sp_outputs.py b/testing/devtest/verify_sp_outputs.py new file mode 100644 index 000000000..35e09397d --- /dev/null +++ b/testing/devtest/verify_sp_outputs.py @@ -0,0 +1,208 @@ +# (c) Copyright 2024 by Coinkite Inc. This file is covered by license found in COPYING-CC. +# ruff: noqa: F821 +# +# Crypto verification for silent payment integration tests +# Runs inside the simulator via sim_execfile('devtest/verify_sp_outputs.py') +# +# Interface: main.SP_VERIFY dict with hex-encoded parameters +# Success = no output; failure = assertion traceback +# RV (uio.BytesIO) is injected into globals by the simulator's exec namespace. +# +import main +import ngu +import struct +import ujson +from ubinascii import hexlify as b2a_hex +from ubinascii import unhexlify as a2b_hex +from dleq import generate_dleq_proof, verify_dleq_proof +from exceptions import FatalPSBTIssue +from silentpayments import ( + _combine_pubkeys, + _compute_ecdh_share, + _compute_silent_payment_output_script, + SilentPaymentsMixin, +) + +if isinstance(main.SP_VERIFY, str): + with open(main.SP_VERIFY) as f: + params = ujson.load(f) +else: + params = main.SP_VERIFY + +mode = params.get("mode") + + +# --------------------------------------------------------------------------- +# MockPSBT infrastructure for firmware method testing +# --------------------------------------------------------------------------- + + +class MockInput: + def __init__(self): + self.utxo_spk = None + self.taproot_internal_key = None + self.redeem_script = None + self.sighash = None + self.previous_txid = None + self.prevout_idx = None + self.sp_ecdh_shares = {} + self.sp_dleq_proofs = {} + self.subpaths = [] + self.taproot_subpaths = [] + self.sp_idxs = None + self.ik_idx = None + + +class MockOutput: + def __init__(self): + self.sp_v0_info = None + self.sp_v0_label = None + self.script = None + + +class MockPSBT(SilentPaymentsMixin): + def __init__(self): + self.inputs = [] + self.outputs = [] + self.sp_global_ecdh_shares = {} + self.sp_global_dleq_proofs = {} + self.txn_modifiable = None + self.my_xfp = 0 + + def get(self, x): + return x + + def parse_xfp_path(self, coords): + return coords + + +def _build_mock_psbt(params): + psbt = MockPSBT() + psbt.txn_modifiable = params.get("txn_modifiable") + + global_ecdh = params.get("global_ecdh") or {} + global_dleq = params.get("global_dleq") or {} + psbt.sp_global_ecdh_shares = {a2b_hex(k): a2b_hex(v) for k, v in global_ecdh.items()} + psbt.sp_global_dleq_proofs = {a2b_hex(k): a2b_hex(v) for k, v in global_dleq.items()} + + for d in params.get("inputs", []): + inp = MockInput() + if d.get("utxo_spk"): + inp.utxo_spk = a2b_hex(d["utxo_spk"]) + elif d.get("witness_utxo"): + wu = a2b_hex(d["witness_utxo"]) + # Extract scriptPubKey: 8 bytes value + varint length + script + script_len = wu[8] + inp.utxo_spk = wu[9 : 9 + script_len] + if d.get("taproot_internal_key"): + inp.taproot_internal_key = a2b_hex(d["taproot_internal_key"]) + if d.get("redeem_script"): + inp.redeem_script = a2b_hex(d["redeem_script"]) + inp.sighash = d.get("sighash") + if d.get("previous_txid"): + inp.previous_txid = a2b_hex(d["previous_txid"]) + if d.get("prevout_idx") is not None: + inp.prevout_idx = struct.pack(" 1 else pubkeys[0] + RV.write(b2a_hex(result).decode()) + +elif mode == "validate_sp": + # Run firmware validation methods; write error string to RV on failure + psbt = _build_mock_psbt(params) + try: + psbt._validate_psbt_structure() + psbt._validate_input_eligibility() + psbt._validate_ecdh_coverage() + psbt._compute_silent_payment_output_scripts() + except FatalPSBTIssue as e: + RV.write(str(e)) + +elif mode == "get_ecdh_and_pubkey": + # Call _get_ecdh_and_pubkey and return "ecdh_hex,pubkey_hex" + psbt = _build_mock_psbt(params) + scan_key = a2b_hex(params["scan_key"]) + ecdh_share, summed_pubkey = psbt._get_ecdh_and_pubkey(scan_key) + ecdh_hex = b2a_hex(ecdh_share).decode() if ecdh_share else "" + pubkey_hex = b2a_hex(summed_pubkey).decode() if summed_pubkey else "" + RV.write(ecdh_hex + "," + pubkey_hex) + +elif mode == "get_outpoints": + # Call _get_outpoints and return "txid:vout,txid:vout,..." + psbt = _build_mock_psbt(params) + outpoints = psbt._get_outpoints() + parts = [] + for txid, vout in outpoints: + parts.append(b2a_hex(txid).decode() + ":" + b2a_hex(vout).decode()) + RV.write(",".join(parts)) + +elif mode == "pubkey_from_input": + # Call _pubkey_from_input for a specific input; return pubkey hex or "" + psbt = _build_mock_psbt(params) + i = params["input_index"] + pk = psbt._pubkey_from_input(psbt.inputs[i]) + RV.write(b2a_hex(pk).decode() if pk else "") diff --git a/testing/psbt.py b/testing/psbt.py index 9d5ec6120..6da02b953 100644 --- a/testing/psbt.py +++ b/testing/psbt.py @@ -26,6 +26,9 @@ PSBT_GLOBAL_OUTPUT_COUNT = 0x05 PSBT_GLOBAL_TX_MODIFIABLE = 0x06 PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE = 0x09 +# BIP-375 Silent Payments +PSBT_GLOBAL_SP_ECDH_SHARE = 0x07 +PSBT_GLOBAL_SP_DLEQ = 0x08 # INPUTS === PSBT_IN_NON_WITNESS_UTXO = 0x00 @@ -59,6 +62,9 @@ PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS = 0x1a PSBT_IN_MUSIG2_PUB_NONCE = 0x1b PSBT_IN_MUSIG2_PARTIAL_SIG = 0x1c +# BIP-375 Silent Payments +PSBT_IN_SP_ECDH_SHARE = 0x1d +PSBT_IN_SP_DLEQ = 0x1e # OUTPUTS === PSBT_OUT_REDEEM_SCRIPT = 0x00 @@ -72,6 +78,9 @@ PSBT_OUT_TAP_TREE = 0x06 PSBT_OUT_TAP_BIP32_DERIVATION = 0x07 PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS = 0x08 +# BIP-375 Silent Payments +PSBT_OUT_SP_V0_INFO = 0x09 +PSBT_OUT_SP_V0_LABEL = 0x0a PSBT_PROP_CK_ID = b"COINKITE" @@ -142,6 +151,8 @@ def defaults(self): self.musig_pubkeys = {} self.musig_pubnonces = {} self.musig_part_sigs = {} + self.sp_ecdh_shares = {} + self.sp_dleq_proofs = {} self.others = {} self.unknown = {} @@ -172,6 +183,8 @@ def __eq__(a, b): a.musig_pubkeys == b.musig_pubkeys and \ a.musig_pubnonces == b.musig_pubnonces and \ a.musig_part_sigs == b.musig_part_sigs and \ + a.sp_ecdh_shares == b.sp_ecdh_shares and \ + a.sp_dleq_proofs == b.sp_dleq_proofs and \ a.unknown == b.unknown if rv: # NOTE: equality test on signatures requires parsing DER stupidness @@ -261,6 +274,10 @@ def parse_kv(self, kt, key, val): aggregate_key = key[33:66] tapleaf_h = key[66:] self.musig_part_sigs[(participant_key, aggregate_key, tapleaf_h)] = val + elif kt == PSBT_IN_SP_ECDH_SHARE: + self.sp_ecdh_shares[key] = val + elif kt == PSBT_IN_SP_DLEQ: + self.sp_dleq_proofs[key] = val else: self.unknown[bytes([kt]) + key] = val @@ -319,6 +336,12 @@ def serialize_kvs(self, wr, v2): if self.musig_pubkeys: for agg_k, pk_lst in self.musig_pubkeys.items(): wr(PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS, b"".join(pk_lst), agg_k) + if self.sp_ecdh_shares: + for k, v in self.sp_ecdh_shares.items(): + wr(PSBT_IN_SP_ECDH_SHARE, v, k) + if self.sp_dleq_proofs: + for k, v in self.sp_dleq_proofs.items(): + wr(PSBT_IN_SP_DLEQ, v, k) if self.musig_pubnonces: for (pk, ak, lh), pubnonce in self.musig_pubnonces.items(): @@ -350,6 +373,8 @@ def defaults(self): self.taproot_tree = None self.script = None # v2 self.amount = None # v2 + self.sp_v0_info = None + self.sp_v0_label = None self.proprietary = {} self.musig_pubkeys = {} self.unknown = {} @@ -366,6 +391,8 @@ def __eq__(a, b): a.proprietary == b.proprietary and \ a.taproot_tree == b.taproot_tree and \ a.musig_pubkeys == b.musig_pubkeys and \ + a.sp_v0_info == b.sp_v0_info and \ + a.sp_v0_label == b.sp_v0_label and \ a.unknown == b.unknown def parse_kv(self, kt, key, val): @@ -405,6 +432,10 @@ def parse_kv(self, kt, key, val): for i in range(0, len(val), 33): pk_list.append(val[i:i + 33]) self.musig_pubkeys[key] = pk_list + elif kt == PSBT_OUT_SP_V0_INFO: + self.sp_v0_info = val + elif kt == PSBT_OUT_SP_V0_LABEL: + self.sp_v0_label = val elif kt == PSBT_GLOBAL_PROPRIETARY: self.proprietary[key] = val else: @@ -436,6 +467,10 @@ def serialize_kvs(self, wr, v2): if self.musig_pubkeys: for agg_k, pk_lst in self.musig_pubkeys.items(): wr(PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS, b"".join(pk_lst), agg_k) + if self.sp_v0_info is not None: + wr(PSBT_OUT_SP_V0_INFO, self.sp_v0_info) + if self.sp_v0_label is not None: + wr(PSBT_OUT_SP_V0_LABEL, self.sp_v0_label) for k in self.proprietary: wr(PSBT_GLOBAL_PROPRIETARY, self.proprietary[k], k) @@ -465,6 +500,8 @@ def __init__(self): self.txn_modifiable = None self.fallback_locktime = None self.bip322_msg = None + self.sp_global_ecdh_shares = {} + self.sp_global_dleq_proofs = {} self.unknown = {} self.parsed_txn = None @@ -481,6 +518,8 @@ def __eq__(a, b): all(a.inputs[i] == b.inputs[i] for i in range(len(a.inputs))) and \ all(a.outputs[i] == b.outputs[i] for i in range(len(a.outputs))) and \ sorted(a.xpubs) == sorted(b.xpubs) and \ + a.sp_global_ecdh_shares == b.sp_global_ecdh_shares and \ + a.sp_global_dleq_proofs == b.sp_global_dleq_proofs and \ a.unknown == b.unknown def is_v2(self): @@ -551,6 +590,10 @@ def parse(self, raw): self.txn_modifiable = val[0] elif kt == PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE: self.bip322_msg = val + elif kt == PSBT_GLOBAL_SP_ECDH_SHARE: + self.sp_global_ecdh_shares[key[1:]] = val + elif kt == PSBT_GLOBAL_SP_DLEQ: + self.sp_global_dleq_proofs[key[1:]] = val else: self.unknown[key] = val @@ -609,6 +652,13 @@ def wr(ktype, val, key=b''): if self.txn_modifiable is not None: wr(PSBT_GLOBAL_TX_MODIFIABLE, bytes([self.txn_modifiable])) + if self.sp_global_ecdh_shares: + for k, v in self.sp_global_ecdh_shares.items(): + wr(PSBT_GLOBAL_SP_ECDH_SHARE, v, k) + if self.sp_global_dleq_proofs: + for k, v in self.sp_global_dleq_proofs.items(): + wr(PSBT_GLOBAL_SP_DLEQ, v, k) + if self.version is not None: wr(PSBT_GLOBAL_VERSION, struct.pack(' Date: Thu, 9 Apr 2026 21:23:34 -0400 Subject: [PATCH 09/41] BIP-352: add test vectors Add testing/test_bip352_vectors.py and testing/bip352_test_vectors.json - Verify SP sending and receiving test vectors --- testing/bip352_test_vectors.json | 5729 ++++++++++++++++++++++++++ testing/devtest/verify_sp_outputs.py | 40 + testing/test_bip352_vectors.py | 349 ++ 3 files changed, 6118 insertions(+) create mode 100644 testing/bip352_test_vectors.json create mode 100644 testing/test_bip352_vectors.py diff --git a/testing/bip352_test_vectors.json b/testing/bip352_test_vectors.json new file mode 100644 index 000000000..3a189757d --- /dev/null +++ b/testing/bip352_test_vectors.json @@ -0,0 +1,5729 @@ +[ + { + "comment": "Simple send: two inputs", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + }, + "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1" + ] + ], + "shared_secrets": [ + "028158aff7d61ea66b2fa7f555bc3c5937d1debbde16423d630f9aa7943e14d80d" + ], + "input_private_key_sum": "7ed265a6dac7aba8508a32d6d6b84c7f1dbd0a0941dd01088d69e8d556345f86", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + } + } + ], + "outputs": [ + "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "f438b40179a3c4262de12986c0e6cce0634007cdc79c1dcd3e20b9ebc2e7eef6", + "pub_key": "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1", + "signature": "74f85b856337fbe837643b86f462118159f93ac4acc2671522f27e8f67b079959195ccc7a5dbee396d2909f5d680d6e30cda7359aa2755822509b70d6b0687a1" + } + ], + "tweak": "024ac253c216532e961988e2a8ce266a447c894c781e52ef6cee902361db960004", + "shared_secret": "028158aff7d61ea66b2fa7f555bc3c5937d1debbde16423d630f9aa7943e14d80d", + "input_pub_key_sum": "032562c1ab2d6bd45d7ca4d78f569999e5333dffd3ac5263924fd00d00dedc4bee" + } + } + ] + }, + { + "comment": "Simple send: two inputs, order reversed", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + }, + "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1" + ] + ], + "shared_secrets": [ + "028158aff7d61ea66b2fa7f555bc3c5937d1debbde16423d630f9aa7943e14d80d" + ], + "input_private_key_sum": "7ed265a6dac7aba8508a32d6d6b84c7f1dbd0a0941dd01088d69e8d556345f86", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + } + } + ], + "outputs": [ + "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "f438b40179a3c4262de12986c0e6cce0634007cdc79c1dcd3e20b9ebc2e7eef6", + "pub_key": "3e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1", + "signature": "74f85b856337fbe837643b86f462118159f93ac4acc2671522f27e8f67b079959195ccc7a5dbee396d2909f5d680d6e30cda7359aa2755822509b70d6b0687a1" + } + ], + "tweak": "024ac253c216532e961988e2a8ce266a447c894c781e52ef6cee902361db960004", + "shared_secret": "028158aff7d61ea66b2fa7f555bc3c5937d1debbde16423d630f9aa7943e14d80d", + "input_pub_key_sum": "032562c1ab2d6bd45d7ca4d78f569999e5333dffd3ac5263924fd00d00dedc4bee" + } + } + ] + }, + { + "comment": "Simple send: two inputs from the same transaction", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 3, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 7, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + }, + "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "79e71baa2ba3fc66396de3a04f168c7bf24d6870ec88ca877754790c1db357b6" + ] + ], + "shared_secrets": [ + "03aa707f7b5e94b448abd28aa217e3d7a7cc6bb07f1a8d07be4de91bf7b1417469" + ], + "input_private_key_sum": "7ed265a6dac7aba8508a32d6d6b84c7f1dbd0a0941dd01088d69e8d556345f86", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 3, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 7, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + } + } + ], + "outputs": [ + "79e71baa2ba3fc66396de3a04f168c7bf24d6870ec88ca877754790c1db357b6" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "4851455bfbe1ab4f80156570aa45063201aa5c9e1b1dcd29f0f8c33d10bf77ae", + "pub_key": "79e71baa2ba3fc66396de3a04f168c7bf24d6870ec88ca877754790c1db357b6", + "signature": "10332eea808b6a13f70059a8a73195808db782012907f5ba32b6eae66a2f66b4f65147e2b968a1678c5f73d57d5d195dbaf667b606ff80c8490eac1f3b710657" + } + ], + "tweak": "03aeea547819c08413974e2ab2b12212e007166bb2058f88b009e082b9b4914a58", + "shared_secret": "03aa707f7b5e94b448abd28aa217e3d7a7cc6bb07f1a8d07be4de91bf7b1417469", + "input_pub_key_sum": "032562c1ab2d6bd45d7ca4d78f569999e5333dffd3ac5263924fd00d00dedc4bee" + } + } + ] + }, + { + "comment": "Simple send: two inputs from the same transaction, order reversed", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 7, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 3, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + }, + "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "f4c2da807f89cb1501f1a77322a895acfb93c28e08ed2724d2beb8e44539ba38" + ] + ], + "shared_secrets": [ + "03054f5c84b07182ba2a2e10a35e088778f95c04f059f4574b024c372eb8ce5468" + ], + "input_private_key_sum": "7ed265a6dac7aba8508a32d6d6b84c7f1dbd0a0941dd01088d69e8d556345f86", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 7, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 3, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + } + } + ], + "outputs": [ + "f4c2da807f89cb1501f1a77322a895acfb93c28e08ed2724d2beb8e44539ba38" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "ab0c9b87181bf527879f48db9f14a02233619b986f8e8f2d5d408ce68a709f51", + "pub_key": "f4c2da807f89cb1501f1a77322a895acfb93c28e08ed2724d2beb8e44539ba38", + "signature": "398a9790865791a9db41a8015afad3a47d60fec5086c50557806a49a1bc038808632b8fe679a7bb65fc6b455be994502eed849f1da3729cd948fc7be73d67295" + } + ], + "tweak": "024cad5180a093d3af0f49f586bdf37f890920178e68e80561ed53351d0fa499ad", + "shared_secret": "03054f5c84b07182ba2a2e10a35e088778f95c04f059f4574b024c372eb8ce5468", + "input_pub_key_sum": "032562c1ab2d6bd45d7ca4d78f569999e5333dffd3ac5263924fd00d00dedc4bee" + } + } + ] + }, + { + "comment": "Outpoint ordering byte-lexicographically vs. vout-integer", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 1, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 256, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + }, + "private_key": "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "a85ef8701394b517a4b35217c4bd37ac01ebeed4b008f8d0879f9e09ba95319c" + ] + ], + "shared_secrets": [ + "02cb25a6e7c9b7c6d550e0413da63834678465b5e80853a51d0335d318296ac182" + ], + "input_private_key_sum": "7ed265a6dac7aba8508a32d6d6b84c7f1dbd0a0941dd01088d69e8d556345f86", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 1, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 256, + "scriptSig": "48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac" + } + } + } + ], + "outputs": [ + "a85ef8701394b517a4b35217c4bd37ac01ebeed4b008f8d0879f9e09ba95319c" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "c8ac0292997b5bca98b3ebd99a57e253071137550f270452cd3df8a3e2266d36", + "pub_key": "a85ef8701394b517a4b35217c4bd37ac01ebeed4b008f8d0879f9e09ba95319c", + "signature": "c036ee38bfe46aba03234339ae7219b31b824b52ef9d5ce05810a0d6f62330dedc2b55652578aa5bdabf930fae941acd839d5a66f8fce7caa9710ccb446bddd1" + } + ], + "tweak": "031f9a80d0938cf980b51f7cc4fad713d49037f430646dff129c0570d75a40d8f0", + "shared_secret": "02cb25a6e7c9b7c6d550e0413da63834678465b5e80853a51d0335d318296ac182", + "input_pub_key_sum": "032562c1ab2d6bd45d7ca4d78f569999e5333dffd3ac5263924fd00d00dedc4bee" + } + } + ] + }, + { + "comment": "Single recipient: multiple UTXOs from the same public key", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "548ae55c8eec1e736e8d3e520f011f1f42a56d166116ad210b3937599f87f566" + ] + ], + "shared_secrets": [ + "02f6b40ff17f4010fe732ac4b0f2f211281aa09c9a5fb41f1c151ec2606fee9ec2" + ], + "input_private_key_sum": "d5b8f02cbfe3f1d5295af9fb8a9320e859e9cb07115856486ab1a4e4fb89a621", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + } + ], + "outputs": [ + "548ae55c8eec1e736e8d3e520f011f1f42a56d166116ad210b3937599f87f566" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "f032695e2636619efa523fffaa9ef93c8802299181fd0461913c1b8daf9784cd", + "pub_key": "548ae55c8eec1e736e8d3e520f011f1f42a56d166116ad210b3937599f87f566", + "signature": "f238386c5d5e5444f8d2c75aabbcb28c346f208c76f60823f5de3b67b79e0ec72ea5de2d7caec314e0971d3454f122dda342b3eede01b3857e83654e36b25f76" + } + ], + "tweak": "0319949463fc6a2368d999a2a6a2bcb2dbf64a2ac6e00b3ba5659780c860a6d9e0", + "shared_secret": "02f6b40ff17f4010fe732ac4b0f2f211281aa09c9a5fb41f1c151ec2606fee9ec2", + "input_pub_key_sum": "03e40664e222ba71e29b80efc907fa22a3c6c64f45e89dbb8511dc7a3712b0a186" + } + } + ] + }, + { + "comment": "Single recipient: taproot only inputs with even y-values", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b", + "prevout": { + "scriptPubKey": { + "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140bd1e708f92dbeaf24a6b8dd22e59c6274355424d62baea976b449e220fd75b13578e262ab11b7aa58e037f0c6b0519b66803b7d9decaa1906dedebfb531c56c1", + "prevout": { + "scriptPubKey": { + "hex": "5120782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + } + }, + "private_key": "fc8716a97a48ba9a05a98ae47b5cd201a25a7fd5d8b73c203c5f7b6b6b3b6ad7" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "de88bea8e7ffc9ce1af30d1132f910323c505185aec8eae361670421e749a1fb" + ] + ], + "shared_secrets": [ + "02de9719785c6d09f71571dadf44bca59edba2af3e689c65cbc3bb5a4a387732ef" + ], + "input_private_key_sum": "e7638ebfda3ab3849a5707e240a6627671f7f6e609bf172691cf1e9780e51d47", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "02782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b", + "prevout": { + "scriptPubKey": { + "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140bd1e708f92dbeaf24a6b8dd22e59c6274355424d62baea976b449e220fd75b13578e262ab11b7aa58e037f0c6b0519b66803b7d9decaa1906dedebfb531c56c1", + "prevout": { + "scriptPubKey": { + "hex": "5120782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + } + } + } + ], + "outputs": [ + "de88bea8e7ffc9ce1af30d1132f910323c505185aec8eae361670421e749a1fb" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "3fb9ce5ce1746ced103c8ed254e81f6690764637ddbc876ec1f9b3ddab776b03", + "pub_key": "de88bea8e7ffc9ce1af30d1132f910323c505185aec8eae361670421e749a1fb", + "signature": "c5acd25a8f021a4192f93bc34403fd8b76484613466336fb259c72d04c169824f2690ca34e96cee86b69f376c8377003268fda56feeb1b873e5783d7e19bcca5" + } + ], + "tweak": "02dc59cc8e8873b65c1dd5c416d4fbeb647372c329bd84a70c05b310e222e2c183", + "shared_secret": "02de9719785c6d09f71571dadf44bca59edba2af3e689c65cbc3bb5a4a387732ef", + "input_pub_key_sum": "038180a2125f9d6dd116e1a6139be4d72fd5057dab6aaabaa5654817c11baeb3ba" + } + } + ] + }, + { + "comment": "Single recipient: taproot only with mixed even/odd y-values", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b", + "prevout": { + "scriptPubKey": { + "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "", + "txinwitness": "01400a4d0dca6293f40499394d7eefe14a1de11e0e3454f51de2e802592abf5ee549042a1b1a8fb2e149ee9dd3f086c1b69b2f182565ab6ecf599b1ec9ebadfda6c5", + "prevout": { + "scriptPubKey": { + "hex": "51208c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4" + } + }, + "private_key": "1d37787c2b7116ee983e9f9c13269df29091b391c04db94239e0d2bc2182c3bf" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "77cab7dd12b10259ee82c6ea4b509774e33e7078e7138f568092241bf26b99f1" + ] + ], + "shared_secrets": [ + "030e7f5ca4bf109fc35c8c2d878f756c891ac04c456cc5f0b05fcec4d3b2b1beb2" + ], + "input_private_key_sum": "cda4ff9a3480e1fbfc6edd61b222f280f9baa0652002c1ffdb612efcc45d2ff2", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "028c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b", + "prevout": { + "scriptPubKey": { + "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "", + "txinwitness": "01400a4d0dca6293f40499394d7eefe14a1de11e0e3454f51de2e802592abf5ee549042a1b1a8fb2e149ee9dd3f086c1b69b2f182565ab6ecf599b1ec9ebadfda6c5", + "prevout": { + "scriptPubKey": { + "hex": "51208c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4" + } + } + } + ], + "outputs": [ + "77cab7dd12b10259ee82c6ea4b509774e33e7078e7138f568092241bf26b99f1" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "f5382508609771068ed079b24e1f72e4a17ee6d1c979066bf1d4e2a5676f09d4", + "pub_key": "77cab7dd12b10259ee82c6ea4b509774e33e7078e7138f568092241bf26b99f1", + "signature": "ff65833b8fd1ed3ef9d0443b4f702b45a3f2dd457ba247687e8207745c3be9d2bdad0ab3f07118f8b2efc6a04b95f7b3e218daf8a64137ec91bd2fc67fc137a5" + } + ], + "tweak": "03b990f5b1d90ea8fd4bdd5c856a9dfe17035d196958062e2c6cb4c99e413f3548", + "shared_secret": "030e7f5ca4bf109fc35c8c2d878f756c891ac04c456cc5f0b05fcec4d3b2b1beb2", + "input_pub_key_sum": "020f0ab50f420ab1249bc2a21659c607f2873400853035aad0ca6d0ded04d62623" + } + } + ] + }, + { + "comment": "Single recipient: taproot input with even y-value and non-taproot input", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b", + "prevout": { + "scriptPubKey": { + "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "463044021f24e010c6e475814740ba24c8cf9362c4db1276b7f46a7b1e63473159a80ec30221008198e8ece7b7f88e6c6cc6bb8c86f9f00b7458222a8c91addf6e1577bcf7697e2103e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9148cbc7dfe44f1579bff3340bbef1eddeaeb1fc97788ac" + } + }, + "private_key": "8d4751f6e8a3586880fb66c19ae277969bd5aa06f61c4ee2f1e2486efdf666d3" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "30523cca96b2a9ae3c98beb5e60f7d190ec5bc79b2d11a0b2d4d09a608c448f0" + ] + ], + "shared_secrets": [ + "021cd92ff153e638d0a97bcd11fafc81c321b111f5ba1efff593371b7b688efdd3" + ], + "input_private_key_sum": "7823ca0d4895515315a8e3bf602c080b6b732117272429e94751eb9b13a01943", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b", + "prevout": { + "scriptPubKey": { + "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "463044021f24e010c6e475814740ba24c8cf9362c4db1276b7f46a7b1e63473159a80ec30221008198e8ece7b7f88e6c6cc6bb8c86f9f00b7458222a8c91addf6e1577bcf7697e2103e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9148cbc7dfe44f1579bff3340bbef1eddeaeb1fc97788ac" + } + } + } + ], + "outputs": [ + "30523cca96b2a9ae3c98beb5e60f7d190ec5bc79b2d11a0b2d4d09a608c448f0" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "b40017865c79b1fcbed68896791be93186d08f47e416b289b8c063777e14e8df", + "pub_key": "30523cca96b2a9ae3c98beb5e60f7d190ec5bc79b2d11a0b2d4d09a608c448f0", + "signature": "d1edeea28cf1033bcb3d89376cabaaaa2886cbd8fda112b5c61cc90a4e7f1878bdd62180b07d1dfc8ffee1863c525a0c7b5bcd413183282cfda756cb65787266" + } + ], + "tweak": "0233c2a447b8b244e4ffcfb59fe365eaa3bb22288b31e2113b9998861f40d4d6da", + "shared_secret": "021cd92ff153e638d0a97bcd11fafc81c321b111f5ba1efff593371b7b688efdd3", + "input_pub_key_sum": "031ecda9c64faaa6cd57c9f3d7c62bcfc0763c2627ed8dc0e2c3018e9ff37a0bf0" + } + } + ] + }, + { + "comment": "Single recipient: taproot input with odd y-value and non-taproot input", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "01400a4d0dca6293f40499394d7eefe14a1de11e0e3454f51de2e802592abf5ee549042a1b1a8fb2e149ee9dd3f086c1b69b2f182565ab6ecf599b1ec9ebadfda6c5", + "prevout": { + "scriptPubKey": { + "hex": "51208c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4" + } + }, + "private_key": "1d37787c2b7116ee983e9f9c13269df29091b391c04db94239e0d2bc2182c3bf" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "463044021f24e010c6e475814740ba24c8cf9362c4db1276b7f46a7b1e63473159a80ec30221008198e8ece7b7f88e6c6cc6bb8c86f9f00b7458222a8c91addf6e1577bcf7697e2103e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9148cbc7dfe44f1579bff3340bbef1eddeaeb1fc97788ac" + } + }, + "private_key": "8d4751f6e8a3586880fb66c19ae277969bd5aa06f61c4ee2f1e2486efdf666d3" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "359358f59ee9e9eec3f00bdf4882570fd5c182e451aa2650b788544aff012a3a" + ] + ], + "shared_secrets": [ + "03d9437eb3676cf5cc00feebe68bc44c4567332e4b89788dec9eceb3779054442b" + ], + "input_private_key_sum": "700fd97abd324179e8bcc72587bbd9a40b43f67535ce95a0b80175b2dc73a314", + "input_pub_keys": [ + "028c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4", + "03e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "01400a4d0dca6293f40499394d7eefe14a1de11e0e3454f51de2e802592abf5ee549042a1b1a8fb2e149ee9dd3f086c1b69b2f182565ab6ecf599b1ec9ebadfda6c5", + "prevout": { + "scriptPubKey": { + "hex": "51208c8d23d4764feffcd5e72e380802540fa0f88e3d62ad5e0b47955f74d7b283c4" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "463044021f24e010c6e475814740ba24c8cf9362c4db1276b7f46a7b1e63473159a80ec30221008198e8ece7b7f88e6c6cc6bb8c86f9f00b7458222a8c91addf6e1577bcf7697e2103e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9148cbc7dfe44f1579bff3340bbef1eddeaeb1fc97788ac" + } + } + } + ], + "outputs": [ + "359358f59ee9e9eec3f00bdf4882570fd5c182e451aa2650b788544aff012a3a" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "a2f9dd05d1d398347c885d9c61a64d18a264de6d49cea4326bafc2791d627fa7", + "pub_key": "359358f59ee9e9eec3f00bdf4882570fd5c182e451aa2650b788544aff012a3a", + "signature": "96038ad233d8befe342573a6e54828d863471fb2afbad575cc65271a2a649480ea14912b6abbd3fbf92efc1928c036f6e3eef927105af4ec1dd57cb909f360b8" + } + ], + "tweak": "02d4e4f2c4cdb71c9c39a700a9ee1a0fc05b98362a441183f5770af7d6e2b3038c", + "shared_secret": "03d9437eb3676cf5cc00feebe68bc44c4567332e4b89788dec9eceb3779054442b", + "input_pub_key_sum": "03bc118b1c8178915b716d6137633722c71adfe721551ec7b3938054691de6a2b9" + } + } + ] + }, + { + "comment": "Multiple outputs: multiple outputs, same recipient", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + }, + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ] + ], + "shared_secrets": [ + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "d97e442d110c0bdd31161a7bb6e7862e038d02a09b1484dfbb463f2e0f7c9230", + "pub_key": "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca", + "signature": "29bd25d0f808d7fcd2aa6d5ed206053899198397506c301b218a9e47a3d7070af03e903ff718978d50d1b6b9af8cc0e313d84eda5d5b1e8e85e5516d630bbeb9" + }, + { + "priv_key_tweak": "33ce085c3c11eaad13694aae3c20301a6c83382ec89a7cde96c6799e2f88805a", + "pub_key": "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac", + "signature": "335667ca6cae7a26438f5cfdd73b3d48fa832fa9768521d7d5445f22c203ab0d74ed85088f27d29959ba627a4509996676f47df8ff284d292567b1beef0e3912" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "Multiple outputs: multiple outputs, multiple recipients", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + }, + { + "address": "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn", + "scan_pub_key": "02062d49ffc02787d586c608dfbec184aa91a6597d97b463ea5c6babd9d17a95a3", + "spend_pub_key": "0381eb9a9a9ec739d527c1631b31b421566f5c2a47b4ab5b1f6a686dfb68eab716" + }, + { + "address": "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn", + "scan_pub_key": "02062d49ffc02787d586c608dfbec184aa91a6597d97b463ea5c6babd9d17a95a3", + "spend_pub_key": "0381eb9a9a9ec739d527c1631b31b421566f5c2a47b4ab5b1f6a686dfb68eab716" + } + ] + }, + "expected": { + "outputs": [ + [ + "2e847bb01d1b491da512ddd760b8509617ee38057003d6115d00ba562451323a", + "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ] + ], + "shared_secrets": [ + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "03dd5fd04d3c8863be750a1bd7474df06161461d38d3ce1397a5c78cee112cdcd2", + "03dd5fd04d3c8863be750a1bd7474df06161461d38d3ce1397a5c78cee112cdcd2" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "2e847bb01d1b491da512ddd760b8509617ee38057003d6115d00ba562451323a", + "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ], + "key_material": { + "spend_priv_key": "9902c3c56e84002a7cd410113a9ab21d142be7f53cf5200720bb01314c5eb920", + "scan_priv_key": "060b751d7892149006ed7b98606955a29fe284a1e900070c0971f5fb93dbf422" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn" + ], + "outputs": [ + { + "priv_key_tweak": "72cd082cccb633bf85240a83494b32dc943a4d05647a6686d23ad4ca59c0ebe4", + "pub_key": "2e847bb01d1b491da512ddd760b8509617ee38057003d6115d00ba562451323a", + "signature": "38745f3d9f5eef0b1cfb17ca314efa8c521efab28a23aa20ec5e3abb561d42804d539906dce60c4ee7977966184e6f2cab1faa0e5377ceb7148ec5218b4e7878" + }, + { + "priv_key_tweak": "2f17ea873a0047fc01ba8010fef0969e76d0e4283f600d48f735098b1fee6eb9", + "pub_key": "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8", + "signature": "c26f4e3cf371b90b840f48ea0e761b5ec31883ed55719f9ef06a90e282d85f565790ab780a3f491bc2668cc64e944dca849d1022a878cdadb8d168b8da4a6da3" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "03dd5fd04d3c8863be750a1bd7474df06161461d38d3ce1397a5c78cee112cdcd2", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "Receiving with labels: label with even parity", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjex54dmqmmv6rw353tsuqhs99ydvadxzrsy9nuvk74epvee55drs734pqq", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "0259352add837b6686e8d22b87017814a46b3ad308702167c65bd5c8599cd28d1c" + } + ] + }, + "expected": { + "outputs": [ + [ + "d014d4860f67d607d60b1af70e0ee236b99658b61bb769832acbbe87c374439a" + ] + ], + "shared_secrets": [ + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "d014d4860f67d607d60b1af70e0ee236b99658b61bb769832acbbe87c374439a" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [ + 2, + 3, + 1001337 + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjex54dmqmmv6rw353tsuqhs99ydvadxzrsy9nuvk74epvee55drs734pqq", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqsg59z2rppn4qlkx0yz9sdltmjv3j8zgcqadjn4ug98m3t6plujsq9qvu5n", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq7c2zfthc6x3a5yecwc52nxa0kfd20xuz08zyrjpfw4l2j257yq6qgnkdh5" + ], + "outputs": [ + { + "priv_key_tweak": "51d4e9d0d482b5700109b4b2e16ff508269b03d800192a043d61dca4a0a72a52", + "pub_key": "d014d4860f67d607d60b1af70e0ee236b99658b61bb769832acbbe87c374439a", + "signature": "c30fa63bad6f0a317f39a773a5cbf0b0f8193c71dfebba05ee6ae4ed28e3775e6e04c3ea70a83703bb888122855dc894cab61692e7fd10c9b3494d479a60785e" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "Receiving with labels: label with odd parity", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqsg59z2rppn4qlkx0yz9sdltmjv3j8zgcqadjn4ug98m3t6plujsq9qvu5n", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "0208a144a18433a83f633c822c1bf5ee4c8c8e24601d6ca75e20a7dc57a0ff9280" + } + ] + }, + "expected": { + "outputs": [ + [ + "67626aebb3c4307cf0f6c39ca23247598fabf675ab783292eb2f81ae75ad1f8c" + ] + ], + "shared_secrets": [ + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "67626aebb3c4307cf0f6c39ca23247598fabf675ab783292eb2f81ae75ad1f8c" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [ + 2, + 3, + 1001337 + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjex54dmqmmv6rw353tsuqhs99ydvadxzrsy9nuvk74epvee55drs734pqq", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqsg59z2rppn4qlkx0yz9sdltmjv3j8zgcqadjn4ug98m3t6plujsq9qvu5n", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq7c2zfthc6x3a5yecwc52nxa0kfd20xuz08zyrjpfw4l2j257yq6qgnkdh5" + ], + "outputs": [ + { + "priv_key_tweak": "6024ae214876356b8d917716e7707d267ae16a0fdb07de2a786b74a7bbcddead", + "pub_key": "67626aebb3c4307cf0f6c39ca23247598fabf675ab783292eb2f81ae75ad1f8c", + "signature": "a86d554d0d6b7aa0907155f7e0b47f0182752472fffaeddd68da90e99b9402f166fd9b33039c302c7115098d971c1399e67c19e9e4de180b10ea0b9d6f0db832" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "Receiving with labels: large label integer", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq7c2zfthc6x3a5yecwc52nxa0kfd20xuz08zyrjpfw4l2j257yq6qgnkdh5", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "03d85092bbe3468f684ce1d8a2a66ebec96a9e6e09e7110720a5d5faa4aa7880d0" + } + ] + }, + "expected": { + "outputs": [ + [ + "7efa60ce78ac343df8a013a2027c6c5ef29f9502edcbd769d2c21717fecc5951" + ] + ], + "shared_secrets": [ + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "7efa60ce78ac343df8a013a2027c6c5ef29f9502edcbd769d2c21717fecc5951" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [ + 2, + 3, + 1001337 + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjex54dmqmmv6rw353tsuqhs99ydvadxzrsy9nuvk74epvee55drs734pqq", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqsg59z2rppn4qlkx0yz9sdltmjv3j8zgcqadjn4ug98m3t6plujsq9qvu5n", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq7c2zfthc6x3a5yecwc52nxa0kfd20xuz08zyrjpfw4l2j257yq6qgnkdh5" + ], + "outputs": [ + { + "priv_key_tweak": "e336b92330c33030285ce42e4115ad92d5197913c88e06b9072b4a9b47c664a2", + "pub_key": "7efa60ce78ac343df8a013a2027c6c5ef29f9502edcbd769d2c21717fecc5951", + "signature": "c9e80dd3bdd25ca2d352ce77510f1aed37ba3509dc8cc0677f2d7c2dd04090707950ce9dd6c83d2a428063063aff5c04f1744e334f661f2fc01b4ef80b50f739" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "Multiple outputs with labels: un-labeled and labeled address; same recipient", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "03a6739499dc667d308baefea4de0c4a85cc72aece181bc05712d3919662610ff1" + }, + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ], + [ + "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c", + "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca" + ] + ], + "shared_secrets": [ + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [ + 1 + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj" + ], + "outputs": [ + { + "priv_key_tweak": "43100f89f1a6bf10081c92b473ffc57ceac7dbed600b6aba9bb3976f17dbb914", + "pub_key": "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "signature": "15c92509b67a6c211ebb4a51b7528d0666e6720de2343b2e92cfb97942ca14693c1f1fdc8451acfdb2644039f8f5c76114807fdc3d3a002d8a46afab6756bd75" + }, + { + "priv_key_tweak": "33ce085c3c11eaad13694aae3c20301a6c83382ec89a7cde96c6799e2f88805a", + "pub_key": "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac", + "signature": "335667ca6cae7a26438f5cfdd73b3d48fa832fa9768521d7d5445f22c203ab0d74ed85088f27d29959ba627a4509996676f47df8ff284d292567b1beef0e3912" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "Multiple outputs with labels: multiple outputs for labeled address; same recipient", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "03a6739499dc667d308baefea4de0c4a85cc72aece181bc05712d3919662610ff1" + }, + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "03a6739499dc667d308baefea4de0c4a85cc72aece181bc05712d3919662610ff1" + } + ] + }, + "expected": { + "outputs": [ + [ + "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c" + ] + ], + "shared_secrets": [ + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [ + 1 + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj" + ], + "outputs": [ + { + "priv_key_tweak": "43100f89f1a6bf10081c92b473ffc57ceac7dbed600b6aba9bb3976f17dbb914", + "pub_key": "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "signature": "15c92509b67a6c211ebb4a51b7528d0666e6720de2343b2e92cfb97942ca14693c1f1fdc8451acfdb2644039f8f5c76114807fdc3d3a002d8a46afab6756bd75" + }, + { + "priv_key_tweak": "9d5fd3b91cac9ddfea6fc2e6f9386f680e6cee623cda02f53706306c081de87f", + "pub_key": "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c", + "signature": "db0dfacc98b6a6fcc67cc4631f080b1ca38c60d8c397f2f19843f8f95ec91594b24e47c5bd39480a861c1209f7e3145c440371f9191fb96e324690101eac8e8e" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "Multiple outputs with labels: un-labeled, labeled, and multiple outputs for labeled address; same recipients", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + }, + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "03a6739499dc667d308baefea4de0c4a85cc72aece181bc05712d3919662610ff1" + }, + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjyh2ju7hd5gj57jg5r9lev3pckk4n2shtzaq34467erzzdfajfggty6aa5", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "0244baa5cf5db444a9e922832ff2c88716b566a85d62e8235aebd91884d4f64942" + }, + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjyh2ju7hd5gj57jg5r9lev3pckk4n2shtzaq34467erzzdfajfggty6aa5", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "0244baa5cf5db444a9e922832ff2c88716b566a85d62e8235aebd91884d4f64942" + } + ] + }, + "expected": { + "outputs": [ + [ + "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae", + "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701", + "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa" + ], + [ + "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae", + "3edf1ff6657c6e69568811bd726a7a7f480493aa42161acfe8dd4f44521f99ed", + "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3", + "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa" + ], + [ + "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae", + "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3", + "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c", + "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701" + ], + [ + "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "3c54444944d176437644378c23efb999ab6ab1cacdfe1dc1537b607e3df330e2", + "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa", + "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b" + ], + [ + "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac", + "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b" + ], + [ + "3c54444944d176437644378c23efb999ab6ab1cacdfe1dc1537b607e3df330e2", + "602e10e6944107c9b48bd885b493676578c935723287e0ab2f8b7f136862568e", + "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3", + "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa" + ], + [ + "3c54444944d176437644378c23efb999ab6ab1cacdfe1dc1537b607e3df330e2", + "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3", + "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c", + "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b" + ], + [ + "3edf1ff6657c6e69568811bd726a7a7f480493aa42161acfe8dd4f44521f99ed", + "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac", + "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b" + ], + [ + "3edf1ff6657c6e69568811bd726a7a7f480493aa42161acfe8dd4f44521f99ed", + "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa", + "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca", + "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b" + ], + [ + "602e10e6944107c9b48bd885b493676578c935723287e0ab2f8b7f136862568e", + "7ee1543ed5d123ffa66fbebc128c020173eb490d5fa2ba306e0c9573a77db8f3", + "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ], + [ + "602e10e6944107c9b48bd885b493676578c935723287e0ab2f8b7f136862568e", + "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701", + "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa", + "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca" + ], + [ + "83dc944e61603137294829aed56c74c9b087d80f2c021b98a7fae5799000696c", + "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701", + "e976a58fbd38aeb4e6093d4df02e9c1de0c4513ae0c588cef68cda5b2f8834ca", + "f4569fc5f69c10f0082cfbb8e072e6266ec55f69fba8cffca4cbb4c144b7e59b" + ] + ], + "shared_secrets": [ + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae", + "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701", + "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [ + 1, + 1337 + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjyh2ju7hd5gj57jg5r9lev3pckk4n2shtzaq34467erzzdfajfggty6aa5" + ], + "outputs": [ + { + "priv_key_tweak": "4e3352fbe0505c25e718d96007c259ef08db34f8c844e4ff742d9855ff03805a", + "pub_key": "006a02c308ccdbf3ac49f0638f6de128f875db5a213095cf112b3b77722472ae", + "signature": "6eeae1ea9eb826e3d0e812f65937100e0836ea188c04f36fabc4981eda29de8d3d3529390a0a8b3d830f7bca4f5eae5994b9788ddaf05ad259ffe26d86144b4b" + }, + { + "priv_key_tweak": "43100f89f1a6bf10081c92b473ffc57ceac7dbed600b6aba9bb3976f17dbb914", + "pub_key": "39f42624d5c32a77fda80ff0acee269afec601d3791803e80252ae04e4ffcf4c", + "signature": "15c92509b67a6c211ebb4a51b7528d0666e6720de2343b2e92cfb97942ca14693c1f1fdc8451acfdb2644039f8f5c76114807fdc3d3a002d8a46afab6756bd75" + }, + { + "priv_key_tweak": "bf709f98d4418f8a67e738154ae48818dad44689cd37fbc070891a396dd1c633", + "pub_key": "ae1a780c04237bd577283c3ddb2e499767c3214160d5a6b0767e6b8c278bd701", + "signature": "42a19fd8a63dde1824966a95d65a28203e631e49bf96ca5dae1b390e7a0ace2cc8709c9b0c5715047032f57f536a3c80273cbecf4c05be0b5456c183fa122c06" + }, + { + "priv_key_tweak": "736f05e4e3072c3b8656bedef2e9bf54cbcaa2b6fe5320d3e86f5b96874dda71", + "pub_key": "ca64abe1e0f737823fb9a94f597eed418fb2df77b1317e26b881a14bb594faaa", + "signature": "2e61bb3d79418ecf55f68847cf121bfc12d397b39d1da8643246b2f0a9b96c3daa4bfe9651beb5c9ce20e1f29282c4566400a4b45ee6657ec3b18fdc554da0b4" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "Single recipient: use silent payments for sender change", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + }, + { + "address": "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqlv6saelkk5snl4wfutyxrchpzzwm8rjp3z6q7apna59z9huq4x754e5atr", + "scan_pub_key": "03b4cc0b090b6f49a684558852db60ee5eb1c5f74352839c3d18a8fc04ef7354e0", + "spend_pub_key": "03ecd43b9fdad484ff57278b21878b844276ce390622d03dd0cfb4288b7e02a6f5" + } + ] + }, + "expected": { + "outputs": [ + [ + "be368e28979d950245d742891ae6064020ba548c1e2e65a639a8bb0675d95cff", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ] + ], + "shared_secrets": [ + "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "037d12c02c3aed482658a28b8d1be030dac1daf995551491d74c00543af98572fb" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "be368e28979d950245d742891ae6064020ba548c1e2e65a639a8bb0675d95cff", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ], + "key_material": { + "spend_priv_key": "b8f87388cbb41934c50daca018901b00070a5ff6cc25a7e9e716a9d5b9e4d664", + "scan_priv_key": "11b7a82e06ca2648d5fded2366478078ec4fc9dc1d8ff487518226f229d768fd" + }, + "labels": [ + 0 + ] + }, + "expected": { + "addresses": [ + "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqauj52ymtc4xdkmx3tgyhrsemg2g3303xk2gtzfy8h8ejet8fz8jcw23zua", + "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqlv6saelkk5snl4wfutyxrchpzzwm8rjp3z6q7apna59z9huq4x754e5atr" + ], + "outputs": [ + { + "priv_key_tweak": "80cd767ed20bd0bb7d8ea5e803f8c381293a62e8a073cf46fb0081da46e64e1f", + "pub_key": "be368e28979d950245d742891ae6064020ba548c1e2e65a639a8bb0675d95cff", + "signature": "7fbd5074cf1377273155eefafc7c330cb61b31da252f22206ac27530d2b2567040d9af7808342ed4a09598c26d8307446e4ed77079e6a2e61fea736e44da5f5a" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "037d12c02c3aed482658a28b8d1be030dac1daf995551491d74c00543af98572fb", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + }, + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "be368e28979d950245d742891ae6064020ba548c1e2e65a639a8bb0675d95cff", + "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "33ce085c3c11eaad13694aae3c20301a6c83382ec89a7cde96c6799e2f88805a", + "pub_key": "f207162b1a7abc51c42017bef055e9ec1efc3d3567cb720357e2b84325db33ac", + "signature": "335667ca6cae7a26438f5cfdd73b3d48fa832fa9768521d7d5445f22c203ab0d74ed85088f27d29959ba627a4509996676f47df8ff284d292567b1beef0e3912" + } + ], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "Single recipient: taproot input with NUMS point", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0440c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b22205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5ac21c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac00150", + "prevout": { + "scriptPubKey": { + "hex": "5120da6f0595ecb302bbe73e2f221f05ab10f336b06817d36fd28fc6691725ddaa85" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140bd1e708f92dbeaf24a6b8dd22e59c6274355424d62baea976b449e220fd75b13578e262ab11b7aa58e037f0c6b0519b66803b7d9decaa1906dedebfb531c56c1", + "prevout": { + "scriptPubKey": { + "hex": "5120782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + } + }, + "private_key": "fc8716a97a48ba9a05a98ae47b5cd201a25a7fd5d8b73c203c5f7b6b6b3b6ad7" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 1, + "scriptSig": "", + "txinwitness": "0340268d31a9276f6380107d5321cafa6d9e8e5ea39204318fdc8206b31507c891c3bbcea3c99e2208d73bd127a8e8c5f1e45a54f1bd217205414ddb566ab7eda0092220e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85dac21c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "prevout": { + "scriptPubKey": { + "hex": "51200a3c9365ceb131f89b0a4feb6896ebd67bb15a98c31eaa3da143bb955a0f3fcb" + } + }, + "private_key": "8d4751f6e8a3586880fb66c19ae277969bd5aa06f61c4ee2f1e2486efdf666d3" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "79e79897c52935bfd97fc6e076a6431a0c7543ca8c31e0fc3cf719bb572c842d" + ] + ], + "shared_secrets": [ + "036f040608cd1e5ee79c54e78bea85904c895591f547beae080d0c5f6946c2730d" + ], + "input_private_key_sum": "fc8716a97a48ba9a05a98ae47b5cd201a25a7fd5d8b73c203c5f7b6b6b3b6ad7", + "input_pub_keys": [ + "02782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0440c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b22205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5ac21c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac00150", + "prevout": { + "scriptPubKey": { + "hex": "5120da6f0595ecb302bbe73e2f221f05ab10f336b06817d36fd28fc6691725ddaa85" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140bd1e708f92dbeaf24a6b8dd22e59c6274355424d62baea976b449e220fd75b13578e262ab11b7aa58e037f0c6b0519b66803b7d9decaa1906dedebfb531c56c1", + "prevout": { + "scriptPubKey": { + "hex": "5120782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 1, + "scriptSig": "", + "txinwitness": "0340268d31a9276f6380107d5321cafa6d9e8e5ea39204318fdc8206b31507c891c3bbcea3c99e2208d73bd127a8e8c5f1e45a54f1bd217205414ddb566ab7eda0092220e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85dac21c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "prevout": { + "scriptPubKey": { + "hex": "51200a3c9365ceb131f89b0a4feb6896ebd67bb15a98c31eaa3da143bb955a0f3fcb" + } + } + } + ], + "outputs": [ + "79e79897c52935bfd97fc6e076a6431a0c7543ca8c31e0fc3cf719bb572c842d" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "3ddec3232609d348d6b8b53123b4f40f6d4f5398ca586f087b0416ec3b851496", + "pub_key": "79e79897c52935bfd97fc6e076a6431a0c7543ca8c31e0fc3cf719bb572c842d", + "signature": "d7d06e3afb68363031e4eb18035c46ceae41bdbebe7888a4754bc9848c596436869aeaecff0527649a1f458b71c9ceecec10b535c09d01d720229aa228547706" + } + ], + "tweak": "02213b872c9a6ee28a0d861384a1b3e3ec7257f4855ed09b4323e3899f3b028989", + "shared_secret": "036f040608cd1e5ee79c54e78bea85904c895591f547beae080d0c5f6946c2730d", + "input_pub_key_sum": "02782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + } + } + ] + }, + { + "comment": "Pubkey extraction from malleated p2pkh", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 1, + "scriptSig": "0075473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 2, + "scriptSig": "5163473045022100e7d26e77290b37128f5215ade25b9b908ce87cc9a4d498908b5bb8fd6daa1b8d022002568c3a8226f4f0436510283052bfb780b76f3fe4aa60c4c5eb118e43b187372102e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d67483046022100c0d3c851d3bd562ae93d56bcefd735ea57c027af46145a4d5e9cac113bfeb0c2022100ee5b2239af199fa9b7aa1d98da83a29d0a2cf1e4f29e2f37134ce386d51c544c2102ad0f26ddc7b3fcc340155963b3051b85289c1869612ecb290184ac952e2864ec68", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914c82c5ec473cbc6c86e5ef410e36f9495adcf979988ac" + } + }, + "private_key": "72b8ae09175ca7977f04993e651d88681ed932dfb92c5158cdf0161dd23fda6e" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "4612cdbf845c66c7511d70aab4d9aed11e49e48cdb8d799d787101cdd0d53e4f" + ] + ], + "shared_secrets": [ + "034773b97ccad9791cb4213964ff9896ccd6581ee69345de5d114786d9d86b03a2" + ], + "input_private_key_sum": "610e0f75fd05e5e80e088b57af0a46da06cb0700c0c5907aa6d29c6b4ce46348", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "02e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 1, + "scriptSig": "0075473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 2, + "scriptSig": "5163473045022100e7d26e77290b37128f5215ade25b9b908ce87cc9a4d498908b5bb8fd6daa1b8d022002568c3a8226f4f0436510283052bfb780b76f3fe4aa60c4c5eb118e43b187372102e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d67483046022100c0d3c851d3bd562ae93d56bcefd735ea57c027af46145a4d5e9cac113bfeb0c2022100ee5b2239af199fa9b7aa1d98da83a29d0a2cf1e4f29e2f37134ce386d51c544c2102ad0f26ddc7b3fcc340155963b3051b85289c1869612ecb290184ac952e2864ec68", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914c82c5ec473cbc6c86e5ef410e36f9495adcf979988ac" + } + } + } + ], + "outputs": [ + "4612cdbf845c66c7511d70aab4d9aed11e49e48cdb8d799d787101cdd0d53e4f" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "10bde9781def20d7701e7603ef1b1e5e71c67bae7154818814e3c81ef5b1a3d3", + "pub_key": "4612cdbf845c66c7511d70aab4d9aed11e49e48cdb8d799d787101cdd0d53e4f", + "signature": "6137969f810e9e8ef6c9755010e808f5dd1aed705882e44d7f0ae64eb0c509ec8b62a0671bee0d5914ac27d2c463443e28e999d82dc3d3a4919f093872d947bb" + } + ], + "tweak": "028d6617f9bfe08604beb2188f4eebec923f5f8cc436fa6d14e4256e49bc32e7c8", + "shared_secret": "034773b97ccad9791cb4213964ff9896ccd6581ee69345de5d114786d9d86b03a2", + "input_pub_key_sum": "038b0d201fe111bdc0e6953772bd02a41959d25d5b2f66bcbe348af27bbdd42735" + } + } + ] + }, + { + "comment": "P2PKH and P2WPKH Uncompressed Keys are skipped", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9144b92ac4ac6fe6212393894addda332f2e47a315688ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 1, + "scriptSig": "", + "txinwitness": "02473045022100e7d26e77290b37128f5215ade25b9b908ce87cc9a4d498908b5bb8fd6daa1b8d022002568c3a8226f4f0436510283052bfb780b76f3fe4aa60c4c5eb118e43b187374104e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d6fe8190e189be57d0d5bcd17dbcbcd04c9b4a1c5f605b10d5c90abfcc0d12884", + "prevout": { + "scriptPubKey": { + "hex": "00140423f731a07491364e8dce98b7c00bda63336950" + } + }, + "private_key": "72b8ae09175ca7977f04993e651d88681ed932dfb92c5158cdf0161dd23fda6e" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6" + ] + ], + "shared_secrets": [ + "0295a54c359da5b2640601ddbedb26e040cb97b6a3432e60b76d1258e85f72fa64" + ], + "input_private_key_sum": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac" + } + } + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9144b92ac4ac6fe6212393894addda332f2e47a315688ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 1, + "scriptSig": "", + "txinwitness": "02473045022100e7d26e77290b37128f5215ade25b9b908ce87cc9a4d498908b5bb8fd6daa1b8d022002568c3a8226f4f0436510283052bfb780b76f3fe4aa60c4c5eb118e43b187374104e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d6fe8190e189be57d0d5bcd17dbcbcd04c9b4a1c5f605b10d5c90abfcc0d12884", + "prevout": { + "scriptPubKey": { + "hex": "00140423f731a07491364e8dce98b7c00bda63336950" + } + } + } + ], + "outputs": [ + "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "688fa3aeb97d2a46ae87b03591921c2eaf4b505eb0ddca2733c94701e01060cf", + "pub_key": "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6", + "signature": "72e7ad573ac23255d4651d5b0326a200496588acb7a4894b22092236d5eda6a0a9a4d8429b022c2219081fefce5b33795cae488d10f5ea9438849ed8353624f2" + } + ], + "tweak": "02b04034f00da0678507d1345b7d56fecef825a1151f9dc7d8ca6946452a9e1f43", + "shared_secret": "0295a54c359da5b2640601ddbedb26e040cb97b6a3432e60b76d1258e85f72fa64", + "input_pub_key_sum": "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + } + ] + }, + { + "comment": "Skip invalid P2SH inputs", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "16001419c2f3ae0ca3b642bd3e49598b8da89f50c14161", + "txinwitness": "02483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "prevout": { + "scriptPubKey": { + "hex": "a9148629db5007d5fcfbdbb466637af09daf9125969387" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 1, + "scriptSig": "1600144b92ac4ac6fe6212393894addda332f2e47a3156", + "txinwitness": "02473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab", + "prevout": { + "scriptPubKey": { + "hex": "a9146c9bf136fbb7305fd99d771a95127fcf87dedd0d87" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 2, + "scriptSig": "00493046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d601483045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b97014c695221025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be52103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233382102e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d53ae", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "a9141044ddc6cea09e4ac40fbec2ba34ad62de6db25b87" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6" + ] + ], + "shared_secrets": [ + "0295a54c359da5b2640601ddbedb26e040cb97b6a3432e60b76d1258e85f72fa64" + ], + "input_private_key_sum": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "16001419c2f3ae0ca3b642bd3e49598b8da89f50c14161", + "txinwitness": "02483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "prevout": { + "scriptPubKey": { + "hex": "a9148629db5007d5fcfbdbb466637af09daf9125969387" + } + } + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 1, + "scriptSig": "1600144b92ac4ac6fe6212393894addda332f2e47a3156", + "txinwitness": "02473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab", + "prevout": { + "scriptPubKey": { + "hex": "a9146c9bf136fbb7305fd99d771a95127fcf87dedd0d87" + } + } + }, + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 2, + "scriptSig": "00493046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d601483045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b97014c695221025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be52103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233382102e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d53ae", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "a9141044ddc6cea09e4ac40fbec2ba34ad62de6db25b87" + } + } + } + ], + "outputs": [ + "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "688fa3aeb97d2a46ae87b03591921c2eaf4b505eb0ddca2733c94701e01060cf", + "pub_key": "67fee277da9e8542b5d2e6f32d660a9bbd3f0e107c2d53638ab1d869088882d6", + "signature": "72e7ad573ac23255d4651d5b0326a200496588acb7a4894b22092236d5eda6a0a9a4d8429b022c2219081fefce5b33795cae488d10f5ea9438849ed8353624f2" + } + ], + "tweak": "02b04034f00da0678507d1345b7d56fecef825a1151f9dc7d8ca6946452a9e1f43", + "shared_secret": "0295a54c359da5b2640601ddbedb26e040cb97b6a3432e60b76d1258e85f72fa64", + "input_pub_key_sum": "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + } + ] + }, + { + "comment": "Recipient ignores unrelated outputs", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b", + "prevout": { + "scriptPubKey": { + "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn", + "scan_pub_key": "02062d49ffc02787d586c608dfbec184aa91a6597d97b463ea5c6babd9d17a95a3", + "spend_pub_key": "0381eb9a9a9ec739d527c1631b31b421566f5c2a47b4ab5b1f6a686dfb68eab716" + } + ] + }, + "expected": { + "outputs": [ + [ + "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8" + ] + ], + "shared_secrets": [ + "03dd5fd04d3c8863be750a1bd7474df06161461d38d3ce1397a5c78cee112cdcd2" + ], + "input_private_key_sum": "ee55616ce5a93e508f03f21949ecbe70a2a0b107b6e1df5d98b4e4da4adaca1b", + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "", + "txinwitness": "0140c459b671370d12cfb5acee76da7e3ba7cc29b0b4653e3af8388591082660137d087fdc8e89a612cd5d15be0febe61fc7cdcf3161a26e599a4514aa5c3e86f47b", + "prevout": { + "scriptPubKey": { + "hex": "51205a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b972103782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9147cdd63cc408564188e8e472640e921c7c90e651d88ac" + } + } + } + ], + "outputs": [ + "841792c33c9dc6193e76744134125d40add8f2f4a96475f28ba150be032d64e8", + "782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [], + "tweak": "0314bec14463d6c0181083d607fecfba67bb83f95915f6f247975ec566d5642ee8", + "shared_secret": "038efbcbc1b0938fba3bf59fea1219a3c54b6d6f9107560da05001407adc13f413", + "input_pub_key_sum": "03853f51bef283502181e93238c8708ae27235dc51ae45a0c4053987c52fc6428b" + } + } + ] + }, + { + "comment": "No valid inputs, sender generates no outputs", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d641045a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5c61836c9b1688ba431f7ea3039742251f62f0dca3da1bee58a47fa9b456c2d52", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914460e8b41545d2dbe7e0671f0f573e2232814260a88ac" + } + }, + "private_key": "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1" + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9144b92ac4ac6fe6212393894addda332f2e47a315688ac" + } + }, + "private_key": "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [] + ], + "shared_secrets": [ + null + ], + "input_pub_keys": [] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + "vout": 0, + "scriptSig": "483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d641045a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5c61836c9b1688ba431f7ea3039742251f62f0dca3da1bee58a47fa9b456c2d52", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a914460e8b41545d2dbe7e0671f0f573e2232814260a88ac" + } + } + }, + { + "txid": "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + "vout": 0, + "scriptSig": "473045022100a8c61b2d470e393279d1ba54f254b7c237de299580b7fa01ffcc940442ecec4502201afba952f4e4661c40acde7acc0341589031ba103a307b886eb867b23b850b974104782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c3799373233387c5343bf58e23269e903335b958a12182f9849297321e8d710e49a8727129cab", + "txinwitness": "", + "prevout": { + "scriptPubKey": { + "hex": "76a9144b92ac4ac6fe6212393894addda332f2e47a315688ac" + } + } + } + ], + "outputs": [ + "782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [], + "tweak": null, + "shared_secret": null + } + } + ] + }, + { + "comment": "Input keys sum up to zero / point at infinity: sending fails, receiver skips tx", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 0, + "scriptSig": "", + "txinwitness": "024730440220085003179ce1a3a88ce0069aa6ea045e140761ab88c22a26ae2a8cfe983a6e4602204a8a39940f0735c8a4424270ac8da65240c261ab3fda9272f6d6efbf9cfea366012102557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149d9e24f9fab4e35bf1a6df4b46cb533296ac0792" + } + }, + "private_key": "a6df6a0bb448992a301df4258e06a89fe7cf7146f59ac3bd5ff26083acb22ceb" + }, + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 1, + "scriptSig": "", + "txinwitness": "0247304402204586a68e1d97dd3c6928e3622799859f8c3b20c3c670cf654cc905c9be29fdb7022043fbcde1689f3f4045e8816caf6163624bd19e62e4565bc99f95c533e599782c012103557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149860538b5575962776ed0814ae222c7d60c72d7b" + } + }, + "private_key": "592095f44bb766d5cfe20bda71f9575ed2df6b9fb9addc7e5fdffe0923841456" + } + ], + "recipients": [ + { + "address": "sp1qqtrqglu5g8kh6mfsg4qxa9wq0nv9cauwfwxw70984wkqnw2uwz0w2qnehen8a7wuhwk9tgrzjh8gwzc8q2dlekedec5djk0js9d3d7qhnq6lqj3s", + "scan_pub_key": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "spend_pub_key": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + } + ] + }, + "expected": { + "outputs": [ + [] + ], + "shared_secrets": [ + null + ], + "input_pub_keys": [ + "02557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "03557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 0, + "scriptSig": "", + "txinwitness": "024730440220085003179ce1a3a88ce0069aa6ea045e140761ab88c22a26ae2a8cfe983a6e4602204a8a39940f0735c8a4424270ac8da65240c261ab3fda9272f6d6efbf9cfea366012102557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149d9e24f9fab4e35bf1a6df4b46cb533296ac0792" + } + } + }, + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 1, + "scriptSig": "", + "txinwitness": "0247304402204586a68e1d97dd3c6928e3622799859f8c3b20c3c670cf654cc905c9be29fdb7022043fbcde1689f3f4045e8816caf6163624bd19e62e4565bc99f95c533e599782c012103557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149860538b5575962776ed0814ae222c7d60c72d7b" + } + } + } + ], + "outputs": [ + "0000000000000000000000000000000000000000000000000000000000000000" + ], + "key_material": { + "spend_priv_key": "0000000000000000000000000000000000000000000000000000000000000001", + "scan_priv_key": "0000000000000000000000000000000000000000000000000000000000000002" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqtrqglu5g8kh6mfsg4qxa9wq0nv9cauwfwxw70984wkqnw2uwz0w2qnehen8a7wuhwk9tgrzjh8gwzc8q2dlekedec5djk0js9d3d7qhnq6lqj3s" + ], + "outputs": [], + "tweak": null, + "shared_secret": null + } + } + ] + }, + { + "comment": "Input keys intermediate sum is zero but final sum is non-zero", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 0, + "scriptSig": "", + "txinwitness": "0247304402203e5537fa8c876b3475e7efe4f1474b0f48b7a6e4169179db5de9bb5b55ad1bd10220200e06f8f4d29dbc48bbcdf90df3278e798ce6cbf3c9fbf90427599fde147867012102557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149d9e24f9fab4e35bf1a6df4b46cb533296ac0792" + } + }, + "private_key": "a6df6a0bb448992a301df4258e06a89fe7cf7146f59ac3bd5ff26083acb22ceb" + }, + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 1, + "scriptSig": "", + "txinwitness": "0247304402207fdad0faf46edc54f5a5c67d33b2fa8d3f1fdc869381fd96e659f9e0c470ab1e022044f0d973339618b18667cef9a6251817f7f431f7f2b252a8cb760ccb40e7d823012103557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149860538b5575962776ed0814ae222c7d60c72d7b" + } + }, + "private_key": "592095f44bb766d5cfe20bda71f9575ed2df6b9fb9addc7e5fdffe0923841456" + }, + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 2, + "scriptSig": "", + "txinwitness": "0247304402203e5537fa8c876b3475e7efe4f1474b0f48b7a6e4169179db5de9bb5b55ad1bd10220200e06f8f4d29dbc48bbcdf90df3278e798ce6cbf3c9fbf90427599fde147867012102557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149d9e24f9fab4e35bf1a6df4b46cb533296ac0792" + } + }, + "private_key": "a6df6a0bb448992a301df4258e06a89fe7cf7146f59ac3bd5ff26083acb22ceb" + } + ], + "recipients": [ + { + "address": "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "scan_pub_key": "0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4", + "spend_pub_key": "025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36" + } + ] + }, + "expected": { + "outputs": [ + [ + "7e88a7536c90770be4d2693a84ed03abe3fdcc5a29f96ec3433effec3b0c2194" + ] + ], + "shared_secrets": [ + "037dc4e5904ab4770dbdbb628860b54265fdbb7810b8afdf9f582fedaabfdebef0" + ], + "input_private_key_sum": "a6df6a0bb448992a301df4258e06a89fe7cf7146f59ac3bd5ff26083acb22ceb", + "input_pub_keys": [ + "02557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "03557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "02557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 0, + "scriptSig": "", + "txinwitness": "0247304402203e5537fa8c876b3475e7efe4f1474b0f48b7a6e4169179db5de9bb5b55ad1bd10220200e06f8f4d29dbc48bbcdf90df3278e798ce6cbf3c9fbf90427599fde147867012102557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149d9e24f9fab4e35bf1a6df4b46cb533296ac0792" + } + } + }, + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 1, + "scriptSig": "", + "txinwitness": "0247304402207fdad0faf46edc54f5a5c67d33b2fa8d3f1fdc869381fd96e659f9e0c470ab1e022044f0d973339618b18667cef9a6251817f7f431f7f2b252a8cb760ccb40e7d823012103557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149860538b5575962776ed0814ae222c7d60c72d7b" + } + } + }, + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 2, + "scriptSig": "", + "txinwitness": "0247304402203e5537fa8c876b3475e7efe4f1474b0f48b7a6e4169179db5de9bb5b55ad1bd10220200e06f8f4d29dbc48bbcdf90df3278e798ce6cbf3c9fbf90427599fde147867012102557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149d9e24f9fab4e35bf1a6df4b46cb533296ac0792" + } + } + } + ], + "outputs": [ + "7e88a7536c90770be4d2693a84ed03abe3fdcc5a29f96ec3433effec3b0c2194" + ], + "key_material": { + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "priv_key_tweak": "3d5b7a284108f93b9fe78f2c300d2ca9ef3b4e0cd0de673fc72990f2a4f417b9", + "pub_key": "7e88a7536c90770be4d2693a84ed03abe3fdcc5a29f96ec3433effec3b0c2194", + "signature": "f8d5222f1a682215c40ab677f2104606f2a0e6c5cb1a2d248d970fb61d4eadb31702353e6b41ea5a9b24817efa0eaf535552eeee8a794b662c3cf303b6c86672" + } + ], + "tweak": "039c68bacb7efbf2175d781822f460afc4839a5798fabb055b50d939231bf57bb6", + "shared_secret": "037dc4e5904ab4770dbdbb628860b54265fdbb7810b8afdf9f582fedaabfdebef0", + "input_pub_key_sum": "02557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975" + } + } + ] + }, + { + "comment": "Maximum per-group recipient limit K_max is exceeded (2324 matches): sending fails, receiver doesn't scan beyond limit", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "3cde0e7ad8adf24a4e52fd18efafffb94f73f4c7facf2627a5b588ad1c9db87f", + "vout": 0, + "scriptSig": "", + "txinwitness": "01407ce01bc5ef2e4aae353e7f291fec32623d6a491b5421be6dccc70345f32ebae5baa6654c60c074e72da76fd06b343474370e56d3ec0413156ec6261757125ad4", + "prevout": { + "scriptPubKey": { + "hex": "5120bca87f72e604e8850064552bedf380ca4584227057efe12a6cc238470658aaa3" + } + }, + "private_key": "0000000000000000000000000000000000000000000000000000000000001337" + } + ], + "recipients": [ + { + "address": "sp1qqtnvg7hxjck9ag24naytgd7pjwsmevwh95ydwht58w3uh7uw0ta7kqmk4a3pm24z0yepw6aw27pku56md0hq5ace0l3p3jstkqaajwrsjqc5dde5", + "scan_pub_key": "02e6c47ae6962c5ea1559f48b437c193a1bcb1d72d08d75d743ba3cbfb8e7afbeb", + "spend_pub_key": "0376af621daaa27932176bae57836e535b6bee0a77197fe218ca0bb03bd9387090", + "count": 2324 + } + ] + }, + "expected": { + "outputs": [ + [] + ], + "shared_secrets": [ + null + ], + "input_private_key_sum": "0000000000000000000000000000000000000000000000000000000000001337", + "input_pub_keys": [ + "02bca87f72e604e8850064552bedf380ca4584227057efe12a6cc238470658aaa3" + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "3cde0e7ad8adf24a4e52fd18efafffb94f73f4c7facf2627a5b588ad1c9db87f", + "vout": 0, + "scriptSig": "", + "txinwitness": "01407ce01bc5ef2e4aae353e7f291fec32623d6a491b5421be6dccc70345f32ebae5baa6654c60c074e72da76fd06b343474370e56d3ec0413156ec6261757125ad4", + "prevout": { + "scriptPubKey": { + "hex": "5120bca87f72e604e8850064552bedf380ca4584227057efe12a6cc238470658aaa3" + } + }, + "private_key": "0000000000000000000000000000000000000000000000000000000000001337" + } + ], + "outputs": [ + "5cfb6fd7a7e5d2af0fee276f2104ce2e5c86cde7955b98f2f1fb32811b448f2f", + "da290e0d79ead5cd2e5d150aac80dcab54dbd0e68f241a6c34dc30906eabd13d", + "d4a2b1458f0c8b20d756bde8e545560d7e7a65f6b4158f01ed34a913ba3a4603", + "24752e555b0edcca123f769113692224bf1e6db137cddeb7d69ae52e51144e9e", + "c911f722ef9a3594d6b85c585d4f3ed8dc437f850591dc627a0154723644114b", + "ef91ddaa83a0b748d638dc9be8c9771b049a04815f03967b7ee993bde6c260ab", + "ee4ed334fb38af95f52c6bbadcf2f491e646b9cc8ed31da67635f36c3cfdaba0", + "a17d61b4772e453b32782744902261e051510cbafc04f086f53480d1ceee1a9c", + "44d89f5e903739072e3aff8a3eb2f351520f77ff288ac8be277be3f28834bdd2", + "3eff02a4a04d66d63f6bc93a693f23db703f351c0a1ff1656b907ed348a9a35f", + "628c23a6e21e6a47b80274fc80e4decb98ff79b8040c7f9ea5972e4920b62b6d", + "e72190c0a5ea167c2663b18d378520b9228da61ebbc99c3fa2af39e01fb9501e", + "24183edbc5b80588e0e5b803e924e77fc1cab1afca54cfd285dad9bfc2a34f6d", + "c45bad25a223f0f617e8167f858037907e4454210a745f3b9798c8913646dfc6", + "9f9cec85011d7f718f96ee1a2940df21920a857cd1a545255579cb615f285a42", + "8c60891f9bc2f772efc51d44f7cc885161412835b6fd5aac3b0cf57c3c2f9154", + "85ac46a6ac9569ed67d1bc5342ed3b591af5e01581d1b09bcb2c71deb9b2c2c9", + "8a6bfe47e616c6854fc797a4af53ef51c942b99eae18f316594fc8eb8869ca05", + "ed5e1aa6a8b4e805273367b8ec3ade16ed6494270fc2169ba920b89770efe8eb", + "2448503c55a1a7035c069e1d5461b81774c43bf6061421fdd0157009bfe96a8a", + "d0dcb3d7b551eac8d31fceccb83df415c554860d5541dd08ff5fa0028ce5704f", + "f11a298b54b650613e0b0183552c9c9e42c3812e03cf713d351ef71106b6ee3f", + "49749206f23791f858c453cb60160d48710075bdbfd33907b0046d10f0b0295e", + "3fbfdb52cbf0ea9e6655a211748bf2ac2dc92ff3cfeeef0f0a26be9987016de0", + "d4a29144511981919cadbe8227fc68379e85d3fe399f177c2ae36c304b6ad6b0", + "c586cc196ff56f42396f426a0200afee3a6c41058d81f19caf6536ec0efd5605", + "c666994f027ceab025256af28d8ea6aec452fb8b0e1f69e7e13a4f3c5119f4ae", + "5c9216cc4529c3f9c62caf70b04f8354ce9ec2cabaef745092bea1b160328fda", + "d9aea54323503d78c026a8cd465c19a6df54b32ee866714d190e8260054361da", + "ba71f87ca1d74eee115d8e8a26293fe2c88d9d66cff185a7a079282f02f931ad", + "b8b930666b2df74c33dc8963221080c115246070e3fcd51f39bee71312db4fc4", + "b7f42d2f18a3ac61f570b64ae6864f7dbff774a370ba27358d76797e841d5304", + "d636d179055241a0f8bb7db193912da513a8999684d9829b266985a8083819a9", + "be9622aec125f9605bcee193a99ca27c16bc591122ff8b44c511a85e6f63ec9d", + "af5beb25776f84fadd6079c3ffd85775a35ad74096a58229e1d5076d836ca25d", + "75fb55ec31e304456f663c9a66321e67f9d9bd8f43749494acc5189ed57b0d4a", + "8dfebff33c514486d06eeb4ab8eb8471496556858c4382f73780620101a77f71", + "93bfd4e75706951de4a59c7f70c5d2ce4c617b4bde0b0b23ae046df096116726", + "b6eeca22f43bd62a4fcb3eee719e07d39ea703fa0707970fc197916f2efebbb5", + "0437c3971f73342e5c41178590e1cb1364cb855b2d20b7b6c1c1ed0e7da5b57b", + "d284c831cd9d52793977925ce3111b68f36d1ea456e46716158fe6947fb6d635", + "d95b8d2789fd06cc764d47cc7e0697404220ae8f938ef47dcc9a1bba299fbb9f", + "33599fb1fe313b5a2680b126bfee93cb097d938915d425a63e307e5834479b95", + "05ba86903fac2f02ef2e152072bc6067008ee8ee34ce55ad460801303373eaab", + "0b757802e56728b6d5b28e671a90de573d7251a47fc1bcd9319b617cac8e1463", + "b4a2451e725e4cbcdf47fc736139cfe29c847e2f75cbb7653d80c8522bd48a6c", + "8dd800c3a7cb1ee60f52db3bb69413c4c4247b0b134576552c675970f9903c9b", + "4de21129c6fdf5568040346bbdda272caaadd58218ec6f1f152518068dac4d4d", + "22f6927eae0c3717395df6483d756028839fbf0814f8cf0391159efa65dd2854", + "192d26fe0bc772c705c2657dd5c5033ac41ba408793e6c721f74c53747be16e8", + "9527b8e19570a16ce2d8dd3620dfd915e461bccc82340fe682f7f811b978814d", + "f84039ff95cd44f842d7cf6982a726957a89d90bb151a368e62770720d3efbee", + "b5b36dd84b352cddf715246d0463984b9d7894f50b566a20042c4d485df41946", + "592e1bd733a1095b9e5b770021769090df0c001260803fce9a9b761ba697a5e7", + "dd2fdbd6932d8b56d6ff91db3ed28f282a6ca01588ee5a552d061da215580411", + "82f95ef71d4d0b32e3f0cef89e6e90a8c271cd5536b38c507fc69b354ab51062", + "1800903b2d5f8483a12f0b98a5b35ed39d6cf8f4a52f495395f1816d6e3c139c", + "121a2c2ea70a6986af8bde71b7f75ac9f9e1189eeb9756395e7281702f01936d", + "8578df7e8ec4b068f64dca679310894afec095dbbedbefef5944c3a319809b8b", + "5cebde1dbb352ff62841d7c50c3c45cd0fd1b7b3ebe884a7cf29cef6686695ab", + "362f7a73f2620ea061586b5edbee01f9c026ae6e0d95131c570c44933fc41f10", + "3a19b5976236d44a3d1d6920b348fcef9ec830aac56aa672353c711471ebc36a", + "842c43c5293b03811165f1ff7e04c189ccd355fe08d37808a843a0995541c075", + "0ab1fdbf7117c88aed3f882d5f7dee8964c9246030086b9ee3e2ebed4eb2c731", + "7cf8ca4463d4bd500cc12623ac9d3984cc48e7fbb98bebb4a498c2fd66d54cde", + "631676f3369eb479686256cef33c4fb061c212cc215ab442d8f7837c039ddacc", + "2fff6de5386b65efe6062cc2242b692a1e811a083612ab79fa7f7517f1488767", + "3c7d8b7f2a56e22ade186a70a3039b4d4e4e3c0be6e661770b0a7b2ef18b178b", + "e030882188281a754c00706f621084f96869bf95bb5d005ccc7b2649fbfc747e", + "072cb899c3eb621240792a39bf727bf59398329748317d5ca1addfd8ee2f7e92", + "37cfa6b7214e99bbec6323802115b9615b10851ac85cdc26f213b9532fdefcb8", + "68b14b71ad6b5e2d41ef47fe1b9229a0b8297ede0812d1b9cb95aac185d1a5b8", + "652ef549580cf412bb217fb15b2a0a1db8feb3c79969b95364a80dd97d565f09", + "dd3504b7563a65115a050505bc88ee23a50e37c354773cac329355c16c43d839", + "6d7f05d6ee71459d2ea982f7a5cd4a251d7466d4892e6c8b6aaf45eec66472d7", + "14c28adbf9008d0cbcc978006b6c1ec7be51a134bd5587e94ee33844b62c1ffb", + "f9c20067f16feaaf3f8daa8456dd9334725ebdc8b49b4f74f5a02c38ef5f2804", + "e2c537948a01054b7a0d630952c2ddd395a3a265d618e22ee9d99d4597f82322", + "70e3a71945fee29350b5b10a8ee8dcbd19c2f734e22407bb6b50ec3acb1035a5", + "effbced848df72cd467b1ada7353b1ddc0b7f3f08190c0f2fc747f18303ed9f8", + "02d6eedc5abc295bcfbd4c30a8fa3406c8256d8e51f4714800b4aecb795a976b", + "92134c6158993a0390af92565e166418561c9b157989d02304b68c2ee1babe14", + "6065e3e3aff3e2b2f33bf4af9256e9368b8a303335b0587c8cc9e31cb9db42bd", + "732fd2ba9efabc6d79bd7404c1c6f1d5c1f14c9bfe02ee1320621824847935c2", + "209f9c958b5f4813b32205a44d05c83aa1009cb7b9c7343f0ca3717ae069defc", + "1d274fcb65b6d4c846e95030c37851a97d161f926ed88f6c4dec4ed7007fc23b", + "1d3787106cf47e1e9d08761a6c6f427ef6c07d4a571f23d340ae2d31d34b1d8e", + "5697a3f56a0a2a6bd6991ba05559df9b526d5c42e19604c398548a7cb0dec0b5", + "8c0f581f38238215f10f8017e3d234cbda9d94ca017bbd6b076ac8666014b3d3", + "78f061b0fc912fbbeb0d207b92528ad78ded55ec145c8f18133991847fb9cbe9", + "1e3555081a869f3aafa3d74d6b5afa942baace60869ecd4cd33635f84602b715", + "4f0e36ac0c4813db3fdf79d85ef0db89150dc1be2c879ba06299c049288ab8be", + "6b048c38924b7a1f970cdff081124b739202b703db5c17bafa4ad23a5bcb97e9", + "a5f5e9238aec20bd706262f64671ca2d05961f55ca383953d489edf857e4b2a4", + "a047b08e2af7ae5bfb9e54f98051ff7cd5e7dc88a25afacdd9a324526cd33c63", + "66ae2b9513a0e0ad125001bcd5f3a36e18b4ec009db4020ea4afc4951cb39a34", + "621d8269c8f93b6336f8b7480516d2191cfb15a1d9501463771d0fb70c1afa33", + "76b94079066bff52a077ba1d1ba8cdec4d6484d1ce2f7454b2b04aa3d9cf52ed", + "33c6a108f9d4fe054c085991d89d2a5c32b8f108c95b0e688c5763424c283e54", + "52575ed2ad84295a070a99e7785ff0e4dd32a93d3830be7f7c2811804f3df2f3", + "158dfe014c271c148b38459ef16b49cc3b5c6bdfe052795a6f6a6aacbb3e47b4", + "d471729cb231deeb2f1a67f91962ecfcb9e8c66f66b6b79fe1117d34ae86a7c0", + "e086b1a09ab5307d953e25366b1acf7c41047a926aa6a4d122c5a34e3e0d93d4", + "d541d825401a1734d9961fdb4f0e9ce7af220c6929648e0aa2e885cd28696343", + "a555af7a52ac07e681c247f1d6597f8240d28e76036bbf3b2be1f7cfab90dfd6", + "8598fe7a4a6c6fa865c0ca8e8e65c96301c80965e19e48f5d4ca29ac073551c7", + "70c9ac61ab3508a7419ead73503d8fe51b4ecba73a55d4b167cd4db6c9b0cb8a", + "e594eb83b38ad916176abff3f0ec16d7a814a461012c8f9bc8286274af3f1856", + "fa4e0df6df82f21050394fc2caaa8a8713b131d0d1f7d21eb92b56796095bf17", + "891711c535579b555105e5ec18ea0f2f610c6fe5126ff0f6a4257e99a24033c5", + "f192c9b2c49dab7515d405052f825abead30ef9a870ba3bdad98c1d6256be461", + "70c22f6ceb81744c83eb8dae69980f4583c75431457dbb14f5ecd6c9fae3e63d", + "7d563f44bdfcb2a10ee053f4c05b8d46fa90d44822775f97ee8cfbdeda7a4ca1", + "c09b3df69eaa232a9119e2fb805cdccacb658b2fb9c7f3a2106c8399aa928033", + "15b4b3d50fef72de80fef6e3351dae0f203902e4c4db8ce8d8737b67aed9104d", + "c9b7718633714b3ce1b489f13e53fc647be53cba7703f07a35a8815245b23ff3", + "2d344af9852fc2451ca5d2ed7155e074efd2c53ca9cbed7f48c74658967aeca6", + "c8b778b5c1fc378365d8b342915215117c3d365e12f61f3ccefbe4091879e373", + "1deb076e44c029027c1aa10000305c3eded5d401a036c21a4dd3d3455c0c33a1", + "d2d2dfe410cefbae2309e746690818e8d52dcd80ebd192cddaa00204b6833d05", + "d18a0a0bcc678908ff00b236296f0a955a9aa52a802ee4175849d0bcb3d6738a", + "7af51e08357e455e4dda86d60da75899b5ffce4bebc7f96037d1e404b1260ebe", + "65b930580f9738e1a7af2ac56faad5bdc6a417e75cb872b7f62513f4e8e36b33", + "71c8e88c7c478a4d919d0c80d351331102584d032d82aa25510801e18bb5d6b9", + "2166bad16a6e4a1f77a22b0fb13f7f11d618a123c3c077dbf1ed1504ed68cbb4", + "717a3a5903c2b12aea8be15599ea9864259a964c0139125e649fefbec763890e", + "0d042f5767f6cb2f94526b5b6da8ef986e4a5927eb5f734bdeb6c6ec3bb8211a", + "bb67d586774ae9f3653c609dbdd98f216315b54c0ce24ad9e359d0c2c21614a3", + "945b2962ec44c54ea25e3e35e32a2362c130fc3a9495b16871e8a2eadbe457e7", + "7d5324e5e158c82388cba0d497530c6de0c1ba97131688931c03dbfc60ca7541", + "21805a8f8d43aede3e927b80ef04924d388e96f3cc3947a0dbc1bd1b812539f0", + "27ec492fde5fc3d3784359d9a270b735c1820bc4a6f15ac87797d97de047a6b5", + "4fda2f855ab08a8d4dcba1874402e1662315c872e3ad55681fc4d6c5a89665a3", + "b0dc69204deaa17ac4e0f197f8b23211418b5d54f5bac55414445a66c57fd6f2", + "209262521ab45331639a57523f2e3bbf8250052b84fba81c50c990166a6f58b6", + "b02857949ebddecc58aaba80b9d635ae95cf71f4bfc5ea8fbe05fc55d4c73e96", + "5194133163b28182a261ce0473b1f3ab991a53a08d0e813d3bfb533cfaf1255b", + "c56fe98848fe79124ae1ee09d1b214ee87da51c1440134210c67fe15bf6d1bb0", + "851d949ac91f439ec84f07c481598728ca93acf79cb6505bd77ef776559275f1", + "eeccaf0cd29cb002e2140cffa9fe2c08c53ffd73b99167f4b5e6ab5c94481066", + "821f1058ae54732723937c5ae535cdc0a9ce673eec7fc02bd03c240c93aff24c", + "de836fd21ce91d4a6add661f5d259d0ade4e0ff927d03f67ab5d0b24bff37242", + "fdac0470c61d81d1498e4e0c6fc4ca5ccd02f727413e33c84478ebe844feba13", + "469b4f5af2b2377dc09e5824af17c57f1dd8fbe02294059e16641c1307eff125", + "b77348b40d52d531378dead61cf2eb6fafb4c89f85285a98cd4b6032c0e30a16", + "2cf9616aefee83eddb2df0dda1a3331185f0b772c3a8a62ea3ffbb325290f32b", + "2d23a9035ec627187108b9d13b24134d69ad7cb6f77d2c3ab939db17cc6f129c", + "4925a7008584e04fa769661dd9eb766fe2ea3b66622691249142ca155423f368", + "69090019b3c1635da9d9e4661f55863cb3ab561bcedf2632360745e62b06afc5", + "5cecb744c3e65889c22e14a58e42bb69d068c721f1c547c8c704fbc688c6c6e2", + "2f7371ba97f17c64c4c487742f83755ab61aeb1ee537bcd5f16beb4440d0233a", + "9d1e3dcad79b153296a67238771b91a92c430432a9cc9f7b2ad7667fd67b4de3", + "e9a34ca0067dbb6dbba48e736e1d32337cca5e93f2b76229fafef501979d84ae", + "4d5d36724a2baa0d73657a140493a9ba95e1de95cad74c9753eaad785ac18cbd", + "d135fe3d44b6b0875c1662ecfe33556be0f1b39bc8279dc8730d5e9e351f36ae", + "1fb8439b54ead68f72b7ba4fcaa5041f38d313d92826b57dbda299dab06ab716", + "b96e8d59a7c1006f15b0ac10cd35c08a8008e0c2ecba26d87db3f08c0f6fc991", + "73300dd04c53d270420023957c50410147ea4a2814085d3b98ef25d8d44afeed", + "6941323a74081c1ee28846c4ffe3b4023b29eb3a3b64d0d2dea0f47349fc2138", + "f7cebcfc608a982a3e11b3941abf482d8108a7d59c3719279563788173a2cc6c", + "b76c687ff464c50b58e4231379c5105470264de2826574e8d7fc58d6889d0753", + "f0148c800120bd34159684196bdfb34f08d1af93c74232dd9f59e2ca0a66aed4", + "51e0334c027b5e43e7cd557e301bceb0189903a189dadec2a11c1e2d675e3e9c", + "32a3f110862c9340106f2dbba85c8af5d7ed575635d55cf2af7637a59c83103d", + "b35bc38a430ebd8c7584d0c90bdaaa15aa252b3977fcac456646e839746f9c0a", + "87ea74b899c0b929e83bf31a8d146faea3d26140ea99a3d0d3e0be93a4d6eeb4", + "e222ed1dfcf6505fad77b9cf2e3e38d0ea86fe89a969b88e729ebdf2e6c63f0e", + "d5e92da54ae3432603ea96cd770f4da442f7dcbd0a4f2d82774a33675690297e", + "01e372d5dee08beefd03317d0897d5ef1c5126bbfe00c8967ec9aa05523c5e25", + "369df1d577f66ea1c93b58b770783a74606907713b14ad86b316319d94f84ac7", + "ef7e648860a8b3490440f2a8d541a268b4613f4a94c0dbf685df5973b55f0e88", + "f19f4b29d4d7b70abc4624c01a4ef7ab772bd4feae8cb33bb502f30a11dab29f", + "8ccbea64791275ea047a3648b092ed281acfa21f62a4b50ed111b954e534a697", + "d60a6b4846f218a8369db8deb45972760a1df33c7532d0ef1ae679ba0294216e", + "7aa4638be336fb77bc1ac5dfcd3f5ae002aeed8c42bb46475f718e3c278f0097", + "06a82a57d7951a5629a1153240f6b1f09c150f0b9b777d7c64a0a628e24a0bdc", + "d23d2ce73e24b434f2fe5a6eef2b88eaed4e57848cf357055da6914bb234851d", + "0dfbe791dfc86570004538c64195a7702e33ed121490fee5819537676a021932", + "8e2a510bc84d4600f25812994dfd5b4566c281a153e459cc9460c006ababd093", + "cf73a8cdabecf4323a194f3249cb5b1674037f779c747690eb0d9c9f703f7c8c", + "a8999928014db24e80a27cfb572eacf902b50cdac259b5be80229fe73260ce08", + "f2a13b90ffda09f999ca5d7f9a2cd171ac33ee2a9a889c70a2e2d454dee0ddeb", + "a5fa0377e644e743a38f0b427adefab90d218ba8e9e2894fc1f1f71cd815a92d", + "1a27dc6f452362eca3745218915d24726b72f5d6963a9c41a34b9b7a12aeedda", + "74657a8b361a7d235d94878cf2ac2cf3e18dbd76fa1a88440e3be7ac7a8dc54a", + "15059499248e579d66827fb6700d3c31ab3c1e824fd0b0de583668631f31abe1", + "21dab269f60f67bbce69447b7fec674662bbfe2bf1fb998e164d44e92086a89a", + "a266bfdd44a5969f46985337359fe5ebb6083b8a21cf310ebdf4a62aa16dcb89", + "612ebf41822f25ab638867c1232596a83de60c5bc1a62aea81464cd87c50a53e", + "7c7e8506946118e3af1f5c36f94fc5cddb945e6346a009d21934ea0a384778ac", + "82cc3dcfa10188e9cee8d84a60ab86cef7b564208734ebe8d1c6f4fd583e5466", + "7ec2dce8c901de5c5b5da218d4ca6c304c4a8691568631b1d9d625deab025e8a", + "baf8884aec756bba04cafe11f82e84d5721bc66689a59418e24dba0471e5ed9c", + "2033109b98dec88046390619d056fba7ab1e207591b049b5ca4e5ca7905a0736", + "04337d0bc9948530c0f6bd541442a14cb8da9342cbaae84ffd21f49a3a4ff9b5", + "95a390c9ff01592aefaab09d6409dd618263bd596d5134e024d2e04fc080f9d2", + "c314b11e8ab0957c8c11770b6dd3bf9ba8a281c312f0c25d0dbdb0dab2bf6176", + "9372c5731f8e38ca30845e277b499e77dd3f5fa442f5496c4bdde0512de1e922", + "84ff2e4e6c23f0953aec51c9d8642b1d71c653731d7585fdf021e045ebaa0c11", + "c4472b40a9ec2b01de30d79bafcff2cd4853edb77724a5ae02f4387597deaf53", + "de59785aaed498deb953dc239d06847baed05797fe3dd2420a5c6f35a4ddaa1b", + "9622558b5b744223868445c32fd92ff2ba0d9c56f5b34bbf9de7f3e26206a277", + "80887a104ef050b442514ff8292132f050bfda9b640a840c3258f01893e75f42", + "cbfb1b0ad1df2f84e6ddfa190362225f9306eb62a9f5541cc5deb5da781fa213", + "b01734822f1598f9edceacfe3d828203c629313c7ea0f51111f6b10474e070f9", + "a12cab7ec7e781e90a49f837e6efab253d896dab615aba3f6327b264df5b91be", + "ff54a2a3cae5ac505347c5577e010f713411b5401bff7491cebc18b34592683c", + "99529fea4b50b9b8bd91aee8f8a25cf88dd3612ede12610acb24e73a1fda35ae", + "679c55a753495d26c5ff8ee7e9dd2f6329fe76bc3bba1324f27ff5f3ecb7f8c5", + "c805e4ae5d2358af561cce2ab0ae13a83b68a80886fd11ce5e8200b0194a0085", + "5fbec47c66e62ecc3c483c440f0e39711f414dcc8c0ad72b17325bedb8bce577", + "c8e43b97b4aae188ac288e16f856f16e839e67ee149d8bc8f8bb6aa05a186704", + "ff4748fce9a654b3876905aef033f19030938880da461ae9e05bfe84698658ff", + "c6e39da9593ab92827ce0e81d29fd85003d110bb2e85d530769eaeb0b3fcb122", + "0a1cd405a53aeeb8c03e69eda64aca2dc6df3d599c41551e0e71067c2c3299d2", + "41a3b0883541b8e28e321b9cf326c99f07fe0bf8354e080539511dc27d382728", + "47f3ee76ee3a53b8b6c84de48dbfe40d4487c0f1e024be7ad735b4cb01b240e3", + "4605541e0a8b64ebfb694d092456455e366312df0fdb6edb975d5df6738d5f64", + "f140f701e73403c39925a8ec3bf6fc033df1de9c5d013a0b866b71808f77c3b2", + "0a9f71c5ea3656600032d72147b1fb795f1ec515eb0c0e9b142a51b63ccdd236", + "773a797fa4bb49ec882c2c972b71e509bcc094b89083340df1ebdd64a68f6045", + "bd004ac4dc73dd5304e33abe88de5b3889f233d1b27327b14814f2941f47131e", + "5c2b636057904e70179efc5366acf56b238780b1bd50d5733f3cfd06e4a894f8", + "30cd462a2b16211e365728808b2dea5591fdae5f8e7f816300440e255839d9aa", + "388cd1a37c37a2e7fc75da6363e894618c7e011f6db275cf64011312f3d377ed", + "f88beb132412107250f73babe32b820fe6b277b2cf21035bb4c36e7b60a9585a", + "c38eb4323358d7ae5f9aa8d459dee525427a9a490650246a2e8104d1346599dd", + "212947c08a738977407b769756f1f4d192eca956b07413bb3f702402aeff1307", + "c6bb090f1ea6e4350d6e71cba3c096adca356ce16d997f48dd081eaeeac50267", + "2da0a61f2510fe2fbafb40b27ba5aa8d0fac8254d7d69e475fdff6f3777b4d6a", + "785fc19dee1f3e84307dc836550f5ace30b672460267751e6fcd5e33ac46c296", + "370020c80d7e1f3f53566b5f51931a1297fa1a4efdc81ccf7c5ab72e2577ae40", + "259bc6129f4c136073173a83e0d5d5954203beb997ce140d8f69d7b950e0187c", + "11cb148948a9c92a2c962f6f2da0bc9a024ce63c12e62aab3f0693847c23ad0e", + "a09df031dc5d362e71b730b91a0e84677353406309aa06fce96f83eb77671b4c", + "046bd72f9bedc26c0ffa2bb7bb9679b7b1afc7c9cc72a0de2da2fd9e9f08837e", + "9ee8b7df8898711a797fd8816a32c181e641ae77f9d04f69fbccdcf5916cb668", + "98813c8870bd227cb607e97a296195e673829e66f6c18434e852f36719fe823e", + "5ff5c13d156c6c20c0018848eb761cc24a1739b1a2964e279e1841d587ce3441", + "11caa777f57c824055e6cfec2281deeccea4cc6a9a0cd971ec1b9ea7de49cbca", + "3a8e126522f84bb01239c8d1c51bada77fb0e3e76d51ca82245cbed04dcb7739", + "860a27fef1b6b537a6be688753599f84f29a2600f462bddb5180f0575cf10bf7", + "0bfb8295a95da4b08f084135ce5b221f4e5ea4cb7e63d96410e1b0161f0eb5ec", + "684b917015396fe12a0b84845c805f3e07534070e1a0410bd6319f40704fe392", + "5809b9f126cc43329050dec45c6ec7215c588ae85a0647a23816a73e2eee7e8b", + "21ce0014bae97d4599230abcf322b031d49fee0f48e578f173b317478f0098a2", + "79192c7dec85ace4a9cbb6daa82e76105d10e988ffabf1050a0b27e1eddc706b", + "9a4545f77055b0320345d7f147adae0552191e0b77ba53fcd82749b5ef45e334", + "e154afdc575fcfec7acc74e634eb767a87354b7e4c9277d6218174919f21fd7e", + "12c94ad4e5fccd6a8a24229298b1aee2efa0f231fb209aaa4581a5ae970e4636", + "cd089347c67b34ab0d80db569233b6f42792d9fbb08eddb769c5d2c06c03b78f", + "c95de3ac861cb2435096b17b6a6e96880331ccfe730b15fb14771ce6414fbf36", + "b355cc801fd8712315d0247517eb2ff1ffcf90ce66e786f66c0b70b05c3aac13", + "ead6b1e3c8ce5380567394714a8d3e71b739a128872a4310fd52ccc0cd015bca", + "b2aa10099a3d806f3b5fefc4cf5aade2c91e518a93a03eff4b4bfed37aa98bc1", + "ba727d2be80bdb3b47b860b7588a46ac93984db5de47ee999ad946aedc411a3b", + "5de5016468e7f8b981bd5f1b04b270eb7c5ba3665481b9f2215607137c5d6ecb", + "44a38331d4f01c48fd89cb306be7d40910f61e85c01efa64be56007e168eb704", + "876407f1f2289e2212c3f09fbdddd40e4d99331e618fe1fe76e54c0007146cca", + "3c12bc0d8d061735b0b03371c4869f9ebb423eb84ba6a80bdddf863601287190", + "35426258f74c650aac3cacfe5294871a989306eec1f93c85f34648d3e1e64b57", + "24b0f6118578f557278af2deaea6bcff73b7c1fc2c034f0529b804b5a3667f7c", + "a853095e6abb3da36dab40eba98107044c9bd706a59569c27df4956af6a2867a", + "7bc75c278a522c3f2fe32b83c4e5ac1f002b970424ea9534ecb70519e2ffe1f5", + "968a9fabed55c4ffe4df25e7aa61da56e67bb39f407d6c138d8949f0ebd2d654", + "c01b876bfce242254ed98ebe8999d5bce9d6aa8a0afcd643f192c9c58ba05697", + "0f25ddf33af868397a40586b9b29c759b5f48c5d5ecffd65c8025eae40cd455c", + "9b2aa176b8978b1a6ed7c1a7ea238fa59414085797fcc91a2f0bcd4ba2a56b17", + "454807437182e5bd112654fa4dd079fa0ec3d701f61075d1671c6300e77cc3a2", + "dfb43a5c2c31241a80a316403612fc16007a8bb04652eb3316bbcf1a0f8783ef", + "f0c2b72b9e3f3e0dda04e2c94ad826890cb8fa891b519b63a1646fb00690772b", + "8fc8c2fb737c13eee55751ce1dc798fa291d428858e1cd862eabd89507dd0f65", + "a84481a8966b29dcade6a3e58692ad8868a0b729eeeffa1e25cfc95f7b3912db", + "91c8e0ebbee601828719aa29d7664b5d94e3501f3778999c60a975ea74bb00f8", + "86862070933c5b4cbe7d1b29e15c728766079109dada7f51ab02b03796ffea61", + "2aca32ca5da86a14878e221dd132cf11e9f858a1694eb66c29cd245ed49a81c4", + "621a41b83f8e9299fa89f2f5245ccbe34ddf352e1270c6ef094161708f86edcf", + "23984583b0ab9321f11a5c054ca891c1b5940ca0ee0174a701ed91d8f7c52d33", + "69dc06a85efe0e51884bb0e8215d50ea2d2cd59ff9708079e90434bb2412b217", + "96bd0d2f1ff8360f4846e79d20a31b6eab3705f52fd737741bda0568e629acd0", + "7df4dd373b3fac18a0ec775c111b47f96484f3270a6d5d9b1455d4337c031b62", + "65b585500d0e4f021bf4f625c7f48bfb02d32e9e532ec9cbc0c264247f9c9446", + "28e2b11230c728131c2312f86434b934b1e34e985c1601fa17740b7820775fc1", + "f1eec6722e3a8a3626a3b9cb45ce9c80fd08bb7e71c38d7b637aa986c6206273", + "cd5c00f5aa138760efd51fabfba83c0964c47eaa2e54f95b952b437ed66a5a80", + "16557e57e3b29f120e52c5d9c08f07f93340bc79910a29953df8a4fcda6b745e", + "683fca73c707ae662b516a2c0e2793e6a764b990af2f2ce8c3151ea75e9379af", + "b77d4a94dbc5ce109210288aa0cd3edc83f671ae9a9172495e705ea902ba90e7", + "5506fe1e6126cabdbfdeb4cb59bf30bf21edc868046b263d692345649b3fd6c2", + "e94b83fb44f81d60f82a9844edb2559563ffc876bc584f4fc4e11049237ac60e", + "395cc58f6dc01018cd334bf6ac29b8f5ec3385ec325470b408bc2e8d9af11755", + "3463442e45c1c1df952e9760f91b99ea8a0fb604b203c27f03a955fea0381ceb", + "41f4c041586f3e7468fa44de1ea745e3d41b9942dc19cf35b5565978449a78dd", + "31b31a285469f516015a5045dd8434642b2f55f19373b9e0d5530e843deeccf7", + "943b282f0be57bc8c9b5ad4f47aadfc0a439af58522a4495b7cb36e0ad43a6ca", + "f1d7d6d9dc97dd43e3b76bc13c6973e31572fa1792335ce0387ca171236838b5", + "01cc0fadd0cbb9e8aaa0dd49291e39f3f325030943c8041178738bfb662a716a", + "d96ec821e29cbeeb8b9f25f7123c8d5d708159daf8acd12e7a800c72521a4efa", + "b5395de909f1cade846176880210f4a560ccd3180f8b70d2d4bf15325f196ddb", + "e447d8ecd54443d4674c84cc84763a18b9161c76399eadaa82dd74cf31535064", + "8f47c23e998213388a6abc7d3b5754336bd0eacf4eb545b0825abade1ae48feb", + "b2b553a0af737c3912207071469517222d3d3704c7c45bed01f3cae1b50c54d4", + "ebd2711b2330377b5d7fd2f39a720b896a7eef7d7f0ac2a1d0739002a1511a00", + "d62a3142e4c4a2c87e8014012b804805dfa6f7d5da1a270f7c3401479a3b2f51", + "0142c36fee839b588918bdadaf8c737f91d61b920dfc581e05335f6f2cbc3310", + "e729c42028460ee33d01a15c2e369048bb79f8ddfd70a22dccd43b1c58d41933", + "6fd227ca8a63cd5aae1cb590c6d3baccc3518306e22db68095de25f0ccb4b49f", + "80ece14b164adb418170ba9feaa4d352cfc6cb1e31e47b3239163d2cdb54eaf8", + "04205ac29beea2aad32008fe47c9acc02e3ebc9f66c16db685c8f0976f3562aa", + "071d3e6a4659c37fec52601fe99ccb4d2a2480f3a4a7bcd16f12ff21fe84a666", + "57f2fce9dc52bccdec3de4763a02e3700d13953003190d560a8ab306b81c1221", + "076c6ea3b84d7f2535d034e5371378e9345dee62947ffe4de3185d02a2152340", + "0e386ca6f2161a1c64a4072ce7a507e1131edbd90446723d84a41dcddaed4324", + "48042f945a825bc8cea4e8fef1da5c85b252054137adb5e123dbefbcc189db93", + "410d27dddbea610ff9c4e6354b187fe8a2f7c5b19c5563e2a1bca1a4b4b8c6f1", + "453ce5c10b3de7a4fd1b0bd5f96512d05fba41117299d588a4740585fc295590", + "677e34874e3dde27ba4a987778de7b1a64b6c63051f3cfc774ebd4c3fc605b7a", + "c9bfc40e1be4befc1b44e38b471167667f6b12457d5c82662ef3a0a0e9f66e2e", + "4cd169e13f4aca41b158924d9f1b972aa4d167d6d9c116e7094a7a06d96e6387", + "aad5a84ac08dcbcd06b4fd5a0c5d2c1af8eb0d6568f17b3d8cc47d064b72a3de", + "4d495f70907d93c7c1142990927f1a3d59e3218a34db881714250ea6e9aea84b", + "8c43d66f0d23b88c17d19aa01c64ab1d2af7c43704952326129b0dab4453cfcc", + "c12581dc707a3a6da47886aca1c2aabb5babcc0e0fb21808c27c6d5a939841db", + "2c63aef84a0c812b53e37656cc6d5e8f64f8e4f8552e4e502dbb1aa0319e13c1", + "86886a41f2639a791085b6a2be4f2ac4f76d951880eff5cafc722785ab4d64f7", + "73bb646c6363f96e1ecc19f5ddf7df417327b9089c1b70a867f799af03cb3d66", + "ebe518fccbdf53bfed56fd1f8f3b114b5849a8fb6e14ad7bf3f2a2baf29775c2", + "db82684a4b314c554fa6139c4c7ede0245f68b32a885c819efee12ab0c027414", + "5a985ff0be58aa5a46a0f4122cb70c7ebb937f7802a33a32d8262e63b3771796", + "938ffa6e22fccdc71d6ca1544cece54518b9fb75cac5736a0468420cb9f504b3", + "4726ef072888e9d5ad65342790b285c7ff024d60b084c32377eae6faf67db536", + "57292f406904048855148e3dc04cdb08ce05a58f174867de688b252e448096f0", + "ef8e25e005dda6d6cac7947006e1f688c743efacb7633c34ebbed7f87707a3d7", + "b90e5ada245515dc90c2fec028ce8359708a610927c3f9cb92bd93eff2fb59de", + "32ded7b174c9528307b8042692bd00480d31db9683c9476a4f50085aa6810893", + "532a40b49048d2695ab6ce15572377ea0befb57bf6311e5bc89a3b579561837f", + "587782fd3913fdd01f9f475f25e0704ab834d89fac46a0be1d88e54de6b50701", + "b91389a5cf8a1c10e890ee4c740fe9994d48e999b59a2c6320397a389ec7a316", + "6e737036b6c0c9d72a72c8545cc835d4cf7da70c5ea33f6c6003fb844565354f", + "2f239f75caba3909f2b6f059a782c2624a71b591a7e132ef72b4add3c9c2d738", + "95d4dd64bcc89d80efe84c9fb5d4a17ac7115d1b38a0ac0262e7687905eb1c4f", + "4487d612260e1a6c676d2967cedd84cc5adee2ac845ab2900aa193a1b86fade2", + "97edff35d1872b6a95f43606f084de35aef0292cd411541243bf7336a905a938", + "9001c5d627af968d68f12200662585921aab14619935c8be4775c457e2a40867", + "ba959223c1636c7b0d10b43b78c1821e7af6f6aee1f80337c555a470867c5ad8", + "9f8b4937db8172a5e01b31310cb3b74824910f9c52c356c17035d70173794089", + "1750c07b09dfc52f0cb0f09f4560095db135127cab4c511c525f560c42025abd", + "a51ee98093bf11eb0455cf106b3a4e027135e870e3e5fb212c42d62e190f153f", + "35501a82a47804cf7718d6bd2e4bb6fd67d7639984eade0c1232bc2c74588343", + "9c3192c2435a9cf815b717ecbc6c539cac03c7f582dbda889b39485895f3e174", + "ddf04cdfd5366d08b5886ef736dbf547a403f583cdd7c089f9f3c4239e554210", + "2675b30bcda3da6a2cb6837e614ada858c1bddbd42e6c3963eb220c290fbf967", + "dbd9134ad3f09406a76eba91323ab3ad2a4fc0bff4975b2cc480bd4403ac7560", + "2929520c43b14ce24a94bf56870520ddfe4d29bbcba0d0e1c4624292d8719832", + "f71513cd36ec057435881587013b2fea181cb57df1cd9798e9b4bc2b0457e778", + "b83971a9cbba7903239a1d2a5907351c61028b952d4dd207dd49f6fcc9abc13c", + "c3b7e679bd4d0dab1a2e7938b0d5cd8c28200c5da9534bda97ea0f1ea81c4aaf", + "77ccaeb09a35c5a1df5bece681062f6ce9fea08bbc2c2075ae235946e8e1d9d4", + "51001f07d1462cd9312b077be915dfd5225b85c3ba760e2a414275aba5fee655", + "ab0f6f8f5e58803093fff168c38de2710c2aff8b47661eaa3ae2a337c0e71ecf", + "96e9ce518bea74432b7aa4c857b2e2423a4b3f48275fc4b48f87caec87800b87", + "60c0b7a0ccbe7792b9332ad6072636d9790ff736e2d83a12f50e7dfec65a2680", + "38175abae6191a78d957e3c63121036688cb6b8c46d42d026551ad37a6aeccb1", + "48d82a8ce43a65f567584bfe7fb28cf8c84bc725c73413b8768d2e6688ae77f9", + "18621d94f2733bf9289e0353f066c53d95ef8dde449b2e160e28232caf17df74", + "e86c65449e6b871ac6886526107b8d7bfaca468ef270172576bd9f39fd208aad", + "c32bde208f9087259fab6b053db25b1b136b38276942e2420482855a5d7ad17a", + "dfb55a5293f934d40ff7c0a6749aad57806e571df185f592044e69e680e995a2", + "8c2a1c5eea4c8dad313bbc6beae0c4d94828fcb2a4877b19761e75c74fc10164", + "eed8a70bc0d94fdd32629373b50eb9ef830282b42dcb1d8b96fdb9b8a1797df9", + "2c4735a60cfae0273c4f309be579a51c6ebbed0200715a826048b1ee568d4934", + "f7e56418539529401d0780879ad1266aee0f0354da07486ceab82011a069deef", + "aca86fb3d7d9fb64e920ee5ddccfa78227a0a3a3e40bb3b275f114186e488c78", + "bd4b2c02f07305164010353383415b08f570fbf3fb297df74a38d6f6e3ae99ab", + "589908e264b0c91b1358f1a51f020daf473b7e4d5faf493b3625782866b476ff", + "70360b520b95938174c5b0c2400da3b047743e60d837bf567767732d748e991a", + "a54ed87456ed361b714da5c56fae7c4cfd92f8ac4a6e8e901a565241a39569dc", + "9df7afdf237605066f98cf95611f49f5c5f383a080c86dc3753390c5627efca1", + "6281424793e144590ddb68a85972c45272a5ca39227f9d24d0bfe78e2bb82580", + "13657e27b82c768942fab407deeb645ecfd958f506a6e02c95d119620cac86ec", + "cc67906e35cda000740c83f50b24b92bd04c58f2a0c45580e9a134c284580804", + "44e92cefa2c869560d185d18baafa780bf16f148d1a7ea186f05597b18783606", + "8ae261dd18679d8e203e7b4c8dd241a51634a84f83855b559f7ba55728d9c9de", + "0269bb4c3079709fb80f3aa451a895b639e3b7db83360a14f078f26816979dae", + "2faf079e75b3e9e0298fb15ef8c6d53715cba427c8c551e98d44a3c46a67414e", + "745a15e40bf06483cf58188b9c7df99e796754dc4bf3eb0547b11fd8016c5c66", + "70dbd06038f269ead55d560b7f960d24c7cb3a9c8864fe68c0daebf315cfcc9e", + "1dda0994af0142dc5f71646735ed3bbdb4f6eb40955836db16fc7524eff22ed7", + "492af127ff75fa55f94ed919386917778ed9c51e4cd193b75d82524c186a1b5d", + "5031aec77ba13f73b21e5cf92708f44c0edfd1081c89b4630a0ee3a50b91794b", + "859b7197bd1a5d6b8dbca9d6c96321e706708cba23866d44bf3f014deba6a4bf", + "3108f998d14696b3e945569ca9b47346b26f8a3700cdd444f545fd0a03968891", + "b7cde7af47f0df23419ccba57da19a5ff7645fa160e136d43c827f41b460decc", + "18cb7236904f9784d611eb67b53daa31efac1a8a9a7d2ff47dc34255ba276a57", + "1670703aaef6d8c722bdacacc31a80dcbac0326dcee64becba1339bcf630e330", + "6ae67bdc91167c7efd005be6881b58d24abde9f8c3a71e6aecdb8e6738f3d169", + "3efdadf9ad79dd00eeee1d80e40a8297254f249a9dde4b4d94b656d58338fc5f", + "d14ad9887a66067658afeb25a64866bf90debccb49cb8213184b807e9f1284aa", + "7f2bb055f5dd834bedc5ba9d63b3c83322e4325de7866b2af7ff8692bb2b52ec", + "729e0ab27d04bf1c14dc28c42ea56cd7fc1a8207ef207ac34e676577fc32006e", + "3aea585e172df036a10a0a3c26ebf4705972eb3efb5b61602231b8a2b2942b19", + "a3b01753e934a16eea44aed4a756b7582aa1b469ac462ccfe4c92268705591b4", + "d5af668caeda6f6af27a778359ce9196ba091cc04d9f9b3928f8f5203fc3fc88", + "a6319eb545257cd4c849e2cca4c6faabea9490eafa3723434800331f222b86fb", + "a4f001d05640267e07caac4cad7122771451f3f997caee435965cbd19e64a621", + "f852577eacf926a5db6921da93b4a78f00f57e06fc064ac02633976e35d9e00a", + "c48da9db46193fcda552476b8c08fe35a73ff1bc1950a41f3b1ec098d2f75a47", + "7b26f8d832edc5d6c025be9189216766b58ab27f59e7b253d0ece4d28f51e2d8", + "cc5b9121f74988f1bafbe4ebdb7296d2255a4af6f01f6967c7391568c32377ce", + "29fe88933391cedc886475d8aa7b68415a7f3e80e153d8837cacbaec3f47d8c1", + "392cf2ab942625fad754d738f33732d3172f4213a8606368330f72373ec99c64", + "b9ca5c8d1d64334e586ba1f0303d3fe802a03eca9c2aa12d2f57e79836d0b64a", + "c47d0f78a14f36ea4a9d1fdca74596a88f93dd9a0e746d97c91a79762420390e", + "74a1f274dda992663e03a2a10f29c84d41e2e202bf56e658c1a42ebed46db202", + "dfa9dcc132701d8b1f4332e2a6bc7faae3c7cf11ac0909a83c4c7e30fcbe7dcb", + "35d4395190d570f8288d255533eca2fd7bb13e720d6e8f5a7113094f97538c5f", + "70a16244e7480d092b617242786deee67056d07cb15365fe51d0e8ab1e8932a1", + "a26843f48f4f2a218b8f5b219147641ca236a1abd96905d8534350e570b164e2", + "5d9eed350175b4d1217b25e671c2f3c9868c8732b6dfa80e62e4a9bc7010dcf6", + "72db3913aa066e04662cc170f3363578fa47799b64561d3b9e84598b43ee8c26", + "e406db4deb9cc79c8eb7d658c382c2291668d7917d73c652c415f37a3f713b0f", + "a0faece933213756d22239d1a066c1730fe58b3e815df52c2de1fca102b03caf", + "9d6bc10478d9345260c53c40de93ccd7b1f344dc25e6e4cc8199e1ed9c6dc824", + "ff1a79b9d954943147a0b29d67ce6fcae1f9f8d5476c2b8eaf78ac575f95247c", + "ba31c30e4a28d5ad22a364042b7155e5f4ee008929f22eceb3fb7371d0c1c2a0", + "797bb553ef79e09eb1aa5400a889bcaa513583662c3708614e29b202cfc3b80d", + "3df07ae6890b2c332556c247ee91abf341c5dce226e38df09f7010b1c21615f6", + "30de2051725d9f0fc371cfa55aaded73b12e0668b1624775b657ae0f41ed8daf", + "035e448afdafd5069a783abcd6e268a82f43a52d9ea805c1141d329557d2029f", + "1cd59a8ac8c61f8f97cfcd1e43d633f41f0b3b3782e3deb3d0a9d80942b52077", + "b1bd938d8288167f4a985abf342f977cfd1c2f1da70c6037c9bdc4295a705726", + "418297a2f0c0e5c3d6b2c4d80824e1a909a61fce6c18bc937720eecb1ce3682f", + "06031df90b06aa84d58da9de78808f7b2cd7d563f41dbed683e74bcd7884720d", + "28961517d508b8e963f98272dcbe636af5f99e6fbf436d14b9b64273b17857a0", + "bac113e3e3572e90dad38b0c2b32deb78f9027e59b75db03d0fb86c49c2d6d9d", + "26a5e2f817b0596d95c8a82cbbfeec6971da2247ce1cfa52bc5098ebdfd3c084", + "ba7bae49a577e15e14568cec5f779c4700c8ecbd21bc8cfbd3aa56eb0948dd27", + "90bdd504836627c40d4c14d54da1b3dc5cf5b6b1cacfe2e220d1aa44850f6fba", + "02f1553ab9b4f4486fbee6f5735ffe0d9b305feae9a120df2ea311fde4cc6076", + "2a9ec46cca5184106d4df225de39422136c6cc995fb9d124bdd640ea45667a13", + "28a25bb686696fcfcdeed1a996ff4f8956dd4c41587d599eb78a83ab6b1358c8", + "422bb78c5107f8f0a5e1a253347a72894704cc4d8d1f60a49a49f8c5dbaaf298", + "74f3c43fcc95c26354129e18241a1e747c78975c4bfbb0b90a2b67c117dd85b5", + "8c0f5a2aeb81ef4e5805c1070bfb8667ae185b59705c3cab2aac50363327daed", + "87deb9c6b62b237a5f83b7333776baeebb4eaf804ef78b9ca2c62ab92388a697", + "42897cf080c2e405a77fd501360a7a86d0a1cb7d573f5fb07e094bb13a942f03", + "0d3b80df67851ee640b906d761fd95ad7e47d0186cdcddc59a10a22e011816ed", + "dd222577e63a176e688a09834ba7dfbc7d25af9cecda7b130e48a25fec558e2c", + "f6f7bd7315404bee4a9611e69fe5d3387de5e4577ac28267d04d69946f42f18c", + "03cce690c88d34689a3fa66b6f8c9da75747ed568e63fb20715def88e7228b38", + "d9a4eced4646f53c7840f817b4296b5bf16e7b3d5e906953b6302d7b8a848dd9", + "319741447aa9b6c819cab13368125a52f3c35d264249d5b4068d2f379010f4d6", + "0a0f3eab30a538a23ac52e4f251d383d418bccc96d5975446e093cb424e8c247", + "550942f02799dc998561d8695fdafc4554c5a89f12333403cfd7c4c9cb15bbec", + "1b0d7536d6774149b4ed8db577268f176e4c1f76e88c9f956d51577d7349cfa6", + "5d27bef5a988fb678c4e178b4b1063c4151c5d3780c1dff1ec2ca898f8f8cb5a", + "6bb4b71ce2a72c465e83586c39a2c1d2f77a47ecfca14b45af365a4ec29448ca", + "938e0c409a837260a9fc27ad5878f3b8936ca0e6219ecd3f9bd4bef6c402acd2", + "d8aea1404c3d5fca7289e2512982bda873437b43e7b8b2a912f383340f821c8f", + "1f4cd386950035ca3cec81cba5d6a506620863056da90c7dc9a5afe47d0d9dd1", + "dac066c881d458341c7db30fde7d9197e498ee577bb4f0e0e48fb859f3790143", + "09381cdc27896ab6c73c341673a61927099eaf2d300d3e00ea37ea6cecb262b8", + "65f65598a48e7b2e38efa51d454ef1f26be016c6a70181e26bf35921998671ea", + "98d991cab4e708f9281d1f56b1a507026a114ab0733ec2dd572bbeaa22fa4887", + "1c2a4e2bf0dc9a09e511baff42c297b321cb8da45c18ec50e4c39ca2465d7cd5", + "327c7a6d05d522536e61aa1fbe8fa19f781f915e20a66a647ea90abed8879fb4", + "cb46cc08d32b5bc7ae9480f30884c7670b8e8694d66d5438e5f8fe81785dcd1c", + "537fa4c41690903a48b7a632249144f154c5dc4686f51868df0159a0350a4ea5", + "75a5e4322582d7e240de8e8b0ab9ad73b7e283428537338b41b35107dd63ea2c", + "1f87054001c06863b66f55b3a897ac0d76f361908900b30e1d8ffa46742bfd16", + "22197f4735d51aa39ef48c88c4d60818245fca73b98df8b9669dc434c6ac8796", + "a2e14dc37362b89a5b85c57b3b48169adb2e6dd5360b8030de7a0e028a6db3b2", + "676f7706eb7a57397f6c9f69de04cb037d3a1045281b8ad8390244b9afc7a2d1", + "8defc187fb1f0d7bfea657619f9a020f303f0cede255b473d18817b500b94b75", + "be1166434669922a764541789705f9d86af0587241cf3da9e33a7983d048177b", + "c5adb9840c2cba41c6e49f9e97c3b78d8d0a1c4af88929e89af205f75f61cebe", + "a83b4a5b3282ab0a2dfa4b1620dd0e3ecefd89cd43fcee45a1a6e4760453e9a8", + "ae2117b3fadabe7e3d94153da7e68c6d7b371efc20373aa8e1d9326ed9a3b369", + "a0b5970a81570a1b2b4d058b32ba5f207273765be398986490ed5e9109d07863", + "9ea221fe02ecd3c974957ec24796afb677672fd1ca770a13ec9c3a94135ef06c", + "a8316aa74116d533973b74f528dac5bc257a3e9cfdeae39db7d8d32f38085f4e", + "efc5250bdfe42346a1d032ef4c7189cfeaf303af28a12b3be074daeea810b171", + "9aa7194fdc5f39e9ea59a13d04158913df4c87ed385b32a37f216c17abfc69c1", + "a17f4cce7a3aa86d9bd5d51f3c38f235fcc4b086a746030af939997d05e54fe5", + "98b049494b468b0c6cdb3cf382283110668d919005678e4e8a5550a892ce133b", + "1ff264905c3f040c3fcaa107b7df3c38ec0dc7d59ddf9ff8780d6aff0381da57", + "ef6077b9e143f01f8b500e2eb6b6ff02043ec00befeb78ee44db5f00d037bbf9", + "ca1af382997fd751c70fa1fea1cdee6ee1d2a22246463ed7867d56e57619aaa5", + "be8045324dcbd46d31a1b24be314d5f0ed7bd1d1ca67bf71ba5cc43043d5c9e3", + "70455e4b87d4b01585564a77a6a414a53338c05a984de6dcd14d7126306e22af", + "5bb2bfe0be18cf76e3f70ab3c6ef2816dd988074d43389a3c4479703d1a61041", + "3c95b917d6409a12360186d7c8839b33d6fb9a7f66f2e0e3a887601927d14043", + "0259cb83d1129316ee620361341d083c43690ae542e5fec01f887acaf2fb04b9", + "9aa9b67c720b3b2fe3eff8732fdc359ab15ed4fe1092e289fc27b7e55a9c5b50", + "1151155d7be1017544c0c2b7432ea1f67cf3191baee64771e9364f3bd1da3708", + "9c45b3560ce8419825ae84affed5223683fcccfd6e35247d1c03f4b988e8f48d", + "a3242aa0a01b82c6d5faf748c22a616b950ecd30ef0f72685aa5860f9320761c", + "0f07485d78018a506a69021080b41861f801ddad09666090e53fff3bff0cfa92", + "e819c861150099438a5ef2613bbc8e4c854cb8410521e9699fe90500a9127443", + "4e78cd42978462aaedb993b6a49a5ba1315519db360522a26add6a17c8adac8e", + "b21ef6dd5976ca60b6e335e78e479a655409da184e68c10e0b4010ff9d208c64", + "e8bd4c3f3e0a8345ae5b2b5748060b15ef0c7529fc3eff080bec1a9a77584592", + "3c8d2c54c7d5d826498d730a289d36f903720b7e2ce1f699ccfa152999b5a0fe", + "fb6e025eec367e2bf4b44af67ea674d767b77397d0568528e7fe3aa7574ae730", + "9236e92010421a2c1674eb0a8044ac2b215b605c0b94b903f3a2872d0fabd344", + "9ea25f2f9472292aba590e298fc5ff15c4cb22608b2f0f2ce1bf26e148920007", + "d4d18a3b2db8540a7bf72e0cb14b176919f995e70f0df607489d5adeedb0a932", + "e6f6e272b36731484782bcd4844087cf45678a05d8b84819f9d41f5376f0f8ca", + "5088a2b878336dd33c3a7c55c09aa70bfb1d34815f031d4b3e92402c7633b400", + "3d12743c540c798ec2587301a3fb2b4f0f6e1278e4bb15280c247272ffed0651", + "52c17f712792472ca80df50f7b9f96f51a6eb155c872ba9ef460aa6d4e10fe39", + "b97f17e90b9fc70044f8789379639e52f97707eac2863a35e9a19376555f52dc", + "19701f39368b26bd3c71a2f0630b5e89586f7249431843eb6c890045f7789280", + "49ea123cea990f6fb2029e8cbc9ff7ba7e049c32db1f6519306ab980d74d0d38", + "fd574068f0c0df88faf7b54341a310446c0ec94931bc459748e11c58435d6ea4", + "fdd6cc2c790b22471f03a32b906635b4028debfd691a0a57f847e15061a2904c", + "b7a173017905bf55dfe03c1640a4e808dd6a1d6bdaeb27722a7c839766b8465e", + "74b799aae53dafe2131b183068d8cf5fa8f2a3006c9bb9944aa493c7491b94cc", + "cef9c06a87ada326bb03e6a301f53fe5fe6d68df015b4d72f1965581545c7fd8", + "db390feffd9cdd7f8a34acafa77d80889a820c9275095e84b439ff5f05781ceb", + "57e17c1b71a226c7bf02687565e92689e5c966f5c864e64d9a621bb6757f4f2f", + "b8c8dc2624b8aa73874647bb89be2765fda8223fa7055796a59c7f4d1918e8ff", + "08a2553e3004a255c9a4135930bd9f8724423747135c0dfe45747285549e4ea2", + "4d4966d172bd8c367d828eb8a14f853999df1394fda96fdcdf5e41d70725ba21", + "23888052d915017c4b47b5307d25158fd13daa02bef1d4a2c11bfef79a851470", + "52a97f2b532139784f4a6a6250b2e61a3989a2c94534c2434041aefa13af2871", + "73c82b469fce6ce8b6b2828441bd31b66784b0994e57b82d331be9e03cdccca8", + "cdbb2bec43b864ec0d7caf5def1222c3cbe20c79d97c7642350dab42b5d1af3e", + "e047c075c048467400806f61489cc503dfcdffc73d4b9b6bfa470427f95127f2", + "82de0f386c63555542e8a34ece6dd42f2a4671d437e00aca7da175e7d18bbc85", + "fee469874ca3fb72f0871a24f410284c04311446f4c5f04480d7b3ceb4e78efa", + "830d8aa08ae29fa0941efc576cb59975d035139cc27213d0a04a0153e45207d4", + "f444da313f6e7bd9e27396f9a95129c83977e1462f86e7a9b5addb1a7ff30580", + "fa601478a412743bdf29bcf44ecd5fdedc09792c8e469a7399bc17c64e134585", + "cec5ef97aa6a39f3c146c5e3f955bc9028798591d4e38094f38f70e981566d58", + "6bbf46cb35bc96854a8fae0e20935f2ed32ab5a940e7891fa7f268d28ce5d549", + "955d9741503c2e5244f513e2c2430bf814201a2d7dc74e2e5c9c9aeed401ebc5", + "9f2e6590991e25b4fbcacbee5bf7381092cfcd7d4f3e258bf4b41b84102fc179", + "647c657c3c930537bc13047cf886869f5a0699fc52496ab30c997e5fea1b3dbd", + "9802afd3ddb4d5067fd0db7ead8c66ffb3ad1c29391ce56321c4b8f34174eeb5", + "60f782f178f30f3d9321017b2c6591f25a82f957ef1c704c6901fe2fc92ed76f", + "109992589b06b8eeba15fc2f6104140fec043b2031c8df3e9025fb094978ddaf", + "091adb2a123d0cbeae7dd399a39f4ca4a3b68086410e6c7aef0526bb2ad2fb82", + "64143c36d10d8d0659f9431dcf30cec804f4487452d5376639157354bb7ee637", + "9602ec038d85b2cc617dbdbbff0a3293ec62048f70b16a6b38702e26b99074a6", + "1c6b6508f0f0c772137ed1a53cb559fb1aa4b3690f6e1f6fd3ddbe5b74da7676", + "a4df5d4c393b255674bfd64aea4ae82da5175732d39591fa671a233004d2d0bf", + "928a67d956422b29189df8c6e88e345ed2cfc8ac941d06f15a7c24cf30bc5296", + "79abadbacc8e8bcf8930e8295dbf6626e3c2c71b8c4c6883318dd1c72e03ecba", + "ddfc0d445cc013734947279fdf7c6f0d474a622da65db4ab1c0c9cea7f60d0fd", + "61ce62f67c3526d4183f74ef0d457216c7ba9913c9a0243944c972cac6dbf42c", + "9cbe363f9bc69639efc73b9bc02264e29f7d0f8ea3b1f35ba16640a5767c5db2", + "d7a25bfdc1e8bfba013bbcdc8afe41d81511e15cece155e9be7bf1ce81af27c3", + "93f9632756d3b0d8bc72c4718dffaac5ef81630d6bd79364b7bbcc9ffbc302d5", + "2311829f9842404d9cc2243dd149bdb26d210031ea78dfb066e90381a392e641", + "cd08a8a153ded8be5d705390e3bf53cb56d7b8c20e0e08c39adb3689a68b9602", + "8d310a900176ade581ad42108605cc6bf867f21cc115e6abbf2a5e083c2bbae5", + "43c5cb40e94874eb80ec26b7df732cea255453f511992fd61ddbf4de739f3b35", + "a2a9abf1c835b824a9d311105a4c92b3d6ca8eb2761b45da7241f5879d05bcab", + "ec48aab645d64498938781156b6daffadc0ec9f3556b7e995c8dbd63299c3121", + "05f6c84dd8ff3468d8992d9dfcb4e31597f7a378828cc0108320c009ef16ceaf", + "d4d39f9d3724cad98bf1466577b79c4dcdca104ecb489e877fa8f44adb1b2ba2", + "b23a123b0bb6c11060658fd14786dd345ad2a2c699e4fdc7c8de79b1eba41fc1", + "f27d04707f4b1110ffd978f8610b2f094ac0f24c1dc819b59b70e1f64cd86a99", + "42895aa8dc4c0ca50b98c7157fbaafa53fc3d8a5221b660dc86837eed7e6d319", + "ea9f13a6e1cbe9c308bf85b50ddc729abe112c46d74b50ef53d0bd7ece84121d", + "e8d250858b5de70d138213342a6765948419b81b8e8ed65b3763b20ddf009fdf", + "827b1279e3ea50b1b7aeda4a7969cdf18bed45fa018e552190e8341d2b8be2a1", + "3584a32e4fa98cc72c35e0050fc00f46462b7286e9d6ad675c340a8d1e56fed2", + "196435304b5e92922c3453ad9f31a8d1b2821634ee6a29c07543b05eafd7b061", + "a86b7271d28b011a2749b302fcdbbf712f89d9f3efa24b9a169e97e67a57e594", + "d40ed1342bca6c536e736f1fa15aa5f5a01274b4208ac4690a4f8c293dd40b0c", + "513256a2ae5c50af825420724fadd88aa0a77d93f64e1425f768f33bc56bf862", + "83381a3fb9ec95f2fccc410ae48e0581ee4f492881cd0c20c90cf19823ffca7e", + "0d51b0210f527afde630887455f5d231425f8a8aab5d8567e5ccd49441f5effb", + "c584a68f8f6a5d8841d9b51fa9cff1a3aee73b1b4f8c8f378843c79ba5ce5902", + "b5396ef2974c2a1040b8e8ff023a82ed4ddbff2b69e5569249d139ec01dafaef", + "e52c0b2f5da5c4c5f68f4c1b7e3dc81e9572bcb6299d3386d54bf881c43dcec4", + "ba60878ab1ffd5e5b85d843ba049d669ec4d0094330147c3942a62f0394c32e5", + "e412b797b242a5619823b6b33008f45bb0b11bac0ff365b4f8c73c9f3fe6e590", + "50933f5388c97812aff9aa52db014d71556383c63c6b1b7ce294195c8efcb540", + "643ee4638b7d9c626522f9178bce2a53a875453252c46ee3ed4d524ad2710a4e", + "e72b8739dbff60185cfe3da8783fd9af56b7da9974610428a11adaf5c433b2c7", + "48c3cb8b5c7a90728fbc104f8b191a98119f8a2777c00f8c1000244013745527", + "34845f23b0bcf4e5e7fac5f82c059cd08d9bd7cabb11edbd62fdf1b40df95758", + "33bcac68cb4ae201b3d3fd356c62feac888ea3f7e0f59ff0dfa2fef97f1eb558", + "778d833969b28ccda7711e0f6e37345fa598ac1a9fd1c6a497dcfbb0d2a9d590", + "5fca36d19c656d347e71c9ca43df0d701852d9811b758d63b3ae6522dd4c0b68", + "74f0e0b61425240202486eb26a74e53bdf8460203352f1c1adf698be9c01dda5", + "d2b4e304a065b74641f42966a43398a96e85c14cb209ff06d18e6fdd8a30e1bd", + "df6401c07b51c72f6ea2654aa3069fb6bf0d8a3adbf00d926d534400d88733b0", + "3850acc410d21b19110d9f229c63d67e36e2484915693f21569b627b0f3395bb", + "6143ef6a8f8edfb6b40ad2314c0f9595fbed1f55fac3b8abbacd72f691da7780", + "b14ae396d6da8ee43a3eaf5e9a06333ce6515cbf1819bb5283d73a68cd39d2c2", + "2ccb1721e1ed7add382cf8838f7cd82106232c7b0bb7fbbc5f36291936fc8f52", + "cbde7da6d0dbf518da6923c7d82749def1260eb6632f03a7e3eaa62cb3a4eecf", + "9a9df0550f1629c3cc3c539ec83ca7e815ab8c9319ceb91f42b6b9dfc3384ede", + "f48737960c6bfd1b4631cd39048b55cad33bd0fa925a8ae094456466e16b7791", + "2514869fcc6ff50736da7f509dcc55cfe8372f82beb46529d757c0ad98fca10e", + "b21124fa2ab9868f3e7375cebd5cf95a48d0d62ed6fb62ef0e0f08f7337bb212", + "84835fd51e9bd4624f4b6feaf2387bf3652f0b03efd56cde086079f86bcf9cc2", + "868492cf4941bc0fd0ca8c37a30008fabf58e56bb3b41f7bd91e09b43914618d", + "00a8ba1a607be27447cfd6f60447a22ff6e603e347eaad21604bf56cfd3b1434", + "e50a1c9ab7655b55cda75ff82bc1d28ea48cc7fd292e5f7c72e0f48acee712de", + "249df64d683697b530c6013692fba966655c6d4e38ba40fd05a282f60570ee67", + "1e66d4f9bf24724b6ebeeba7f2ccce22cc039cba53b7e7fa76723f1dbb934e34", + "db6767231847109ee8ae86b459f0303e08e2fcf5b4165faf7edc33c66909735a", + "406ee377180093d25cc204105aaa3030473ab112f209ae1dd608ebe115a3f95b", + "0763bf2c13cdd4525a95f123d5a42ddcc9b3aad27c90dfac1f19fe2cc643f636", + "3cb4c58f6597a2e937c8bcc870bbef98fe4a2ef16089c94a0afcd0ecbbca140b", + "1a448036689115f5ad50e0587d114cd77901f23a07070b4d18ae816256d8811e", + "4bc718cc25242feeced0c3f07c5459d30e5ecd91011237dd869a2b1d32c390b9", + "127d4282b45be11fe780f20db6c1737192912449c0ba6b44ac499d9fcf546a48", + "2882d864f8aadec1babadf7ea312ca3774fd0202a4702779415a7296501e5828", + "2c1a8fb6d739f4ebfd01044c2ca11b484de6933d33c6d120c5bf36475ab7b457", + "d4224f53e199e315ffba0bb317dcf7743d764642d93770e8f6eff12506df888a", + "b8d8b26045f477d58aa21e5bd835883ae1a7bf47e416032080750e80ea7b008a", + "fad3f5f3c9d29a2165efdd3e33f0aae9e58365b379f0ac61f41ff8912f7e9281", + "c05aa5280e7bb5dc66265a8862932aeb268162c25ac2be8fca44949f94ec1ee7", + "af2c85d7085cbd5ff2760f744d22e1e5be0bb8db8817deaa14c06ba9e4cdf516", + "00305a938c19feb580e7945aaf55f217d5089185176561c5896d3643551c1aa9", + "8ac01d950862d0598424e3488ede8e9a285dd068c1d401759ecfa3c97f9bdc85", + "33f3b9159541a44f2198e6e7bff59160bb52f81c35c9f80433992edb5ed0a340", + "31244c0e5b1f7c934f92aefaab2e06b0c2b88c98576777d3e5c514a6b8ba97ad", + "72ed3556b3a25c229bb436b6bf809173540368bcc434c74548373c043f4f8602", + "00947670a458adcae6c83f223cc0b2b05cc1debeed514ea4011044ce375c8eab", + "123376bfe0702b06b98915e38ad3c8d3d8d270f2c81db595922c298d980a7991", + "b9ea637bee6f3f3bee40fb76dd375b6419fcce5fbab8523785d04b1c4956570f", + "601b25e3e686fcc9c3470bdbf4fd2af9d008ea1858cef028180e3f62df0fca7b", + "6d5a1265a95ee04afd7df5c9aee4341f31de35b9e87f2fc9e02d2fd7e0d5fa2d", + "77bef4f6fde9b94b5397e63d1690c6bcd553ca53b58c2bfcdf92726590246317", + "27f110882479c6cf64c0bb38d121e389d5ff17db4b216597c75151b78b24b2be", + "3d1d9cc9b494b22ab1df806d7b1e9745d132dd6d72ba4726f55af9210f3df4b7", + "84d60c1d787bc5d15a952183acad447856c0501c2bd5809145f8d8582c97decf", + "b79fa13459e7f875488cf30ccd2f0431cbe8dffc671880c10cd72d7e2be7e8cd", + "061c36fb310210ab07b22f39178b7f451d5142a395ececa1ec783af9c52b730b", + "fa16976c19becae31248c8477ff0e746c4e28ddcea5ee36408c05be86a142471", + "82235891577986898debf0cc0bab31fa765e925d01a27c27ec694103320d82a3", + "39989431d3ac81a61b0311181d499018fb4cddfb74b1afe4a9260b5841135989", + "a846acdc0cf349a8d2b352d3dfa8784893f5038c05277d327341d3ef7de41bce", + "f3cd88ff101e9dcaa9e05998db425b590dc45dadfcd8b8a6bc0ac7e932372055", + "a159443648d0796956f92ec4efc5aa44af0cc2fb7ba97de7e6a8e0dd16638530", + "9e381ca3bd9488a656e965de17a44487f8c0da8896ebf9c0af4c0146ce034951", + "4cfafb85f2faa88a88034c4e04b7a37be20eff7e02d3e21bdb79d5aa7de833df", + "eeae101eeff05cb6a0dee3bd70b7999858b898b8c0cc7fa96a5e9235d1377381", + "786ad41ea86eda551d0bfd3e702622e118b21e619c604772befe546e55d4cedc", + "2c2f151ad2b9d7bb8f52dc4b060d194bcc63848754d0d2983def1eb992f194dc", + "530b5035473e95e2bf117e3ba2d88d6de1e648f8672baa0c9dcb83e80ef47580", + "b34801289f8a80277b7d5fdb602ed3df305d9e915138761eb20cdd42b338509f", + "eff8301ccf9032fb1398c62896f8502a564889242c9cce7cfddf1b9b87dc9189", + "1babe594d5c84b3e67237b6abcf14b9a091368c587958eccedd4ab0367601a6f", + "b2e8b56a474d41acb1a53646d825bec845cb12c7b96dff588d6d1051136dae11", + "7b400ad7fa14af9182259b51e810e16029c947f2509fb129ebe111fdd977af3a", + "842d63a701a80a9799357ac704f2288ab62af3a62d476fd740c0f8f5c35a46b6", + "dd146653c3aabc3747df891c3a6685d24e9cfe4d61e52f5c7fc7df6f079d59ee", + "2564c5ffb78c4c132cf8c6dc06591661f2d7ee12004af6ec078af8aca04b42aa", + "8c01eb1dcc1e13892a782e9826288711f28ca7c716bb9756e49b41c8d9946694", + "f68743f290c5002b746d912702c1084cee82bdd3c323200dc0710381d98a41c1", + "292a6383fd16ec5afa4cffbf7a6fcc8c6553d4cbd2574886f623b00bf12b1e4b", + "4980e074baa3623551a56263d46933f5fca5465615467ea914fcf6e389e5eb6b", + "4cf461bc4b7f8e1104cb225bae1f3be5dc70ea47a3879257d6652b42ee302a6c", + "79f626c481d62c454a9a8e5d008141befb190c0f4e78c0f9796cdfd8b490c2d0", + "8b4ab8a45964bdb5ab237c0e014c840e224ab1ef50cf2afe79f8810613de8c9d", + "6daef9ecc84a1d29833c0edbfd38663b0e5b76f6ae1d5a22cb081984be8a1ba1", + "7cf7620117fda4ba2e7e1392a39c2c0467e3b90ef96ab021f90708e46df97e94", + "44f6020ce6f1831ef60cb293f456a5ed770aa92b1837fb571ecbf00963e77249", + "b53bc8f19e29660d7c2c9622fc080eb3839eee4b601df47eb3ac20aff8ef8343", + "114f8884785cb1ea54087bf3d19418129fbac44f8c496677778714743e678c72", + "640e38abc942b35d60027a7ca1671ef96da9dbda8d3aac61917189e0f1613a1f", + "23bc1dfe86d5be148155bcb7aea39b8cb68a887a07c7159a8832d7fa8af8d449", + "8ad3f2e44ac576c4a9c364fe497b840bae3a5673a29e69f0806208499332a001", + "ba11731e009801147b11770a0822e2f1e6cab3923726ed79efb3ed5675289c05", + "409e700d67c2541afa301f2c09a4a98de150ff30662f25dcce0bec82da44a1bb", + "74aebd9823146c25c615aff0cac7a2a7b43a3678fd4acdba428bc874c2de2351", + "1ab29e97945c3ead550846ae8af77e6f02d77d24fa8d6af4a866c45568055be2", + "729944aa7565a697548f162e0ec9f39a634fec17615a4b1b65c7b68d06da8ec7", + "dbff2d93d089c5fc366cb89c702f99022ccc53ceb39418e2a9921b1f9d895c95", + "170f0177e2fd6e2ad5e96bf1c7d5fe8443f824ca80c51cb19fe985020bac4dc6", + "44321c4c2e53ab3faa16443e0dd56d0bb18ad444224c09a686285528c04333fd", + "2af9827f953129f8eec520d1409be4d9747fe2213e877ccb06a82e9bfae761bb", + "65831a1f6d27ecf91d452140be9219d010695af0fcb2ef3f19764a4f6b3e07f9", + "103f4a32f26764273b7ab1abed25b768e7994a6bcfe4c029d2eb5a30c4e506ed", + "545d4fd5dcc11f7c29a6ba552562cf4d23890761c76ff86d6940dc707368a0ad", + "4ff9f091da95e9e8892bbe017a8fe29a05955c5c62992a78e23d3bfa4b3c7d15", + "8e82f5c6062204966bfff0f299b26b5921358e22e0880a5130004280c418827f", + "1a6df2e84c39918881ec151d620cc74007c0d122020f6c501dcaff8822f46891", + "01ff674c4dc5d40f0a53318e4a210f418dd2e504077f80e640360db4d2470be0", + "fb4b597769166e58a3b28a698f18ad0bd4c1e24d6c0e3cf58cb800b131f4fea5", + "dbef3658df7ce530752ca69e5248cbf2832c1c458f0b85918f2a4f3666d7b301", + "9b651ab03463dbfb3e7dff410e758430fe535d409805506018bb3f9ba98d726f", + "0795034bae75b616aa3d94df004f4b80717c593aae42e0eeea2bda508fd091c6", + "52d8998c0c3ea0a42e6271a43660f24f17e6201dcbe28a4e1374dd20758327b9", + "a04159ad9cdb943b39160af9eba203f3aeff9bbfd933843bf6cc32f40bbc1f54", + "cf250507d4d9f066221a2c5ce190da42e2c8e9afce5a539f09305af5074b759f", + "5fca2bf5cbda4284eb2a9aa26b55f54d43e28d0efb97e429482a11b66cbc7f8f", + "a740d86574c321a0d3ffec5124431c9a2e52882f85520f296bdb230778e74201", + "5543633ba06069b459f10a9174dff488575830c86bd32c1da6724847791ea055", + "8cb684f24f0a95ad5f4376aa8f0d9bdda6e413bf04a3c8821a547fdf46dd1938", + "b167590ad1040def2161bb854d08fc62b8e4ff4a2d60376c1692c87cb2008e7b", + "a00f55c70f539a98a23b51888c892f2b5a9b86328ec99cd56a11f0e5d8d4d49c", + "73dc98bc6b3862a513320e0e4cd61f5021b30170a2d054abbb62e87036f4ea08", + "ac0f7cc6fbc94a64b50565a929ed6aebd4c6c36000dd40b4f826052b60e98103", + "e24d3edf80ad414a6e5ffca904a259c6a28f1058c0488a524908d1ca8a2faa26", + "38d020a513200b0a6d7bad5fe1e87e39efc7f80b940698ba23a78bbe2cde0fda", + "ffb2bdb644990f4751b4795b94784b5e3c00a5d40afa2b110822eb7dd0cf2d63", + "40a6543d5faecc7fd797d8aaf091d5e4ddf5f075e7f4798b36b6ff2669afbfca", + "07ee87b5c221a21104881b0a6255c2354abfeca80be635803a387a3ef9032f3b", + "d3fe1eefcaa0d03434e6759f8b48fc50f4223edec547c94bf072d49427e2f418", + "0ce4d7ed2eb07f798588df1df044d9e124604f0178ca8941e189854daf64f26c", + "4e5657ffdeb3b88cee74452cd24a8d78ea33013f600d0a6e97c56eef47c36819", + "8e5a2d6f8b4d0878a438d7b33ed8bb7c32294968f71ebf45ab51ba45bc3836e3", + "0f81dcd7f649bbfdd0db6fc69ae5f5a7d89b99388e7d20312705ba07d16a4ab8", + "1cc3486005fa6151d957d0cb6e2599df2680055949b81d4dab85562622ded07d", + "78c8021936527768d5cd7e1dcc30ce55ab13ceb6a1209996a829e3cff8e7239d", + "ab1747694e6e07051b6739e3df2916e09d7cd8a135753c9136a8dbba0449e83a", + "25d6f0d435679e7d84147da65006a48a5a0f893ed2e956518bbcd6b98f40d368", + "3554c7682f565a20b336c40129b5f7182239f2b0b1169f39f8421f25b9ad52cd", + "51b263e67a4421f6b858eb3cafe303af0b3339e0b0509eb068fe3092d394f530", + "2bdcbc0df01dbdab2c91c4658bb9b160fe3efbb5dfecdd85ab525dc21033d90a", + "aa0105f9628907cdeebaa743c45a458553942c3e089d64a02bdcaef293581337", + "d4636ae50f908fb11cfa1f338314260f587f26c29c86cd682e5003fccb554efa", + "31ae9547640c8ebad28019e8eb66cf608074d5c1a95aefa065db97da4c1e1044", + "a228c94293d05874a00c3aa46ee128a41d10405c28e5bed3f7e7f548243fafd2", + "a7d5f3e4630be48f88cfe45147b94b9010718e55d6eaae6462a41aac52e866c3", + "56d4a383be9efe8694a572a143649be7bf89b1eb12842438162532827f7bf101", + "79f7177cf2655951fe0fe7c98cd1cca252e7eafc0b81066aab0841f7cd7895f5", + "abc1746768383ad59c647846b13dbdf51d50f9a5f2c50fac9f676531ed6d08a6", + "a1ad8a55e14acf37cd4eb5085405b62a53948065dcd3bbf299477d03b1d8cc6f", + "c731487e9086642d4e92ecbada3dc31b72049583d446d65bda3a09b4370cafdb", + "729c914190c753c6ab1f648ed04889baba5adc43e05102587672a7a0051b279d", + "3fcbf09cd64d4070062dd2eaf9ff595d3e1fefaea6996ab134e9f394e0814f56", + "2efc8bdc74b41138f0075e2603ec227f7265d3eb6e7ca16a7e1696aa83cc3635", + "cf05b470683e4090959a5e6222aabb1026d60907f9df98256ed0dc62103eff79", + "cae8a98b1c421ba34af46610134a71153d525636c02cccad8e0362b7109d7410", + "cbf00526ae885899747bad4c395b9f2c02e62bbf39fcee82565fecb1224bc311", + "b6ddac871381353848dbb438f0b7ef14fca4eb39fbda7b4eb1747ea454b3155a", + "375b66c16668308f1e768c09bc2dbb0def9dd04d2f90c42c49453f558220a338", + "a2387da7be7ec4a0ce7ef03cb1bd701330e5e950be120854efac13d903367248", + "21f4efbd857d838626a5b6eb935c1d8dc3a0a6c8defd23928c8018c4956663c1", + "ac96b176999b37719fe3a67231b811a7a435ee7b5e807fd1430803a29cab70ff", + "9c06f32a7f016a0e702b928f7de9a82297498400654109ec3a17a1c2531a36d0", + "fa932de504e54776e5b8fe75a2aa7067cff79865b766882542608eb31de1f3af", + "d994c1c85ab3611ad12fbbd4ee7e7afb30ff9ce3c67ca619d9786553b0383668", + "2e5789ccd625cf20f42a72de7cdc246ab92a1cd85ee619570549a8effa476ff9", + "ec4145c429fecc6b5109d5a4e1434c4418925fc65f53bda6cd06620dbd2d1b69", + "0978239a7a14bb768e1ca71e1d40e37a102091ad01a75f5f92c5da900761c79d", + "3382546aefe321d644bd3626c7b767bbf940df0cebfd3917c05f69c7973136cc", + "227e8c8045928af96e794585a87d6869c3ced7dab3689c5565cec54e168641a9", + "c0a3f1b8c27d0234fc64fd8d1ff9f6d3ca157b03033e505bd443f1b7bba62f7e", + "2e848b33465df0fa0a2b75d23c4df4f02824f431e78e80c0221ff5aa61348a91", + "14656b6da232af334beffd02ffb86992637993ce4aa530acf8bbc2081c5dd2eb", + "1697567eea595c835310638672cc7ff2067a568198731128280bf4167b2e45ee", + "749a784a544085ed3fe56e3ce9643d0e13aab8f3480f2fdfe7c16e15ef08d0b3", + "0b2b27579b615e086959fb35f7741791615e25c611f8ab7851c83bdfeda7d7c9", + "e444de3a6fc90b1d2626987fe98c956c1e0db2008cdbe6d863ad410e9fe0a8a3", + "89a757ea85e9d24b3e584538cded1e5db3a90bb01066af609d3401d1bb5b205f", + "b00b5a1ccbc1ec142c5ef063daa88aaac1d3e52af12256cd892803aa348c3f30", + "0ea22dee4f62ac35e5b45a3beeff82c8c32231193bcc33ba7575916dacbdebde", + "5c428762fa847e9a97fce0f306c7f0d8c4b4abdf9defcb0df0dafec41590ebb8", + "8eacd0d7d08645ad8366807a5cc9f91a4b22fd52ab4d8c74efaeb9fba398f24d", + "648ed141936c9497702be348e260b9a4aa9ff5dadc6b654381c9e54160a07f4b", + "682cc4ae34101c80a98fe4a674ef0b16d11ce70b56b3a7fc5b191b360deeaecd", + "2b82b8fa930e14bcc38f1b9bf6a99f3987b32c7e74363d20acf6bd05057cfb5e", + "1d2c04136aa4ce34040a9756ba9f16af6a3fad26b7a9669a62c3563d66a4d4a5", + "04ab01586e7e4615656127d95cd558e318457ed1641c2229b75ed676f21ae1d5", + "a7a5c84706284a3c98121e35e89e3361c39ab8b5ce26c3e479cdb4c2f30aaea9", + "d12b3299cd334b9899ce855a088577d8d757dc32125921f2ee561daa94814b7b", + "48714a6b92c6e98e3406ee38539721a3ba60254ace52c741925222955a89a8bb", + "27597f719f1a11522733a0db69462fd7d28f0a64d6cb508af5dbfee291b52f81", + "44c2fc25551c204419d798aafacde9e75b4aed663d47c0cca8c5c3482b7660ac", + "9cfc7a76eafe717ecd56501bc16aa644bac189cab58dbb90bbb0cf3a4e3053ef", + "029223d300c7186ab0c823474f67590a86e7d08a9d1ed39588307def876ad59b", + "533054cb85955768daaedd98ccd79495e4726b2e5e7d345a3cc70beb19538a57", + "60e7f410dd3c32e1c88638ca4e758db9a2a8f7e52e2faee358fdbf5dd3fce27e", + "3ed8f47b67c5cc36b0e6745a29251d0470795cb14f0ad9b30170c0e5c8efcbe6", + "1f889c28d68e869bf711e214dbe739acc35780e8b19ef9576dede8e2e91bdb9d", + "dbf00c8bd10f5ae12f38c625c8af8089cd28ff92f34a1d949dbdc20d7a80d797", + "960ef9daa1b246bb656aed819cbe898dc14ca8e558070c9468f840487c05db92", + "fe1b43ac2709550840c682ecc23d2699e9b3fcf55851999d9f09b02370aad502", + "9f58ad99bdc049a7cc29f7bc482629302d56b32ba3b4a703223945c8a61f4254", + "af61383d241fa4cee95f8065527537a237914d9b1494ac8fd3ed476a604882af", + "503e10b0bd880beb400e91fce69c4fc9f36e3c816ae86b7b8d9729d00d08efc7", + "beb9c475c020f4af8659aa27ef0d1dd143479029a8ef2f605adae61bd693c9ce", + "73b93de4843e323d7db0726e0bc301ff0194b9656bb40bd3baae073b9a4df96b", + "3f3a78847d9964cae0df94acbd73ba24eb042f44e5a473b1dc665a4db518dcbd", + "240d37aeb82815e4a61db5729ca10d069d9554e3f209eecd881d12719a47dab6", + "87f8197177364e5b345abc75771b0418890afaa0c109e2f6da58df071868c7de", + "9d0f1a386ab8b2192f4531281d50df5d354a96afca98b9122198982e0120d384", + "0bd411fccce089fbbd2eb04da0cecc3f030d036a44b78f37352816bd2bec9c1d", + "a5587eb1bb907b021e206cf17beaaeeff2c34c22a9857c0ead14d68f62b1818c", + "ed96c8097a4fa7debe2db8b1aff9baea5ebad839b60b7ac878fc93dd704f9633", + "c244897280ea22de3494642c6a8219500b884ccc77802b953f71cf12de445e28", + "e11b64f780d2e2314fe969a74a86129b8cdaf4d223376843b94f4e64e9be7eec", + "1a7771432e6782bf9a5ef436874bb9aa44a5f46d1a5a7aa785dd1fb2311d9d58", + "215be42fb8c3511dbcbccd1634895857d48d2f26de9f9f167ffa86f141819298", + "5635725b8e48404be37a8c9db3274195cd7e36a651c65d09ee8419c571d1d233", + "3bbe9d510574073e795b4f843f272a1900f31510f9ad36a522525845c90075ee", + "1b19a47569f1803ecc66d1d5163c4c6e7ab9f7e99abe3e8bcf55f8cdbb00ef7a", + "c155578db721fb204f9759119f8ff004d78ba068869c938d9ce0a57e650e085c", + "017d7f31830417c7a0ef240d7837ef9cf047ed0a8414eb085da37fe2cddbdf64", + "78ea7551cf28cb954259a28ec1340ee66d715f02c5eb7fec48145298581464f1", + "b89ee6474841186f5afab538f9ca17b4171c303d5dcc89247b79ce38389bc0da", + "f15ceaf2a19e8eb599bac5959aba3518688d4791321e618b5ff4af1700fc969f", + "6c0be8eac8a473b665f89bc3a310c033c093f5b062527a227921b072aa3123be", + "60950a25415add062c9bd5427cf5e0eb75d6fd7363af9d44656831d04cdcf7fe", + "c8ee6f1b5cafc14571642946e8d8e56191c3a9a020e5322ec30a698258c24a17", + "fd5a24fb185292c845fb8759d924a72f24c18758fe9ac5e0df99d1365e0657a4", + "85db138de6940bcd58f37836e431c6d0dda1722d21f7fe2e519d08ec8d990d7b", + "13a18fb4b02a808771e8a5eb2a64829bf27c7e6fb82b2adf8d44a920fa6a5900", + "cf37460c8ad19a604cd4d1475e8258ddbf72e3163d07bad676a0db39248f298d", + "16aaf7854629a4612442c7c7b67836990ce60a78b95bb0221646cb9d27454e2a", + "f3ff2a33d32daff5a2606ad41d8b9fa469fed175ab2d12cba2432d2cec320bcd", + "3f84dcab7582376089e959b42b47ed237ad52f5e633093bf7fcbff6164b74cbd", + "1776d3f2ca165cc20e0736e7ba69ce320b1e19575245e0e78bf628bf8a3b4c90", + "4b815273385785fe9e57dbe6bbab75423b6302f8daef245c12bc4b8572696893", + "f9daf148d2ece99869e00ed44ffc1a740792569a36d6dc21a94388453c31a08b", + "0a7f0cc9bc54b816a21785f84414bdb99f34a49a3e33e5fa1d105ba026540627", + "05ec349ece9f47e92ec0bada62dc00a7896abe818b213914b95d3cc301afa0cf", + "3f652f63459aba4684390a90687e117bfd79e09b42542733acb734adbb0a01cf", + "d7be18e61d11c4e5757f2ad5fb6b8eb70ab1f621f7785d048baec87e3c81ddb7", + "cb4ef5ac7ff2c34808e9398ff7e313cfb5b73e8b3cf9c0c3ab8059983159213c", + "c1f66f86c3dc26b2212cd7536bd40bde14015a19108d997e24d0f5b1532c5201", + "2e8766d4dd56646f8fca1cc12fe66785bd90f42d27074c71e3380732f5616558", + "feb95b15d26976b6b31bd488430da464d87102d5b35cec8bb578cffc91bc7933", + "bef956f6a785e9937e4e3bad0b1468c428534fc06658738d5e02c1a604c77003", + "fb471f8b762add49e6d91eb46cc018a6990ca7bf1fb15d26aec90f6ba968f6cd", + "d4f35e4a4e006546af1bf09f5e49b5dda60ae5dd526b85ba92d871f4f09df77b", + "795fda42bece1d711437fe504f78e940f309c89830bdb5e9dd46afe3fbb1b150", + "abaf0bc879b70ace0a82af4b9d4f32085ddc7c5d920a673c47e83199959b4de6", + "ae69a784b18524bf95e7b2349cd1c36709eb810b0168e7e140a7a411443a02dd", + "7858fa7acf40bbc2168ebf05e3389ae646d1fd4567b17470506596baa5e00ea9", + "d9f1d5f5ba2a228915342e41510bcdaac533e10025531eb9a1960b93ae667332", + "5a0def567978daf9e17209cf27f261256f11d0f8cc946c888ba3bd15e56c786a", + "589c40f1e0e442e1e227c1d45ddbd799c41cc38d025ae871bbbad98e0b65d2c4", + "d25e897ed507bc4dcbbf349cc2de3d2240ad6bede49c89fb07c9b5dcc138363c", + "b480a7829783c502490abec998b2d0253aeeee68e54bc165a5f1e98cb6a9f4c5", + "ae8c6d400c2d517eb69379c486e1ad35497e692292bbe495f0d01b4d4e48e265", + "27fe2f66e35f873b8094d7e2ced46e55811f5a936f9019e5e2db41b7ae5e819b", + "1d767698a7e6a1d6adfb55c1584880350f2c4e80f40e51776bd33a6a2e47ba8a", + "70114481a06394db7de45673ff702a2ca4047d2715d780884f3f841a493790b3", + "404487dd890566585291dbf1a22cbbb7fd70e4870b36f39ee7c710320aa0c270", + "b908e1a132f73bc705594db6e08b82fb277a87456142f6e6145fa4701d7de09c", + "7f0734a0c77fbb88b5a5a4d49f995bad567f0a676cc9326c3267211d06ffffe7", + "204e168e47177bf41e3066b1ffa5f0779d98fdc7a0ff8ac5399f1c3abd6998cd", + "fae75f8b1c0302a15813cdacc724fb9c9d06d6ac7c6a358b1f1c33a9df3da5c3", + "c18e90a57bd273f5d27751fe81ea9302f5604f24c2a2a9d306e2b0b26ed65cdc", + "dc084d1ec5c777f8cb78fa955903adb7bcc68b0d18cd2de66f9c32acfe9e9948", + "4fbad69a041e89833b72a21907459d2a9985bef82d05f70a8740f4d1abbac471", + "f0d752ca1604efdc9102728c70fc2198ed466b21acdafe6a234f7124cdc3c531", + "96a291d08e64c21d74c94982a2d1a146ca25ef24b4c2ffcdb3a8bcd77288072b", + "d84f7a140461dc63b72d66dc97af315127f8260a6176159f7120ad15e0ffbb42", + "e323b02b16317a133f695b892900cbed463c146310f13847cf52f5e8a1556403", + "56f9986c62059e091f741f5febd25cd26400acfd51302e09e853c49815345372", + "4a91c13e08448237509eefdc09ed41470f72309aeb0f3577bfbdaf2f45b359ca", + "3f1214f03f2bb53d779d05f2a3a647d0bc2550b5540ef159c2917cbab8abe006", + "c00d7a898094e86d4659ecd1ebead956c2d74969a9c7ea05b2ef5daf456cbfde", + "c9f7b7bd863e12133688f089abc3846578a8c50f8fe95d33ffae1472cd61d396", + "9c4cb359614595f16ba7a76a3a5f7a78205c32a23653a935400f147206eb4a2e", + "f81f1b1b6ec3af3a09c79607ff09a025162ddfc14cf85ddaf4ed678599031bcb", + "07518a7b6771f27678761c04c584da6475af520f2358b0886ac0f792e5b07e79", + "3d8edf9ff36d26b12f22af02685c72a8f9106295c7cd06cfe74fd59967501ef9", + "957afb2e2abda010d44ee4eda67a2b70b61c56594a31964f860b26a28cb8454f", + "f136ce60520308496e1802b6de253f4911afe61e910358b2ead474a9cf48ee6c", + "7c90e7fd57edfe1fd3504153c5fc31342a7b354e93038b45140b67fb6fd18e65", + "629c3a127f091ebee42b4d487d029bd4c3fa2ec72dbecc715e6c8c9d2671b736", + "41e8646e02f9bb0537b627ae5f269154b03d916fc490d38abbcfc3ebf6d9dda4", + "72d66600ed0cc1faa6d91c2a0da81bd90d4538cee893aae4bb0cc14eeb4dc280", + "81889ef1c6d2c81067e366ab7185eb2199be8789f114ddd6a3b693ef7821bbec", + "8adb60319e326ca0afa70e7f8ce7209bef89e1ec820a5d70f13d606add534ab6", + "ddcebfd51afd77e78f06d5a5dccbfb4d6dc61977c47ac9b1a2f6402940d9a156", + "b4cc18127051cfd93b1a5eb0358153c03f1d44b841a41cf3c2a7a23a14dec4f4", + "a3d44b5e13a0c0e6eb22da6e8811d4995d495d4d780e840ee85c83f2b1656082", + "eb69269adfc48cad8200b8e31807e9454ec615b8d33b67e7191cead52549007a", + "cc6bed8de65dc9b905e2aa95ad5fd57bb82ee21c49968cf30a6cb4b002be5f6d", + "0ee85d0f8f0f5bfb77f957de73fcb2da0ff2691b2971ea681432a67ae5c7c378", + "d8a2af3e7a30804574e74ed97275804fcc22c19607ea30251f7fcecfc86c8cd4", + "be4f45e912a7cc5a174d6cd1c058412042308381f9882d2a74c43cef9a93e51c", + "b2137011b2206e9737392b735787c1861d5df47690b5682cbd432fcac4c05198", + "f4fcc63e7a123783b643adbf0b97580b789def70d8ce5af5955b35b263f4a4fe", + "1cdf85f46a7dd1937cd43c941f1b555d582f36d3091097231f86602c73c84c7d", + "76cd77e06f946eab3f59cdccd3a3e20395f04d5e61ebc5ae6cfebbf72d96214a", + "f080f232fbf74a104a25ff2df6958e0008662596f81cfb84cd72c2a940c9b5fd", + "70a13b34f284353ecae70355403e6297fbab263f207707860ec22dc8a2da4c94", + "2d1bceb4417eabef500af978c975f18ab1b01b12946ff411832af267652f5d49", + "74847cb2b631547a13df246f10f21053e1d412b4bcc83d2a28285033c75a2839", + "0df6e0d42f19ca95d31d9b762fb58b9ee4ef0a2037cab32e49509c575c6ed19b", + "e9b6acc84e087163ed1ea23f7b7aa0fa4ea37f15473a47af6618d7f30e8f56a7", + "3578384eae5e7a10731d6de0972072f1f568a764ee9a2c2c6152eee141fdd3d7", + "69653aa6632c7fb7c69a8129861e9f3226b726a8804471165642481b598dd099", + "a296c05fca5e44afc5c2cd583cbde4a1791bdb7a8461c6676b97ea63c11fe393", + "077900cf366702fe8add4f0265cc52273b343a14218ea59ab26cd628a38240fa", + "a63d694c0e6728166e578d90061d24146d56ccda4ef281c41ce6076ad51727bc", + "1623e53bff3af6346b27b38cfc0d98f6f2ec80830789f88bbccfbecb4ce1162c", + "ce5c3ddd1852bb75590b6d8db16b4e6264a8993a3aad89f1731753565d5e54fb", + "3dc87d48cddba8c9aea71e8307e9d803925c9e4c4f55d7730d3e651dbfc7ba45", + "1cd04f320cca7fe33c2f43dd9e0098cda82edf20162a67320e68ebaf3fd74fe5", + "8d63274c4a44170e5008d2d1b790d5f468269abfa91a54c329152433a30665b9", + "89ff3946f2111436afd2b41932c475a0d09223e23b6b9e9a9ccf164d3cbe0b11", + "db63caf3eda1222a308deb317a0bc8f1deb95a6b3b0108f71d2d16691244927b", + "3d1ba03634ffaeb5d906032273191fe2595bd655a70dd8c22680fa4929012c6f", + "0d355563eac60a85c52b4b2a54c21ee7610819a9a3b30e69a9a37b5655b9b5db", + "373a44ab3936104a3d9d26a246d2365127c1726c34d2f1d7e87d7d7f6058f248", + "16022145fe055769433d4c3cd9639ce0f8f668e157bf9711e2c7bd7907178df4", + "6b34e7d77649a72887fa46cb34618d813a32fbb77e4ebdd6691527eacf5fd84c", + "df915fc7ca49225b34f2d419554d2594c8b2ffd834b2bb92f49397fcff381eac", + "6002c0ef73c781b20d7d4d9e01322f8efa8aa78e5e9792bce29a9169c7032f57", + "3a0debbc0ee42304a9edb10db770d0b8180c403971f42dad8832cc16e395c11c", + "6d76b23d46aae2e574ec2947c490f2ead9acf9592e417069e72050721224fba4", + "593602ee2803bcdd743fce93962f672cb877edc7d009be65c02a562b8604a74c", + "64759e44d4e426d1c147b405330e2fe1ed1afe168b8db60a87c935cf07ea10f6", + "d8f1eea3b2c56c9bdeeea5cc57d5fb38cda7c2dcef9276ed5602d27b9788c194", + "0da1328dfa5efb29034215279a87bf026e70aa7ceb2793e8c0ba9354580d552b", + "8bf631c56ecb7ab31c0d30bf31dd28a62877402cd6825d0ecc9c71e26f4be643", + "ae29941b70abb79f690de45e32c8b55f8114b30cae4376e991b963d4e03d970d", + "0b87ec546259a15a8c8752634c3ef219459c382d383f155f219c04d9d5bd7f01", + "87605721bbed02e5f279a29dbf5fb857a5e1d41ffbc50689ec4e1ad1ed3f2b76", + "64d33c169662adb9ae01cc1a902b8725ea84162226d860b05b22c1cf8b716b88", + "dd3e22b9aaf98f165f20c449618ebf776727386daf5695e68847462a1573f1fa", + "2eed687fa82a0df68fb2a1ccd9c7e0679f5ada28b831b105718dbd0580c0aeb6", + "3748437a03b2e086825a1b26b9a363495cb04ee3b5c6125f16fa7153d388b38d", + "d6f69cb9ff2388175b1e549df23171ea6cf0f181c52902e90740dec0fef941b5", + "81e173033c052c2a8b6c2ce928c7d9e7f7b956e9744156c8b40cf815f093de69", + "627027e95f078f86d70df8b97d509bd556c6397693025367ae4b43edc9b6fdf2", + "9c8bee1ae58091342dac7901e5846df4acbbc409656457b03e1702eeabbfc8f5", + "ee387d8e66f5bf75dfdcdeb97d28b4dbbcb1302bf20d6bf8465b7b41832550ad", + "681f0145ff4dd8a84e42b02ca5bdf4bbe8adfdff11e3ae57673740a4f98f0c67", + "9f7d29a27a80e64603c98125d6f77e23afac3ae85ab0fbbe91e74e498fa69c89", + "f23c72f39810dfa196ddac4a2b30fc97f3e05cfd67d91ef2e6ab063ee29483a9", + "cb02c55cbe1a20d200bd53e718c78f9f2307d0476082bb425d4476a70ef47172", + "2c56d7a46e2e989c71d754a9ed2ed22285adb9bc7ea0ce85e7ad0146798836e0", + "161f8ede4832a65d9d082699e93299189916a9feae06703aabba7aa7100c8078", + "c14f24845530dbca3372c7d7453441113682d76ca7c5ee93a86f8705dfa6754b", + "98e2302a8c27aff16705eac3c9b4861e0d670571ca493dd0077280785d1d32a3", + "1af7252bf32de08559d47dc9273c82a7e6cf89c2ad0d755084116bdc30e2dcb9", + "b662f05da0258a7218659df10926cb716fc6d092654ebdf9d8a0efcab72f311e", + "ad8807bdc9c0db6fff8ba8963af51f14ed809ff5cff5944d27b1923bc5cec68e", + "4502bbe76bba11effb1f91a822732bb4d1c6cbd20a12722cf7cf2276bcb224ef", + "bd100da2cd60b60a2923299e505c6c0fd23cfdeebefbcec8119567fee2b8d5ac", + "2725060e6d944dceab24729b82d3a64275ebd82cb42ab330af43f53cefa27893", + "9cad96ee381a6d63d841569e475eeff6dee67836e2d05113a8f18aee590673b2", + "c22c8e48d846ad43fc8319c4d3ed8c4af31ea7c3e079595cbb557b78e50f0a60", + "24a9bcf359c2345fdc35812a10f9f08229d11f17c5951120cda1264adb2e6d71", + "54658722a2c31e13616e4a38a817927c01d2df37830dab7e76ec16e7ec93e298", + "fdf9d5820ce67e076d78db09766a5827c6d14678d1336c8f936608d80ae83d72", + "f3c55939c47563aecd9a0be2fd16c8d839331c811403ea22d47a8dedb636f389", + "9a62ce2c9a3238370ab983857b27a6ebba407540c6a55b8d3e62fb012b9177d5", + "32ea29fa721d7727b0ad77f534bba0ccd4f08b16b1c809c60da2e83c37cd052f", + "0c8eab2d814623966122a83e079ae8629897d405fc471fe70eb8ecf63d53a6a4", + "b5f81d6be6c5ed881db8e195b850c3ebfa2cb455d0a1d14df79740eebe5d549e", + "ff39acb8667a42faa265d97a90fa7d5802c6a581dfa6bc868fc6e953b4fe3b10", + "cd1a9a932859370e971587fa26255782a1aee9a1efeafd17badd1aca3c822363", + "780034cf738e520971387345b73f42cd13770dc8cf68948ec9e8e1f6a6327f61", + "0d97a70b467fbf4af625a6b539035b19e86d011782bb7a9ce538bb89d81438f5", + "ca8dcf9e3454d6c2a346a01372c798cf2cf8c49c38f9581d705c42e4f1e7c4b4", + "0c21834cdce637a85f931e8d2d961573d1dba0ab7bee93189f74c6331995c914", + "c8aa251601172c9479b4ab2c1382a2d6608b547cf6b7a4a04a75a91fde4c08b3", + "14d36f3db5b2cfac7a99df066016eba59a21ef651e991d631c04acb11d1d2b51", + "89006b74bc61637b0808bf786df16039d0f5a26d1cde1348de0f33718d47e75c", + "098621c303cb1b9dda387a0ee66ecd267172a70defc1b403887ea74c53d5b911", + "f9428c1dc527138be5c9ddbfeed43077d06f2826b75edf9218e7b90df8b5ec29", + "245270fc3442e19475818ca0d5cd32a4728a25b5c4f2231d571eafa281e61e18", + "753e79f5b9edd2e49c30c17d3d5050a2c0265027abdf8e661281d22e6cacb701", + "7ac9b5239a33b2689c63739de793dfbbd0955c044fe062bab28f7b9e72af4755", + "ba6c405725d69b2c74661f3e4259242b054d13f197db5700d1d7728110e56955", + "a7ff3309d156a8d4af88c92e5959c98617e0c1b95a10caa544fd761f93715b80", + "4185a1fd84ac173ac31493ea80b4a6d38d37325e8d82d07ee31bbd7f5c661e17", + "78826fde40d9fed3355c37bcaaf0656a4236d58404a892d1da402955698e2904", + "9f591f6bb853601a315de1edebc0927bde202e6cdacacace8dd32bc824a8a094", + "3ae950afe6ce59737c943cd90dc8f100de10de1ee952b2d295514c4f710aa7d2", + "a75089fa658b1206f03622608239f2de628b4a4693548c864d6096e2cef76490", + "efa7ea258d706b04547b8d4a791b1113fc77a4e5547c8a308a89bcbbf8161e56", + "f0c8cd991b168fa30685d9adb508e9aeb4f2b63dc08a153b814b0cf1f989183b", + "6f1946a94c3138276073dcfe0d0d48d3cff0452993b34965a8fefe90161f0fcd", + "2bc40489956125fa47c9cff896091977b8dd0b7a0e0150f614592b11a2e4d1ff", + "b2f96fc311567ddbef1bf0fc487f973145f717f283883606ee03b4384da74003", + "afb571e0e140ddda917b23d993474493d61a8414b0bd191092b6780bed309756", + "687a64c739ccc3941a0eb74554bcd0135e0063922933ff892c7b90b88e21c7b8", + "5ddc34627e55a68c4fd82c789c10d7fecf3e380b458ecd18eb8c5ae041c0b288", + "ee7584bbd58e279c2667ffc07c1c4977654fc948a63e33633a563c757f0dd9fd", + "3b7fb2e668fbef730803f10eea0e6cd9a2819eee7c1c1418431d1dc683def7f2", + "b4e18431bfedbd98c924a64497c60ca9e4a82f22084fa1ad24c09f79b2ea6a94", + "a5073a937e8b5cbbabb8915cfd2f2fe7307e4e334d5f434077995815475f0df2", + "455b0de46808bf01d625c22f0cea27120780c8c69c0c11cf837e98823faf58ff", + "a2b26681847ad348da10f7b578cae28087a3f5aabc5f84de188ae7ba9dc754f4", + "f03694a80d8dcf0b98d4c4ae69a797218cff7688f80ea97e627e817ad36f3795", + "006670166e382b2bf369907cb2b4834d58ccdc55a4bbd6494e8f9c129f5140e6", + "ba02ab95f8cdf7e40f03a629e47a0f7d5b77096549f17a158c73e2b96c6cf0ed", + "e1180c4ae2e094ff0ef2dd8107e5f2b02bebfad6501b18965b75ce8689efea2a", + "a8114db88256707afdb0f589c4e375a7b165380a0f8c2795c0c0dc0d02f5684c", + "a8ff66f47c414f56d8129e33a45a0bd9b9d1a640a3a3454d3496ba3a800b2d1f", + "f36ca0f95e603f806380dce52d91036d8e3a5545e1dd7620a19196397b91359b", + "1c207b576a1e9e765209ac6756c7948fa3f252a4687696d0f8e831f14ca52b92", + "cc5eb95f7759dfb6cc55027d49a5fe9c52f3006568cd97a0c544638be7a887ee", + "4e15d5885837d4e5e79bff21930dcacba97d2bac39e506896e005fd55aad7e67", + "5e2e62808fbe25793a6917dfbfd06029ea30eee0892116fe6ea4696fcf62ef53", + "334d575dcfb7f6b606866af045d0a378f53447ef51d5b3d1afd83d78c0aee1eb", + "591c6dc98541b9fa044ab89f78856374c3f42ca5f8021bfa0e119d8a04a28646", + "c502d6853c8eb8a2657e069659c1f3b06878498d1b1a15f771fffaf886a1ae52", + "2d4b16c2b6cee606af3c02ae8d6a86560e2393306fed2ac0b72456a8e35e24b6", + "b2ee8ad11dbd4ddbca245b403ada57354b5df94a9de54bdf574bf0eb41645c89", + "a895e7d8adaec8c44b603648f36774980707d30ede4f5dbaf2bd3d2e3d4e90b4", + "1e76fe8a5aa1b516db5d04f3496e69170d3a6910aea79ad7554e2527b81b6b5a", + "1576d0f08a566bc422049efcdd942ba455e61a1bb2d6e1ad470e098899128f75", + "ffc42cbcc82b0b23c5616301e90aa6ed76f485cd63506ba52097a42b5c17420e", + "27fa1edc6938b7d3658c5c9d894136857fc0be8fa743924a86ee4baf583599bf", + "4c8a502fb162a9580502f4f2618be83041782f245c6023e1d6c3ecd7bbf2cbd2", + "5b72391f63f61ba48fbf8fd308ca6afb7d72b9545d1812538f2e4d1414c6fb1d", + "1968aab09560c49509dc7cdac8c5c919629a3da0a39d7628b172d5e7bde99c20", + "97656482e3f4c9dbd01cf1fd91f0deb0b319c15a89b5deec6a57fac647a81753", + "d1392d6f39252c12b76aca6762fd95086785433913e5960b3c14a708401c2897", + "c11244439c754d91aa30a2fcddeef5a0be7e300b94a5c98967785f112cdbcfff", + "21c529765b6a1048c8c946578be14e63750eeae28521fd845bf7a3ae669f203b", + "c2f22169832b5de185aaa5642f125738f164001083438328d2541c15a7f986af", + "293583e0b2b86f041204e4ddc9546ca74431407f88ce36665337a5602dbe3bbd", + "1c270bcff184b5efcdec7f630e707c3e7c90a519302233fdc08aa744d4cc0f9f", + "88a9d5a81d358a14cd92c14d669903032c93371915725d764fb01c7c1673d4e0", + "c733a54fa8d1ef07070c52ce77898eb93f148b13cdd1b6fa69884dae4b62144c", + "acc7546cee77ad0a641bd33253869e0459325db8e6e3a9c7e3812916939e5345", + "edb6a177be83d61f8e67db1b3837db0316d0205cc7303c242c697fb3c2a1af25", + "8e1e002d811734ae8033333794c2bdbe826f1c69f4dd6197e595e75837a3ca64", + "316f26c9d7b2dc523838fd4d8a102e7b817a44d00a4f31dcd30bd6529ca3070b", + "0ae34d23335c3138e2ad4a282b3bdb89542bdc29a4df69d202ac41f140e15aa9", + "6c6d48776be2e5a30e91af97bd6b0bc5a5eb76a5fd713adc399f8664918cee9f", + "dfd7c371eef529314fa853918ed4fac86e473d5bfcd9dbe261e57201d70c082f", + "0046ae85e6230a07ef27a9c7c75dc6f6ccb7742433cf8be17343ea8666512259", + "dd9fe83a560f0897bd19f23474fe744c8eade026cdb1f048e84f3459e0f19303", + "3e6a71ec2a652defe81127e60e22728c5c2b6b7ebd3f8946e347d662ff3a868b", + "a4229eb078f80905f012a474545e0e2786f98bf7fb2073dcead7ec73c65fbe9b", + "7dcad9638f5473ae40af1a5d9334ca763a09c66812806f67e75bb44e457f87c3", + "374ff61877eb866ee324a87077eb71d0a269e9845847e55a5e10fe5f3c77aade", + "ef6f393a0d140250e071d3b82f5086c13bb429266cf944bae8cdaa28834cef8b", + "9651ad41b55c6e8d6abb345d4ea06e4399cf2902d2c1cf13ebbfba0b7140c8bc", + "9d0540e58a6445fd868ea65c40185a7da7858524f419797084a602427ace7477", + "5d812312bfa56dced2d010ddbd98b79ec946a4c13fc545088c80d037e4df3c3b", + "c75d28a33c292a50e293d4e88f25421bc03c83fdbafaba4f526b8c6a7e5c2e2e", + "53cc98e7b41fa8cf94ae5ddb9807fcf8c73c209d910c892f266621fa05782ece", + "f6b589decfffc6c33957cd061404dea6482435abcabbad3485266cf4a8e7fc05", + "e4e03d0c467c2420923815fdef774f530d07c0c415e9975bed75db2ce4227dbf", + "7178a3cf86b9b27023e576a0f112ddbd3e240289bf8c4256ec384962207d749d", + "58c29327189acf5670bf364f2c9023439eab2dff643a4ff36f3d35b43263111e", + "d9b365bae902827f415288ab30e5e75d93038ffc1466356d6f5280863f18dad2", + "ffd371a7a95b47d197bc947e0e1c3cd50a96657ca14116fad6fb7ec96aec3bf1", + "10ab513a9aa33ce2ea4cf293dd0c435b5aad5a1adff65604dd3f07cfa1f340ee", + "40863aa43e50ba80bdafdba66ae053896370421d48f59c2aa962ec5e2914bd96", + "0363498ed651cf53bd469fd0dd8ffdcee6c6b4641a67bf52fd177ee7e9e81324", + "7804a9ccc78fcc0e6b6583e2fe28a32d3b409a08dc48061233f8faf88dbcfa03", + "68ae59987180df7089fe2566c5d2a61d554b267332a24dc44ffba97c1ab1b596", + "f2c29ca8dd0b0429df3fe25fe3e36e6fdef1170dbed8baa30cde80f13cd093f5", + "06d4400c68d16ce0b1b70f8fef726fdf633af85eac4e285694db95c0f8e503cd", + "8db9481d31cd20f8ebf15b2ac559ee46796f0da83b8a94139ab998e2be19f035", + "4c4a93fcff164e070a9eac32c8b7a582a00c6d32f8dd146cc603520d91fb11dd", + "3d70cb493fee1f8575dc7da9c7627d31ebf42c9842275f772ce6f0d42e06db0a", + "9f28537ea916ceebf76f1a42544c43e13e9075929228f32190d9ba4f5bb5c9b0", + "673af69eacb58312c01c9b4e93167bf8e5bec2ccb4450ab833baee81cdbbd95b", + "0d0b61e12e81bed69380c9b8eb23a2384a48bb13a4b7808a21ebdb00960e7e4c", + "284b4b1d0f126cc76b743eed1d255b181a4ea45839ef0c1dd2749ce5ae83270c", + "70cbb1998efc52d6b6aecca67551e42bb44eb6dd6e400241d2e2bab34ef9c1f5", + "a47582681ac364f031f9d19c42e0b68edc0749c5b3da9581009b5187b8b503f4", + "808c8d746109d74eae54b97f45ab7b9ed24f32835cf8a1ec9d7d46c3fae5178b", + "ab0e3e550b11a95ebe15edb506a534d70e4bdfbbc9172b251668cb8eaffa5c7b", + "8d24d23ec2012ff57024b1241dd401eea2ec104645e5dd4088b32546fd8ff904", + "523fc99da5bd881da326c94b303a852c0796792c1f3abfc1fdc7590c9a1ad80a", + "bef023158f2dfff9af92f2aa64e7da3087afe08b2cd5bed4d6a0933e46efd411", + "bdb056bd0ae30d8b926688b56a6e06029905ecb5b25922fe4f6f2004d4adfa11", + "94a65dc8805bbee393a49a95ce8c95574ab280d6cfcc4a1490cec8352754c6a4", + "50410fb63b9759e697bbb5c62d39820ce5d1f76ae9697e064578a15e0621b792", + "90bc57b7055d84741c13f3a7707770de07ac2118015e3f0d08ac9ca3a4a6e177", + "4b703ad6aaf1cbbd6f4fcaeb9745fa82f6fb055611d7164c572892b0fb786114", + "0ab836aa1a9ab4467708652e8dbec2885119358e37b32f51b46d45f33c88046c", + "1a118c7d922133ccd430b9f9857b62f8f2ce4df7d648a197f6edd3fefc07cecd", + "40e846cc774ddf6392d673f69ce95245690f25786770051ba5ad49461310b0df", + "5aadcafbcf0b1b4723d39c5d4048a8d9f3889a3f68aab66cac0ea4f0ef7d549d", + "acdd2f2a548cd325fc06b49c257bfbc9b09c016ab0859cb947aac64c4570f6e9", + "0b3ab537044f2e6142ff425079d25fcd87e0dd8187f03bf0dfc479142d8b9abd", + "497c6521a301865863f7dfcd03316ae0db690e98546116c14df05d98e8cdc893", + "ccdf5949457b2394df193f21d8cacd4971942ea3a1467e2ab13fc0cf38a2aca6", + "b38079f35e81d62e2ec89a5511537abd020e0d49f47cfeacb1fdf0000e3898c3", + "b5477b70b3e6f62fc281e349303e8e160a5cbf6af135bf3c991955b3cb963039", + "64e8bcf3fdb18248ead8b6c5a23b156d76cbc6ab5789815a2b45c365ab20d353", + "86c981eecb0af6e8ada8e68a9ba9a6cb93d0ed527a366121ab0dcf9f44d2a38d", + "93ff8bbd4dced9f09d343b2227099d63a28c121389dda386c8b58acac7e020aa", + "b9b7cc4a4e8b9f5a1ec1116d378e3f90ab3e8e4605d4cdc95b3e4b7df2815a1c", + "f2f37eaae0ce72d792c65a906b6c7334c2377c3c31e454063305e7e63e5329e0", + "cdfcf71c42e3d8d056cab0fbf3625c1b13704870709a4e0850006447f128efc0", + "83566f6ad1536d4aa2543258bdee98989807ffa133d36af3a26672708ead8410", + "68b89c27a8254d5fa39096943bd9bb0074e950fac7e686209c0113df088ae054", + "0e8c8d00c7e71968371f4597da934aeaedc4142586c6454790fff7a4e61af30e", + "0bc7e2ff2af89d45812349f03973406f27a4475c44e71589c4121a9cae9cf37e", + "53738bebafb5a06ce8140b83ef922a31a05521c07c42cb09fbcf6619bf959697", + "809f6e691647916082cde741c82df020254de10148b4b712744f1db345bc2694", + "82238f89893476756a48eaa42cffb4fcf07c8cf4cdbe12a1c43145d2b67aac07", + "ee995fdc7633e803741fffcad712a48aeafef16e5a91aba899e4295bcfa3b577", + "b65b0489ecfa62b9725b7a4c4150caf0f01350de9cfd613c90c60d0fa4875ff2", + "7988a77872e593e831989c6ca5e5e6861b63e1c2a42030d684b51fb88ab73004", + "914ea37de5dc3b2f9035cdb7fb80e6e692a0a5934756beb6d8e2ea8eee7a3895", + "d9c28dc8bc385283650fb2aeb1efe10caf848c39de37a78dbe6f47b8f3bd8b51", + "49a2581f6ebc753d70dc30d3b093882153fef2d0825252354e5beb1b35eb90aa", + "7791d37475e1e15bb9b817b180811d784963d2398c5e736a851af2ef8e622e77", + "3957f179aa7676eadd2c312cd6096f84b7a0424bc99f05c8997bac9fed057ae5", + "9d954ab5224ffd2e0301ff9b33ef834d019596a6c3f56fb634ccc9779b9c694f", + "e6235eda52b721bcc3b997bc8da554f1998b5c7ff43cb86c2d7f1915150c4ded", + "c0684e197ace1cb57ab553203b16fbccce5c993b876b90499e96d94ce308b956", + "70cb7be7ca2d01bb41c09c06fefc04e8d6dbfcdbd9b8df4bd38caa3c7fbb6001", + "96235ac39c397550e28b63f63a4bebf549215c5e72cc78488efeef131b0cdcf8", + "f3bc2994745fcbbc792d905ce1858978814bcec9a5a0a3eea4913bb87939378e", + "caf6345a1bc6013c428933fcf151ee366a11ee41070c3de2a3e5036a65145194", + "ce92dd8170fc721b8bb69c261cd868b82a2d1ccc556bef3999128a3c20bd7c5a", + "45e73df58de1b26bdc1b842b5a951da84381708cd15b40eab87ad44641777c6f", + "1a57c8e01d94f7455719c85c662f76580b9f4f530aabbecee9c5abe00fd7def4", + "c92b4679c9376df3e41d79131f42961fddcdf99afd2c476168daf9657f769373", + "2a2893a114df2630e4b32c47bd60612b4f3d9b04891e944af55fd2767d260314", + "98dfd86f3bb1b56d0e5b3d0a9b3227642b09ee0a2ae78f19eb504edd1bd91ba1", + "2bca879ad4553c1406e38ab072cda33740cf1681f18e7cf548ce040528fa5d05", + "5c3039135e50309be3292559fc0f0d6a5de7ab2803c83f206c8cfcc06683b54e", + "7b46b23f8ca2c45baf6124165030a1ee5fc27f1ae3d1226defb2574177cf728f", + "b37b504ccbcc5ae9f8b787fcc8da194fdda3a25b94fbf217444c13fa4a0863d5", + "36d5d669f4afaf603a54902269087a0f65f89962f87ba03be56b552bf04ce81f", + "f57f94affbe464d876235351bd20660ad5896e5f5bd38978d64346564a089754", + "4637eacec37dc577f7d0c780ce46a57de6da9b5173f4d0626963af480b95213b", + "e22295a0995837f730cf99e9465b0e5c41c1f4a99456f6b27d26d66b8ef2c4bf", + "33d01fca1bb71c53d131b757afe6d97342006694ae752c17747a461717f42f8d", + "ed239b46bcf7f8a66b92c15135488e1249f668625c6fd0a08a0f49c733806de0", + "324c9a8fbc527d9e9357595b1b3509847847f340cd557b9305e78fa2ba963be4", + "2fc5f4089b8b6375a41bb70257be3281cdd32778db05663c55f96cbeb976ef1c", + "691fc9f8e0e0fd9c0a0f42f17f33ea83c3462e35d777dd54734108bf273b5a4f", + "e21e3a565655f1f58ebdb421c94110e19a55030777dbbe455e350868020a574a", + "2c3e5c5791cb68bb2177332f5b79c8f7d1cf4a577a903acf225a0d11e45aa5c5", + "5707100bd5a978ef7fe1def6ba895ad388466a4db13679a899c93bcb802d3a7f", + "fb537a7e26384ea9867ad9ac845067553c1461f5c75a5bd50df1afe40b063b1c", + "afea4fc11996d2552a83a4b7bec586c9dbf3346cf2b3ee7a862b8f6ccf163522", + "67a83eb66b438519cd92e6962566f3d1277395d2edfcecdb06565e33b9b4200e", + "a763a731e9fd04d5ef02aef4e7cdc1726a34c7a048cd78c45ddf9f05c52773be", + "c992b26e5d9f56c3f1615fe30fd5d4a70d639e192583e5792909baad8695e90f", + "5f63a2abf7fde874a260f469f56f7392c715f43581fa0e0ad99522dde7c047da", + "2d92ebb998b264b0c7fe1d9dc94c8f3ac171f31a38867eefd8687216342ad4ac", + "36758fd2cddfa3f6c1658a649508727ede3db00c36b5a619260212b50b3e5da7", + "19237f8184a40216542e1f326527f7e512ada4ff9923380f9a7a7e73a0c4aba1", + "3f2d551638a07d4c6b03265f131adae2639d1600a9f31a337d5561bc22c41af6", + "212a3841885d5890d53c698bfc2ee6114c13ed4636483f65bf9f43e2a23c2dc7", + "30c6c4fede61dd964588586338cacee4e0ef8977b556b4fc104fcb6120d45d3e", + "413981cdcd8428b9e76a34010c95f810ed5f39ee66edfcda92ab0ad94f030871", + "c70a24bad26cd871d82aa4563199ce82ef8d00cebc48a1cd698ee1933ac8b6a1", + "d228077b8f08942f4f5c445f5431f6a388d8dec122471f8c24a56ac158c90742", + "6d25f50ee65fc7f46a86e1742f30afc9b9536b65762f75d9bfd1f9ca30df1d75", + "2a7ac6f4b98849eb4d6962c424e91537967350ccb60c5cad40400d46fb0dc3d6", + "002721d6c430ad953c9125dac7b4235a3f5edf80309b23fe9e197d0ef12ab0e2", + "5464573c76aa26e98ba45180d7783bf83a1ec7939c8fd8a210d635225ea1ef42", + "18395b65b1a46358ec085bafcc873706fb482866f54e02e042522ca09ff0452b", + "f4ff0049dc8e5a4f06c6274a1bcdbf8b5f8b841f921a264ea5bff329378fd620", + "19bdc09f26645d82ea05cd1fa0ffaa68885c66530b3f0eb05caa55b88aee4efa", + "6e749013aca97a5ef3b156da4dc621bfefa7e0186e5e4780c31332f9c62ac7f7", + "83800ecc6922e2a6ec0c34c1736a12f2dfcd94eb9f27c6948a5b28d961bc4ae9", + "86b6fe2935f0206083c952c07ea38c25388955eb8a806c10b69d3e52d6ec26e5", + "c7db870f8b09b9498d39b22d828b60a806f7a1de694c43d6bd29f3d76a11677d", + "b0a5809735c83af8e2a3eeb93da682bce95a699392c0c4abc8d39188563e381f", + "63af21f2f1f82d3120e4d8d98e7fda2d9f39d102c57d9c4111d07079a9ffcd47", + "ad654b3ed5a11b9a2a52fbb8dda47e91a72e4b7bac3a4ad75c074786f14c046f", + "6d9c4a44bf22648c07881e2e92a81ffe002c0177d9c7892416ce01ed1f693872", + "16f279dbb7b3f6c3d4f190b36fe2283efd5fe4669a8f70d209eeed96bf55907c", + "f79a83867614dc4d2e47353f53cb5a833582446329dbe4d5e8df941b0926dcb5", + "0cebcc9ea3729487c1b20adb8eafc6fb1398710ff6179a7fdafb1985e5f4a8e8", + "5a53e473fda88a9fd818defdc2c8e68bcea0c5aeded0c1910d6004b0e77ace89", + "f97965894c4a296fca42905242a27228e5a9a0150d31a55e65d637dcb9e60ac1", + "ec72e9e2fe2f4ab9db10b7075012c9e7cd2a4ec02b4c3b76df17f6eb27348ca2", + "a4e92900f9f5490b66e21fb66c0ae094d106eed5366a85418a86a8a3f8f87a28", + "225f9b50f64a97b9eadb625662b1a3e1b400eb86cee50fec8c62260027b4d390", + "7cd4971b0e5453d210c097904480403bd53c689c19d52e4c6a37925d14e4272d", + "3edaf61be8b6cfa06e1d42d7abd2df32033bf63cd14df8bb3ce337e62a822f16", + "89fd8d0e59d8d757b7b8a2c3a2b826e799c028df166b6897a42f08f2284d3bdd", + "0aa2fcdd4e83a4395cb5f514e1ef61ad4bb517d7c60f81bea030d5191c3c79b7", + "80a275ddf6caa4bef4039860d4c5b0c4bd1009953c19ec2c63294ad2c5c56d1d", + "e85d450859d702a0473363070a6e56d5021ebd1111232f2af28a60963acdac16", + "54d48012bd8af661baae940fb6f0d10348137cbb13c650626f42051ede55ec8f", + "bdb3a9bed24420afc6eb80930694b4afe0992318e49428156acdba5762c69e16", + "cd277985e4b4c30a1999e5bf7bf7d1cc903640a04678a93efaac1f9bb5482dea", + "d1319c6862feb76be11c089c753f62873519ec29a0c83b186efe57f50c4e342b", + "1662d8e6db309700071a801a3d066ce97f942abce241c8085f3c023258927eb9", + "e179e018705eb4a49ffa4e5271ddaa4fe1273029b521aea7a69f8f3b764ae017", + "0e7347cdb154f6d96fc8f9eb8991d4149fbb21aa3270c21fa5df61ca140a4fe1", + "34f182c2f44fab5ac9403543493be5006814b2379e0e6b7603d9e0fe76390367", + "5d710a970ba007bffbecdf12d1c920fbda1f57023719d506825e0895a2affc49", + "b99e0f318386f90df96c1d1cd4dc5bbe4726410f327ecc108108ad898e450eb5", + "7eb9ae1f66a6bdc4482175d031bd6af270fe4ff8ed1138200d6eb49e13c0b8e8", + "c508f259179f67bb6e05f2b9c5c5ea751f3a013eb925c6bfcc2a2624b962e059", + "f3d0dab6f1d30ce74c97b89f551ce0820bebad2bc1cbf4a449b11d5408cbc140", + "c116f6b0a0852a30c8a913f9e0f1680ff1be06165e19eac4d00c4e426ca9b6b3", + "25df122cffe53ab88ecb94abae69e0a1d4323eadb7537c5e4894c0e082d58529", + "a30d97485d4162e910b12effc549374221217c216b0a9487e5a07ff1fca835b8", + "5dffc63818983f6a7db2ab65d621819be9f9edac58df38571887cba22aaaf1cf", + "f042fb4eb01dde4b285f2df328f191d20621b66d7630d7691e7c69d9dcc04aaa", + "d4190e2bf10aa9800a1c2395c0c4a38737c21f8bc42dffb23addf762ff309aa6", + "4745eb0e771c9f2144ffd4abf39e63cf6d0ebe122df5f32ae399cc15fe3f7011", + "806c6fabb4059c51865f723ae619e0c55718f973680ce7eb84c49b935f59ff02", + "3352add492d3a7fa9ee046040a3f7795ec375af875c87edfdb0bc876ba14fb3b", + "27dacac03594cae3db57550410bd0f8d166863992895548f6ab782a8332462c6", + "1708396a0792c2a33b8174dd950c4a59ff06e969db873eaf2a7d82453e233b99", + "5680174e172ddbe6943cede98f8d854dabb66ba65e3349889cd6262cdf462a80", + "4960f0a4c46286d62e5bae021da9236ed0258f6c4c779e1797a9e66a47803f0a", + "06af18499315d7dd1c8d16533f0e13465d606fea2946115f23735f3fe2f6d882", + "73b0ee02de1c3c8a9b2bb8a9c48705c94df76c9c2d68a222c8493848c75327ad", + "42044a69f91d56cf8b993166dc1c724ec7d311eff01c8255987cf563d58fa5a2", + "187382209cf9b45c1df5655801a651463854a6495a7aa303887d65ad0e5b915f", + "3e44b609a8f97ea0b412abf88d7748edfa62b7ceaa174bae008e508b1b133e7e", + "d7b1c0b1bb02a6411eeb888ae26bef44c20364113bcfc1a4a3410396cb52b950", + "5534bafcac199f54a48fa713c6f7ce0568abb11b341e38b4a968bddbffffa507", + "84044786d9f286e241174796073fa47ce25c154616ba27bcca69fee1482942e1", + "45eb4756d3895fffeb913bfe149746f56e184f4c336dad29f6f81fc2a3c0168f", + "b583374fc47629a3f17476f4c9c751e851b7c4881eda50e4bead35afb77808b5", + "4a99c32e81aa36e824bc4be78495458020b1faa47d558e7263f2c0477a16e6d8", + "888b7d3a32f4566f21407c251b753b3890604001db91f88d45773bd8a53b2541", + "53eb65e5b425e7acd56ee6234ebf3d40d8fc45a3dab9968ef4273cee307c38a9", + "4bec2659f865dfae69862e128e710680f6114866b3478de257aa5ac596a66555", + "543cbc31d271c10cabc9417a4d4b6dce2dac73c20ff29bfffbbe55584e5329a1", + "4970e6469f1ace57971103d1cb2324b595ff12e34504ef8249971c76296bf578", + "010810a21205384741812fe98489cd7369d9f6fd9e6818b11dea07c78a9073b1", + "6114e32fefd54c1c2352ddf9327727bb6a34a9d8b3b7d01ce59c6e0d32700c7f", + "ecc7248b7093678e7e0ae58333dcef0eaa18e3af261b2d1722d29acacce2b8f5", + "0dc74b6f19b2bbf2f0e7f511440d4dbbc67952050bd1d962516b683ff6f9ec9b", + "fb8447ff1d5200c3acc768992705d2108c37d61b0451c7474304803e76cc09e2", + "f7f222b44c49d2d927fc2e345d64e2f0ed5f9a602758fc5f5ccc73d3b087f8bc", + "295fcc7e7fcb601b3e79c1fe403f920b622bde0f4975419c3641c4d432de8f50", + "e016f042fea1d93fcd4b2326b3ef6051e293b4abd066b3fa5c430ee7773e443c", + "7c8347faa1ad96169f5650a1d138cb10bfb60dcf861d5e2dfce6a986997d2dab", + "060928467611f28b99eaf284bc6c09d6760904ab5a6f9e072a44915a646e3ec8", + "ba582c64b17221c46d27aaf6ce1e2818562639b321666c9513c1e85727a623e6", + "e73793b5e2f33f60887c6ab428339d40d21fcf75530640977215a18db34fd7b4", + "0ea32380009a639b705fda94d93ff032d88c3126503c0d153bd0f104b039bf60", + "13bc02f7f971910299b8c61d1a16782726f22f63b31b2c0c34faece873f4418e", + "a99b3ff6413262f46cf9a44c3fd5d0424109a6373e2580fe97938c3dc04e60df", + "72b149e7ff672ec6b23352493cbcac166062282911e46d2b7ae5228d5814b720", + "58d67077a2b7c836dbc19457eef1b1e1f734370a800388bdfb1012840fb7a240", + "32beefd48538abe6eed6ae137199e03e05229d124628205cce7deb53f16f8f16", + "3e466fb18e2a437292f00acf9f6e662fdc6e0b7cb9c0606e613f81dea3393e39", + "9e537b504916eb6e9838f13eccf0c753869351778201c0813ee35cc19205409c", + "404c0560dbcd46d1aa9cd76246654bd01f62ecafd40ad2b364c426f849941c5e", + "89e5cbab667b81f08eeee6203be0af9cbe9dc0655af3272b0cb3fa722116c200", + "2fac933a1b980ba75339703bd02f055199d057355a8dbe94eda724b79c2ac534", + "c0200b5442f41779316e0e250b7bd011e12551b2babc96c9228f3187fbd17eb3", + "f3269d2e80bfa7e80397a8d32815f8fb8fc0f8dc01dd1c75cd57028a23e5d462", + "d6be8612904259aa6ff43ff30a2bbeba9d58e02f479f56480a8affc2cc9bee64", + "a67a26fdd90d624fff7e501a2a946681134e32e3afe3094a0c3776229e7db123", + "43234eef33f6bad45358374d23ded2731a35c12f472cce58d05e6d9ee56c9535", + "f0217ee0507b13f56f8417d0c92e3c76026da461c22dbb7fdb653442dcf65ef5", + "d9572135cdc5ba7afbf9871de3ffb68a1ca933e71b80e8766e678bde59ad2b52", + "9d32d8b859188827a48fbbc7660900fa51bdb1bbf3dca2ecac1392a1cbbf4757", + "daedaf79fde7f4e49a736f5b81f8b6f505884a073c5aad83997b93bb9685ee52", + "fe7b3ac50841778d1283fd836996b1865f45392d53b95f3bef90ff657a49c498", + "b89b62e4130fe4d40232744fb0182d477047acd40d32bcd15fb6181ddc890a6a", + "0ae8786dcd5bffb824b81fa038b10c9127b811664e0d9655d537d95377d6d93c", + "8608661859b838a7e8ec16e15db1114aa9db6b141877851e09439c591b46d830", + "f5351c6f978f600be1a71c95abb638bdda6a7f6587e3f66d53bda682c7aa631f", + "b6bcd591af74caa9970d39e0747bf20b56590878cc5b76da411525fd34b71cab", + "bff91200c32ad862bfee68ac1fac4b85a5e6dbba4fd00a7d09e217cd226ce777", + "40e5ebfabd309ba228262431317a2ffa268074cdf83556682d5f5e8c77660c5f", + "c379dedb960b327f684e794ec212b11fd1eb8f20a6847676554be85aa4527dd2", + "e405b5be582345aec0595f1a8a4aac6f938b539426fc7910d1271f3e2d1ba81d", + "e27a84e97deb5450a38bffa685d0461dd90e2fc9c42aa1261da9d3b9fc8fa0b0", + "c8b7e2506c4a067bacda36ed1bba81327b18a08df3fd373be25690754b9d8439", + "5b8d011d0493a5217b74d086f4b8db0bb38cb357c76b1d59441af36806ead1f5", + "4ad67654188a9c920bf0bfe25d22c433035d876e28f79a7c09c5649ae7b970eb", + "2a0abcd054b303b2077ba72f2681a7832712b526b145b62c601741efecb360db", + "bff88f3f33650251f8b9240b1bd94621460baf5d7b224030ff9619a6c708c56a", + "d8846d0b025e2eb7eb528eabb478902ad5990d507837cff5c90b1113addf4c75", + "e57728788dee9191e55c5588236680bec3f0d2cb8791da18064a6cb341b5b7a5", + "f291bfd6644103b66aaa5208ecfb536a28d6209462f98493847ba6454896a369", + "8b0a1b5d290d1069f771d50369e662c5f3c777c2ec3efee722d1a0ea58c6d9f8", + "cdc255d80343d5967d7418ad4edb8dc99ac7138c1621bb8beb0869dafce44cb3", + "cf363923e12340b2e95d7397df7775e3d6d98539001d8262048c67539be6a7c4", + "aa8e17f4657e2aa01025d8c99112d7002fdb1abb086cecb23d428081c87de6dc", + "59faa9c953bfd7f7d5bbfd363c25ed4089fbcce464b2958c9aedcd5729d4883b", + "fd0e1bdf4b5130bfaff244ebd4654e4e0df288abf7673df010bb909286f93ce2", + "f354946364f1449f4cb93847742ad2c2ec82163ccd7fb4e0d5687fccf1a2a018", + "8be151375abca57a5df2d52428068eff6f82dad14d5bfd08a699f8e747ddcf99", + "14a1cb09f11e6401ca5b119808a3176f893db83a0c23fdf9c393ac78139ba429", + "1043a8492b8a8b6a8b9355669a29fc3f2e1e01df59741458bfd3014420df60c8", + "338caae1b0d36e70fb8bbfb3e230a25fc9eab8a1c5b727e1313d61174c878411", + "8e1509bd3f536a9e263d5bbd5cb5d892aa0a860c104f0ac7af74493b9d164bd6", + "de5f3b69cd11a453b41b1595ee919dc2175ef867541c66571e6e71abba2661e4", + "653934f935d080105495891b1889aaf0403223077af687feab1570d03cc08d29", + "0cfc8f472eb4c7e30b17ecf91ba335ac1b479a01154e442d33fd0ef3c0e5dc4d", + "fbc10b32be63288c096a64a70c75dfc76f162707be9f3b09675eeb08d98a4f52", + "d76bf859e647ec2d77a7e5b5f726e8eeef59c6ab7fc1bb01c981b5cde26f3eb3", + "64fe376e3defceb8149411cc4cdffdf3dac15aedb2ae45263a0b94877c8b9ac4", + "3faacaf41e61750af0ac6df1b5a79927dba509d293a7fa2fa9e76bd3a574fd3c", + "a7a80a4cd46db9010cfe1fa8859d658d7b4534832e7b44fddee51c53d6be6408", + "c0268812c0e6cad694d5632f819b5623383fbc3e551122cad33b82536f733791", + "a5a2a39a433131759be0f1f6339c4730de3d401c54c71813066def40e6cfb046", + "61f4ea199859377dd681fd26610068f87e99081866cbf9aeaaaa1163e68fd950", + "65e2e5e77b37be178505f7f40de4e64fd4e86acb9c6236ffec62392e8184692f", + "bc82892fc9c6dc5d7bbf16ba4b2bea2cb9666815bf3f680f72be395384a299e7", + "db5139acccf8dc1294eeb56fae06397f17a040e093d307a9e7b0d62ad6b42ae2", + "43e63ea9672a65432e1b1c21baac7741c9a5f1d6c4e60ae0b4618587415c5a9f", + "75e8ad0712bf9f279d89b252e7fc17ee0add1587df3f355568999fda4dfb0a2a", + "83491196e6dfdec6dc2d09e12380cf55fca8acd4ed8af12012e41f3ac2270978", + "b31d6592a4bedfc5e5d93565a4824f2917326566070ea981e45bdaadaf3022ba", + "ad3b86deac6998141aaaf372f299bc1c39e8bbee4807cb2b6cab7cff32749815", + "e2ea5f557fea88d002756c080dff0350e2ae9c15dbbd423a2be45d660107813b", + "7750f2575cf347fc1b24fdd5b149eba76a438109f7ae02a515e2451179b2c98e", + "c34cafe9369b18ed88c2936cd7cfaa2dad9ff105a9c3a53e49da5e7ad4ae4b4d", + "c7542b4b36dab508ea0de2e1957d451160fb3616c4c81ab967d2aaa97cc0d8c8", + "9da5cd367d3dc450b2c76dfa1ea0ad1e52db56eb7426fa031f2d08d919eb39d6", + "340a3d854262aaf7a8a6bf005c21ae7ef62d58d052c1d108e7e09e708ac3f0d1", + "dc2baad94c21cf7e37a4208a6dddd74bcc84aec852eb308a39ce9f81f6fb883c", + "d21cb6a6f34d9a66c167c4939619a8823be213ceac2bf401721495628d2ea3ff", + "55f3144838496089eb2af67adccd4b27340155cf2b1cc885427f4c7d4e7a8666", + "86ac6e18b9931bd435b38f96d97aed092e1fa8be47089f00bc44b6f7897e64ff", + "b4044a883dfb2eb9f4baa42d259f87d5ab39821470f977548a435cc65897a162", + "d75f0fca387134162a37b5037c5006c3e25c991fd5c0d3eecaed3e75df90b30a", + "4ef8fd941ecc624d1f13ec8c0004744cf907bf91f0a25ea0986294b81d5e45ea", + "015e5322f9f2153091b70b0341912ea37a0da3ed20cfe9b8356c1ce882c00900", + "65f0ffa646fdd7a98f1dde849611f19b2f443703a11ff5a61568b0ba7f85b0ef", + "d9515617ba3fddf4595e395e0e033e9eae484810a478be85bb0eb3851000459b", + "e3858e031fe47a5edc3ec572173de5ea77e9ed292968af2c6ff2fbd98e5d7996", + "4fcaaf279411aa84d92f548b1dfc05458af2afe9ff577221e4b1d82a2e37368b", + "269b84393f62de52b612e2f9922a67d06e523e27d4d2fe6d3aa68caed7a2a190", + "4d179db7af1ec1b6094dd55ce21d26a54e395f23cc3428c0de6ef171d6b015ea", + "1a508533186b12799e418ae46978c8bb8bc88fbd8a478fbea38b86987d197ce1", + "ca4e5990f8a59ddaa61ea319c9ecba88cf321558b8735fc262aaa172185801b1", + "0d48ac9f64fd82bf2e95ffb1eb9f1f73a8dc778417672fbdff374e5093a35f23", + "c2b88c4f59cea3fd60369fc386ac89d22f6998a69b24f4c8ab7fee63247851a9", + "75fa241c04b786f0f2670e0b1e45134aa76445efb26280cf6dfd926f0e77446a", + "b6b80a7ed9aa4d50ec56812cd5a04fa290591976b0adce14e6657815764d1645", + "c29d8b54a265d59ba2e8eb1bed27450e411ee34ccfda853d3a83c1da2fb75b3c", + "180681a90fddc13a6f216b87128055a0947736248d967a5170149a50ec8020f8", + "f65b08dc2c498a0f01adf70e45c5ba21205e259186f928305961718fd086e08b", + "43e8f556219e8e6a7508a2c5ae19d6de0cda7b9f6e893bc19bb68e361c37c786", + "367709af13a857bd2b97701b27c88a7c430a0e791a76c72896b575e017d8d9d6", + "c9207c31bf4517e18513602801a0780242fdb91c1ef85924c2ad4ded7bbf1ada", + "9e48f7bd1d77dc7269d121584eb914303aacf25a336d42914300659e0f67871a", + "8a2b8b728756feef55e9c9bacc138eacf609589afb4422ba2ec2bf9aaaa6b0fb", + "5440c68bcfe6a804c5865c3bbf033033bcabe29e20dbd9f36f5968e2eb0bef02", + "432af6a45d6f2a44d5d6de8c82c4b43ebfc8b289b08866d0c4b4dbfe7337b31f", + "4fb77ac98b549ebda2ba41cf0ee99b55c23386dde4cb505ccc497c4337b243be", + "3f1af916ee3982bb79c31921da5c90a315c9719ef93d87be323bdfb13c6e2770", + "4268889b9776502d948382bc1c9e065793104a2ed0e8aa75b2153b62b4ccc097", + "e14719c99770cf507552d3d64eb822c8c7a6c4d12c769d6cecb6e6e05db85e47", + "70adecdd90fccabd0f39e9d41dc19c6ba9afd11ddb7f09c6ca9c3e568b9e7194", + "c9a94d170bbcb06d9170badf89f2f3533daf8e15b633dbe7ea1d02c62fd2d847", + "538c3cff924df23105e51cb100c844f356d0d05d06e3aacb7c30f98c91292f72", + "bee2c32fb72004ceb24d207bd890ba8fb4126848d2a7bb02ba580c2669f7d27d", + "98db2db86a3da56f16411bf6c2e27f2755afd38673bccc15af8991fca283cd8b", + "fd8f89cfc412008ec0752fabaec3ac72d6c89ad81286980e8138edf6ff4cd992", + "009704c84f0954d45036969fd15c7293048156ff97a76d9c72a08248a4dcd725", + "593b8d1e74c299da61950db52fd3b08f44d6cf972ec05a5c5914da9f230cacc5", + "e8a6d9cff900567aef290b62a57d8d5528b7468adbe2ee0bcef8ac47e2dc1d7c", + "9fbba3e66b12c7c926b88afb5b4a9eb03d1afaac94f673d45639ce9d4dd51416", + "b7f9c83320d1b04ecb9b4f714da462b7bb4e4ab7cf3625a5f0bb497f5405a038", + "4da28a828ab79336ff2e766d3f32e3a5ad11af8203c4428d97ce5c0054aaeca6", + "d1d9ee683589c16d6d043f383ec2023953c482f9c32704fe1a461ba17da05ea2", + "0706b6349613201f5bbb9c6125c48306ff53d4688f64dd994405abad1872d450", + "b22580d4aeda8ed6d73c59bf74efd26c3edbdeb0865c0c4b6ca61db39fc6fcdd", + "978e4abd23ead67962bb223e372c8873f283f2d6bc3b0b0ef6a21fdedbf48420", + "d37e209428acd60797e1e77636bdda5204c56af262d487469b6eb069dc5ba0d9", + "44622d438823091e0823695e5c08b633b3f0c46af0286989798e27530a20273a", + "8902b51c808d5143cf6e368faa11e4e86ff0d373cef041553662da373376ff59", + "8250faa8be69d0ccbc2df66b1046d1ccd6750503855943542b6610a9a6e9cfc2", + "e75d7f1982478da0379f975f964410f4e5645f954ace65f0ba0eeb1ba7d7b190", + "5836da561d17e30faac4342fc555878d144b1108f27112af7f425aaf90f42efb", + "b0d06739420bc6d96ccbae8336bb9b6a28adcac61f1f5712915ef42456222332", + "c8839deeb39bf4e9743d617cf5efc29e9a59f39d681128baa4e900203acab6bc", + "9fca90ccfc4d102cb60b2a6d992c9086a71b1f742dd805cb40b945e598bd255f", + "b08651ed30172874bdb63711d32ef549b43861bae4cee530da74b7874d0deffb", + "f59d3938a18249d47eae4be568d3098688df1c5eee393a913203af87f92ab871", + "68b30e55a656422b4f7757e887a7356781f17ec91acd25d2f062bb9012741423", + "ba79b09ddea8bbdbe7723a906c367b4a51cd8aa47fbe2836c169ec28b4e51af4", + "51b2803fc4d01eb5e9f011c74c5e6b294327f44052e9e56fd0b75475b3f2167b", + "2a40ad807c8ec22752fd4886570008b62762d208a5ea24140813808b64792c48", + "f2abe05e84099e996c1f9a2be789b77259322c5b28a1a24ec418038e77a7c252", + "e39996b22b171c30c0d9d7f3f9b89c8cdde606af69dbf6936ab50d4a8540a43c", + "6782c67e3849c9ce43967ee303d29b12545af84fea12c5cc4cf1f973214eb2d1", + "3477e62c947ab134c3242522425c234318e22998b4f6d7b08422427e36d01004", + "c2020358b71b1f043bff47e117027bc8112d4dd0d65131063e667da9e0974357", + "5e3c95247d735f46b45940288d0e8c0016ee553c4939aa4192ba7e52cbe63b63", + "f3ef5179680400a2a83fa5b01d823bc3906d68ffd29ef18923262472afb8c685", + "5a2f1f9be05ce5402fc0728614f98e6c5d8a30a7008fd7114d2e32f128b99468", + "80489be62cf13a2efe0f72ae08422eb8b9a033bb24783bb075e5a030b12f4d12", + "01aa376514be84131de256c9fd1f3cfa05edd4408a332e699c2f0512e8653203", + "6a59eb72f291d9209aa9ee2580a977707b28e3714d04859352826b7003759f1a", + "1ed1699d9c8af25571a1280b6f5251cf690d0005bbc222829ed1b5c8368fb7d0", + "2b8966e5eafc875e7df9b828674d7adfca2225a5c5458efe5d3490932c0011be", + "d0f30db6d5b92d763aa39c910bfd007d8ce08f58cabdfdb67e38b12478851a81", + "2b5370d6abbb3e0c0cf3d9187e5173d7784622b770dfba6c33b8d672e22e12c9", + "7a874cc8981afc43943b02be3428c2150ca2d94dc2735904be475872fd48bf4b", + "ab8bc740762787a90716c3f1fee072e57031a1525d52ce20214a984e793307b1", + "40983e94cc324c141ba33a7cc5682f3f187d832dd665a2503c4101ce3710b2d1", + "ea73153725b2ef43b2e10a05b7426aa8e241284b1702214e8dd9cd04b38df68d", + "4ab724b8efa9a325df30695daea6894d5da08aaef739f20e716619f4e595885e", + "cceb8bbf3b3bbef90da4b219fe547ad6a3edd9dcd2ae48066f2511a8769e286b", + "b8c442596d32a409e8fa7b4401d52cc8cd2e82ac216d374933dd9013535b443b", + "0a7d2aaff8434564372ad339e2ed316650f490f9932afbc9cfb5f9726edd227d", + "117e018ab57319440ca476a5799a3eb87eb7738a793fde1b95c34d32cbeb4522", + "7c84152e37659e4be0e0806e11fa7ab154e5dde6bba50409c8c475f480016120", + "4408ece10877a6ac3f4320941617b72c27fe122bf0a0b94932bec6f7f6c5953f", + "5b425b6d0c9bdb4fe93fdcb1314b2ecf3cafb77cadea5a3fbc1a377c04c77aa3", + "2352dff4400aeaefaaaa61cf37512d2076e3f5bea92d2ad51aa99f630ef25a67", + "08c9db753634d99a25264104c5b816ebc15b95e0d2f84855d32e52aa90aa5aa7", + "91d5571d7b2e0566426cef2498a5690d32e30268c0a3fc17d81e4d3acdaf65f4", + "71b408acc816438a0acf055260a433b5b0fca4a71e627e54ed7dc96079846c44", + "4c925a3c7a5c74d7ddc2095fd3c303fe9af708cc54ec1992f89719a45dd2e98e", + "60f56a735c8f2f31efd7580c90234e9fc622efcae366849c63a796bf80006a12", + "43961c4f8130c54f32b45f9ee39fe88faab957a734501e7b49e7d7ac8f81ba91", + "5a503cee0a815b1fcc4ee6000b8d88e7fa176f7fff7ebf9abe82379a9b87037c", + "b19e6f323d3ce96402d8ced832944a02728d9df0674a9a7bd8e18dc8896de94c", + "a743c955a7b559a34cd8907b9eb7a40d86f8f15a58e90b91c9fd87414a91b3ef", + "b40cb00eaa805c0d27e86cc289e34dd354d820453382954ed2ac24b27d38c2d4", + "e6016c78523ce714a360f77ad95b39bb8a724277430e6d2ea5a2130334011727", + "e8b448a80c197809e559b30fbff6a7a99d1bae7409ec00c766a129ab70e47f5f", + "4b42f9bb88185504e200703c9fa8dfbaf850978a60827cfe7688c434c502de0f", + "d48a1aaa1f36222f4acbaaa8218e249d5774acf8abea087c9e2ee9e21dfb2ab1", + "cd11b4f441f834863a99988fbecdf8b19be665edfd19ad4db62e9d290a98bd02", + "2d6152c003c48f8f6a1c2693dbb5cc5528e7e164a16beb798c772dc85bf2ee21", + "0f9af43eaaeadb7118498e562e45be1ee1e9b7f3787cbec3aeadf671a2c3138b", + "e87a2dab8e4945b8ad5fb7866efc8dc76a990638822542050506d1d0ce78fcb9", + "190a2cb2ea8d06d989d23ff075bcf61b236841a27975f89bdc085cff823e55b5", + "9b09d9ad2f3a069a4c9b33e77a833fdd6605a2095e8062f8b79a5fe197dda466", + "06dd4f3da3273bd8fe869a976006745235347ab53612247d3e0428fe152787a6", + "8dd9a7dcd863f7a8fe98ed2f452615a74560ab7ab964ff161834a6a6d5b21b4e", + "f68bdbccd9955c40848cd3acd5133f991becbcfbcf167e5d2018633229d1c0ee", + "d1990ee38345d528f0115a99aad45cf41d3a579ee1be601bee3820f181819f4a", + "b09339818aa6b2bd5bf955109969d4ed43830a672c479cf34bca1661e31eacf1", + "c5dc68711d6a27092ee6db8a779fb1972d769a4d571b759e6bca257493b1031e", + "6f7e4d57051949b2abee3b329b299d5a6f555d06cdd83811fdc7d47531ff7179", + "45862ace8f36c0a3a6d4326817f0f80f3041622e85e055e2eb89dbd20d0df324", + "b57841327c49f6c475534d0cd18ff578958790ec3c819fa5b97d8971252138e6", + "e83615f0779683ae32d0f019b20cbf2da935403f509bbb9d2856dc6201b613bb", + "be524d2863d41baa171561328c9435163eca92d6e085ebbc29a4e1e3cc6753ca", + "9dd3c020ae3e8be0f6fcc97e6fb0e8c76ce9694dd5ca8a2e8a122862f552a421", + "a7e5ca5d0be1d24c69f4992a3c1a8f6acee7929afb2538045cf737a5da62898b", + "0cdda68b16cf1e43b41e2d2eedd6547972eeb5491930f9057a3c07743219c1db", + "5c83bb522e9a09d6c81af19b7802ea30ad22484b2ef0c609ade92089e7cc7248", + "078a6ea5a4b2be65c7c423f7ad5e4ad909248729b08264b8f880ac5d90f009f3", + "47a73b39d4c6c631d148b9cc31dd43311d20d91592a9ed38d87579491cd9d855", + "7c625f9d16a27bd30064682fc896a15c4b504819233610fc4a88cccd271059a4", + "5f4c8d2cc5c67a0c393493474e74f770f8c09751cf4d712f0c906d9d3903fcc0", + "60a628f0347932c8679436a3990fe3dcf4d02fb9c24fe4fa9754717c176591e0", + "2fb12765c5e1eb877c55f574c7dc61a4123ebf7c7e72cec7d7e83420fa578853", + "2ef3b7fb03472c1f5a850b40e9b35d9a35d87f05292c1d0d43e863d7e7ec6b4d", + "16c54fff31b4da393130f6eb18111392a96e85421fcd1e928e17ae6359172221", + "56ba9c544d0ca5de806803a36a1a19f53ba914f286d92bce307f91eca1bf5652", + "e8df51a49ab47130db5332e1dd3f1ddafcc2ce80150ae3c37eb100f5627b6bf7", + "3df4f7f14f87f1ea6df31b9b8269cbdcac2d8590a89a2753d7bb11fb8ec576ce", + "ed2560a20088fa40572837ba321394fb3665cc60c15b19a2fd07333101636953", + "a5ecff5434cd0aaa835073066abb2b9f9e493dc4cb7b26983f93c94016c09297", + "af3ef059dd49490d483b8b9a99b245695483aaedbbab25bd1a54852a26b28802", + "39d2d8d4da53e0c373a1e39b4847821317f10d9fff8b7ac598b59b7e79e2be6f", + "b1b6815684cc275278a6a3b0a7de9d0c7d4216f8f1b8c8f1d075be64f70b79f4", + "fb2abc840ce8866537feb12531f420dc89ca9de12b4e192e1ef7cbe765cc4816", + "c7b6c8d3d4ec9457b4caf29f6a6198f893c51263d73d0b12e8bcf5630fea1e7f", + "aa5ae0d35bbba924165abccb826604c80f6ad55781c49e6016bd8207196f66bf", + "650d0eedab56b6492743e7c5692651e8aad37d1a9939963141a67482a686e9c3", + "22d0b3451a44adb8ef87a116097e3ac46b5f8345ebf0e5dcec960d2d55a72d93", + "e3110bee29e6162f431aa68c170d622f819bc4e289f6c3e1d695cc444c8dc171", + "92fc6ae91caffeefc1e16e816a0ef299e17c63a968d41bb91b7a6f587d34f8f2", + "76d986dbb1668f0069867df25251328e1aa15e6f31233eacc856e61b5d328e6c", + "560b821428968d6304aa517c6b0df4469059a097171e7180c0bdc1de4c8c2dfb", + "199db247cd1e61526d67823aa89c7d3e9a849a1c48983902f4e732d37491ac95", + "f3000de6fbdf5997bcd5067bddbebd4c1057346a69164446e4a2fd0fe575461d", + "a36d62775f7abac51834f25572e05a0238de20394f0b8a5cc1f33b47984c4a02", + "b6df530ded76cd3cac5eb5f6516b7b5aad5ee43beb0876c8f1eddc38f4e173af", + "a939753b3d570927cc8d90e512239cfb6e52d81b5d56ea80eb4d0c46572d9ffb", + "915cf3bab38606e7266a5f7c2179ad469b07b134765900ff6ca2a5ab83fbe80c", + "c084076c1d75861928f6a28f566527ad2913a2bf829489f57dfc8947c368c50c", + "b71e574bfd980be24d08395d32430a000953a021556ffc4d7693190c00e74e77", + "4cb8e212261c1ec6fbc52df8cac337d6f5d189537645f7d5a7f911db882db716", + "533abcd8780f59049a8462ab7ef505f5ccf1d342150c30dbab5949fb084cdf21", + "db533c3913044c03977baf092f0156071c2628208d14d81872162436b87123fa", + "ca8ac0dbf15bef994221f78c0248b9a6408ead1166e623c6db7652a16c016c06", + "0990b3a317a95d36b6b6ff1fc6736fea01529a39c0fe06e49b7fd564080b6df4", + "787469298f138d1c490251895a85d6080e52aa1df375643d195dbe7e87847949", + "68a371372ba0f489c8ab8672e257f265a418e50c6c969bbec4b24105850c371b", + "f8ba30581f3cf31050db47b7a43a5551d13b9ce7001c896bb79409f4f1d0a31f", + "23a5c21151808ad600e97139099b79c3e1ce23ac1252db87b2d4cb88359cde4a", + "9886c12c93ec0ea5d14478fa4a9a38c4a1025f8b9d595deb371d6aff79f93b04", + "4e4f81cf1628b6f43db1db218773db5f7a405311aa7ee5ae2072148a867a1437", + "a019556336364cf6a38501be26e917b0aa2cc2c37c137fc269659aa44a3e5ee8", + "7c6b6a1324fc40c2373c6215ad699f723b826f02397eb6f6326c1a5ed558a115", + "bd21001934e50a47ade3d713cec8dec036d54da0a976ed3b690ac080a7bc9ac4", + "4db0292758deb6ab35aac12fd6387276b2f32cdc859a15642f01931c845fb0ef", + "5431a87a0cd32b11db5ced545effb22f220ffc69a60ac552844db86bc7998e84", + "c6f343782af6f6ad784f9f85c1123fba0b82ac07119a61ac39ed2fbd92fc0a90", + "c412d2dea34ebbda964b17cc12c1da70e7dc428c92eaf494e17100e9ac65ffa4", + "e9b947aba6755de52a67725be3849e3383e187099aeb1bef5315d22609368b23", + "0b2d1949bead9e9995b717a821f6e5dc3136857b178638350a16c1a32149c6ff", + "dffb51c4bc98c9f0c07ce18a88877d48947706cf57f56cc6a29ce82cf2f74c07", + "97dbf9a48f3c92fd4674b20ed6f635bbd92af003de523feb5ecc4758169e5857", + "cf701be33d1b3abd3357a74ab2f7f03fa78f7ebe0362994256020fb1fad75251", + "fb26930bfdbbdd6f69be65c3c01536e09a30cedb747b69719035e31636e47937", + "5725b8ebf2345fe7e660579ae94b84e251259487da4428a5f1f0cfec19db0639", + "61b92f8043e5a035b2144fad7b1df3ca7130c56cabbe0dd2757dd737719719fc", + "35a2f85adbd0b6a818d84a16d8ccbc0947bda389b6cf43ce6ee9aa9b4aea19f2", + "69dbaa6d8a1d44259bf095b55311dd39ce028ab20de30ca49b1a173d6171109e", + "3b68203efda022be691480952c5132129d514b2cdceb0d3a8f137595be7f1c25", + "388d3dd82eecf369794186b42c964871575c03fa9772d57d31280d678f87a636", + "6b493f049d19b3d1e268babf0211d48abd018c912787a913ff71457d54ac3606", + "53261340605f5e63ecea85eabc5716f31be1d16d1c91c04f3a090773b288e62f", + "7bc9e1a6b36320bf97e60da91091c0ea848653a56cfda13f129e42719623c500", + "7347ad263d90e20635eca6fe1bc89df06a4ec273ad50e1ef78a27fb9fcffca13", + "fd286c0a1d9e4a0e0aaf97b7f2da4b219e385d7a9afc4982698574d72ae49daf", + "0f42f9f37bf77fc47e1c75e0206654e0059703f2b7dd261f91719e49e586e7ad", + "5c1eb8efa7c26ebb6a3e2cb19148783df0b7d5dac0e80b3c793ecb556166a88a", + "0fd0ace6df8a7ba03aa6d52f78c3e58a4720a3852ad936bba80e08bf7c61a287", + "020d473e1c9504366a2204d566b1ca6c968320e30382129f95a40c739cba7f19", + "ff7051698eaa84a3ffc25d5dbcf923933a1a59730db33e8161698160a090a45d", + "df0b1d015cf77e47512cda3d49be662782e52715fb747cd0f73934109a066ff1", + "930edae2fb341f18849c9b8aace01d5ed2cfaa013f59647cb542daf33ee60db6", + "acd5d0212d8d1bed17253050038a481d968cbb8007c5c69f35d328cc887723c1", + "17f76ba6af39c2d64b95554ba27b12818e60284d166a9da60a3110091c1dc3ec", + "e03914821b7b6185e239eae45598d504558175443c4f34b700c2b329beaf14cc", + "cbde6cf03818faf19d93a082a509c3601a6b043a66a222d389cd44d4a91d38cc", + "c42abe41dfa793e60e2ab797e626bd8a5904e03633b61c513c9f80c2be9ef0d0", + "b47f9040a5561c94bb5c11ac8042f34d80e144a3f5a8b7c0e47d7aa3c10812ec", + "07f44825dbef5d2c5fb089411e2eb2d4f7e7eeef6697852084acc7b1f48aa77e", + "ab143316522be7e11b267b89677251a5a1d48ce7c90ee27a6c66e1857d71e576", + "3e03c42ebff10fddf113e731d91c96cba59d8d29acb8f6e63e0fd171657414d2", + "12a073e1548bd7551d477f3ffaa790d42105596f7c161a623650f1a053c6f053", + "4882fb1b192fe817b836fff3baf788d89442f75d3ae7a529297febc3ea896779", + "a3b5c64eb6d70663ce13bad27c28cfe46ecbf721aa12d667f3903e155f37471f", + "19283ceafa4e91731909817f264f997836d529c523881913fef99c04c23f636a", + "2c9ebde51c783478616c534f8cf30c1d9bcba627e82873678054f8c05f72cd20", + "6addbacf1779166778a472eafa5388de1e51765c9264db7f44297808f30cc940", + "33c39d4cf80eddc5b93cbf11f5cf6de02023709b71c3388dfffd485becf93de5", + "73d7856eb00d8f0eef1cc6ebab299384aba68e5e7c90e4526c4a33a3f7b9725b", + "f45968304cd3eaaf430b7744dac3bd2c287c51ab1418e02973fb2f6bfd3d7847", + "1e18a797ff5a58a2a3251358d7ea2e84895a939dd63fb5a3c77753f324b9c86e", + "3ff531919376e2ad060436f9d27129b7ef17fb8ff29cfce1ef3726833aed96dd", + "92a1626588c06d5a3d74a59f23e506460f99323c09d35bf5d49bd73450803f50", + "be288f4cfe34bc80521860940d76e5a42c85f68ca190a4ad71dcdc18c4198103", + "9339b6786bf2c8c1dd4830c384e03dedac22e92bc1aa9cdc3449c674bef72ca6", + "1b22a0e578c641613e3602764129e027e101e2d423d9fde2a6718a7dbd726eb7", + "c6be938d80860b8ccc96ba087fdb2a00d980808a61dc79483710ba87f1529dde", + "4bbb241fdc1feccd155ac9feb2ab91cbe714030cab20dfbf34318ae72ecd4a6c", + "706c4c5215f54df3c0c256e9d6c54de897716618824d1fc630d00d3af059352c", + "93e883284fa263b442a033252e84dd637a6943f49f9db224855327139dc8417c", + "689dc122cf1c3b550ac11e0041b45844b794a45c31a2896a4238242422b23819", + "1aeed96414641bbf27a32c1a94b5bc224947f87bb915a53dd2362a5baaac9ba0", + "0c0f53761b2c3f168b01cb9cc05894cb86ee53a02ff0c5fd5f160a8d0d15ae76", + "da8b72cfb9146b496da6719d87da1c52f295086935e1f15da60a86b24bf29b97", + "2389058fa5e0174f217260522f49d07b76c7758b0d3f7296809104cf78561b40", + "0a59439df43ceb691a13038b87b7ed5ed2d05f7acddeb2cc502d6df537b71311", + "ad9989dc2e5e4d1a473e2f30f9581ad5dd161f68765adb6d2e70c8effb23f3ff", + "466309e21fe5c8555a231e5214596e196ad44683a8e8376e453daf42b8085d9c", + "a6ceea7c560556cdba4d7b433400688ffeffcbf27bc7d05ea507dd2d4ce948c2", + "b77e4ed4bee931d43571d6f22f0ae253ae2dc63871c5e4845c6676c7dd3f0eb7", + "7ebef185856fed824ebc3f38b79f82746b2983f8106c2ca6a8b64e410040de10", + "e9a0458703175d02b8fce2b8ca87d2a6062270e97499130aa81aea621b42567d", + "ae17cd0fa9460c9caf2c158e1ac809d0baa510933aca2413c316840ca42d69dd", + "0d485a3ddf329e8b8dd47b569c7ba6faf17d4dbe280521a520ece56136ecc218", + "20241e5f5bea83a9efe54520cb4e18b2bbda3eb83b0875f44c62994cc2f4a481", + "ecd706d3f483600f37f3b2b268cf38033db1290e0359a089e7dd44d35300eb39", + "326a9ece9955f2f872f0f6e401ff4281f1992d9f22f247ecaf25a44f5661c732", + "36f0d608c831ea7365b0ab0f2d78d44f9b6cf0a3edda625d02a0e8db1250c644", + "fb476cab0554ccbd17ef87ab086fb70310f1b468e61050e4c47a9c003f71a88f", + "eae0d52bc60c959f73cbf3ff7a84f1005b935e3d71b64dd076f23851b61e19df", + "c8320f5862f6c97350570d41ac318ab729aac137043d0ca73f467eca670fd2cd", + "ad83f844f80d1bdc54559399d55f09160e3041f63bd85f9482ef0e0159e576eb", + "faca90225e0b75e9ecdb380a4f45937016f843f188f48a956b24601dbe2e7eeb", + "da4e04a00f8b7a2724c60b78a8df4caf6d3f65a8f5b8a86561ceb9933eb87a72", + "c17975d1893a8b62915a085e714f9c6f85d9442f7916ddec6a822090c8dc655b", + "7b7f3cb7bf35478e8dab8f33acc8746aa6ed70189e0daa8e893783deb55fc50d", + "d0311b9d76278b80d7f55b8c4bacaa8dca293cccea20a784ea9fe254abe93b5a", + "91d99863528e63d01fd353457a910ad683d11614458708b31fae2454fa224b5b", + "b0ae1e07f65c9dd764db153aa46cf42f68d780e4b28e642a4559ec90e8e3cc39", + "43fea848ab8ea34e591ac9c9f98783b3f83a812a9bef6339e81bd380d4d0b0d9", + "80695fc224bc3d9f16e1be9078e62d91b1769c4147dc44421531a213b4a69460", + "ebb6cfe7e39f666efb4e256af94b5b21aac14902ef3c23e6788ffb32d16da24c", + "ef5b6beeb6cf57ad290d3be9fe6790221fe4685d99ced85082f66cea6b2e2d96", + "a4556671f393544c118880d5e2b6e0b6a9d571325e35972c8bfa5ae70a9aec8a", + "0df55165d1eb0fdd4b62a25222e060b21a4e5be7b8388e29380b86b2940efdad", + "19b60ec413d47f58a62173098d1591609281e701dd079656a09512e8684badaf", + "52e4284b527671369be86b4b20545217254f85faaa8abe39953b59fa1557442d", + "8eb1a4325c5783a09e0febbc365313f3c4d35a2c1618ee6532572ab2ef1124e3", + "48a251c051cc0c8b051b806600f00342ab81e3aa111e066e74adc044502379f9", + "97fefae91a85838a8b93a4a8cc0edadc2e50b43c1ac0e36a259a40fdf8a4e213", + "aa1342bfc905f3f255c44aa09df477228c41977c060fb5f936fc6b4838c5be7a", + "b9e6594d64492899962352ee5c918c3ade3efdf92e16bd4320e0da27ab3ce2ae", + "1a5db6b7d6da5386f76ef77cd6ddc99ff67de917819afa746dc3c5378a95f30c", + "bf64bc337a886d5d799d839f03eee210acab95f613a17db30165d3e249d07e87", + "37b794fdf56c4ab8d2b4d00506ae67f02060625d55adf6c208cd2f53b6787cb8", + "7df41b919abd69e7acee85a552ed81023aad7a4f1773b35f104af8d253e9020e", + "71be6114d2cd31bea00baa69981edc59bfaa7891ed5849178f3711f37e5a9223", + "7e8908c6f9e14300d44c2254d022578f689d8c0cab56ad73ab97c748a71e7371", + "06a70fc0c9e0e0a3a67dfec26eb5367836dc932f20f65770cd27511f76a4ef7f", + "5f902ed069cac194a12c903fd9231b3b9b73ae499e47206179a5db78053b7d48", + "c4587b59006d177ecb76f64a083c8bafc926b243a6e9ee6ef12bf0f3fae367ff", + "eeff57364b4cee2e43ed7811728c6e0dc155c94bd8630567981c00e7983c202f", + "d9ed39b27fc2cd3e1c3bdda317c856557795363bac22e5475f58614be9da5f0a", + "5fe8295650a3ca6dceb6adda98a9b2a52c8ff5aa2b879dbe74dc479c14df783e", + "bb74a5396ca5059aee5f6973f760285858dc7ee84f34631100b641d8f48b89b3", + "bc357b63fb90baaff808482eb645d5523323bf52d98c3fe493ac8eaaa4773677", + "2d052d15ac1ce4eae8e7988c586779ca83b7f20134899d1a72bc05bc94c0b35c", + "ec20f72f981ef2d1397d3f05c0cdb32110e4c7bb9b876a9aa8296f5daeee6cc4", + "039cb433d2315ab0011d4f1b3d040ec7e1f1006fc3278b96e9a8e0491d1a9d60", + "2dcdb4800462a1c11c0e832d04a1c49d9f62103f2da332286c48fe94b456b92e", + "4a8b6e2279a7392cefb1e7da03b42371a678f84c856de77cf13ff9c0891d9b00", + "57bcdcfc0ded16c30a50204f409dfc81df4ad4b1fe673d99920d9f79a397d8b7", + "0261b6d4b9c1c5a585ab93951761c05ae9cd62c56359dd821486d2b1fbbb3177", + "2a71c8ea5108d9a459c6ccb1a614cc2546ddbd85efa1eb39ab3ce0a504cdb916", + "251698409786d137dbce1f4490f83fecedaf384809eaea793c3e688bbf61811f", + "2ace8689de6c19ba00afddca95b6c4d32b9929390c628b9339a77ed21dd9ec97", + "10e81239fd71cd6fc6a7b858986c7c4e1d064811ffa0cedff96ec34e3fa9f454", + "1981916f528ccbc3547bd0daed092031c4045e1d1426398f88298f7d29e61f8b", + "271cf2cafb0c86c1058d1247771cf90cd398916ee1eb4988b19765673a2c03e6", + "9d086afd05abd5ed8e554891229752b2bd98bb124d83e5c517c727a6e41750fa", + "5f2c7ea24040a74f3badd941fc602bb8ba2c2f3dc8a6f12bf3565579587b5ac9", + "0cd14ff3e26eb0253503592d3c2231f067c0d34c9a08478b3ccb6f9708e63bb3", + "7d8c41eb7c106d34679fda959f40538e268441214561488988384d52bc4959bb", + "ad844d292ee314dcfe7b9673493aa46fc09437a3215984514f7d6e25516d82e1", + "1a2a86d0c46010632d2cc42225c28e81d33831a762904c07fc165696e0b21f56", + "dd5549881dea36dc21d79af4fe8fd523ea7198354b09f11d45cdbc16f2f1a593", + "f163f190fa2603da18b5c4d6a8ce38135027e1e27765786dda3d4aea2a9cb80b", + "6e09fafb8b6e87d6189f46e244bfac72ac097f881fd3e20548bc9b2b77a06494", + "050e25827579544b11a0659b33779e36091a9386e10529de15661476f621b4be", + "2e106b4ee4214443a32a625a8050bfbe23c994d5d11f7c06604d67449dc4b65c", + "f46f7dc3ed0045f94584f0638fed6b4a1428e757d0286e64a7d09b90bd379f44", + "4a2c43aa7fa22812393b64ef4735c4ce9dad96b2324d06204d17cd489d7ce412", + "98862e2f2fbafaf00755c99a60aa0476cb449041ee71556e1e7c6442e149e51b", + "4c118375e7aac9cd504042c81c94f58f123924bcc2dbdd07efdf3ac283bd06ec", + "bebddec9428e7802423acb00e58d998f5daa5a26bfdae57697deb463e9e86feb", + "53b03c24b8c7b3c56e56ee1e708df3eeb032bf383d7cb1b2d3fd0bb11cb984b2", + "784badbf46476520b5c6635401f74e99ef7c7a003a393aa1fd57867f185dd721", + "2f3caaeb46d182b613605bcb8bedd3831bfd1ea4e7a041c4f76e0d4718aa9eef", + "1b3aa9204c47e2d2ba2657e13382926d2ead35d868353551eaf9a66a70c669ec", + "c9f2a7d878c3f80d7627ae2b832007dababd27fd2fc13709901faebcb14b2932", + "5a39dc81cb0b6518f00f5c66ac659dbd72f881a78e0c0b13dc88ade430abb90f", + "2f0ee5fedfa55f94832fb2744a80af32bdbf7708ba65a3e0d08b446358da1499", + "1d07c7dda8607fe8e06cefe30123fb4a38302ca4e091f5ee9df4013778e13fb3", + "3fabeb2e7e8cb221b62d4e11ded6d5eaa1db1380b7639c943f60a1c5c30cad09", + "51a1fd08466d6b37cbe7a6bab184c21ca50c9feb5938283d58d89fdc1035fc9f", + "0708c2dc87f7ffaecd46d3c7dac910700bbdd5f9331f262819ec9fc90545d3c8", + "2d8f59f27fbf1306ba8453c032a2d8bc6a18ad2d8f3fec4ec260af16f6213dde", + "3a7455c90f216f2692b108f4c907cde0f64872ed13e6f75b44e5f857695ad824", + "5f1fe505ad82e5de86f16977be619103b511b0ca09393daed964ec61962cb942", + "3decaf9907eda934c124f603d3252929ccb9b99aeacf745018f2cd612ba3dcdb", + "4d232fa8d81cb6abd1fb6806b45c069b7fa7011248f55d1873daa335312dddab", + "55000d6b9fd4132be58fdfcc87b55b28dbb2bc259c33d50e03a9d470e503553a", + "225d9a9f991b12fab890ccf06ee654afad4878a3a8c0bb3ddfdd54af3ba74ee3", + "40df7f285dccf966031f1e8815bec7473a748f37c9405ad98b0ccd40c87f986d", + "c4156b9659801913909aa5955548725ed2a251e9d3b3a587786094dc299a8f61", + "5dc3a95d6f96b946237a9977b4c1e05b24799729f03c191b084c6118106fd712", + "118bf0b7868f02b1154198107b4a86873ef471153967ec7bb11341caf70c4355", + "1ad3a5310730b0b698512c8c7d3e7a8552f75b5c7eec4546860bfdc622f75e7d", + "fb74a1c13b1eb19423dd805a4d85ee771ecf52e3956b51b0409cc5bbeec34569", + "7405d158d51c83cfb8dabb3201f692e3bc089f020cae6b62a2af2c88dd8f03ed", + "08f20e5a8dea1f3217c990bc112fe510ca5aacdefabd5a2a6958339abb88ad7a", + "dec3f7bbee141e55a68d1d164e891d9bf832cab148061a1551475fe33c1bc868", + "0a311678a6266de62ceb20154e6ba5ba5560507d58d8c5798474967b4924651c", + "b4f48fd17a7cd9e0b26e90a8adfa2f9a150d47e9a203cb89df114585645c87b6", + "26a5c76a25d02b0feb4b22e549ac88447abb8fe7c86196a73292f13d8eea61aa", + "2f41b58911b04c3418bcf76dfcc500d03a55fbf1749ee83a4e981fce4e32eb4a", + "411a18b6785d5cabf9b666a9a70cdfc5a1e29228f92f80b9f8d613face0195f1", + "b17d0a2cb46dcc365e065267bbc2cc36e92e20bc0ce24d144089d69282e6fa19", + "30ede26b25bcc2e6cc42f248386c61499ae477d4fb392ee289238c40c88ab5ab", + "f1bbaafdc5f0e00a5dad95c9ddf659747c74d093e1cba8a0e72f1db1d5cd904e", + "09e411ef140daba69cfdc2c3c32fd84cd572a842f53388124b51aa2eb1e40fa5", + "2c408b685afb2574e9fe2a212e92c638090e851026ac80c9a639daf234fdb984", + "a342b54ed7092264595569a37a5e5140a48d5117f62833de3dc1923516d5b917", + "b90af846ef17cbdfdc06399f2d6790194fd2d781babbcb2c3ba005031a278650", + "16c65a8054f7c7c6beedb172498972f2c3dcf0e8da240cc8f120dcee7439c95f", + "8979da949593c80f9164828107f04602d70ca494947d6ca7722180ca85c8c0d2", + "eb4ef64a1eb138e6ec7414b3d841d24e61d6aca94a870d3568f89bfeec28ce5b", + "8db828055ca1154a1c1b60b992299b2a3cc9f9ff217e15a329b642c8d5515344", + "5813ff09a79cd74b6fb3307c277caf7e80f3506afb677eeec65555b7fdb8bccb", + "e15883831714acb3d5c08a3898ddc6280114f1b41c450f6e93a27bb36e7c6766", + "95ee3e0acc204a6bd5f5b484e907056695cf5ace25449fabe87f25d61b1262f1", + "8eb0d5da9c247c962eba9081b9b58413b8f7aaec03df2813c77ce44573a3ab1f", + "afb841db4f6c64fcfda654cf058f0a883166b4066fba6be6df5dad564da30515", + "68fce267894ffd76f551a169c9508e53810bb12e773015aa4c547a56a5806fee", + "6e614d1afb783e6b45301b2fa03788a1fe27f2808cd2b513eabeb1226e6241dd", + "6bb0cdb7d8686d79abb5453c3f5045c1acc2e268b3f2b32444e60796a18d4c12", + "9b99c863068f24297df3431025ec6564b66f2b9f64c1678b528a1dbc4bf71b16", + "204b6f2f3ec5bd0f1907fdb460e4ed6fb0d25de5cc12f777a1ce10aacbed40c4", + "615fba5e47ab0d959fbcef39996936da656e2615b954f03b61fbfaa8e1a4f500", + "529895a7de063cf6e2497d30d849a8df3c4f7339e22a486044cbb3e7496fec22", + "b7fd2e4c0b845850f044f32c5d5123af9d5eaaa693d4350c4ca8758bfb857b19", + "059e015cff4b33f019921f9242533cb45cd65e507ed882205367b746b27f4442", + "1b79153a3a25bc82c7f52a577c140d85854d76b3268e332b5871a4de4eaaa47e", + "b9730c36bf7402a5d06c8226dc11ebec9c0a4bd6a23762a6e9e78d1b996a4630", + "d22427bf91dccfacba55357d4a8038f797eeff2c4dab56220cb00d9ae897b783", + "da19f42f6dc60fcc3d075d6f38671949ce2dad31b37496a638d341757822e92d", + "78132589eb98ac63e53a329f7cee32584dd447bb9fbbbc01e27245ca29c23a23", + "e467ea63a727b9c36e666d435664875c822f94f047f60ac0d89f2733bd4d1f01", + "f4f89149b1a5779dfdfa3a9b7dc5b88791deb32c20db6d611fa013b9a2eade6b", + "7b40c196aef97aa032f8a1ba0b88aed12baf4331acacae6513e8f4fbb102dc98", + "dc87f4206941dfd0431dbae606358b03741e52c9c9830017847042f99caa1a89", + "293c650a8f2b442da199ba6dc31cbc7616c09bdfcb685d216fe5f6964ebdcc19", + "cf3736739c87082a71653540be254cad9dd2b80c788910ff51833053de0f6833", + "b7904a9d282ee147c41a87ab1de0c68f6fe6e8681b728a50b07dbf82ab61990f", + "ff43760bacfbd8a86b77ee50524df729bfc322d221bf39d73fbdcc5172be25cf", + "94b19511a901d6c9863b4e698bd3203bb45f459a706f17d5fd0217b7d4d2e880", + "5fb42d90123e7d17bdf84717dba17f8d6e2e4cb9856ebcb5dbf6892fd227d4f8", + "d403da452541afc98ea45671522db8605d28a1373baa96279149d70fec56e8db", + "c515c1f3132d7124546c2149d2f96bf8899954ed28db737d81149cbd9f84ba87", + "7559f506a7dfdd3ac7f13dbc616629b56b88f8e43e6039205182b17136e45e6d", + "6b3f153c83caaa5f7bff608f4fbc514feee1ad49652691393b26e60a3860ac49", + "b25dc960443d800d107491ed43a224db6df66c12b02b7dbd3415ad4cf38c1f25", + "a70e10b5d457c0c10ae765d7696e96d1721bbd0557386cd00db27f7dd61c8039", + "c12df355cfaa94c9154a29848e53dfb2d1bcc7b68cb1506d067f5feebeca2134", + "c9a697b7434305777c8068af8b5bfd654d74bc5ad82220f84fe16e1cc9cb2173", + "261dab494a2e8adcbdfa76b171a1dfeae0a70cfee528d781883537c35ad37546", + "df2aababde59eec1b7b499858984c1204557f599659f05f6671d1d66d2273d68", + "36bbadcddfe80758e7b91dc8bbd2d2cfca89aa1c50ad41a706c99bd192c1042f", + "bbbd1e0d041cf1b340f9b0873d876ead1b76c60f593e8ba82e2d700309ea5b4c", + "07708bd4113b5e2773ac0d65323a793e5dcc366b1260eb55f6ed80f6fb3eece5", + "b7fd39d21af1c3ff30225230a86cb382680bab72cd83c081495df252bbd31dca", + "a01f7348d23cfc9c72d4c6c8d41d00f25331a9f6b28f704e314f46b9a5fe8836", + "e14b6869725e9f7c8b4d0fbd88d1cbf9a969e800bddeb3b426ab13a9e1c6873f", + "ad16ff69baf5690783aba8de17d09a92af4fe62a985e33c0969ed734d09bede2", + "d3edfb7f2ee7cd654793fce245666efe24655095b9098152093b3e5a12cc41f7", + "50cdf981025f02190aef3c09b5aded26472fe5b155c689acd1600b6f163b0aef", + "d944eee476fcd32ecf4d85d5796e17ec2adca8f9f6ce1c1f66687e2d99a29f2c", + "6eae57da9514dd54a3f5920e1891529982d88c17e7ad6f6d8d24c731e1507992", + "ba0b8bdba07211878e29c71e21bb5aba5186e50fd45b4303f846897b8c409ae5", + "16828f8c425552366cedc41a7ca7f0df1c5e5a9dc543bfd9b0df65021d087a48", + "338222d8ae91833de9008c65cf519b1d021c6072d09cfc08f78d002300b6dbf3", + "c0a24805f980cbf60892cd89af249fb06c079c694e3cd84f0cba7f21f9e6fc9b", + "fbdde53f5541ec1feec1a381409d5ec9c6baffe97ca0c7e06f24e841d2b1161a", + "1752a73a37c14d5080efc1ec13bb1dccb9bcc0281a4d95cc2ef4b853ecfa6c31", + "fd2e0c2b50b472b90d7f4bd119085224219ee533a99922ebd8cb0f2cbee9cd7e", + "3a1d28fe96af222b8bcbbd2e937ad0d1f4128c7de8c7ae4ddf7015b07a1f6bc8", + "7919fe4c1265bc194272f2d3e0a0a0dd4853b9f318baf6287484549b01404b68", + "10f6bf39d6329af3916a571ea4ae1de70cc23a9818a866be45c267284d3abfd5", + "cb0c691d7266460c4af283861919c3ee427c09831e70161c0b7485b3f420c051", + "69d7916a1618b94a9794dbfffbdafe155f921b57b40c6a55e8ca17405d1183b0", + "0c59dc8c3caf16b480847e086cc53f4bcc55c0ad0b2d6954f943eedab457c86b", + "8accbc6c5c4abd38dd2574cf0a84286709bb377aeae9d50668b2145190ff94eb", + "66213a6bb4469587379b204233f5c4cb9213c9443c6ac8a8f5748f339223bcf8", + "1512294a5bacf0e03dd013bd22c0469b02c6a56ae6ab03d089d1b59f9bf47ba9", + "a5ed327b1392f514a7ca393657194e0cc1f5f454aefdba63e867a3905c9f3ba6", + "af21c0215b6b801617c9b590a5bbca4874f5a23e7fff46e2fc380b4e501b1b42", + "48d97a310cffb3c3f576b5615ca7d30491461980e9e6ddba01e9ab8b69c6fb87", + "c23b5db245f1cc4791a6a7f57dcbd3a72750431e1a67f5f783668c8a2825a0ea", + "ea2c2b9190a3a2e7bca55d33bdd1566863284587cbcfcdad74a617a571d006da", + "f00c701d6e9eb10e8ef79276cdc154e8ba8c4422f1d08ff330ef3f55d054d337", + "43a9d6c9ab48dc22ca3c9cf8250db069e7513537e53cd632424035f96371b52a", + "9668811e88849fe80a78b79fe33a05252ec3274a8c4c924609b8c85281ccd46b", + "f2f93449bf57bbd79c852a412dc55922802044e40a10d5b70b940a585ee720ee", + "d20bda52ea5a7e785ab94177f1d90f5688d21b3968326e9909c8d26cfe160b6c", + "1eee37e54171be9e11fdae188b2edfb0bc024b5f94de55dda4b175596d449bde", + "0af11c745a8c4891e888eed30309edc37748d712e154a078d4bdd5b13cf220b1", + "15982ded9a62a5482a3acc1ad4c33159fe6c42f09aa14365a292d1f8e4434861", + "429e21c28b9f0e415e2211ff953a01b408b9399dd2b67d0cbf212653aa9e3de5", + "9b21c3118ea6bd778beb58728a3e319c2bdc18fe9bb2218024e4d7d537758988", + "730d819c74a968d95a749664b659fece7f28f85ebb9e860542969b1f83f7135c", + "07734cbfaf9de00aa8bfdda5f205dd887fd7df72535ab729d873a5ea23080c8c", + "472f6c62614c64e30fa642fe8370b2108fc6c624bfc3652ddcabdc943b93d12e", + "41161aea39995afac088fa514c8df9905a21984920ab7ed9f5ef52f603932f4a", + "ff0ac19b15cf71021ba255bb88b9b48b8d813446364defcbd3648719c0ab4a4c", + "d9836a3268981bfe94ad1f77f2b3ced20b7079f09025391357de906d03c40e83", + "7e55b991f5f34ac4389f5574bb493fe43493e65668918329489fcd9e473eadad", + "d32bc70e6246bb9345bb5efb2ffb68f6173a0b675a8cd4c7ca74b354adaa2909", + "b9d8bbf671e794da22b3d2318c9ba690448e3a41f406b903f638b5025f7564d8", + "b28a5816f46942f4270bc625ec876659d37c5e40aaa913a6223e49e7576235d2", + "43781bb2014fa51a94bb3498c99623b76eb963f48238f9b1df9b6f31322c0970", + "8dc87e8f4df3ae436fae06c170909b87542352d349384b9c7027e950b402f65a", + "339cbb45be7f44b72f31f96503860c5a25c5f2abde498a93561fb59b433f293f", + "f2e6d476a7d47acc13d2eabd4d309398684ca739f8bce57eb55b1e79f3d1e519", + "56af0198847aa027beeb25867b66c211c78fddbf74d32c1d833d87c778120fac", + "9ac6f60c776459541ec6bc8801fb2fd02e36585debfcf3212fb0b1614ae2f6cd", + "e1792f3d1d3d161adf761720889612dd3cc96eedbbe2a432a03f7539b0cf405b", + "0618cceaafb6f8e91a6c592127ea2b5b0cb1194c3210c3d643cbd25e047a2c5c", + "c7deb398d09de0de32c114870e0843d7700252917eb69fb0546830437308e970", + "e0ac7eb0b844399d04bdf65c93459a19b00c9a23bfbee05b3deca40a05b9d389", + "23a16f8f604e45d067ae5a3b94755fd327505b4a0959844aab30ff5808f79b46", + "488b6589b506e1a4501b2485091e717411867900783807af78f87dff7a46cf0c", + "56c965124e66ae2c716bf67050bdb320f38385280e7a7c6cd51bd7f7ce43d32b", + "19edef6e3e69990ec222877913340628049da39409aab79c93af2b6948a93d58", + "128eab2b73e6a6e9c535e15b22559826c3e9d678859d92653a5b0611acd12d52", + "b60504a4e6fb685fefeb7053d02d89bff2c41c86795c4061a89d0c3685da8e84", + "6038bf6c7728e0927950e6865113a34a6646cf0ec0a2d15e1f1015b87ed6b091", + "1bc443a013d98a82943adba3b89cbdbbb38d8aabbc0d4df57d218717d50f50c1", + "9765ae2f7bd51d2631470a84f4acb6d9669f3e211ba7b3d1480b80a0cb53dea5", + "cdbb6c307084183baa8b44cd6a93f014687b2e8f6aaae063fec6eb2c61d3a331", + "d386012578fa5b91e761a714209d38301129c8ca4d1d393549a4801a9b1e0094", + "05387de7db27a628101147c5e01cf481a68866c5f4be570f35a50e5a96dd8976", + "ad2775261f5a12d7fcaea9666b48dac6ffec096d643df0bdb53dab400abc9fa9", + "c95adaffc299856ba5bdceb376860a43c0a55383ccda166614af9333986f18b5", + "2db34fa42ab7e9970883aa5744fd4ae926463a3acbd35ecabd5854f369bf3f5e", + "068881adabd87a5d568f27064212ab1bb362583ab9fcae18fdb03dbc0f3185aa", + "9ef7cd94ebb5f2b74db7933a06459ad972f43f21260ce84baf26904eae9090a6", + "99afd610f6087a27df4c16d1faa3e80af5dba4194e7aad1347dc282f493951d8", + "d036a9a86f34c9eda2f4d54a8f9df4c470c0f97695c4e5dc9de60e85af56a1e2", + "7f0137290a2f6b51638f1a439091c26c66ddd7afc9a8525c86d0490952957f5e", + "a755f2fa40c875c9592313dfad65fbe58d17940dd1fd5ffc38f9520f91b8fa63", + "6690697131f9aeea3f3a74f83c6e34475cf3c1d6c63e1555174ad875a908ece5", + "26f83c084041837eafe3647ce38404a2e24b2c3f5a870fbc57ee2f75fe863156", + "aa90255d432e68be319e26ab5b1423400d2013117121636cb27ec494a887ce49", + "72a7f09acd5ab6283df40bd92802a67c66c5308f661e98f3c12b2dd3c26817ce", + "de85e7574117c4c773bec442121ac01cdcdecd533946624f5956258644eed440", + "51e4500dcd4477c425cf9276a556041162c6d9978d56f394d32a10c963f3049e", + "7a37ec2c99e082dac260c89e7fb72c23a1f958c31e50624217391cb31b715ef4", + "1611fa2786e97a786d6f0a9eed8bf4b9a30a2158c6b9722eba150b4d53398e1e", + "0ce07e0ba171681afaa50f91d3ba9e1c1801f6c9d49d7d695d2bee3ca563dab2", + "4a9cfeba7938b7c64cd17a04e6191e9ee3b07eb39720f76794518b264817eaed", + "ba2e9a35c933057f7775202da766bd3686c4268f32d9287d8cd3e0a371002d76", + "41e92e37ed2717cac094610c3da3c64079d81b0f18adfbfbcdc46860082d05ba", + "1dd6a4446b8615ea23597f2f1fb4f01e8bb999c5cd098099694dd2d9fba09e71", + "a32552daccda15299cf311e0bb4c7ef3378f303997e5b2f3892cf3265c9aafd0", + "4a17194413577d14d26f1c1fce778081c7cedee904af0ed3a25abbde34774885", + "2d5b0ed95502bae6f4bd6738def6edf4e7e351f879b8c034646fa7421d0bf675", + "0c32676576aa6862d224cbc313ee6576fdcfb71c8041e83a789380c58413354e", + "f1c53b8e6989c4f0d55a5a08239393a9b8a5517244d8f04577300048f9e21e87", + "4c6e479e828fbd26116908338cf72758557d523d190b7cbe3c33cdb00f91f281", + "fcbab6fae7d8bacee71d82f2c1ab679c48a85ea750247f93478baafe4d8682f9", + "f79fced898dfdd08f18178825490803c4203a029faf29cbf08d8f1602f032430", + "d2f0731c4ff11f4cb6234e6f22717d0a2ae395409329cac53785269a7c26ec3a", + "535b3030171da4c461763c488d7da9e89c8cfd7c1c2dadbd360bb99edeb9b0aa", + "9f5e861a8376f92be1917f3157180c119f5b2bea66ef40bdfa77ec8f6136df7b", + "9a7f91c1a05612ddc81567d6637a6279b614dc9fba3cd0322777f437f6cf11ee", + "3e1474061b17403e96e750b3ad725b570d4ca96f98f583e0cd5dd26b84877cbe", + "c046e99c6ceb99a1ee02f92bf5099e2c44a5adebd5290dee742cc5ae9da7076f", + "0736d3d6b42c0b68cea5a9c774183db0d7ac138e6303036e46da245dda405f44", + "2677862a927266eedf5f926a1844495ed7f31f671dac9f58996ae17c637ca140", + "df622da8693db1d4245400e8bdf8a28190c1d29c27d30046f9fd1178a7554c67", + "b0adea932e628a977282825083c96a26a276dc13e623380a45a590fccd543be1", + "1c54ee5a29b8ed8013b00cdcbdd654272965ce4be0e38d7afb413e65cc8525e3", + "62b605565cc85abfa0861daebbdb0b13d58732e59bc1163d9ee5b411fc6f7af3", + "7b7226d49d687fd471e0eae0f54d9529f330d58b40a255aa871ccd36c8b048c4", + "9ea175109678095977395a2337781a4b7a0bad3984d030b6bb0223772487d27e", + "949862062b71287fb7eba6eb72efed9a06402d4372e8d4c32de15961298b9455", + "4200d4862ab89d7e11f465dbb15e722eea2ead1b6eadcf55eb76cdee2dcaaeb2", + "daeb4b3ae41eab84db5c30d4032541872bd9910f36c2f3708467b640f3d56217", + "8340ac58b1ea529e8f4f0bcf297dc402d89f412252deb830d9e6ea626ec2221b", + "b1a09ab896bccb3a2b2dd487d97392e5a3de1f2a8937cb30091a5be8320e43d6", + "772812821e2409ab4b668507b3cf42fe3bef220d4970081db69cfbb992c54a0b", + "af59ff44fe6084dcb0f148dd58429a66985c8f445d58bf7d734ee5d6cf80002c", + "308def2d531cbe674b75dcc421bc3a5ef9d1ab5c8df737243643b2692a7280a6", + "e207877fa88deb5ffae9b19ebc61d0ee6453d6c7bf911aa01263030cfa64f8a2", + "eea9b387577ce6c76eae8f5d2d4fac9de61dbfe4b03382024a752c7f90a8e366", + "ebd0fa6d638bbf5ef8948054b2c2424d490b16dcf19ba35801c25cb388a4004f", + "0f41ea73a5debb480585af132f3910f3c7b98a577fd595882121631431af470a", + "4dd11303be6ed6afbdc8a9017827c6fbf2fa8ea263117a9f08f09284559bd3a2", + "77dce608339c3e4933ebda49d99d52c3eba9e585f81bb6b94de1eeb6c4f19aff", + "e6bca493413498ac5b2ecb083cd17687e02f2fbfad5da93d4c31a02c9eb72c81", + "4b7eaef4ba7578f43422618c729ce5b1d362a11c437f4d9693da8eee9bbe6b01", + "0fffe2e60e034ee0092da0c22f560bcdce5553fc95eaf8478c3aed2d9713dcf1", + "d7dc0f79e6077711fbd11be2c49a57d984dfe43e2357de902f694f561cce6691", + "51cfd0c3aa1b96da6be92c65ef7dc25ac5f10236b515403cb7f8492791f3bbc3", + "309d74e89ffd04cc8f050dfc4be50085f197f6c23ac5f84c22f79a2729ca62b1", + "a139b028838d489dce5fa08da18ba5ea10969860dd813eb64c755f9f8a0c856e", + "2987cd385ac6ee4a84b0c2c472fea3828306b7addd11cdd28aa416ad9950a9f2", + "97e9199855dfed3d4fc6a8746ed9dee32586d73066e024e8a96bb124a187b3c6", + "d5aca4fca7529a7917cd26c7710c20eefad94ab118b592db8fa22a4c258e99ff", + "08a67a8a0f262f70e4039e10091a296fcc196e9520d5ac37f836ab109205181c", + "e71586f3b63c70b6d65672a7d84781aa67ce0d70f41e4240f56066ab67d1baeb", + "f2bfba19ad8573d2c7d48527ab2cc275f91fe08d82829908013f53dacb9478e1", + "8af272ab08b9367911a97394a580c59d6e6ffe763aadc619edef7c3b827bc927", + "8980fd4836c9ff27cfd5a999fa5a535ca557e32adce854752addef70c4144aa3", + "5d976c7296257e3a0b8411bfba3f372f8d35bd7e73ed92bc26af88e322177178", + "a01565d4915e7fb6689db3f1fb7fbddfc9e8647381c115e1c0a7b1490e8f755b", + "a8fcedb1c3ed358fc5305bdc8b618bc0f354781472eccbb8960c8ca3a0f3233c", + "094ac7a83a427bfab8eff10ecbce65c26670bacd70c941f623ff0298d354edc3", + "d7b2b22315b3ee15e124dcf4560d3bea585842f4163daf0b879a8b0c55390637", + "e6e8072a24ab7bffa9ce6e9a359c33b210e8b66172e1d35a5c8ed28871c40029", + "39c1bcabe1c30d0798d8bbc275d83a503299b08fa2935552892ce03bad2c0bc9", + "2ce057410a13bb152f276afa305eb94e0e31c5dd82a2eb828d0a01710a276756", + "86b8f99ed5240df548dcd85fd87fb2dbc78e21e117524eacebe7ed88d7340a8f", + "0ace53d368852d27daea0ec59bef8f1d5088ceda03719add6a02bc70e3aac785", + "48c7e89b19636c77e186a093b1f2946ddd692f964ba6f2d2ed136b8c2f490566", + "6d9e0dcbe46da467509a5a8a2aa709a31d47795f9f3bdb3a01812ced98dddd5c", + "1526564dfcf5b6ae528444ee7a260771bbf30aa846da37d07dafb1d743c9f68f", + "2987aef1d875722ea6f1684883eefb0ad566fd0017b7ef6094a1752e2ba68550", + "22bc33eea0b2fdfd447021a90c90d10d24652add142991676418a72e8151682c", + "0d72148b5f75fe9f6e36c5f042244bb5e35a27b62777db7ca1e1072eee9a8e48", + "ef71137c514cfa65fa5fda9b517e3c267a9c7a7a7fcd4b9177dad57d0fc2add5", + "11efa0f3f84cd47c1cb0c2d4634f317202ce00e52fa18468910a68cb317326fa", + "750711ec221178fb1ee7549333d5dfa060283226953f9096782c24cf78771345", + "9d621cbeb49423a46c56581dd621246766d6c1d2e885f38cd36ca18f88c6966e", + "e459b29d49a394e84000903ccad0edde2b83096f73e93d144cf8a4fd041d37bc", + "902e39fc44a6a9a712c9d42e0b98a08f793f9eb468ab13c120c87bf6309b68f6", + "5fd3dd562fb5d0c97a66fc5d6f2d047b7c12e9518b95d6d4b96d3cc649e893c4", + "ae5a35203af76d78f8d4c506b18fb4e1c67e5798706d7a1b98912e9fbf6669ed", + "8806e940bc2274296217b392b69987b4772bac5aa5a96980a848c1ec769bb8d5", + "bad155b7d45404ede0f07382e8d74d344dbbfe462c8b3658dc6ead106d418e9a", + "fcf3012d4e101fd7affd972b1768ea8200fddce6e0fb7e403e4fd9ba3f01bac0", + "8ce68b64c7b5675e0663e81e61c4b4379cc5f8845dbdf191031b591a0e10914e", + "ec2253aabaa2731500b94ca5b60c8226e405ea23831e87882fa127cacbed1e70", + "8333c77cd6b63b5e538dde44a5f1c37822c5e1259d7c6674ebc98d17431720af", + "abecc9a68c658a5c31008c6c594d581d36fee313f8ec2aaac469f2fdf4525569", + "e4b493bfaeeb85f35f83e84a318b3a1df7df1497ba1b03b498099e747956ef52", + "8dda479f521d6dfee106e861380824d6d06c770d1472a189bcf251a1bf0a0f55", + "e38a654a52e216ff4a200af142e4a8b9c38c448876b70b84dfc9de5211ca7024", + "12b0bf0288ad6eaad0392192143f5765bddc84d7c99c3ce7e33711083251e878", + "98055e28a5af0dbe2cdc674820e18c92a38ac89cd2b6d3e2f87a589e1f054eab", + "8e05d03fef5e1e2f69f9d4fac674d82e351e34106ad29073ae9490e9ffc15b25", + "bcbb675310f133824ce336a3c43f36f8f6bc1dc9be8efbfe3e7270fa0e7eb5af", + "20af3852b4aef5ea3fabd3847cd03c064cd822b30b5c1652b91b414d08704fb8", + "cc18a3362023966193c072630da0afe74cc08d9eb767866d85c557e6a6f26387", + "950e603915e7fcedf0dc158daff822db034c0a240f7cdc5063bbb428d1408414", + "12658fe8bebcd857c22f584c8e31d6172a87f089e1d883130b7dcb4c1600518b", + "661d8c02f86e16355681f3a682aa0efea86a985ad29e2b64b343f5315a9268b2", + "617a333e2cd2482f83715845421a1e25506724d4737f7bf8dbe9f3faa5a94aa9", + "1cf208a9abaff984c259300f9345c92683eadd83d11a6a4024ee47b3b4d1d045", + "db15ccc93275a34f2728c92076086f0f4c7b2068fab2b009adf7f0d48bdb888a", + "befb08a1da6b7c3136dca3d29c7c0c853c2d91644e55e4303cfc8be64f699538", + "ca3755a1d62e3b4a74fc458daa9a7faa3316fe7f6fb40a62282e9128882d4675", + "4fe123bbaa5d874195f63e85aea06ab08355e0e57f2204308439917ffb080a92", + "cae10b8938dd5806cfe5ea1944b39296a0a73b5957a82f308d9141558b21c6eb", + "124dfeb77b60b21d782aeb2e4998ef15ca8755a3809fc3420b1f4a7125a1f4f5", + "406e044140ce58e8cdf36d57a41892fe4b15a16871f8318afb4ba0ce43365b5a", + "59f62af4c197b3ab5b58998677a39f42ae62738fb962f775529889cd7db10925", + "7eaa2867fa01e79b9e64e17f41df246f099a3f1ec05f9feef690274f55b00182", + "3c0125bf287ec0efa250f7dfdc4f784a4b11475e7bdc5ecccbf7c6dc591d0284", + "06b9701560e87fcad9f9f9eb761b9b78bed1eb979bcbc252b9ebaaa465319a2b", + "64bf409c31578efb2717df97ff8125c218e5b2740cce771186288de418110e2c", + "91adc1e2ecabaa94988334b107b23a78af49d6cd6a8a7fa45dd0a3de7e7a5bb5", + "99ae7e7cbf973d9eee35901a95212ced0cacccdea07eac0d88b5cd29e980b956", + "563e70183d98c899d0f0fca96634f77ec89ad4bacb3f52ed2f736555149779e0", + "7f01f980bfd6c3c60f3628d61afd9bc5c92f50998b3ebb0813db0487d2c23f56", + "aaa5cfc4028fa4a0b2f1303372ab35e5c4e4a6d5816bd6b819926e8949a4bd73", + "52968b2efd496a5de2dcf26a6502e8c6c74dd1249a40723a17e84bd331dae9b6", + "9137b4da3041a7e4a3b88deffe35f371c0d8f746867c9959eca986d4a24034eb", + "1d81a4be4ab49d3baa09a94794061d770bd224d3701fe00b76680297ca819bee", + "628cc2eb26c7278894ed8ec317b4c60afe8ad5fda359f151300e1501d6b27091", + "cc9378c99c54db8ea7cfa4261e74349b30e53fea0232dfc65e595419b7311c78", + "3f3a959ed7bd378b9ea2822b166760ececc99ff65c340e9a99b550b4e233bc38", + "234aeab4fff850bdd013574828def84a96ebf53a59187fae764d691c1e16fc9b", + "b065e4e7d29530028fe92e1f48fd4944cfbcd4a4bb1aeedab43866b694f0fba5", + "5df39fea0e235a747476259f34f8b66d739f9d7bf47f50c19891222fb66ed6f3", + "67fef34becf3a89191220819e985761682583e9e2fac7fcce2181843e567b13c", + "587293d74305af4ad1bcc2d88f6ac16c47ba265e3ac5ffa5f0f6235ea8cac952", + "36a9a03e9fbc0237bd52ecf7fa23626d8ac83e91d54cc0471cc9277929582879", + "78a673152ae87540f2b3a38ba47ec5bd5cf047da62cd6be3682a723bc87ee1a9", + "8b48afe535024d84514d81fdea58934ca0f23e031565d7f74d05ec7a7d946801", + "d81ee7e407ad1311d68f0b53994e6fb68131c596735329f76cb4d18c4ddbfb77", + "16be4607f8bee1e191857372b0263ed401bfa173f2752736fbe50abb7e58da98", + "d05083dd5e6d5e0a2c320a1752c724d3a13428b9dbd2833fc67c86628f6eb1c3", + "0b2f6370271a17242d09d0292a1e0344d2806cc89e8e6e125c72ed47317171c9", + "aa1332229c78544ada666a1e7cc54fb5fa31c586370de5388bfadd86176b2250", + "d605e3d0ca62ce111f73d2ea48c5fbb56c5d47c2bc28eb68c398515703119072", + "9e0549f039e6c530dc1432adcaa40a3ee2d69329fe1a2245c6c0461c16931eaa", + "cb2f3789ae09d724f9eddb3f104e755ed2ddc3f5bac87aeb91f76fa53784e881", + "6e3b3835f989decf5441e8c524aa95b6b312d5732d614fe24d80f9dd39bad1c5", + "318440cfef57053d806d6f9c03c1331947018cf2f479b71d9f5ff4d1bf940ae9", + "51050b2569885e0a61fc2487c8428e6fdb8861727de7e8d97f7901e6f583acc7", + "02e37462d082a033c382c04ec6d90c629bd96cd0379eac6399a718d9988bf3b9", + "3515eaa553cf9f35d85fdeb367eb3eb930a79dcdefcdaf2e6eb00c550deea9f5", + "1321c47c060f371589bf9a1dc6557b9b49434a4ad6ad15f6749a2bf71e26ce14", + "627cf526b8c336e3a3d8c3e82e5503fea6338f14a438e8de6bb3dc5674a10da6", + "7cd3b2289dc1190b6ea21b9d011ec5574fa251d222af63a52bebefecbd89d7c1", + "9bb3ad4efd34c6839bf4b641d1f745d8ce60c829f22b773de0fedd566c3ca60d", + "679c477e999ae78bde65ce99acb6c2bacbcea8214ba4b7fd477ae91b1d21792d", + "bd3ec90f50cdbfa74372cfcee0f017fe7342935eb93d9367ca277dff7b02eaff", + "6a73b3ac5c74db3e940df13ea5e049432e2488b3997767dfd700e9aeb34f9cfa", + "a642e0ef2b4c17cbacb868ec0ca7d43ae9cefee5e0dc29e59e561b44aff05615", + "1a77398f0d8673a9fccd3342338f6e5fc1e96800beebe04f4aba48afdd41f6a3", + "d2bf9e00bf6050ad68e7a3ea1261b3c9f9b6394d53da2f9f1712199ff5fa96ac", + "d17c0276250825f6c8ab121c999c61cc892874488a4bc95a104dc0382e511aaa", + "7be2cb478a857b81957d7169a01c6692a254e7b029b42995b6c262e6d30f0038", + "2af54e9f62193195b0b927462e63a661c5abe69fff22037e047257dd41089646", + "120849c155437bbec39e71267d3320eae464e949c7ed1e812c91f3c5ead6ba1d", + "4d77309ed2522ec89b7e8e0f0189cfe9124babae465007ab5c905a9541d63a4b", + "4eebf5a0cca448832d9a5224a39250ecac4a18c650baafe2d8804241c274dfc1", + "5d29b8c14ac83e531b87534ef17531cfec84f49c764e6410c8d5682fd80204a7", + "625d9a10f136b103e85f0e7863df74db8049f77a75e52361748873fbdb2a3f73", + "eb21a9d33e58daa0ead2dad3a71d4e5eaa7b0321c6cc2d4e86464c70cf366634", + "6b9066c0d9049b0634edf92b34140d02a49e7a6d76483d14c32125f3ea41d8f4", + "b68f5ebb20554bddbcbd92371c4e536210a0674e61577d552b6b405939acddfc", + "2f8fc98373422a6dce98f183f25488520794b45b947c18ab0e1b924dee353b61", + "64643340086927f78905c52784692557869bcf723b2ad19b69fd0349601aa7e5", + "39c72e17874ba3a3850231ad77319c564e5fc1f23414c80d0531f8e618895ac6", + "9e2afd30de5bfa30e237d9f2f773766a82e20d1a7efa10d34e37048b172d2e91", + "c0888a46377fe1194a84313d3e9f64e90cb94648cbadc93ca1c077960b2946bf", + "c7a54836aa914f27df8424e40d4c42183c7dce32798f7964fade258768beaa4d", + "485865c169e3e60c2b0cd97fe7caf04bb5592a9a08c5abf53de92f5fa745845a", + "77038185b0024d9e2e0881b8d57e4dea0b59fcbd2bc2a776c8d7b29b5356a240", + "19be080d3f5d828b2826c221f35a07200540c47c5bd5c374175f8d1b55dcc8e9", + "32d5a77433130085014cfa02eb0b0ff36be96763b8f100502ee09a93fa4a62bd", + "9572c95caca053688f8cde1436a7d5652f1bb5bb4da92dd200df11d2a27da378", + "b3db618f9e7680be0c485377b1f9e874798b5b9cb2800a098053b025c47e70f6", + "67a77a0cdf101d5fca5d17bf2b49f3c00632bb4a53c4ef06617762f36c8c8e07", + "1fff3805be7779014868c91462838db4e8f88e7759179f144008534a1724fcda", + "efd453c249b898711874f643c4b66efd58e91ad5b3aee1aa6ad7a477b7248a94", + "bf94e5f1c7b5c8483285a8dea4345e7519581d486fcb27a8da43a2b48be22346", + "7ccb34279395a288bc3ce100245c6de77fd9fc35956f9ece35e6475bbd6f6ef8", + "810ce536aa750b60cfc6acff3ff65b36515f60c1abe5816aa5e38549b0cf21ad", + "be1c2775730ae524f44e05fc989ea33b24d262db5cb630cd13d56a2324f8fe37", + "7b8bf85e45285fa4b800e544da002c0c43c2b87644dfb62c42090631c5abd1d5", + "96e286ddeb65c5e54b4a8325cd695b53f4aff1fda635ce72c7b14ce1e926c7d4", + "12e0310edca52b08cb8a18dd2e382da62908b476f14b1a8e0aa993a945e84399", + "e8ceee44ab4241cb19d5da582abc8b9c7ec4d71bbfa456bbda2d3dfb120c1e82", + "e3951d2637df7a24c3fb48360da87247d998c9f092d7ebe349bf5b493cf89034", + "2657c928cb139ac30cb495a790e8a125d452a541267e71ca1635cb69d830c349", + "4d0fab3685c9e14d8382253670d0453430010fdb95da9a0cf5427760ff8f4bf5", + "85a65d69081dc88743067a1ae0f5abef0adf79ba23500954217f990bdd17246d", + "b3d6e83386b11a0d736d43f1eb3235388abdfaf2c90e94ba02d4c50a3c830a66", + "f1f207e702a02318635f35a70141ff96d50b1058f57c01f84fd5973112eec5bd", + "10e412a4f7c37f47b63d39cbde4721f65670bc2085ec8db8a6ebd2db0f19531c", + "a7679d3b0d86f7d19b865f9c25aa91c1bbcfcc89cac3415138393f68958699f2", + "9be5b69545813b368cb6fd8e8e2f0843a3299c268f3c78691d62f14cc08e1fd5", + "c7ef2594ead75dd56e8effb151e72c72efd2e3151c22f113a9952c2d2a094ef8", + "43406fa30813bf114ad791f19f91783ee623dbf5882e9361dbb9dd42dcc124a9", + "f45c2618d639e25d60a6ff4e3d3c54aca3afda8887feeda48b3931d5fb3a890d", + "021d36f9b63ae9509a139f5919a2c7c6daaa8b775b67d175d9fdc2caf1545247", + "221662e3384acfda6b419aca64194a7e2b515c470eb515641a43ad280f5d8c64", + "93a2280c52123349f7143d8f90b8862985eab8856ce01c1e65847f74e82f3585", + "97595d2f3e15492623c1180c3448d91e27e8caa91a2286ffdde6e0e01d73487c", + "554e51f4e422d00765369712a73dbe5e18c4f59aa55546b9aff3f1b94c8f75ee", + "373c9b4a6fa3fc747881123d342ad6fd4bfe280c1550517f329e7b5fd9c90824", + "5466a29fb42efa17c090eedb46bb213988ef7656634eff61d399c4540bf185d4", + "68882db32387229d3c096e4f075c9075d1128759c3fdf5e5d8bcdfe24072d559", + "f703f98c5b75380e73f861b3ceb685094aee6341309d5161b761fcca78acda0e", + "59f93b2d63f4643f566199a92d955bd78caaf7ec7e3078fd5264f5b478ac09b2", + "639731cfd7ab582be092da8ec8da53718c206b8f0fa5c75953fcff3cb116a172", + "2bfe2a097a074fdff140fef54c104953996a032dc162edf32dc357e09abb3fcc", + "466dd64bfa5468a071705d8b3f86206a481673ced10e0a4f172d7486cd29e8ce", + "a40e511b719b6275dedb1b46f2c5f8b0cd725312ab239132c5b9b29547f6f764", + "6583f450fd9001e5355551acb58a3c95ac663f8f58a82cc3f9f31135fe492442", + "2a818d069c34b05be52769437dba3051f931aae1b1453e950c591b3920c3b3ee", + "0b26d32e1e31400f4c3a5e2750fee52239b2dc3728f927ec455ba49fcc16bbbd", + "7d90705556fd11248be8e53c04bafeb395b123c3b42d3e0e07f02ae5bba74681", + "79ad2329c40c96cd2e4d694d51d2610b8a28971d6b253f5a54c22301afdb293d", + "147eed7b0ff213c3ba36f679ba864cb2b050de968fdedcdcb48e6916bc264574", + "d027dfcaaf6e04f676c619244515b823e7adff3dd01da6730342421168a61c45", + "e2199dbc29264ddf0edc446706d684cc19ab7c81fd19f2c25a6aedfaf38bff61", + "74219656debd84f572508135fb03c4ddb80a992c629a1483a4b32535156ee1b7", + "cc6b74e9616a1facb82a483e19039348ccbc6a387a3c6991f50133ca844bb499", + "3084b541105fe892ddfad7efe4d428a8cfb5890c6970d4c4d05bc1b1e7ea38ef", + "a0b5c69bf883147418969ffca6cd45e9f710223b8da9bd93d77ce8aec76d4bea", + "e08c7e844d6fa6cdcabb04975fb6c66ceda4cadef3b1e4fad7367207d674e973", + "6033e2342b470e18a442cc73eebfc5e77303cd4ecb3507930f777cd2fb740a15", + "3c20d132ea8e829fd8fb7b18cf5f9a5a71dd88bf35bc81f7cf37b4ab4cc7b961", + "0ee98db4b01bea147bbcb1bd492a66c85abe9e20985738bb5a035d587badff8d", + "bd78400ee797aba19c82c3bf060a13d720be4cab6358a39075e1ad721cfd0b99", + "91c0f7efc5e43eefa3e587d1e2685bbbf68a7b064c06da9b21f3e38be2f8915e", + "f0c2ff1abe61e4c0c3092afba482e7eef6f0744c267b5334e060485d01974b18", + "dd4d830bd248066832624a2a5ceca133b9f5b9fa66c1d3a41eb4cc29169f955d", + "04175c02b43883fa4b3c4b990334e2c3e23e85ddc36edcf04bee9f86e8a116af", + "2eafcbc1db5005dbf74c90a56554ba71201e21d21ef4a77094f4b1c6c6d10497", + "f6c826a659eef7eca7685ce1e574066a007906163041aaba2ac90a12f0315660", + "2dc4d5de794e832b499f493c99fa948e10079f74552f23fc5d3700722e8d0f8d", + "c02e4905c3876a3fa382c1a7f90cf91496d66da1b2495cb3f5a345993360280a", + "5a375be2718ac37a38ee1c84b84476695a384e2a2ff43068c8d7989b4fd3cea5", + "b70b2e6d667be606bd1c511f7e2cf631f533948cbb5af26db8650d4101253f63", + "35a49d20ab277ac8c092985c9faad58320d1af7427124c4828888f4bd7491b36", + "2a67df5cdd3e8c2a1241dfd24554af46feee6b138b4809663f86e9012ec47b27", + "b50c7e29386970d39258f395e05f3caeb8648d9a40a0c14a603ba1e729c1782e", + "0db1d79fc1686e0388b8439fe7331862314b77ced506dfdaccc2a21faf74f44f", + "6b3393eacda7dc18a2ce451f2541681f5dd4e9af21a2624956542b60268a9405", + "8e17ed5e690277e1156294c6904f6899de1497d15d8862a98cfe349c5296ec13", + "e44b9eb141e8ff07acd5bc5a2fdd6d334192e27b27b5f4c26a225ad28cd9ab9a", + "02b6fe45acb7af83932640c81519a7cf4d33af40e8c66510855286f1b869df7f", + "c8aff4d8670456d4e64051e65f018226f7abcb40dc77b7a36a934f4afeb42888", + "aa4a4dabb9038bb1bc8dafa93397b77b81e263fcfff59eb86c07920e6c8c218f", + "3b8203b9ed708044720313b67f9b98cf9e96544e95ada0200bc4ea0e54a3c633", + "524aced0165da7aa4aed8d02720276c3895a37fcfd8db9cffbc9d353ccc960c4", + "553fcf8e9e53d37da153a4f8bfd16a2c5379da0472076719b05a26d10100801b", + "fbb7b3e31f1d0d1606dc34bf1c624db7c62133e173203dad5cf4c3792351fbbb", + "e62eddd4a815b35bf6916c615a52f185395baceaa52cee8a836de3a4db0c5381", + "9ea285ecbb3cc9189511d2148e3d732bd98582324d2a597ccb942e8b0158548c", + "6c9ecf00a9f605bd50375d0793e8ebad382060daebbbad0ec1427d5501b95186", + "00a5392f9bf5114694596652d3f47debb758a1ef4a408490688a8b3b6f4d076d", + "c9d5bf16c017b12a95d62a92b270c9c100fee78fc85c91f830c56be00235ce7f", + "68ea43f029fa915aafc14bfa5eb8ab1ab1e6e20c467c0985dfeeb72af1859659", + "172c4fada590aedd1eb45a16ca2ac669cc0371f12aceecf1467e0dd6e2af387c", + "0e8c60669d5b505ff9f6fb941f3247bee6458fa1d6f1829c1444135c55b5b58a", + "83e174c96ba972dd05b14f9e7d8dc0923ad96cdf6b2926c81baece8c7c3ccbc0", + "55699232a0c96bd45cf5bbb81ae2e033d22b534b2fcec3b70ab661d22bc25b0f", + "9d4ba8d5cb7404ae253587e6a583c595214407007c049988a08b51e8c05a67ef", + "1d63978b718b86d8d84bd1f6e7cd053fec76dbc922c597abeeee64066d02b57a", + "6d03e10f0787dd16296266414cb6bacb961387fbec686348f586a4d053718f02", + "e4ae9203d1b61a37a98b21769f110e46de7ab6772d15b4af93a9f39cb2d096a8", + "a5de66a7fa9666e03e6dd9e114d3cbed11e14454758fb20f42586685509f315e", + "f0accba58611444a9eb7c3d41218740ffed85556762d5245f4d1bbd6d958d488", + "95de4a732eaee2996786c28c3ae80a7bbfd34ad276694cdd64194e7d45d6b1b8", + "59b03bd978a4a5ed212fd094e90048aca406d16c196410eb8be8122f2856d1d0", + "2b6c3018cfd7cc55746864434c9b2c610a4971e60d9128a338451d46c78bfc86", + "2428da7b24364be8aa93c6a255543d7da27f4cbe57dde5f14a8512fa5ffb981d", + "bce26d655a0efb6f287be49da07393f30feee6bb6c2306bbad88e04c8984e7d0", + "0fe2ad6dbadcd9c423b5eebde12b78365ff1c4fbc85e933206523afc2a2f8a48", + "67482decfd58bdc49de9ec5a8147945130a928b98202457647c66865ca336c71", + "7d22130b398f4085766f4909a68b4f7fa2c4b26db1e107f3a2ef29417ee5cfae", + "98778612b5124e3d7d455f725f4f2462ef780f0323e0c36cb9bc81811c00a045", + "51e7511c0f2ef6bfc7e17c7906fd604e42e862f3f4475d50d86bfc1401099d0d", + "f120fe5e0ef2b223977b4519069cac7e4e77c587c5b011663d06aa08f80fd477", + "9d00ace943765ba7f2a3a414f534d8e751af83fed0f8e872c36b311a15ae21bf", + "93cc266fd13aaa341f03d20115f066cb126497bc0d6d5de719c9f80604a2e57c", + "ddddd5d3636ab27be531f09a9a93e5d8b39fb2c03a79d4b7908f2b40b52bd1f2", + "626c9f4c4e3bad8d65523b0f4b820f4e59a720007fc35aa925bc99d9deae3e00", + "af9d9060c20e16bb1f94b3da86b8f4c074c472f2d402ebcadb879d9d5853dc78", + "309db5e72eed85d70fb56caffd8bfc1dffb79fb9b599916468a68982c975dca9", + "0738d677af3228b95cf444baba3469dd67aaeba54a93c91ae62845d2ab12bb3b", + "720666a5e21383c6546a87b8cc93be7044c87c015ee2995f87b55bb291e9924b", + "21d91ecc9946962e60ae1119f45687a670eb725a392425e3dca05d108808a314", + "253c1ba525d54f4075c8aa01ee5383d0ea6a41b62d243fb06d4f90987e557578", + "73429a7a5981f25624a1ea521c95c1aa4e744bca69c6b63f495e3c72571d403f", + "e92100e5825a11d06c55a544f83e71a1cb86516805549d0d16c085a690645682", + "3969b8d71699943cd01e410fb2b072638ffdc59d10eb3316ee12a98783c09181", + "3dd6b9d720af724e3bba14e7fc41213a0c6b7fd5c4a6d6081cdde8b05941023e", + "a8c6b92481b9b52f50fc996f3fc023f720b832f79f306aebe9e1db5d5d680f33", + "84bde27cda62db77fac212cc9a399467cf466e0d5af32984b04f389c28e6b0b6", + "d416c534ceaa07ce856d3fe9fb6d8cae21f28aa45eadd4fee27b791e69c8f045", + "0b370fe3369b09d22ddd43f870a428c4b65974430a18261c59781ae77d941480", + "906ad75351144066d6d0d914c5145664825d2004d778aeb41aec56644f81ba25", + "3c57221b786a6de68d8d8db9db8ed3928a20eff9e688ad1121d73085a0fe9d75", + "e1c262992728e3ede684e77f4a06efde3e2eebf8f12a0406dcede1aafe299648", + "c60819a050b2d4e6ac4d72ea6683fde04dbaf6b66bd74ff988fbc7d2b29b9bf2", + "e8468896b3f9734cd0f7c721ee0896ad1548902340242b7fdd16e39b361c4ac5", + "6a8f24b12c66adc9e771cc6b52392688bb8535c1ba026ca7f79d26ce2c7ed9a2", + "f5d607b7d774d7c5d81d6c8d58b4a7ed576403a4dfce8f2e63e1b7ce9c7f8a02", + "011d439d089fcb3c7d44c2d5a6420cf60cf1b8716db31286f7c9ce390a0f2fa6", + "d6fe9c609aefadabb0efff44e5375ea4eacc5237c21b58a2e199cc2899dbfbb0", + "3a0b54bd93d3305354b07b6bb7807bace50476c4e120a0b327de1cdb93617079", + "41e55404a5998f71571a200c032127a6241b2e7b232e82147fb6769d8256bd29", + "5756ac43c1df14927d3af8ef161c403ee1f92b1ed296d0adc72e2cb45d98d7de", + "f82cf2b7895ba7802d0478d2b20b069d3c8500637fe98d4194da02c884cf9d17", + "3a10b6cc7cc3bb244fbd0d49910e588abe7dbaf759d4cf44783a7139af064824", + "5a9b9b31eaedbb651f42d207a14b502b4b73885330c37f8e615ad89e3e61213b", + "e61688578b28b999d906798525736d64a5aac1b5544b7507badb20b34b556d8c", + "45b27a6ef06340c3ed81433083ac81ce99abcc951f5e334919f3ff56cd1c75d6", + "fceb7a9bd727f1e8438f617d02674039902f195dcbbfb01b43d5f72edea02831", + "d19c5e3b8aeb8f8b4c08ee8b61f34277bfe579398a76e28e58b972cd69089b61", + "a32c7ab77af334e2d5c4eb3caf95d3aaad689f28a2dc3a7557f2528be402407e", + "b6c17c21cecca5ac92a1fdc1032369e4c6d9cf2fd4f1d5b4406e1d7e7606b2ac", + "be1b81276adee2c0f4df4cdc6d1b82df87dceaf516b7e4d994e023a937479f9f", + "439251ab04c231c48b891702a2061921fa88cfef44741ee173853b6bf8490430", + "26b7068c7272d9feaab03fef3083e50d49885e375f77792d59ff0cd502c03df1", + "85dce2eba1a9ae5a41d06854f4db88dd7fe022727be35ad6b18e6087c8b91f1b", + "e4f7178d36429096577518bf47e2d296c021ae7349aca78e2c0a4c606acca5a8", + "e8d88f547187b278275c799b25a94d814f3174bac46077df9820a338b4d9c267", + "ac8f48385b06e1c43da7fb74e522d347603b7b973ac3c3d06412ad72f5762fd6", + "22f39a936e8e401a404457cbbef921c3568ce016a5c75de9256011b988c252c6", + "77fa7038e7ded01577a2ae592cdc9663311b5e1e42f5f87ad8a66ae0e9a54c28", + "87f6e5ae2adc65a736c9b1746ec1f18340bbee45481d7c1f5509ad71d5f3c9c2", + "180e9ee8a321a1e91c490cd90afd74d556ae2a9bae223ec6c094587f359870b0", + "f6c87366cdd0be058ebf9295d8b6b42729be58a0f7f057fe3243f9b2949ada26", + "d45c27211e8a4b77a9e76c12db25e6e9ba9d03647f3691d158edbd8b7c38ab69", + "8ebac15b55c4a2c5d3f4866858fe3ab9324bd785036dc0ce8ababa396419eb35", + "6a80d86e69694ebeec5f6f5a5d37d12c2f813147c1116d5d26538d25f8882729", + "2cf7e4c33c2a63ef54c444020bac3648738bee48779db4a3a0f9e72ca5b4e380", + "9d101afcd85b7331d4008230f29b761b9f798e8814d123140e8b648b230261f9", + "c6ee0ade266785f9dadcf6892bf4b98d7bbc292aaf2bfe5b7dd484785760375b", + "94d239b78781096e3e8e7e6a7d9ad70d0804adeb6a6675fc5da4f05d1152c19d", + "55ca49e0e313f14ae0f214ac0a51843158ee07aa5f381cb9d596b8612dbd3f36", + "e3e3672131fe9a71f54a41b0e8143c63bc0aeb823288527bda069a1616a41529", + "ad1b386b668b79c7cada251a6c2bd19c53e51045e4a4562b4b9212852d334556", + "bd08a3ba2d8603332b31b2394a556edf6ef949ec8d49e5d54a13318213a0da65", + "b34731e855ce7fc834aa0846c72ce7f455f40564b11181b340ec07a003787e88", + "ae292c8d03de63af642539e6559960770d80dc4e9590c46f54ab8a74b68f145c", + "10a28c04e90016bc744986e50d2a240ff553cea32c8ccbfc218445d6f9e32271", + "182df763c8b4dc2c1698567546dac90ed5de00c033322c9f731a64f08cf7ae61", + "eaad2e6f6dbc000fe3b8f60fc7ce7011c22c4d062ae2c33a3621098190027381", + "1e7d630f59f8c968c54a803f8c70e15d85a1214be4e0f8e82cab9b2056df4ef6", + "af485e0990350c9814bf8a8b3db91f44d4d459f513f9e0635ff54a444a45055e", + "c5339ed11420ef44af6d7eec085a7495ac1f59264119184d3183a937d7012295", + "ee4c98e7b5e1b5fc19c8e5e75b9be39690ebf15bc9b1e5fbb3ecb75a2ec89d3a", + "c88b24689438c8f097cec81f2178fd162d4c53ba51f1b835c9b7d1f33f3bfed4", + "b3f12ee06f773536bc4882441d7b40153fd02ff4abd97a5686bc8ec294de5303", + "74b69c91d7b24cbc734d5bbfccf3442b10aa94f835dd49e84aeb9fb93d48f984", + "7249af9eedd2ff198a93c9fd96d3847d05fd24e4a2dee3213f8b0157028a7a1e", + "4c663e23616d31135cf9b4c33a89556d9973b2df0fe8b5a851163ce3e770df33", + "4afede394dff0a2b6f0b1b3dedf82614ca5133814c9466e7856a53cf33a83359", + "b7f3d596f87080e6fe4b0c5e17364dc87ba269ca561689d20085c9890270145a", + "a91c666326b9198e9954c4461da9e173c21042edbc8e63e6527f69aa06144ad5", + "c11375b5ba44d9be64cf8ccc8eaba4689ce8d0a1d75f4b932d14b4e26b962ba8", + "c737cddd051af963d4109063a7c98bfbbe500abdf2761545fb2e3f592f1c3183", + "9b09f03742db7491a7a96f20d2735d669383b59570c919c5f8f4d804ccf552af", + "112ba278ae78125b0ee2a9ae9d4c857d7b09d3636d8afd9e175a3557917409f2", + "3ec2366bdb151bc04838ad4459790d217d7e70104dbb6a13de48c8e97873c874", + "e592d021807bc768bc2eb1b6b7832d7326565c39b82658ce9c340ee50a443626", + "446de54c9e312644e2fd20f49b8d9926edeb2c995e627414da25b664f14e4fb2", + "c0e6c970fb25f5ec11f0c76316e7eff5bb180acd21bc777616ad3212edf5cb3c", + "32c3a1e954262361dfea8dcd6d4e74c436d53e6518a2bfd080302187e454ef3d", + "af6c5f72dbd65e75a91a40ba9c6abad575f12b7fd8b66c41d88948fa8e026f3d", + "2f858194e1da082ac8ba94373768de9fa1842a1adba13b2bf6c67474d0a233c8", + "74b19f6456e34582f963dba6d7faebb6289050227f55d5bead6aed9f6394eb41", + "e249aa1cc573b722bfb4e6613dfc70e2a5d6cb7df94ba1002e7f549f57aedcef", + "0ad80c6bbea362b8bdb966cbc50135bfa321bb8cbb0179f76f445dde3d156c8b", + "898f699a5c52bdada6a62d24ac05ec8cb043f5679b554ae5a9b4d666a440fb76", + "305cf536a22fcbdee3353cdf59ddbd42e24ea1a8b91967d5038ca3f9094868c5", + "2847f3395f902b011e2eb0ce5e995cd97af861c925e04021a5bd893447025060", + "91f09953dda135db571d5e159e07a495b0ca9d2eb6ba584b6bff019ae5693624", + "648126d6266a94fd567040da2a9becb5e6be4055f9f4176d252ea8b29915b8a1", + "46451db7b8576c094fa561a81e6d1300220b42b886e3e3b5faeb95c78090e6e0", + "97817465e9219742eaf8121d0d053224793083991313a7b376093f5cdf7329b2", + "4e5c52de7f2d110910f12126b36f9ee712f4a70ec48a86ef10b21767b876396f", + "6510078a1522e2f137600f9183802c1581f882bd9fa0f8f1391484f84cf0fb43", + "2b687ea5a740865b89abc5657546a55b7d5f7fe4e4796354b4b4266f0c0ec10c", + "879d6960613b3138e2a92c821026f5858a99338db1f769923ccb7f32ec4afcd6", + "6c37cd022e745b6666c0388b81296be90dce442972de52400fa3adb8e734d2ee", + "e58f22310f59fdddb90479cc36c763c1fcf60d6e09501d51c495dcb95c033d05", + "70ac02944106daddc97b53db0a0f9bdc1cdf7e789b698b4234a88d8acb945233", + "e797d50c461ed06e255f8106694f1e3c3dff45ca342b631c9d93fd6868ee7862", + "d645d1ce9d365a5ea79ccaa9b24ec597a029e07e667bdd5461a7cec83344f83a", + "2fdc7e98eaa0910fd04914e2ac4c1216e2a4d37621e23c69daa7539b6d403ad6", + "3ea00f497980193dac3261c3e12d7593b1668465227775c53b01e0029a3dbaee", + "eff07e9c0aa7f889f74bd0daabfa20017aeac105fb09d11647059f37eb1027eb", + "69d3cce33ba2f60e895201dd8d0a92db55e4db99b04de54976d3f11ca280dfe4", + "64aef37268e77bcbbda83cb568ba365aa650c4363e22f08ebd9ea8dd4c5ec3ba", + "837f82d3bed0341335bd5ab9d633bb5b1117a0b71664315643f710321451b08d", + "52b1677f38980e1ba9eee33faf8a60f50d76a9020fc18aadad44ef12d102c630", + "c5727a2a22170ed9a40b4e003e7039bb6f51ef719faa103159869f715cd79d64", + "2bd8376008ef3339ad49383a12754f63710ab01657cf717aa945f8ebeb351d26", + "617d5e3734a176c6aaa970e78f412532263398023f922604d69d73a34d7c9600", + "b508b6f323862d1393522ce67c9f267f8f7a08c4f17ec2d7e9230df6a7dcc83d", + "003b1c8857c2366b415d5b1eb23ab8c0705065bd87fe08e7c25114098bc2d020", + "9c18e71750ab5a52520fa5c6f4b48047d34af42b9feedfcfa96a9b9cf6c2231d", + "c3d69220994caf490d6d8f4c7f7689da6e533bdbf775309af7b13b25359c15db", + "64945a074fe5d593413f740fbb0fb036efc1585073a5c769e6b7bba5083bff67", + "da64240fb5aefe994b80dcbf86c6775e1d8b9827c90ea914dc89ed96994c1b06", + "f3dcceebebff82171d500aa5bfa42d923af47fd9d935ff3b24e4246c2c240bb0", + "5e9c33d78cdd3d5f71a74981aee540c199f9928c132f047ff975f9c4528929ed", + "e83e08ca018747334d5bef54eff1527d03fc478a9a2ce3bc1d08eb74b1e05c5a", + "2b4404ceb208a4cbcca4eca597cc25e50c156d1d4320b937795c201bf62e8e27", + "6cf6e54742a3e3a2469296b51863123d6939a3e4f18973bed3350f361a0a7fa1", + "173648ce3c3faebf66b1b400e2ba1d09a6f7a0e90c4f6eb259cf141cf2702868", + "1602f84cd08034833d4d6b6f0a63017840b0517fcd716dc5bb82071f81cacf22", + "5c9a5a89db7ce103784cd0a185ef589967930fa6e92aa90fb8c02031694a9404", + "a99a83be39be7d0d247f3805d7c78f47bf16a3babf9d63cb68e28c0f630e15c2", + "9a92a01899a649676ac792b2a2be8db3ab24f1f464a1af6b3c03b7f67e572510", + "e0448af4bfdabe13a044362ab133a5560a77e8e6605df7d9b36f22a9ccdd806f", + "8f675662f98a9961e9a67114a98f442359b8797f729c94c5a041ebdb937e0b57", + "6dd8437315fb9be06fcbb22ebc82103648da5b142622857175dd75a0f78c7a8f", + "6c4a96d440dbfc0f26f1bdf1e1c0ac273b573c36f14e55342fd98435e806b676", + "700725449099dc98933ea1c8f1b9fdaf21ccb7f7439451cbdcf763e7b633e52d", + "22c986a29a24c02703a8be6fc3a17f00975fe6f323366da8284a4c1070b18160", + "037036f85de49e6136d1f54c2b1f754d61c262bb88c806b72a156e272d60c535", + "8813017f3878a97b15c272982b95b3534a4475dbc3a6f40aaee3eb9dd593eb2a", + "403a7a97d3c47c57e89982086de458cc1c62d01449945e9adeb160bdb487e7c8", + "e1ae2a3ca0a102d9d7b80462c5c75ce1fd49a341a3ae60a497a98c9e84dc4d2c", + "7d3cf5fdda0516c200a2a5d622c256d481f9764d6a72799995e01b31c97f4f26", + "a080f0e1bf33dc8190c844c3b13c56c058ea08af44e1c7363d55e8fd8a7a3afc", + "a611f43917fd4c23e5bb65ba8dcbde6db510142346cad2b9ab596fa75635d9e3", + "ba068f56418356e2c0ee98119cc3030fa7a9b8c27d5530c93f134e899afedc02", + "81a7d27fa4e8d911410a733248f102e5a9eff4d8f5617114e97c1267cbf3d348", + "ea711ec0f66cec18c17b3bfa39967b00480a0df0575412c0e8a7aa8869ab93ac", + "dc2efe412c0c7cf5d7e838641bdbe2d59877ca74357536da58aaa0fd1b711ac0", + "93e321c3371d69fade1451f2f537579c54934aba5271a018540f70d4ac91a78e", + "8f1368dfc99618f3e1b2302ebee88319371106bef78471b0eb876f2f06a3a818", + "5fffc415587f815bf9645acdd481294fc4d83ac5b9a37275e8725921eaeed7f7", + "3f29e067de0e036efd2684b9c54e0e6b2787fb9d83504c1201c4d0a017a0785f", + "07f4a000178a78a4a8faa370d5aea0aa5628ff669522fbf6ee0d016ce016f8dc", + "773ac8e936b1618243407a82d1ec9a6feaa5ebd9cbd82619d19b5bd7f0297536", + "af56203cef3a9126c3442d964fe09bfeba50d9243fd9bb87ec38a961c59b5960", + "fbbdfc94f38b514470de4290bba2ebdff7aac5523d97a0abbb20859ebc82065a", + "471ab6bea6f7cae837a9fc601f70c7c8e53e84a544e43008d945875d61df04ad", + "e20fa6fa46cd4d80d54d393c86e49b282ea1526c5f339e579bad5b39304498b8", + "cac629d37126684710d0bb74fb52d529f2d16c73734f2005de6de9a504ad84ff", + "a953032ffba659a809d5f733daa9db681082aa65dd08c0b05664dbefd87707ba", + "5bab2244233e9f9f2d7191dfbe1ac968652ea1bc0fac48a5557b01c40d260f4a", + "9d09dc8281294423fd516835ab30f15416cfd011e74dff4bf5e05f87416f0cf6", + "893776d2cccda1f86b0e405d13a75a11a96528a45e0872e4ffc0b87513594100", + "758a1e6461aeb3ffb55c231caacce8f663d83eef4d12f8cf94d69b09252b6e06", + "0dee497dd3a7bbc26c1b2b2f807e55bc62765b3557cd50960e8b913a2e3acdba", + "35a08cc32bdce97e91ba274bde6d6f19c74ae3fd3566cf1c40002a0775872505", + "689104a13715e4e881a4640fd5e4bcd46687c67f53c91db4b8cae8d21cf90722", + "e48d19e8a8a211358e7e7ffe964e981d3a1d11ae76a2b44a44faa856566abc5b", + "28d7c2498774be7540d3b85cd67e873db198267ebd59cefb1164969d56544940", + "8440cbb16acf418689ac4fe6d2b65ddd949e96458542539d30bfe2125e3a88ca", + "6f837c7e4a9f4c4c1b17fb202a5bc7479add8cc0d26564766328f77455627961", + "fb786f9dc125141f04857fd1393abe9172ad9c3aade782bd4d8dc23018c662bb", + "be101e3278740014287a572b2b27fe3e20712bf589db356e800fad1e633d34b6", + "02770ff50283c20a9a9de291de391fe7ebb4744da607a7780b10a20c49a753c2", + "84801d626b5998746e0865aec4fcd1378bb376edcc763a80ee96373b01cbf72c", + "1da1dd3aa77a4e2d8aa0857ccd857d4952e58ab49c26a1f0cb60275030f6607e", + "04fefbda5ec9f182c2a22ad6bbbc42ffa322338e3562976b8d32b3406c2e38c9", + "e8ccdcb248078a482359f4f7973d3b2069794b9777c4e2ac21558fbffee59c8c", + "51507a05fbdfcc522a1f29099cc06458591bcd5809d2b210901e275dc1daed7d", + "05e6b311d3a3241022b0152924627706edf857161004dc785983c5c8e4059b19", + "986ccd7ef43c8085b738a0e2eb84b98aa920fd19f372c34c37569a5c7354d6df", + "37c4370297131fcef6101bb43e37ada63ee4c63eadd53c683cdffda2c22b6a5f", + "c8a736669a5a1c69c6088735306b2aa6da1fa685584446b27c53612344a28d39", + "0c829d4a74a40e4338a406a268de64a9ac1b58ad2f0655cf1412cfe10a81f128", + "ea8aeeeb0fcfa66319b5d1560c1c7e805cb445b678f60735a5450233a08f5146", + "0c03e2902e4374dc2ae6e9d46b27028af86c461ec65b9708829f6e341c5dfa86", + "427623b7f21f13216b47d64b3cce69d8695a12a8b76ceda909038e8ed1ad7ad6", + "309bd0bf85e4b9bb130a17df032a6d057d2f4774abca3a8af6fdbf25de9182d9", + "7f3da6402da41b66b0e5e957a40a787c53a3a31228f06d45f6ddfc275c06e815", + "9453352b0b6541e28b5c36d1ef833b7f49dad472ac7bc01712f04a1d0bd8cb3d", + "35b6a024cb364ee9e7ac55b3ee07e137b7dc7756c6e7131d02d603613f876578", + "6ce8b20bf01933590374ff85f4a2fcab43cde2bbf9bf7b56c7e4c21acce02af1", + "f02acb1e0f786b78b042e5d5e4d25fe711ecc05b2cbdc37077a4a1b66d925808", + "b5697acfcc9d3d4b58bf01ee959bb519b165d6e2b3ff799dcd8581f2e4ecc4b4", + "e5dcd86553008584de8d4e67edb1049198922900801bf51da55efcb7de45c37b", + "e0c3e5997bd114db9c09728c21b8b35748eee68f8eb305b5cc099be3c265d327", + "6c1e0ef8496d1c39fcde030239772ddf1182807dde25d54fea68085434a08b02", + "4fbd6bcb31a607f792cca7f514d8259a05f684092be8ac91b242bc90169a7042", + "9dbd18a509716c53037d8713d0353094d55b48253cb0d38cd7bc08959d7ff014", + "a444e2b82333cbd5dfe250e393e245d5db8b78f91bbb6a572761a0a43ed56b38", + "b163cba8c2d0441ac59033f7742733cb77812bd74de1147ae8173faae4f9269b", + "0ac9c6fc35728d1317490b51b36277e825a49ba95be2a6783ef7af99e49228f7", + "abe44cdbc6aea6876b8f009d6279479dca2c4f17c650c51bd7de410bbf23cd24", + "4b9370d4ae2fe08db33f468ffceca5d9fe6b0273ef2887a4ea8522293870e0a1", + "98b3b29996faf548b808efa1fd4ca779882bb75cc2ab3304f049b429a3638a97", + "dfb57e8a34f4911773133529e0e222f6a5cf691b25a65c288f8d6baa68b5f406", + "d1e35d54b3df21193102e9dcbb194a294323522ae35c68597b4b08f53cbf36ec", + "53e8bb244f3c2c90fcc8ceb1662e03aab3e1a781fa1697f7383e0bdc59831195", + "255874e4ced532485777b878f2d779c62853bd8d4d05ddadfa6163465703dc8c", + "6b61c176da93e56226cb6fb7a4f8acf1df87d02be81f823dc851680ae64f80b6", + "f035af0a109e467fd4ecd7c45bed043dd1ba0d02164c2b2aa0ab1989d8eaeff7", + "81b239e1213841934e989034959c9ca0448ad64ac3ab919751c2289600a20723", + "251b4f7823c8449e2e154cbab4aa72fb2cc55495da5fdc2d31075aa5647ba4cd", + "0769a11a881bfd2f02a087803235d344ad2f005010e40ecd7af5db96245dd719", + "f4963f675eefacf4cdd14ff7b759d5752aecee4cd704744e58b9bbbe078e0faa", + "28916a97e55790f8e0a95c1203c1f8f1eac99b866aac5800445ef2d888b4be87", + "575a46ecc4c7757656b9371e9b8dc058f99f9d9ad20a3e6de2d4e6cbc193711c", + "935994c1df9323d2bdcbab8762904e48edf6298904f3ae7e234599366bfd86ef", + "dec5bac62e0ef64db4936f818e325e12aed29ee0933277259185da1298dd0a28", + "3ba063cbea967fc0b7bb9a25c5a12ee801eaa92f5570d1d1a977a229834fd0a0", + "3327cc41ebebc9e82f06f836d5868f9c5023b05498bd73d836f04179d24fc7b9", + "8d70f449bda2223d0d647d7543bc3a2c29fedffaef789dc5bd73d25a6f0afd38", + "9902826a10b226265f357562bb20774358dbc636e790257a57af7f791b600acf", + "c5821a347232865496580de7f3043822ca56eea4f8266c51e3be4a16016cdeed", + "2817d6dee3e6706b92989f2dcef7cd0fef5d2263ed3d1c5dab8ba99550b1e5d5", + "b918f2ce206701dfe60eee1d40fad119540e928b8da813fe29d77a2e26c2738b", + "7f836479ecd2c4aec31c96935e2ce932135249c6077184b837f724fbdd425408", + "1381c39fb5a68c134b948aacf72b5127a7b0d5a721ed2091da25a3856b9a9af8", + "80e6ab5756de5eba8551f62d8943e5f650f4ae8864ea6bdffc3257ef1072679a", + "ae7dd5fcf4688844f5ef72471cc0273e0e2f8f43ba4fc3dd41208f70b880e5d4", + "e0f1d8c1a745ede1198fefbd0555bc118f7ccbd9ee783d8ed7a148f54fb1903f", + "33c8a75fad49fd3b3bb1e031fb283858f79b05a8b461eb1f8f0e9d41c53474bc", + "3864e97cd6f47c2eaf3fdcbb105e014accb4eb902be8a43dfca77dfe0d92761e", + "e524e7c40053d3d1da35ac8a584ad7034cd30de0e9513bf7731f8e5f51f7178e", + "12e121ad8a9be231659d08746b1a8b2b9247304dddc69cec074711970986cc6d", + "149a0d197a6c2dba3044e43f5fac90f6a797e0d4c8d91e241725e963083bb472", + "6a062ba02e79d2b2c001e1689daa1b3ade7c917ef26b30987798123818b202bd", + "99e47c124d128f741f30e7c5bc7575f11a005befaa26ab60b560fe4a65717aa0", + "147961e3d28573540582cb4a6e266f3a677d9e5b24da19c29fa611d3f8fba8a9", + "59261c94c9000fe26b3b050c4cf7ab06343d4ffcbe3934da65f12d8a7b0c6862", + "7428bc174ef7fd68911d46b35da30bbf8a292bb6b9ea99489b0c28bb55876e54", + "6fbff71f7187e67e5cc11f85ecc7d063284c6829ffc2b647d9439cf6d80c71b3", + "d49db17aa1e54596333d1962db0050b54a96abc6184f28b46778ac3eb9bc2290", + "082436ca15376750587883056c2b5fceafd232f6fd91d839dcf7f138583565d0", + "2d6c7614ddf121cedd9db989f73da61c3e5d5d7a876139d2d441d8dc28bef0ab", + "10b5eb9db4b22b9047b2c9a2b40abefc9786d8f0b33514bcef81c462f241ca60" + ], + "key_material": { + "scan_priv_key": "000000000000000000000000000000000000000000000000000000000000dead", + "spend_priv_key": "000000000000000000000000000000000000000000000000000000000000beef" + }, + "labels": [ + 0 + ] + }, + "expected": { + "addresses": [ + "sp1qqtnvg7hxjck9ag24naytgd7pjwsmevwh95ydwht58w3uh7uw0ta7kq6xcdal4dazgg2txp472hdz4svms98328lqdflmpxppmc6ykamcrv9s7w9g", + "sp1qqtnvg7hxjck9ag24naytgd7pjwsmevwh95ydwht58w3uh7uw0ta7kqmk4a3pm24z0yepw6aw27pku56md0hq5ace0l3p3jstkqaajwrsjqc5dde5" + ], + "n_outputs": 2323, + "tweak": "022c333a8938ca0c7433c5e39d440b469f58374d0363b5bffc66aca1cc10d7b609", + "shared_secret": "03abe0979dbbe4e1bb2cd2e06524a411c0b829c1d2282052da817b46f1d6e598e4", + "input_pub_key_sum": "02bca87f72e604e8850064552bedf380ca4584227057efe12a6cc238470658aaa3" + } + } + ] + } +] diff --git a/testing/devtest/verify_sp_outputs.py b/testing/devtest/verify_sp_outputs.py index 35e09397d..0e9ac8bfe 100644 --- a/testing/devtest/verify_sp_outputs.py +++ b/testing/devtest/verify_sp_outputs.py @@ -19,7 +19,11 @@ from silentpayments import ( _combine_pubkeys, _compute_ecdh_share, + _compute_input_hash, _compute_silent_payment_output_script, + _compute_silent_payment_spending_privkey, + _negate_if_odd_y, + _sum_privkeys, SilentPaymentsMixin, ) @@ -200,9 +204,45 @@ def _build_mock_psbt(params): parts.append(b2a_hex(txid).decode() + ":" + b2a_hex(vout).decode()) RV.write(",".join(parts)) +elif mode == "sum_privkeys": + # Sum a list of normalized privkeys; return as 64-char hex + privkeys = [a2b_hex(h) for h in params["privkeys"]] + result = _sum_privkeys(privkeys) + RV.write(b2a_hex(result).decode()) + elif mode == "pubkey_from_input": # Call _pubkey_from_input for a specific input; return pubkey hex or "" psbt = _build_mock_psbt(params) i = params["input_index"] pk = psbt._pubkey_from_input(psbt.inputs[i]) RV.write(b2a_hex(pk).decode() if pk else "") + +elif mode == "compute_input_hash": + outpoints = [(a2b_hex(t), a2b_hex(v)) for t, v in params["outpoints"]] + A_sum = a2b_hex(params["A_sum"]) + result = _compute_input_hash(outpoints, A_sum) + RV.write(b2a_hex(result).decode()) + +elif mode == "compute_shared_secret": + ecdh_share = a2b_hex(params["ecdh_share"]) + input_hash = a2b_hex(params["input_hash"]) + result = ngu.secp256k1.ec_pubkey_tweak_mul(ecdh_share, input_hash) + RV.write(b2a_hex(result).decode()) + +elif mode == "pubkey_from_privkey": + # Compute pubkey = privkey * G; return 33-byte compressed hex + privkey = a2b_hex(params["privkey"]) + G = ngu.secp256k1.generator() + pubkey = ngu.secp256k1.ec_pubkey_tweak_mul(G, privkey) + RV.write(b2a_hex(pubkey).decode()) + +elif mode == "compute_spending_privkey": + b_spend = a2b_hex(params["b_spend"]) + tweak = a2b_hex(params["tweak"]) + result = _compute_silent_payment_spending_privkey(b_spend, tweak) + RV.write(b2a_hex(result).decode()) + +elif mode == "negate_if_odd_y": + privkey = a2b_hex(params["privkey"]) + result = _negate_if_odd_y(privkey) + RV.write(b2a_hex(result).decode()) diff --git a/testing/test_bip352_vectors.py b/testing/test_bip352_vectors.py new file mode 100644 index 000000000..ac4290674 --- /dev/null +++ b/testing/test_bip352_vectors.py @@ -0,0 +1,349 @@ +# (c) Copyright 2024 by Coinkite Inc. This file is covered by license found in COPYING-CC. +# +# test_bip352_vectors.py - BIP-352 send/receive test vector verification +# +# Verifies that crypto primitives in silentpayments.py match the BIP-352 +# reference test vectors. Pubkey extraction from raw scriptSig/witness is +# done CPython-side; all EC math is delegated to the simulator +# +import hashlib +import json +import struct +import pytest +from sp_helpers import ( + _sim_compute_ecdh_share, + _sim_compute_input_hash, + _sim_compute_shared_secret, + _sim_compute_spending_privkey, + _sim_compute_output_script, + _sim_pubkey_from_privkey, + _sim_combine_pubkeys, + _sim_negate_if_odd_y, + _sim_sum_privkeys, +) + +NUMS_H = bytes.fromhex( + "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" +) + + +def load_bip352_vectors(): + with open("bip352_test_vectors.json") as f: + return json.load(f) + + +# --------------------------------------------------------------------------- +# CPython-side helpers +# --------------------------------------------------------------------------- + + +def _hash160(data): + return hashlib.new("ripemd160", hashlib.sha256(data).digest()).digest() + + +def _parse_witness_stack(txinwitness_hex): + """Parse serialized witness into a list of stack items (bytes).""" + if not txinwitness_hex: + return [] + raw = bytes.fromhex(txinwitness_hex) + pos = 0 + n_items = raw[pos] + pos += 1 + items = [] + for _ in range(n_items): + # CompactSize length + length = raw[pos] + pos += 1 + if length == 0xFD: + length = int.from_bytes(raw[pos : pos + 2], "little") + pos += 2 + elif length == 0xFE: + length = int.from_bytes(raw[pos : pos + 4], "little") + pos += 4 + items.append(raw[pos : pos + length]) + pos += length + return items + + +def _is_p2pkh(spk): + return ( + len(spk) == 25 + and spk[0] == 0x76 + and spk[1] == 0xA9 + and spk[-2] == 0x88 + and spk[-1] == 0xAC + ) + + +def _is_p2wpkh(spk): + return len(spk) == 22 and spk[0] == 0x00 and spk[1] == 0x14 + + +def _is_p2tr(spk): + return len(spk) == 34 and spk[0] == 0x51 and spk[1] == 0x20 + + +def _is_p2sh(spk): + return len(spk) == 23 and spk[0] == 0xA9 and spk[1] == 0x14 and spk[-1] == 0x87 + + +def _extract_pubkey_from_vin(vin): + """Extract compressed pubkey from a BIP-352 test vector vin entry. + + Returns (pubkey_bytes, is_taproot) or (None, None) if ineligible. + Follows BIP-352 reference get_pubkey_from_input() logic. + """ + spk = bytes.fromhex(vin["prevout"]["scriptPubKey"]["hex"]) + script_sig = bytes.fromhex(vin.get("scriptSig", "")) + witness = _parse_witness_stack(vin.get("txinwitness", "")) + + if _is_p2pkh(spk): + spk_hash = spk[3:23] + for i in range(len(script_sig), 32, -1): + candidate = script_sig[i - 33 : i] + if candidate[0] in (0x02, 0x03) and _hash160(candidate) == spk_hash: + return candidate, False + return None, None + + if _is_p2sh(spk): + redeem_script = script_sig[1:] + if _is_p2wpkh(redeem_script) and witness: + pk = witness[-1] + if len(pk) == 33 and pk[0] in (0x02, 0x03): + return pk, False + return None, None + + if _is_p2wpkh(spk): + if witness: + pk = witness[-1] + if len(pk) == 33 and pk[0] in (0x02, 0x03): + return pk, False + return None, None + + if _is_p2tr(spk): + stack = list(witness) + if stack: + if len(stack) > 1 and stack[-1][0] == 0x50: + stack.pop() + if len(stack) > 1: + control_block = stack[-1] + internal_key = control_block[1:33] + if internal_key == NUMS_H: + return None, None + x_only = spk[2:34] + return b"\x02" + x_only, True + + return None, None + + +def _build_outpoints(vin_list): + """Build (txid_bytes, vout_bytes) list from vin entries. + + txid is reversed to internal byte order, vout is 4-byte LE. + """ + outpoints = [] + for vin in vin_list: + txid = bytes.fromhex(vin["txid"])[::-1] + vout = struct.pack(" 2323 for g in groups.values()): + for eo in expected["outputs"]: + assert eo == [] + return + + # 3. Shared secrets and 4. Output derivation + actual_outputs = set() + for scan_key_hex, group in groups.items(): + scan_pub_key = bytes.fromhex(scan_key_hex) + privkey_bytes = bytes.fromhex("%064x" % privkey_sum) + ecdh_share = _sim_compute_ecdh_share( + sim_exec, sim_execfile, privkey_bytes, scan_pub_key + ) + input_hash = _sim_compute_input_hash( + sim_exec, sim_execfile, outpoints, A_sum + ) + shared_secret = _sim_compute_shared_secret( + sim_exec, sim_execfile, ecdh_share, input_hash + ) + + # Check shared_secret against expected (find first recipient index for this scan key) + for ri, _ in group: + es = expected["shared_secrets"][ri] + if es is not None: + assert shared_secret.hex() == es, ( + "shared_secret mismatch for recipient %d" % ri + ) + break + + for k, (ri, recipient) in enumerate(group): + spend_pub_key = bytes.fromhex(recipient["spend_pub_key"]) + script = _sim_compute_output_script( + sim_exec, + sim_execfile, + outpoints, + A_sum, + ecdh_share, + spend_pub_key, + k, + ) + actual_outputs.add(script[2:].hex()) + + assert any(set(eo) == actual_outputs for eo in expected["outputs"]), ( + "output mismatch: got %s" % actual_outputs + ) + + +class TestBIP352Receiving: + @pytest.mark.parametrize("vec_idx", range(len(_VECTORS)), ids=_VEC_IDS) + def test_receiving(self, sim_exec, sim_execfile, vec_idx): + vec = _VECTORS[vec_idx] + receiving = vec["receiving"][0] + expected = receiving["expected"] + vin_list = receiving["given"]["vin"] + scan_priv_key = bytes.fromhex( + receiving["given"]["key_material"]["scan_priv_key"] + ) + spend_priv_key = bytes.fromhex( + receiving["given"]["key_material"]["spend_priv_key"] + ) + outpoints = _build_outpoints(vin_list) + + # 1. Extract key material and compute A_sum + extracted = _extract_key_material(vin_list) + + if not extracted: + assert expected.get("outputs", []) == [] + return + + expected_pk_sum = expected.get("input_pub_key_sum") + if expected_pk_sum is None: + # Point at infinity or no valid inputs + assert expected.get("outputs", []) == [] + return + + pubkeys = [pk for pk, _, _ in extracted] + A_sum = _sim_combine_pubkeys(sim_exec, sim_execfile, pubkeys) + assert A_sum.hex() == expected_pk_sum, "input_pub_key_sum mismatch" + + # 2. Shared secret + input_hash = _sim_compute_input_hash(sim_exec, sim_execfile, outpoints, A_sum) + ecdh_share = _sim_compute_ecdh_share( + sim_exec, sim_execfile, scan_priv_key, A_sum + ) + shared_secret = _sim_compute_shared_secret( + sim_exec, sim_execfile, ecdh_share, input_hash + ) + assert shared_secret.hex() == expected.get("shared_secret"), ( + "shared_secret mismatch" + ) + + # 3. Spending privkey tweaks + expected_outputs = expected.get("outputs", []) + if not expected_outputs: + return + + for expected_out in expected_outputs: + expected_tweak = bytes.fromhex(expected_out["priv_key_tweak"]) + expected_pubkey = expected_out["pub_key"] + d = _sim_compute_spending_privkey( + sim_exec, sim_execfile, spend_priv_key, expected_tweak + ) + computed_pk = _sim_pubkey_from_privkey(sim_exec, sim_execfile, d) + assert computed_pk[1:].hex() == expected_pubkey, ( + "spending privkey mismatch for output %s" % expected_pubkey + ) From a0b11d892b3e15fed1f5b922a7d56e399b103137 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:50:51 -0500 Subject: [PATCH 10/41] BIP-375: implement Silent Payments PSBT signing workflows Integrate preview silent payment address as output in auth:interact Integrate silent payments in signing workflow Add sp_hrp property to chains.py Add silent payments fields to psbt.py --- shared/auth.py | 12 +++++ shared/chains.py | 3 ++ shared/psbt.py | 97 +++++++++++++++++++++++++++++++++++----- shared/silentpayments.py | 58 +++++++++++++++++++++--- 4 files changed, 154 insertions(+), 16 deletions(-) diff --git a/shared/auth.py b/shared/auth.py index 68e05c209..6cf48d211 100644 --- a/shared/auth.py +++ b/shared/auth.py @@ -416,6 +416,12 @@ async def interact(self): ccc_c_xfp = CCCFeature.get_xfp() # can be None args = self.psbt.consider_inputs(cosign_xfp=ccc_c_xfp) + + # Silent Payments: Validate and pre-process Silent Payments outputs to make preview useful + if self.psbt.has_silent_payment_outputs(): + with stash.SensitiveValues() as sv: + self.psbt.process_silent_payments(sv) + self.psbt.consider_outputs(*args, cosign_xfp=ccc_c_xfp) del args # not needed anymore # we can properly assess sighash only after we know @@ -725,6 +731,8 @@ def output_summary_text(self, msg): total_change = 0 has_change = False + # TODO: Test pay to silent payment change address + for idx, tx_out in self.psbt.output_iter(): outp = self.psbt.outputs[idx] if outp.is_change: @@ -740,6 +748,8 @@ def output_summary_text(self, msg): else: if len(largest_outs) < MAX_VISIBLE_OUTPUTS: rendered, _ = self.render_output(tx_out) + if outp.sp_v0_info: + rendered += self.psbt.render_silent_payment_output_string(outp) largest_outs.append((tx_out.nValue, rendered)) if len(largest_outs) == MAX_VISIBLE_OUTPUTS: # descending sort from the biggest value to lowest (sort on out.nValue) @@ -1807,6 +1817,8 @@ def yield_item(self, offset, end, qr_items, change_idxs): outp = self.user_auth_action.psbt.outputs[idx] item = "Output %d%s:\n\n" % (idx, " (change)" if outp.is_change else "") msg, addr_or_script = self.user_auth_action.render_output(out) + if outp.sp_v0_info: + msg += self.user_auth_action.psbt.render_silent_payment_output_string(outp) item += msg qr_items.append(addr_or_script) if outp.is_change: diff --git a/shared/chains.py b/shared/chains.py index 7d58c15b6..e21768b55 100644 --- a/shared/chains.py +++ b/shared/chains.py @@ -58,6 +58,7 @@ class ChainsBase: curve = 'secp256k1' menu_name = None # use 'name' if this isn't defined ccc_min_block = 0 + sp_hrp = 'sp' # BIP-352 Silent Payment address HRP (default mainnet) # b44_cointype comes from # @@ -325,6 +326,7 @@ class BitcoinTestnet(ChainsBase): } bech32_hrp = 'tb' + sp_hrp = 'tsp' # BIP-352 Silent Payment testnet HRP b58_addr = bytes([111]) b58_script = bytes([196]) @@ -337,6 +339,7 @@ class BitcoinRegtest(BitcoinTestnet): ctype = 'XRT' name = 'Bitcoin Regtest' bech32_hrp = 'bcrt' + sp_hrp = 'tsp' # BIP-352 Silent Payment regtest HRP def get_chain(short_name): diff --git a/shared/psbt.py b/shared/psbt.py index e16b2ac2c..5e13a70e4 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -42,9 +42,13 @@ PSBT_IN_REQUIRED_HEIGHT_LOCKTIME, PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE, PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS, PSBT_IN_MUSIG2_PUB_NONCE, PSBT_IN_MUSIG2_PARTIAL_SIG, PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS, + PSBT_OUT_SP_V0_INFO, PSBT_OUT_SP_V0_LABEL, + PSBT_IN_SP_DLEQ, PSBT_IN_SP_ECDH_SHARE, + PSBT_GLOBAL_SP_DLEQ, PSBT_GLOBAL_SP_ECDH_SHARE, AF_P2WSH, AF_P2WSH_P2SH, AF_P2SH, AF_P2TR, AF_P2WPKH, AF_CLASSIC, AF_P2WPKH_P2SH, AFC_SEGWIT, AF_BARE_PK ) +from silentpayments import SilentPaymentsMixin psbt_tmp256 = bytearray(256) @@ -450,12 +454,15 @@ def parse_subpaths(self, my_xfp, parent, cosign_xfp=None): # class psbtOutputProxy(psbtProxy): no_keys = { PSBT_OUT_REDEEM_SCRIPT, PSBT_OUT_WITNESS_SCRIPT, PSBT_OUT_AMOUNT, - PSBT_OUT_SCRIPT, PSBT_OUT_TAP_INTERNAL_KEY, PSBT_OUT_TAP_TREE } + PSBT_OUT_SCRIPT, PSBT_OUT_TAP_INTERNAL_KEY, PSBT_OUT_TAP_TREE, + PSBT_OUT_SP_V0_INFO, PSBT_OUT_SP_V0_LABEL } + short_values = { PSBT_OUT_SP_V0_INFO, PSBT_OUT_SP_V0_LABEL } blank_flds = ('unknown', 'subpaths', 'redeem_script', 'witness_script', 'sp_idxs', 'is_change', 'amount', 'script', 'attestation', 'proprietary', 'taproot_internal_key', 'taproot_subpaths', 'taproot_tree', 'ik_idx', - 'musig_pubkeys') + 'musig_pubkeys', 'sp_v0_info', 'sp_v0_label', + ) def __init__(self, fd, idx): super().__init__() @@ -471,6 +478,8 @@ def __init__(self, fd, idx): #self.script = None #self.amount = None #self.musig_pubkeys = None + #self.sp_v0_info = None # used to identify silent payment outputs - 66-byte (scan-pub || spend-pub) + #self.sp_v0_label = None # Nonzero when output is change; higher bits record derivation-path issues. #self.is_change = 0 @@ -521,6 +530,10 @@ def store(self, kt, key, val): elif kt == PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS: self.musig_pubkeys = self.musig_pubkeys or [] self.musig_pubkeys.append((key, val)) + elif kt == PSBT_OUT_SP_V0_INFO: + self.sp_v0_info = val + elif kt == PSBT_OUT_SP_V0_LABEL: + self.sp_v0_label = val else: self.unknown = self.unknown or [] pos, length = key @@ -559,6 +572,12 @@ def serialize(self, out_fd, is_v2): wr(PSBT_OUT_SCRIPT, self.script) wr(PSBT_OUT_AMOUNT, self.amount) + if self.sp_v0_info: + wr(PSBT_OUT_SP_V0_INFO, self.sp_v0_info) + + if self.sp_v0_label: + wr(PSBT_OUT_SP_V0_LABEL, self.sp_v0_label) + if self.proprietary: for k, v in self.proprietary: wr(PSBT_PROPRIETARY, v, k) @@ -569,9 +588,9 @@ def serialize(self, out_fd, is_v2): def determine_my_change(self, out_idx, txo, parsed_subpaths, parent): # Do things make sense for this output? - + # NOTE: We might think it's a change output just because the PSBT - # creator has given us a key path. However, we must be **very** + # creator has given us a key path. However, we must be **very** # careful and fully validate all the details. # - no output info is needed, in general, so # any output info provided better be right, or fail as "fraud" @@ -691,7 +710,9 @@ def fraud(idx, af, err=""): class psbtInputProxy(psbtProxy): # just need to store a simple number for these - short_values = { PSBT_IN_SIGHASH_TYPE } + # Silent Payments (shares/dleq): bytes (not proxied) so scan-pub can be used as dict key + # and dict can be mutated in place + short_values = { PSBT_IN_SIGHASH_TYPE, PSBT_IN_SP_ECDH_SHARE, PSBT_IN_SP_DLEQ } # only part-sigs have a key to be stored. no_keys = {PSBT_IN_NON_WITNESS_UTXO, PSBT_IN_WITNESS_UTXO, PSBT_IN_SIGHASH_TYPE, @@ -709,7 +730,8 @@ class psbtInputProxy(psbtProxy): 'taproot_merkle_root', 'taproot_script_sigs', 'taproot_scripts', 'taproot_subpaths', 'taproot_internal_key', 'taproot_key_sig', 'tr_added_sigs', 'ik_idx', 'musig_pubkeys', 'musig_pubnonces', 'musig_part_sigs', 'musig_agg_idx', - 'musig_added_pubnonces', 'musig_added_sigs', 'wif_key', 'wif_redeem_script' + 'musig_added_pubnonces', 'musig_added_sigs', 'wif_key', 'wif_redeem_script', + 'sp_ecdh_shares', 'sp_dleq_proofs', ) def __init__(self, fd, idx): @@ -757,6 +779,10 @@ def __init__(self, fd, idx): #self.musig_pubnonces = None #self.musig_part_sigs = None + # === silent payments === + #self.sp_ecdh_shares = None # dict[scan-pub] = ecdh_share + #self.sp_dleq_proofs = None # dict[scan-pub] = dleq_proof + self.parse(fd) @property @@ -1283,6 +1309,12 @@ def store(self, kt, key, val): elif kt == PSBT_IN_MUSIG2_PARTIAL_SIG: self.musig_part_sigs = self.musig_part_sigs or [] self.musig_part_sigs.append((key, val)) + elif kt == PSBT_IN_SP_ECDH_SHARE: + self.sp_ecdh_shares = self.sp_ecdh_shares or {} + self.sp_ecdh_shares[key] = val + elif kt == PSBT_IN_SP_DLEQ: + self.sp_dleq_proofs = self.sp_dleq_proofs or {} + self.sp_dleq_proofs[key] = val else: # including: PSBT_IN_FINAL_SCRIPTSIG, PSBT_IN_FINAL_SCRIPTWITNESS self.unknown = self.unknown or [] @@ -1380,20 +1412,31 @@ def serialize(self, out_fd, is_v2): if self.req_height is not None: wr(PSBT_IN_REQUIRED_HEIGHT_LOCKTIME, pack(" Date: Tue, 23 Dec 2025 15:34:24 -0500 Subject: [PATCH 11/41] BIP-376: handle spending silent payments outputs Add sp_spend support to _derive_input_privkey Validate bip376 spend key derivation --- shared/psbt.py | 18 ++++++- shared/silentpayments.py | 68 +++++++++++++++++++++----- testing/devtest/unit_silentpayments.py | 17 +++++++ testing/devtest/verify_sp_outputs.py | 2 + testing/psbt.py | 16 ++++++ 5 files changed, 106 insertions(+), 15 deletions(-) diff --git a/shared/psbt.py b/shared/psbt.py index 5e13a70e4..bfb258a23 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -45,6 +45,7 @@ PSBT_OUT_SP_V0_INFO, PSBT_OUT_SP_V0_LABEL, PSBT_IN_SP_DLEQ, PSBT_IN_SP_ECDH_SHARE, PSBT_GLOBAL_SP_DLEQ, PSBT_GLOBAL_SP_ECDH_SHARE, + PSBT_IN_SP_TWEAK, PSBT_IN_SP_SPEND_BIP32_DERIVATION, AF_P2WSH, AF_P2WSH_P2SH, AF_P2SH, AF_P2TR, AF_P2WPKH, AF_CLASSIC, AF_P2WPKH_P2SH, AFC_SEGWIT, AF_BARE_PK ) @@ -719,7 +720,7 @@ class psbtInputProxy(psbtProxy): PSBT_IN_REDEEM_SCRIPT, PSBT_IN_WITNESS_SCRIPT, PSBT_IN_FINAL_SCRIPTSIG, PSBT_IN_FINAL_SCRIPTWITNESS, PSBT_IN_PREVIOUS_TXID, PSBT_IN_OUTPUT_INDEX, PSBT_IN_SEQUENCE, PSBT_IN_REQUIRED_TIME_LOCKTIME, - PSBT_IN_REQUIRED_HEIGHT_LOCKTIME, PSBT_IN_TAP_KEY_SIG, + PSBT_IN_REQUIRED_HEIGHT_LOCKTIME, PSBT_IN_SP_TWEAK, PSBT_IN_TAP_KEY_SIG, PSBT_IN_TAP_INTERNAL_KEY, PSBT_IN_TAP_MERKLE_ROOT} blank_flds = ( @@ -731,7 +732,7 @@ class psbtInputProxy(psbtProxy): 'taproot_subpaths', 'taproot_internal_key', 'taproot_key_sig', 'tr_added_sigs', 'ik_idx', 'musig_pubkeys', 'musig_pubnonces', 'musig_part_sigs', 'musig_agg_idx', 'musig_added_pubnonces', 'musig_added_sigs', 'wif_key', 'wif_redeem_script', - 'sp_ecdh_shares', 'sp_dleq_proofs', + 'sp_ecdh_shares', 'sp_dleq_proofs', 'sp_tweak', 'sp_spend_bip32_derivation', ) def __init__(self, fd, idx): @@ -782,6 +783,8 @@ def __init__(self, fd, idx): # === silent payments === #self.sp_ecdh_shares = None # dict[scan-pub] = ecdh_share #self.sp_dleq_proofs = None # dict[scan-pub] = dleq_proof + #self.sp_tweak = None + #self.sp_spend_bip32_derivation = None # (spend-pub, xfp || path) self.parse(fd) @@ -1315,6 +1318,10 @@ def store(self, kt, key, val): elif kt == PSBT_IN_SP_DLEQ: self.sp_dleq_proofs = self.sp_dleq_proofs or {} self.sp_dleq_proofs[key] = val + elif kt == PSBT_IN_SP_TWEAK: + self.sp_tweak = self.get(val) + elif kt == PSBT_IN_SP_SPEND_BIP32_DERIVATION: + self.sp_spend_bip32_derivation = (key, val) else: # including: PSBT_IN_FINAL_SCRIPTSIG, PSBT_IN_FINAL_SCRIPTWITNESS self.unknown = self.unknown or [] @@ -1420,6 +1427,13 @@ def serialize(self, out_fd, is_v2): for k, v in self.sp_dleq_proofs.items(): wr(PSBT_IN_SP_DLEQ, v, k) + if self.sp_tweak: + wr(PSBT_IN_SP_TWEAK, self.sp_tweak) + + if self.sp_spend_bip32_derivation: + k, v = self.sp_spend_bip32_derivation + wr(PSBT_IN_SP_SPEND_BIP32_DERIVATION, v, k) + if self.unknown: for k, v in self.unknown: wr(None, v, k) diff --git a/shared/silentpayments.py b/shared/silentpayments.py index c1e64f12d..c8ccf6eb4 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -1,6 +1,6 @@ # (c) Copyright 2024 by Coinkite Inc. This file is covered by license found in COPYING-CC. # -# silentpayments.py - BIP-352/BIP-375 +# silentpayments.py - BIP-352/BIP-375/BIP-376 # # Consolidates cryptographic primitives and PSBT handling logic for Silent Payments # @@ -41,6 +41,37 @@ def encode_silent_payment_address(scan_key, spend_key, version=0): return ngu.codecs.bip352_encode(hrp, scan_key, spend_key, version) +def validate_bip376_spend(input, output_xonly, my_xfp=None, parent=None): + """Validate silent payment spend using PSBT input data + + TODO: replace with test vectors once available + + Raises FatalPSBTIssue if any SP spend validation checks fail + """ + B_spend_coords, val_coords = input.sp_spend_bip32_derivation + xfp_path = input.parse_xfp_path(val_coords) + if my_xfp is not None: + xfp_path = input.handle_zero_xfp(xfp_path, my_xfp, parent) + + sp_path = xfp_path[1:] + if len(sp_path) != 5: + raise FatalPSBTIssue("SP spend path must have 5 components") + if sp_path[0] != (352 | 0x80000000): + raise FatalPSBTIssue("SP spend key purpose must use 352h path") + + expected_coin = chains.current_chain().b44_cointype | 0x80000000 + if sp_path[1] != expected_coin: + raise FatalPSBTIssue("SP spend path coin type does not match network") + if not (sp_path[2] & 0x80000000): + raise FatalPSBTIssue("SP spend path account must be hardened") + if sp_path[3] != 0x80000000: + raise FatalPSBTIssue("SP spend path key type must be 0h") + + B_spend = input.get(B_spend_coords) + if _compute_silent_payment_spending_xonly(B_spend, input.sp_tweak) != output_xonly: + raise FatalPSBTIssue("SP_TWEAK does not match UTXO output key") + + # ----------------------------------------------------------------------------- # Silent Payments Cryptographic Primitives # ----------------------------------------------------------------------------- @@ -746,25 +777,36 @@ def _derive_input_privkey(self, input, sv): Derive the contributing private key for an eligible input Note: + For silent payment inputs, derives from sp_spend_bip32_derivation and sp_tweak For taproot inputs, uses the internal key's derivation path (ik_idx), XFP-checked For non-taproot inputs, uses the first matching BIP32 derivation path Returns: bytes: Derived private key as (32-byte scalar) or None if not eligible """ - # TODO: BIP-376 sp_spend_derivation should go here - spk = input.utxo_spk - if spk and _is_p2tr(spk): - if input.ik_idx is not None and input.taproot_subpaths: - _, path_coords = input.taproot_subpaths[input.ik_idx] - xfp_path = self.parse_xfp_path(path_coords[2]) - if xfp_path[0] == self.my_xfp: - return self._path_to_privkey(xfp_path, sv) + privkey = None + + if input.sp_tweak and input.sp_spend_bip32_derivation: + _, val_coords = input.sp_spend_bip32_derivation + xfp_path = self.parse_xfp_path(val_coords) + if xfp_path[0] == self.my_xfp: + privkey = _compute_silent_payment_spending_privkey(self._path_to_privkey(xfp_path, sv), input.sp_tweak) else: - for xfp_path in self._iter_input_xfp_paths(input): - if xfp_path[0] == self.my_xfp: - return self._path_to_privkey(xfp_path, sv) - return None + spk = input.utxo_spk + if spk and _is_p2tr(spk): + if input.ik_idx is not None and input.taproot_subpaths: + _, path_coords = input.taproot_subpaths[input.ik_idx[0]] + xfp_path = self.parse_xfp_path(path_coords[2]) + if xfp_path[0] == self.my_xfp: + privkey = self._path_to_privkey(xfp_path, sv) + if input.taproot_internal_key: + privkey = self._normalize_p2tr_privkey(privkey, self.get(input.taproot_internal_key)) + else: + for xfp_path in self._iter_input_xfp_paths(input): + if xfp_path[0] == self.my_xfp: + privkey = self._path_to_privkey(xfp_path, sv) + break + return privkey def _iter_input_xfp_paths(self, input): """ diff --git a/testing/devtest/unit_silentpayments.py b/testing/devtest/unit_silentpayments.py index 35955499b..a503418ad 100644 --- a/testing/devtest/unit_silentpayments.py +++ b/testing/devtest/unit_silentpayments.py @@ -16,6 +16,7 @@ _combine_pubkeys, _compute_shared_secret_tweak, _compute_silent_payment_output_script, + _compute_silent_payment_spending_privkey, _is_p2pkh, _is_p2wpkh, _is_p2tr, @@ -195,6 +196,20 @@ except ValueError as e: assert "33 bytes" in str(e) +# --------------------------------------------------------------------------- +# Spending Privkey +# --------------------------------------------------------------------------- + +result = _compute_silent_payment_spending_privkey((1).to_bytes(32, "big"), (42).to_bytes(32, "big")) +assert isinstance(result, bytes) and len(result) == 32 +assert result != (1).to_bytes(32, "big") +assert 0 < int.from_bytes(result, "big") < ngu.secp256k1.curve_order_int() + +try: + _compute_silent_payment_spending_privkey(b"\x00" * 32, b"\x00" * 32) + assert False, "Should raise" +except ValueError as e: + assert "not in valid scalar range" in str(e) # --------------------------------------------------------------------------- # Mock Infrastructure @@ -212,6 +227,8 @@ def __init__(self): self.prevout_idx = None self.witness_utxo = None self.taproot_internal_key = None + self.sp_tweak = None + self.sp_spend_bip32_derivation = None self.utxo_spk = None self.ik_idx = None self.sighash = None diff --git a/testing/devtest/verify_sp_outputs.py b/testing/devtest/verify_sp_outputs.py index 0e9ac8bfe..95d191d79 100644 --- a/testing/devtest/verify_sp_outputs.py +++ b/testing/devtest/verify_sp_outputs.py @@ -53,6 +53,8 @@ def __init__(self): self.sp_dleq_proofs = {} self.subpaths = [] self.taproot_subpaths = [] + self.sp_tweak = None + self.sp_spend_bip32_derivation = {} self.sp_idxs = None self.ik_idx = None diff --git a/testing/psbt.py b/testing/psbt.py index 6da02b953..77f0ab06c 100644 --- a/testing/psbt.py +++ b/testing/psbt.py @@ -65,6 +65,9 @@ # BIP-375 Silent Payments PSBT_IN_SP_ECDH_SHARE = 0x1d PSBT_IN_SP_DLEQ = 0x1e +# BIP-376 Silent Payments +PSBT_IN_SP_SPEND_BIP32_DERIVATION = 0x1f +PSBT_IN_SP_TWEAK = 0x20 # OUTPUTS === PSBT_OUT_REDEEM_SCRIPT = 0x00 @@ -153,6 +156,8 @@ def defaults(self): self.musig_part_sigs = {} self.sp_ecdh_shares = {} self.sp_dleq_proofs = {} + self.sp_tweak = None + self.sp_spend_bip32_derivation = {} self.others = {} self.unknown = {} @@ -185,6 +190,8 @@ def __eq__(a, b): a.musig_part_sigs == b.musig_part_sigs and \ a.sp_ecdh_shares == b.sp_ecdh_shares and \ a.sp_dleq_proofs == b.sp_dleq_proofs and \ + a.sp_tweak == b.sp_tweak and \ + a.sp_spend_bip32_derivation == b.sp_spend_bip32_derivation and \ a.unknown == b.unknown if rv: # NOTE: equality test on signatures requires parsing DER stupidness @@ -278,6 +285,10 @@ def parse_kv(self, kt, key, val): self.sp_ecdh_shares[key] = val elif kt == PSBT_IN_SP_DLEQ: self.sp_dleq_proofs[key] = val + elif kt == PSBT_IN_SP_TWEAK: + self.sp_tweak = val + elif kt == PSBT_IN_SP_SPEND_BIP32_DERIVATION: + self.sp_spend_bip32_derivation[key] = val else: self.unknown[bytes([kt]) + key] = val @@ -342,6 +353,11 @@ def serialize_kvs(self, wr, v2): if self.sp_dleq_proofs: for k, v in self.sp_dleq_proofs.items(): wr(PSBT_IN_SP_DLEQ, v, k) + if self.sp_tweak is not None: + wr(PSBT_IN_SP_TWEAK, self.sp_tweak) + if self.sp_spend_bip32_derivation: + for k, v in self.sp_spend_bip32_derivation.items(): + wr(PSBT_IN_SP_SPEND_BIP32_DERIVATION, v, k) if self.musig_pubnonces: for (pk, ak, lh), pubnonce in self.musig_pubnonces.items(): From 3906b6af7fcec04047e505bdc115757947805602 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Thu, 5 Mar 2026 11:26:02 -0500 Subject: [PATCH 12/41] SP: add Silent Payments integration tests Create end-to-end tests for SP in testing/test_silentpayments.py - Expose foreign_mk for partial ownership coverage test Integrate SP spend into psbt functions: consider_inputs, determine_my_signing_key, sign_it - Synthesize parsed_subpaths from PSBT_IN_SPEND_BIP32_DERIVATION - Set input.sp_idxs to placeholder to synthesize input is_owned - Implement SP input signing Refactor _compute_and_store_ecdh_shares and _derive_input_privkey to leverage input.sp_idxs --- shared/psbt.py | 50 ++- shared/silentpayments.py | 128 ++++---- testing/devtest/unit_silentpayments.py | 7 +- testing/devtest/verify_sp_outputs.py | 8 +- testing/test_silentpayments.py | 407 +++++++++++++++++++++++++ testing/txn.py | 1 + 6 files changed, 525 insertions(+), 76 deletions(-) create mode 100644 testing/test_silentpayments.py diff --git a/shared/psbt.py b/shared/psbt.py index bfb258a23..b81c0ee42 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -49,7 +49,7 @@ AF_P2WSH, AF_P2WSH_P2SH, AF_P2SH, AF_P2TR, AF_P2WPKH, AF_CLASSIC, AF_P2WPKH_P2SH, AFC_SEGWIT, AF_BARE_PK ) -from silentpayments import SilentPaymentsMixin +from silentpayments import SilentPaymentsMixin, compute_silent_payment_spending_privkey, validate_bip376_spend psbt_tmp256 = bytearray(256) @@ -796,6 +796,10 @@ def is_segwit(self): def is_musig(self): return bool(self.musig_pubkeys or self.musig_pubnonces or self.musig_part_sigs) + @property + def is_sp_spend(self): + return bool(self.sp_tweak and self.sp_spend_bip32_derivation) + def get_taproot_script_sigs(self): # returns set of (xonly, script) provided via PSBT_IN_TAP_SCRIPT_SIG # we do not parse control blocks (k) not needed @@ -1140,7 +1144,9 @@ def determine_my_signing_key(self, my_idx, addr_or_pubkey, my_xfp, psbt, parsed_ assert len(parsed_subpaths) != 1 or self.wif_key, "Merkle root not allowed" merkle_root = self.get(self.taproot_merkle_root) - if len(parsed_subpaths) == 1: + if self.is_sp_spend: + validate_bip376_spend(self, addr_or_pubkey, my_xfp, psbt) + elif len(parsed_subpaths) == 1: # Simple SE-backed key-path spends must not commit to an unknown # script tree. WIF Store is the explicit escape hatch for externally # constructed Taproot outputs. @@ -1934,7 +1940,7 @@ async def validate(self): max_time = 0 inp_have_subpath = False for i in self.inputs: - if i.subpaths or i.taproot_subpaths: + if i.subpaths or i.taproot_subpaths or i.is_sp_spend: inp_have_subpath = True if self.is_v2: @@ -2348,6 +2354,14 @@ def consider_inputs(self, cosign_xfp=None): parsed_subpaths = inp.parse_subpaths(self.my_xfp, self, cosign_xfp) if parsed_subpaths is None: parsed_subpaths = OrderedDict() + # Silent Payments: synthesize parsed_subpaths from PSBT_IN_SPEND_BIP32_DERIVATION + if inp.is_sp_spend and not parsed_subpaths: + k, v = inp.sp_spend_bip32_derivation + sp_path = inp.parse_xfp_path(v) + sp_path = inp.handle_zero_xfp(sp_path, self.my_xfp, self) + parsed_subpaths = {inp.get(k): sp_path} + if sp_path[0] in (self.my_xfp, cosign_xfp): + inp.sp_idxs = [0] # mark as owned so downstream checks treat it like any other signable input if not inp.has_utxo(): if inp.sp_idxs and not inp.fully_signed: @@ -3069,7 +3083,7 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): assert inp.sighash in [SIGHASH_ALL, SIGHASH_DEFAULT], "POR sighash not ALL/DEFAULT" # decide if it is appropriate to drop sighash from PSBT - if inp.af == AF_P2TR: + if inp.af == AF_P2TR or inp.is_sp_spend: drop_sighash = (inp.sighash == SIGHASH_DEFAULT) else: drop_sighash = (inp.sighash == SIGHASH_ALL) @@ -3161,7 +3175,11 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): schnorrsig = True pk = self.get(inp.taproot_internal_key) else: - if inp.taproot_subpaths: + if inp.is_sp_spend: + # Silent Payments: Use spend-pub from sp_spend_bip32_derivation + schnorrsig = True + pubk, sp = inp.sp_spend_bip32_derivation + elif inp.taproot_subpaths: schnorrsig = True pubk = inp.taproot_subpaths[sp_idx][0] sp = inp.taproot_subpaths[sp_idx][1][2] @@ -3182,7 +3200,7 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): # expensive test, but works... and important pu = node.pubkey() - if schnorrsig: + if schnorrsig and not inp.is_sp_spend: pu = pu[1:] elif len(pk) == 65: pu = ngu.secp256k1.pubkey(pu).to_bytes(True) @@ -3203,7 +3221,7 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): digest = self.make_txn_sighash(in_idx, txi, inp.sighash) else: # Hash the inputs and such in totally new ways, based on BIP-143 - if inp.af != AF_P2TR: + if inp.af != AF_P2TR and not inp.is_sp_spend: digest = self.make_txn_segwit_sighash(in_idx, txi, inp.amount, inp.segwit_v0_scriptCode(), inp.sighash) @@ -3229,6 +3247,24 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): sk = node.privkey() # Do the ACTUAL signature ... finally!!! if schnorrsig: + # Silent Payments: handle signing SP inputs + if inp.is_sp_spend: + digest = self.make_txn_taproot_sighash(in_idx, hash_type=inp.sighash) + if sv.deltamode: + digest = ngu.hash.sha256d(digest) + tweaked_sk = compute_silent_payment_spending_privkey(sk, inp.sp_tweak) + sig = ngu.secp256k1.sign_schnorr(tweaked_sk, digest, ngu.random.bytes(32)) + stash.blank_object(tweaked_sk) + + if inp.sighash != SIGHASH_DEFAULT: + sig += bytes([inp.sighash]) + inp.taproot_key_sig = sig + self.sig_added = True + self.set_modifiable_flag(inp) + stash.blank_object(sk) + stash.blank_object(node) + del sk, node + continue kp = ngu.secp256k1.keypair(sk) xonly_pk = kp.xonly_pubkey().to_bytes() diff --git a/shared/silentpayments.py b/shared/silentpayments.py index c8ccf6eb4..3c7f413fd 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -6,9 +6,14 @@ # import chains import ngu +import stash from dleq import generate_dleq_proof, verify_dleq_proof from exceptions import FatalPSBTIssue -from precomp_tag_hash import BIP352_SHARED_SECRET_TAG_H, BIP352_INPUTS_TAG_H +from precomp_tag_hash import ( + BIP352_SHARED_SECRET_TAG_H, + BIP352_INPUTS_TAG_H, + TAP_TWEAK_H, +) from serializations import SIGHASH_ALL, SIGHASH_DEFAULT from ubinascii import unhexlify as a2b_hex from utils import keypath_to_str @@ -174,7 +179,7 @@ def _compute_silent_payment_output_script(outpoints, A_sum_bytes, ecdh_share_byt return b"\x51\x20" + x_only -def _compute_silent_payment_spending_privkey(b_spend_bytes, sp_tweak_bytes): +def compute_silent_payment_spending_privkey(b_spend_bytes, sp_tweak_bytes): """ Compute private key for spending a silent payment output @@ -618,30 +623,24 @@ def _compute_and_store_proof_entries(self, sv): bool: True if shares were computed False if we have no signable inputs """ - # Collect per-input private keys for eligible inputs we own - # Track foreign ownership: if _derive_input_privkey returns None for an input - # that has derivation paths, that input belongs to another signer has_foreign = False - input_material = [] # list of (inp, privkey_int) + input_material = [] # list of [(inp, privkey_bytes), ...] for inp in self.inputs: - if not inp.sp_idxs or not self._is_input_eligible(inp): + if not self._is_input_eligible(inp): continue - input_sk = self._derive_input_privkey(inp, sv) - if input_sk: - input_material.append((inp, input_sk)) - elif inp.taproot_subpaths or inp.subpaths: - has_foreign = True - - # FIXME: is this the right approach? cosign_xfp? - # Detect foreign eligible inputs (different XFP, no sp_idxs) - if not has_foreign: - for inp in self.inputs: - if inp.sp_idxs: - continue - if self._is_input_eligible(inp) and self._pubkey_from_input(inp): + # Classify each eligible input: + # ours: sp_idxs set AND _derive_input_privkey yields a key + # foreign: sp_idxs set but derivation returns None (cosigner or WIF-store path) + # foreign: no sp_idxs but a contributing pubkey is identifiable (other signer's input) + if inp.sp_idxs: + input_sk = self._derive_input_privkey(inp, sv) + if input_sk is not None: + input_material.append((inp, input_sk)) + else: has_foreign = True - break + elif self._pubkey_from_input(inp): + has_foreign = True if not input_material: return False @@ -774,57 +773,43 @@ def _get_silent_payment_scan_keys(self): def _derive_input_privkey(self, input, sv): """ - Derive the contributing private key for an eligible input + Derive the contributing private key for our inputs - Note: - For silent payment inputs, derives from sp_spend_bip32_derivation and sp_tweak - For taproot inputs, uses the internal key's derivation path (ik_idx), XFP-checked - For non-taproot inputs, uses the first matching BIP32 derivation path + Derivation path source depends on input type: + - SP-spend: sp_spend_bip32_derivation + - P2TR: taproot_subpaths[ik_idx[0]] + - other: subpaths[sp_idxs[0]] Returns: - bytes: Derived private key as (32-byte scalar) or None if not eligible + bytes: Derived private key (32-byte scalar) or None """ - privkey = None + if not input.sp_idxs: + return None - if input.sp_tweak and input.sp_spend_bip32_derivation: + if input.is_sp_spend: _, val_coords = input.sp_spend_bip32_derivation xfp_path = self.parse_xfp_path(val_coords) - if xfp_path[0] == self.my_xfp: - privkey = _compute_silent_payment_spending_privkey(self._path_to_privkey(xfp_path, sv), input.sp_tweak) - else: - spk = input.utxo_spk - if spk and _is_p2tr(spk): - if input.ik_idx is not None and input.taproot_subpaths: - _, path_coords = input.taproot_subpaths[input.ik_idx[0]] - xfp_path = self.parse_xfp_path(path_coords[2]) - if xfp_path[0] == self.my_xfp: - privkey = self._path_to_privkey(xfp_path, sv) - if input.taproot_internal_key: - privkey = self._normalize_p2tr_privkey(privkey, self.get(input.taproot_internal_key)) - else: - for xfp_path in self._iter_input_xfp_paths(input): - if xfp_path[0] == self.my_xfp: - privkey = self._path_to_privkey(xfp_path, sv) - break - return privkey - - def _iter_input_xfp_paths(self, input): - """ - Iterate over all BIP32 derivation paths for an input, yielding parsed xfp_path tuples - - Note: - For taproot inputs, yields paths from taproot_subpaths (path_coords[2]) - For non-taproot inputs, yields paths from subpaths (path_coords) + if xfp_path[0] != self.my_xfp: + return None + return compute_silent_payment_spending_privkey(self._path_to_privkey(xfp_path, sv), input.sp_tweak) - Returns: - generator: Parsed xfp_path tuples for all derivation paths in the input - """ - if input.taproot_subpaths: - for _, path_coords in input.taproot_subpaths: - yield self.parse_xfp_path(path_coords[2]) - elif input.subpaths: - for _, path_coords in input.subpaths: - yield self.parse_xfp_path(path_coords) + spk = input.utxo_spk + if spk and _is_p2tr(spk): + if not input.taproot_subpaths or not input.ik_idx: + return None + _, path_coords = input.taproot_subpaths[input.ik_idx[0]] + xfp_path = self.parse_xfp_path(path_coords[2]) + if xfp_path[0] != self.my_xfp: + return None + return self._tweak_p2tr_privkey(self._path_to_privkey(xfp_path, sv), input) + + if not input.subpaths: + return None + _, path_coords = input.subpaths[input.sp_idxs[0]] + xfp_path = self.parse_xfp_path(path_coords) + if xfp_path[0] != self.my_xfp: + return None + return self._path_to_privkey(xfp_path, sv) def _path_to_privkey(self, xfp_path, sv): """ @@ -835,3 +820,18 @@ def _path_to_privkey(self, xfp_path, sv): """ node = sv.derive_path(keypath_to_str(xfp_path, skip=1), register=False) return node.privkey() + + def _tweak_p2tr_privkey(self, privkey_bytes, input): + """ + Tweak a P2TR private key per BIP-341, returning the BIP-340-normalized scalar + + Returns: + bytes: Tweaked private key (32-byte scalar) + """ + kp = ngu.secp256k1.keypair(privkey_bytes) + tweak_data = kp.xonly_pubkey().to_bytes() + if input.taproot_merkle_root: + tweak_data += self.get(input.taproot_merkle_root) + t = ngu.hash.sha256t(TAP_TWEAK_H, tweak_data, True) + kpt = kp.xonly_tweak_add(t) + return _negate_if_odd_y(kpt.privkey()) diff --git a/testing/devtest/unit_silentpayments.py b/testing/devtest/unit_silentpayments.py index a503418ad..ec90aa360 100644 --- a/testing/devtest/unit_silentpayments.py +++ b/testing/devtest/unit_silentpayments.py @@ -16,7 +16,7 @@ _combine_pubkeys, _compute_shared_secret_tweak, _compute_silent_payment_output_script, - _compute_silent_payment_spending_privkey, + compute_silent_payment_spending_privkey, _is_p2pkh, _is_p2wpkh, _is_p2tr, @@ -200,17 +200,18 @@ # Spending Privkey # --------------------------------------------------------------------------- -result = _compute_silent_payment_spending_privkey((1).to_bytes(32, "big"), (42).to_bytes(32, "big")) +result = compute_silent_payment_spending_privkey((1).to_bytes(32, "big"), (42).to_bytes(32, "big")) assert isinstance(result, bytes) and len(result) == 32 assert result != (1).to_bytes(32, "big") assert 0 < int.from_bytes(result, "big") < ngu.secp256k1.curve_order_int() try: - _compute_silent_payment_spending_privkey(b"\x00" * 32, b"\x00" * 32) + compute_silent_payment_spending_privkey(b"\x00" * 32, b"\x00" * 32) assert False, "Should raise" except ValueError as e: assert "not in valid scalar range" in str(e) + # --------------------------------------------------------------------------- # Mock Infrastructure # --------------------------------------------------------------------------- diff --git a/testing/devtest/verify_sp_outputs.py b/testing/devtest/verify_sp_outputs.py index 95d191d79..5fada052c 100644 --- a/testing/devtest/verify_sp_outputs.py +++ b/testing/devtest/verify_sp_outputs.py @@ -21,7 +21,7 @@ _compute_ecdh_share, _compute_input_hash, _compute_silent_payment_output_script, - _compute_silent_payment_spending_privkey, + compute_silent_payment_spending_privkey, _negate_if_odd_y, _sum_privkeys, SilentPaymentsMixin, @@ -58,6 +58,10 @@ def __init__(self): self.sp_idxs = None self.ik_idx = None + @property + def is_sp_spend(self): + return bool(self.sp_tweak and self.sp_spend_bip32_derivation) + class MockOutput: def __init__(self): @@ -241,7 +245,7 @@ def _build_mock_psbt(params): elif mode == "compute_spending_privkey": b_spend = a2b_hex(params["b_spend"]) tweak = a2b_hex(params["tweak"]) - result = _compute_silent_payment_spending_privkey(b_spend, tweak) + result = compute_silent_payment_spending_privkey(b_spend, tweak) RV.write(b2a_hex(result).decode()) elif mode == "negate_if_odd_y": diff --git a/testing/test_silentpayments.py b/testing/test_silentpayments.py new file mode 100644 index 000000000..80cdcb454 --- /dev/null +++ b/testing/test_silentpayments.py @@ -0,0 +1,407 @@ +# (c) Copyright 2024 by Coinkite Inc. This file is covered by license found in COPYING-CC. +# +# test_silentpayments.py - Simulator-based integration tests for BIP-375 Silent Payments +# +# Tests the full firmware signing path: PSBT construction -> upload to simulator -> +# firmware computes ECDH shares, DLEQ proofs, and set output scripts -> verify +# +# Requires simulator running. Run with: pytest test_silentpayments.py +# + +import pytest +import struct +import time +from binascii import unhexlify +from binascii import hexlify +from bip32 import BIP32Node +from ckcc_protocol.protocol import CCProtoError +from constants import simulator_fixed_tprv +from psbt import BasicPSBT +from pysecp256k1 import ( + ec_pubkey_parse, + ec_pubkey_serialize, + ec_pubkey_tweak_add, + tagged_sha256, +) +from pysecp256k1.extrakeys import xonly_pubkey_from_pubkey, xonly_pubkey_serialize +from sp_helpers import ( + _sim_sp, + _sim_get_ecdh_and_pubkey, + _sim_get_outpoints, + _sim_verify_dleq, + _sim_compute_output_script, +) + + +# --------------------------------------------------------------------------- +# Test SP recipient keys (any valid secp256k1 points; these are the recipient's +# keys, not the signer's). Taken from BIP-352 test vectors; sorted lexicographically +# so multi-output tests can use them in correct k-assignment order. +# --------------------------------------------------------------------------- + +SCAN_KEY = unhexlify("03af606abaa5e29a89b93bf971c21e46dd2797aee31273c47f979a102eb51c3629") +SCAN_KEY_2 = unhexlify("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798") + +# Sorted: SPEND_KEY_A < SPEND_KEY_B < SPEND_KEY_C (lexicographic) +SPEND_KEY_A = unhexlify("022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4") +SPEND_KEY_B = unhexlify("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5") +SPEND_KEY_C = unhexlify("02fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556") + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _add_sp_outputs(psbt, sp_outputs): + """Set sp_v0_info on specified outputs and clear script for firmware to compute.""" + for idx, scan_key, spend_key in sp_outputs: + psbt.outputs[idx].sp_v0_info = scan_key + spend_key + psbt.outputs[idx].script = None + + +def _verify_sp_outputs(sim_exec, sim_execfile, tp, scan_key, spend_keys_in_order): + """Verify SP output scripts match expected derivation for a given scan key.""" + assert scan_key in tp.sp_global_ecdh_shares, "Missing global ECDH share" + assert scan_key in tp.sp_global_dleq_proofs, "Missing global DLEQ proof" + + ecdh_share = tp.sp_global_ecdh_shares[scan_key] + dleq_proof = tp.sp_global_dleq_proofs[scan_key] + + assert len(ecdh_share) == 33 and ecdh_share[0] in (0x02, 0x03) + assert len(dleq_proof) == 64 + + _, summed_pubkey = _sim_get_ecdh_and_pubkey(sim_exec, sim_execfile, tp, scan_key) + _sim_verify_dleq(sim_exec, sim_execfile, summed_pubkey, scan_key, ecdh_share, dleq_proof) + + outpoints = _sim_get_outpoints(sim_exec, sim_execfile, tp) + sp_outs = [o for o in tp.outputs if o.sp_v0_info and o.sp_v0_info[:33] == scan_key] + assert len(sp_outs) == len(spend_keys_in_order) + + for k, (outp, sk) in enumerate(zip(sp_outs, spend_keys_in_order)): + assert outp.script is not None and len(outp.script) == 34 + assert outp.script[0] == 0x51 + expected = _sim_compute_output_script(sim_exec, sim_execfile, outpoints, summed_pubkey, ecdh_share, sk, k) + assert outp.script == expected + + +def _compute_foreign_share(sim_exec, sim_execfile, privkey_int, scan_key): + """Compute ECDH share and DLEQ proof for a foreign input via simulator.""" + rv = _sim_sp( + sim_exec, + sim_execfile, + "compute_foreign_share", + { + "privkey": "%064x" % privkey_int, + "scan_key": scan_key.hex(), + }, + ) + parts = rv.split(",") + return bytes.fromhex(parts[0]), bytes.fromhex(parts[1]) + + +# --------------------------------------------------------------------------- +# Basic Tests +# --------------------------------------------------------------------------- + + +def test_sp_signing_story(dev, fake_txn, start_sign, end_sign, cap_story): + """SP output: approval story shows SP address, no unknown-script warning.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + + time.sleep(0.1) + title, story = cap_story() + assert title == "OK TO SEND?" + assert "not well understood script" not in story + assert "sp1" in story + + end_sign(accept=True, finalize=False) + + +def test_sp_p2wpkh_input(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Single P2WPKH input signing to a single SP output.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + + +def test_sp_p2tr_input(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Single P2TR input signing to a single SP output.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + + +def test_sp_mixed_inputs(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """P2WPKH + P2TR inputs combined produce a single SP output from summed privkey.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn([["p2wpkh"], ["p2tr"]], 1, xp, psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + + +# --------------------------------------------------------------------------- +# Mixed output tests +# --------------------------------------------------------------------------- + + +def test_sp_three_outputs_same_scan_key(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Three SP outputs with same scan key: k=0,1,2 all produce distinct scripts.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs( + psbt, + [ + (0, SCAN_KEY, SPEND_KEY_A), + (1, SCAN_KEY, SPEND_KEY_B), + (2, SCAN_KEY, SPEND_KEY_C), + ], + ) + + psbt_bytes = fake_txn(1, 3, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_A, SPEND_KEY_B, SPEND_KEY_C]) + + sp_outs = [o for o in tp.outputs if o.sp_v0_info and o.sp_v0_info[:33] == SCAN_KEY] + scripts = [o.script for o in sp_outs] + assert len(set(scripts)) == 3, "All three k-indexed scripts must be distinct" + + +def test_sp_two_outputs_different_scan_keys(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Two SP outputs with different scan keys each get their own ECDH share.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs( + psbt, + [ + (0, SCAN_KEY, SPEND_KEY_B), + (1, SCAN_KEY_2, SPEND_KEY_A), + ], + ) + + psbt_bytes = fake_txn(1, 2, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY_2, [SPEND_KEY_A]) + + assert tp.sp_global_ecdh_shares[SCAN_KEY] != tp.sp_global_ecdh_shares[SCAN_KEY_2], ( + "Different scan keys must produce different ECDH shares" + ) + + +def test_sp_mixed_output_types(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """SP output alongside a regular output: normal output script is preserved.""" + xp = dev.master_xpub + original_normal_script = None + + def sp_hacker(psbt): + nonlocal original_normal_script + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + original_normal_script = psbt.outputs[1].script + + psbt_bytes = fake_txn(1, 2, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + + assert tp.outputs[1].script == original_normal_script, "Normal output script must not be modified by SP processing" + + +# --------------------------------------------------------------------------- +# Multi-signer - complete coverage scenario tests +# --------------------------------------------------------------------------- + + +def test_sp_all_owned_multi_input(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Scenario (a): all inputs owned -> global ECDH share -> compute scripts -> sign.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn([["p2wpkh"], ["p2wpkh"]], 1, xp, psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + + assert tp.sp_global_ecdh_shares and SCAN_KEY in tp.sp_global_ecdh_shares + assert tp.sp_global_dleq_proofs and SCAN_KEY in tp.sp_global_dleq_proofs + for inp in tp.inputs: + assert not inp.sp_ecdh_shares, "Per-input shares must not exist in single-signer path" + + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + + for i, inp in enumerate(tp.inputs): + assert inp.part_sigs or inp.taproot_key_sig, f"Input {i} missing signature" + + +def test_sp_partial_owned_coverage_complete(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Scenario (b): some owned + foreign with pre-existing shares -> coverage complete -> sign.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + foreign_sub = psbt._foreign_mk.subkey_for_path("0/1") + foreign_privkey_int = int.from_bytes(foreign_sub.privkey(), "big") + ecdh_share, proof = _compute_foreign_share(sim_exec, sim_execfile, foreign_privkey_int, SCAN_KEY) + psbt.inputs[1].sp_ecdh_shares = {SCAN_KEY: ecdh_share} + psbt.inputs[1].sp_dleq_proofs = {SCAN_KEY: proof} + + psbt_bytes = fake_txn( + [["p2wpkh"], ["p2wpkh", None, None, False]], + 1, + xp, + psbt_v2=True, + psbt_hacker=sp_hacker, + ) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + + assert not tp.sp_global_ecdh_shares, "Global ECDH shares must not exist in multi-signer path" + + assert tp.inputs[0].sp_ecdh_shares and SCAN_KEY in tp.inputs[0].sp_ecdh_shares + assert tp.inputs[1].sp_ecdh_shares and SCAN_KEY in tp.inputs[1].sp_ecdh_shares + + sp_outs = [o for o in tp.outputs if o.sp_v0_info] + assert len(sp_outs) == 1 + assert sp_outs[0].script is not None and sp_outs[0].script[0] == 0x51 + + # Verify output script by combining per-input ECDH shares via firmware + ecdh_share, summed_pubkey = _sim_get_ecdh_and_pubkey(sim_exec, sim_execfile, tp, SCAN_KEY) + outpoints = _sim_get_outpoints(sim_exec, sim_execfile, tp) + expected = _sim_compute_output_script(sim_exec, sim_execfile, outpoints, summed_pubkey, ecdh_share, SPEND_KEY_B, 0) + assert sp_outs[0].script == expected + + assert tp.inputs[0].part_sigs, "Owned input must have signature" + assert not tp.inputs[1].part_sigs, "Foreign input must not have signature" + + +# --------------------------------------------------------------------------- +# BIP-376 Silent Payments spend sp output test +# --------------------------------------------------------------------------- + + +def test_sp_spend_silent_payment_output(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Spend from SP output with correct proof -> sign. + + Uses the canonical BIP-376 PSBT shape: the input has PSBT_IN_SP_TWEAK and + PSBT_IN_SP_SPEND_BIP32_DERIVATION (BIP-352-style path), with no + PSBT_IN_TAP_BIP32_DERIVATION or PSBT_IN_TAP_INTERNAL_KEY. + """ + xp = dev.master_xpub + + SP_TWEAK = bytes.fromhex("a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2") + # BIP-352 spend-key path: m/352h/1h/0h/0h/0 (testnet coin=1, account=0, spend=0, index=0) + SP_SPEND_PATH = "352h/1h/0h/0h/0" + SP_SPEND_PATH_INTS = [ + 352 | 0x80000000, + 1 | 0x80000000, + 0 | 0x80000000, + 0 | 0x80000000, + 0, + ] + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + inp = psbt.inputs[0] + + master = BIP32Node.from_wallet_key(simulator_fixed_tprv) + mfp = master.fingerprint() + B_spend = master.subkey_for_path(SP_SPEND_PATH).sec() + xfp_and_path = mfp + struct.pack("<" + "I" * len(SP_SPEND_PATH_INTS), *SP_SPEND_PATH_INTS) + + # Compute SP output key: P_k = B_spend + t_k * G + parsed = ec_pubkey_parse(B_spend) + tweaked = ec_pubkey_tweak_add(parsed, SP_TWEAK) + tweaked_xonly_obj, _ = xonly_pubkey_from_pubkey(tweaked) + output_xonly = xonly_pubkey_serialize(tweaked_xonly_obj) + + # Replace witness UTXO scriptPubKey with the SP output key + amount_bytes = inp.witness_utxo[:8] + inp.witness_utxo = amount_bytes + b"\x22\x51\x20" + output_xonly + print(f"output_xonly: {output_xonly.hex()}") + + # BIP-376 inputs do not carry standard taproot derivation + inp.taproot_bip32_paths = {} + inp.taproot_internal_key = None + + inp.sp_tweak = SP_TWEAK + # sp_spend_bip32_derivation: key=33-byte compressed B_spend, value=mfp+path + inp.sp_spend_bip32_derivation = {B_spend: xfp_and_path} + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + + assert tp.sp_global_ecdh_shares and SCAN_KEY in tp.sp_global_ecdh_shares + assert tp.sp_global_dleq_proofs and SCAN_KEY in tp.sp_global_dleq_proofs + + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + + for i, inp in enumerate(tp.inputs): + assert inp.part_sigs or inp.taproot_key_sig, f"Input {i} missing signature" + + +# --------------------------------------------------------------------------- +# Handle failure test +# --------------------------------------------------------------------------- + + +def test_exit_gracefully_on_sp_validation_failure(dev, fake_txn, start_sign, end_sign): + """Invalid SP output info should cause signing to fail with a clear error message.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + # Set sp_v0_info with incorrect length (should be 64 bytes) + psbt.outputs[0].sp_v0_info = b"\x00" * 10 + psbt.outputs[0].script = None + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + with pytest.raises(CCProtoError, match="SP_V0_INFO wrong size"): + end_sign(accept=False, finalize=False) diff --git a/testing/txn.py b/testing/txn.py index 5ab6731d8..55d29f953 100644 --- a/testing/txn.py +++ b/testing/txn.py @@ -279,6 +279,7 @@ def doit(inputs, outputs, master_xpub=None, psbt_hacker=None, add_xpub=None, psb # last minute chance to mod PSBT object if psbt_hacker: + psbt._foreign_mk = foreign_mk psbt_hacker(psbt) rv = BytesIO() From e93ef318fb722bd772d89d2fce2b5b637629a18e Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:58:22 -0400 Subject: [PATCH 13/41] SP: introduce partial share contribution workflow Add test to validate 'Contribute Shares?' UX Simplify SP preview and signing code paths --- docs/silentpayments.md | 82 ++++++++++++++++++++++++++++++++++++++++++ shared/auth.py | 25 ++++++++++++- shared/psbt.py | 11 +++--- 3 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 docs/silentpayments.md diff --git a/docs/silentpayments.md b/docs/silentpayments.md new file mode 100644 index 000000000..6f0297156 --- /dev/null +++ b/docs/silentpayments.md @@ -0,0 +1,82 @@ +# Silent Payments + +**COLDCARD®** `EDGE` versions support [Silent Payments](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki) from version `TBD`. + +COLDCARD implements the following BIPs: + +* Silent Payments [BIP-352](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki) +* Sending Silent Payments with PSBTs [BIP-375](https://github.com/bitcoin/bips/blob/master/bip-0375.mediawiki) +* Spending Silent Payment outputs with PSBTs [BIP-376](https://github.com/bitcoin/bips/blob/master/bip-0376.mediawiki) + +## Why Silent Payments? + +**Automatic privacy by default** — share one static address publicly; each payment produces a unique on-chain output + +## How It Works + +### Silent Payments Address Generation + +* the sender collects the input public key(s) from the transaction being built +* a shared secret is derived via ECDH between the combined input key and the receiver's scan public key (part of the SP Address) +* the final output is a Taproot address derived from tweaking the receiver's spend public key (part of the SP Address) and shared secret +* only the holder of the scan private key can detect incoming payments; only the holder of the spend private key can sign for them + +### ECDH Shares & DLEQ Proofs + +The shared secret can be computed from either side: + +* **sender side**: `shared_secret = (a_1 + a_2 + ...) * B_scan` — sum of input private keys × receiver's scan public key +* **receiver side**: `shared_secret = (A_1 + A_2 + ...) * b_scan` — sum of input public keys x receiver's scan private key + +In single-signer flows, COLDCARD performs the full sender-side ECDH internally. + +In multi-signer flows (multiple input owners), each signer computes a *partial ECDH share*: + +* `share_i = a_i * B_scan` — the signer's input private key × the receiver's scan public key +* the coordinator sums all shares: `sum(share_i) = (a_1 + a_2 + ...) * B_scan => shared_secret` +* each share is accompanied by a **DLEQ proof** (Discrete Log Equality) so the coordinator or signers can verify the shares were computed from the correct input secret key + +### SP Output Computation Before Signing + +* before any signing round, the coordinator must derive the correct output script from the SP address and the transaction inputs +* this requires the full set of input public keys and the complete shared secret (assembled from partial ECDH shares) +* the computed output is inserted into the PSBT; signers verify that the output in the PSBT matches the expected tweak before signing +* a signer that cannot recompute the expected output MUST refuse to sign + +## Limitations + +* one of the transaction inputs must be eligible for ["Shared Secret Derivation"](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#user-content-Inputs_For_Shared_Secret_Derivation) +* MuSig2 and FROST are not supported yet + +## Example + +SP Address encodes two public keys: a *scan key* and a *spend key* +``` +sp1qqw5jexmu4358tr090qld3egjxkvwftgnwzg7g2v86wad3gywxkln6qcc0kmh5k03cheul53fd7r7h4lg9y3xkrmz3k00ujulyg2pfcaevu9nurf3 +``` + +### Partial Signing (Collaborative Inputs - Multiple Signers) +Round 1 — ECDH share collection +- Coordinator builds PSBT with inputs from each participant and partial outputs (output script not yet finalized) +- Each input owner contributes their partial ECDH share a_i * B_scan and DLEQ proof into the PSBT +- Last contributor verifies all DLEQ proofs, combines partial shares → computes shared secret → computes final output script, updates PSBT + +Round 2 — Sign +- Each signer verifies the output scripts in the PSBT then signs their inputs normally +- Coordinator finalizes and broadcasts + +## Development + +### start simulator +``` +cd unix +% ./simulator.py --q1 +``` + +### execute tests +``` +cd testing +pytest test_bip352_vectors.py +pytest test_bip375_vectors.py +pytest test_silentpayments.py +``` diff --git a/shared/auth.py b/shared/auth.py index 6cf48d211..7bc25bfa6 100644 --- a/shared/auth.py +++ b/shared/auth.py @@ -420,7 +420,30 @@ async def interact(self): # Silent Payments: Validate and pre-process Silent Payments outputs to make preview useful if self.psbt.has_silent_payment_outputs(): with stash.SensitiveValues() as sv: - self.psbt.process_silent_payments(sv) + if not self.psbt.process_silent_payments(sv): + # Coverage incomplete: shares computed but waiting on other signers + # Skip normal approval flow — prompt user to contribute shares, then save + del args + ch = await ux_show_story( + "Silent payment ECDH shares will be added to this transaction.\n\n" + "Other signers must contribute their shares before signing can proceed.\n\n" + "Press %s to contribute shares. %s to abort." % (OK, X), + title="CONTRIBUTE SHARES?" + ) + if ch != 'y': + self.refused = True + await ux_dramatic_pause("Refused.", 1) + del self.psbt + self.done() + return + try: + await done_signing(self.psbt, self, self.input_method, + self.filename, self.output_encoder, + finalize=False) + self.done() + except BaseException as exc: + return await self.failure("PSBT output failed", exc) + return self.psbt.consider_outputs(*args, cosign_xfp=ccc_c_xfp) del args # not needed anymore diff --git a/shared/psbt.py b/shared/psbt.py index b81c0ee42..07cf580db 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -3046,13 +3046,10 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): # Silent Payment Processing if self.has_silent_payment_outputs(): - sp_ready = self.process_silent_payments(sv) - if not sp_ready: - # Silent Payments: must not sign if output scripts not set - # TODO: is this still necessary? if so needs test - self.ux_notes.append(("Silent Payments", - "ECDH shares added. Signatures withheld until all signers contribute.")) - return + if not self.process_silent_payments(sv): + # Silent Payments: must not sign if output scripts not set for all signers + # Defensive re-check - ApproveTransaction::interact should handle this case before reaching signing + raise FatalPSBTIssue("Silent Payments: Signing cannot proceed until all signers contribute their shares") # progress dis.fullscreen('Signing...') From ae722774f6d0dca3eb6a4db79a1c71aba074a7fb Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 25 Mar 2026 17:29:21 -0400 Subject: [PATCH 14/41] SP: introduce UI change output validation Add silent payments label change tests - Detect presence or absence of 'Change back:' in UI story Add multi-signer incomplete coverage scenario tests --- shared/auth.py | 13 ++-- shared/psbt.py | 7 +- shared/silentpayments.py | 80 +++++++++++++++------- testing/test_silentpayments.py | 121 +++++++++++++++++++++++++++++++-- 4 files changed, 179 insertions(+), 42 deletions(-) diff --git a/shared/auth.py b/shared/auth.py index 7bc25bfa6..990a50bbd 100644 --- a/shared/auth.py +++ b/shared/auth.py @@ -754,8 +754,6 @@ def output_summary_text(self, msg): total_change = 0 has_change = False - # TODO: Test pay to silent payment change address - for idx, tx_out in self.psbt.output_iter(): outp = self.psbt.outputs[idx] if outp.is_change: @@ -763,6 +761,8 @@ def output_summary_text(self, msg): total_change += tx_out.nValue if len(largest_change) < MAX_VISIBLE_CHANGE: _, addr = self.render_output(tx_out) + if outp.sp_v0_info: + addr += '\n' + self.psbt.render_silent_payment_output_string(outp) largest_change.append((tx_out.nValue, addr)) if len(largest_change) == MAX_VISIBLE_CHANGE: largest_change = sorted(largest_change, key=lambda x: x[0], reverse=True) @@ -790,9 +790,14 @@ def output_summary_text(self, msg): continue # too small largest.pop(-1) - rendered, dest = self.render_output(tx_out) - largest.insert(keep, (here, dest if outp.is_change else rendered)) + if outp.is_change: + if outp.sp_v0_info: + dest += '\n' + self.psbt.render_silent_payment_output_string(outp) + ret = (here, dest) + else: + ret = (here, rendered) + largest.insert(keep, ret) # foreign outputs (soon to be other people's coins) visible_out_sum = 0 diff --git a/shared/psbt.py b/shared/psbt.py index 07cf580db..3f57046b1 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -1630,12 +1630,7 @@ def output_iter(self, start=0, stop=None): for idx in range(start, stop): out = self.outputs[idx] amount = unpack(" coverage incomplete -> save PSBT.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn( + [["p2wpkh"], ["p2wpkh", None, None, False]], + 1, + xp, + psbt_v2=True, + psbt_hacker=sp_hacker, + ) + start_sign(psbt_bytes) + + time.sleep(0.1) + title, story = cap_story() + assert title == "CONTRIBUTE SHARES?" + assert "ECDH shares" in story + assert "Other signers" in story + + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + + assert not tp.sp_global_ecdh_shares, ( + "Global ECDH shares must not exist in multi-signer path" + ) + + assert tp.inputs[0].sp_ecdh_shares and SCAN_KEY in tp.inputs[0].sp_ecdh_shares + assert tp.inputs[0].sp_dleq_proofs and SCAN_KEY in tp.inputs[0].sp_dleq_proofs + assert not tp.inputs[1].sp_ecdh_shares + + sp_outs = [o for o in tp.outputs if o.sp_v0_info] + assert len(sp_outs) == 1 + assert not sp_outs[0].script, ( + "Output script must NOT be set when coverage is incomplete" + ) + + for i, inp in enumerate(tp.inputs): + assert not inp.part_sigs, f"Input {i} must not have signature" + assert not inp.taproot_key_sig, f"Input {i} must not have taproot signature" + + +def test_sp_partial_owned_coverage_incomplete_refused( + dev, fake_txn, start_sign, end_sign, cap_story +): + """Refuse to contribute SP shares -> CCUserRefused.""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn( + [["p2wpkh"], ["p2wpkh", None, None, False]], + 1, + xp, + psbt_v2=True, + psbt_hacker=sp_hacker, + ) + start_sign(psbt_bytes) + + time.sleep(0.1) + title, _ = cap_story() + assert title == "CONTRIBUTE SHARES?" + + end_sign(accept=False) + + # --------------------------------------------------------------------------- # BIP-376 Silent Payments spend sp output test # --------------------------------------------------------------------------- @@ -405,3 +477,38 @@ def sp_hacker(psbt): start_sign(psbt_bytes) with pytest.raises(CCProtoError, match="SP_V0_INFO wrong size"): end_sign(accept=False, finalize=False) + + +# --------------------------------------------------------------------------- +# Silent Payments Change Detection Tests +# --------------------------------------------------------------------------- + + +def test_sp_spend_to_labeled_change_address( + dev, fake_txn, start_sign, end_sign, cap_story +): + """Two SP outputs: output 0 is a send (no label), output 1 is change (label=0 per BIP-352 convention).""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs( + psbt, + [ + (0, SCAN_KEY, SPEND_KEY_B), + (1, SCAN_KEY_2, SPEND_KEY_A), + ], + ) + psbt.outputs[1].sp_v0_label = b"\x00\x00\x00\x00" + + psbt_bytes = fake_txn( + 1, 2, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker + ) + start_sign(psbt_bytes) + + title, story = cap_story() + assert title == "OK TO SEND?" + assert "not well understood script" not in story + assert "sp1" in story + assert "Change back:" in story + + end_sign(accept=False, finalize=False) From 891a4a3d8520254aaf310b16a3b22f8e67574f14 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Sun, 26 Apr 2026 08:49:46 -0400 Subject: [PATCH 15/41] SP: add sp spend derivation path tests Verify SP spend path was derived from m/352h Add signature verification for taproot inputs and SP outputs --- testing/devtest/verify_sp_outputs.py | 45 ++++++ testing/sp_helpers.py | 51 ++++-- testing/test_silentpayments.py | 223 ++++++++++++++++++++------- 3 files changed, 250 insertions(+), 69 deletions(-) diff --git a/testing/devtest/verify_sp_outputs.py b/testing/devtest/verify_sp_outputs.py index 5fada052c..bd1effc5b 100644 --- a/testing/devtest/verify_sp_outputs.py +++ b/testing/devtest/verify_sp_outputs.py @@ -12,16 +12,20 @@ import ngu import struct import ujson +from uio import BytesIO from ubinascii import hexlify as b2a_hex from ubinascii import unhexlify as a2b_hex from dleq import generate_dleq_proof, verify_dleq_proof from exceptions import FatalPSBTIssue +from psbt import psbtObject +from serializations import SIGHASH_DEFAULT from silentpayments import ( _combine_pubkeys, _compute_ecdh_share, _compute_input_hash, _compute_silent_payment_output_script, compute_silent_payment_spending_privkey, + _compute_silent_payment_spending_xonly, _negate_if_odd_y, _sum_privkeys, SilentPaymentsMixin, @@ -248,7 +252,48 @@ def _build_mock_psbt(params): result = compute_silent_payment_spending_privkey(b_spend, tweak) RV.write(b2a_hex(result).decode()) +elif mode == "compute_spend_output_xonly": + B_spend = a2b_hex(params["B_spend"]) + sp_tweak = a2b_hex(params["sp_tweak"]) + result = _compute_silent_payment_spending_xonly(B_spend, sp_tweak) + RV.write(b2a_hex(result).decode()) + elif mode == "negate_if_odd_y": privkey = a2b_hex(params["privkey"]) result = _negate_if_odd_y(privkey) RV.write(b2a_hex(result).decode()) + +elif mode == "verify_taproot_key_spend_signature": + psbt = psbtObject.read_psbt(BytesIO(a2b_hex(params["psbt"]))) + input_index = params["input_index"] + expected = params.get("expected", True) + + if psbt.version is None: + psbt.version = 2 if psbt.txn is None else 0 + psbt.is_v2 = psbt.version >= 2 + + for idx, inp in enumerate(psbt.inputs): + utxo = inp.get_utxo(idx) + inp.amount = utxo.nValue + inp.utxo_spk = utxo.scriptPubKey + + inp = psbt.inputs[input_index] + # P2TR scriptPubKey: OP_1 (0x51) OP_PUSHBYTES_32 (0x20) <32-byte x-only> + output_xonly = inp.utxo_spk[2:34] + + sig_coords = inp.taproot_key_sig + assert sig_coords, "Missing taproot key signature" + sig = psbt.get(sig_coords) + + hash_type = SIGHASH_DEFAULT if len(sig) == 64 else sig[-1] + digest = psbt.make_txn_taproot_sighash(input_index, hash_type=hash_type) + + try: + result = ngu.secp256k1.verify_schnorr(sig[:64], digest, ngu.secp256k1.xonly_pubkey(output_xonly)) + except Exception: + result = False + + assert result == expected, "Taproot spend signature verify: expected %s got %s" % ( + expected, + result, + ) diff --git a/testing/sp_helpers.py b/testing/sp_helpers.py index 147fb0895..0d1bd0a22 100644 --- a/testing/sp_helpers.py +++ b/testing/sp_helpers.py @@ -107,12 +107,8 @@ def _serialize_psbt(psbt): return { "txn_modifiable": psbt.txn_modifiable, - "global_ecdh": { - k.hex(): v.hex() for k, v in psbt.sp_global_ecdh_shares.items() - }, - "global_dleq": { - k.hex(): v.hex() for k, v in psbt.sp_global_dleq_proofs.items() - }, + "global_ecdh": {k.hex(): v.hex() for k, v in psbt.sp_global_ecdh_shares.items()}, + "global_dleq": {k.hex(): v.hex() for k, v in psbt.sp_global_dleq_proofs.items()}, "inputs": inputs, "outputs": outputs, } @@ -154,9 +150,7 @@ def _sim_pubkey_from_input(sim_exec, sim_execfile, psbt, input_index): return bytes.fromhex(rv) if rv else None -def _sim_verify_dleq( - sim_exec, sim_execfile, pubkey, scan_key, ecdh_share, proof, expected=True -): +def _sim_verify_dleq(sim_exec, sim_execfile, pubkey, scan_key, ecdh_share, proof, expected=True): _sim_sp( sim_exec, sim_execfile, @@ -184,9 +178,20 @@ def _sim_compute_ecdh_share(sim_exec, sim_execfile, privkey, scan_key): return bytes.fromhex(rv) -def _sim_compute_output_script( - sim_exec, sim_execfile, outpoints, summed_pubkey, ecdh_share, spend_key, k -): +def _sim_compute_spend_output_xonly(sim_exec, sim_execfile, B_spend, sp_tweak): + rv = _sim_sp( + sim_exec, + sim_execfile, + "compute_spend_output_xonly", + { + "B_spend": B_spend.hex(), + "sp_tweak": sp_tweak.hex(), + }, + ) + return bytes.fromhex(rv) + + +def _sim_compute_output_script(sim_exec, sim_execfile, outpoints, summed_pubkey, ecdh_share, spend_key, k): rv = _sim_sp( sim_exec, sim_execfile, @@ -202,6 +207,28 @@ def _sim_compute_output_script( return bytes.fromhex(rv) +def _sim_verify_taproot_key_spend_signature(sim_exec, sim_execfile, signed_psbt, input_index, expected=True): + _sim_sp( + sim_exec, + sim_execfile, + "verify_taproot_key_spend_signature", + { + "psbt": signed_psbt.hex(), + "input_index": input_index, + "expected": expected, + }, + ) + + +def _verify_signatures(sim_exec, sim_execfile, tp, signed_psbt_bytes): + """Verify Schnorr signatures for taproot key-spend inputs""" + for i, inp in enumerate(tp.inputs): + if inp.witness_utxo and len(inp.witness_utxo) >= 11: + if inp.witness_utxo[8:11] == b"\x22\x51\x20": + _sim_verify_taproot_key_spend_signature(sim_exec, sim_execfile, signed_psbt_bytes, i) + # TODO: add ECDSA verification for P2WPKH inputs + + def _sim_combine_pubkeys(sim_exec, sim_execfile, pubkeys): rv = _sim_sp( sim_exec, diff --git a/testing/test_silentpayments.py b/testing/test_silentpayments.py index e232e32cc..ae361f5f1 100644 --- a/testing/test_silentpayments.py +++ b/testing/test_silentpayments.py @@ -16,14 +16,14 @@ from bip32 import BIP32Node from ckcc_protocol.protocol import CCProtoError from psbt import BasicPSBT -from pysecp256k1 import ec_pubkey_parse, ec_pubkey_tweak_add -from pysecp256k1.extrakeys import xonly_pubkey_from_pubkey, xonly_pubkey_serialize from sp_helpers import ( _sim_sp, _sim_get_ecdh_and_pubkey, _sim_get_outpoints, _sim_verify_dleq, _sim_compute_output_script, + _sim_compute_spend_output_xonly, + _verify_signatures, ) from constants import simulator_fixed_tprv @@ -42,6 +42,17 @@ SPEND_KEY_B = unhexlify("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5") SPEND_KEY_C = unhexlify("02fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556") +# BIP-376 SP spend constants (BIP-352 path: m/352h/1h/0h/0h/0, testnet) +SP_TWEAK = bytes.fromhex("a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2") +SP_SPEND_PATH = "352h/1h/0h/0h/0" +SP_SPEND_PATH_INTS = [ + 352 | 0x80000000, + 1 | 0x80000000, + 0 | 0x80000000, + 0 | 0x80000000, + 0, +] + # --------------------------------------------------------------------------- # Helpers @@ -95,6 +106,49 @@ def _compute_foreign_share(sim_exec, sim_execfile, privkey_int, scan_key): return bytes.fromhex(parts[0]), bytes.fromhex(parts[1]) +def _setup_sp_spend_input( + sim_exec, + sim_execfile, + inp, + sp_tweak, + path, + path_ints, + *, + wrong_tweak=None, + clear_taproot=True, +): + """Configure a PSBT input for a BIP-376 SP spend. + + Rewrites inp.witness_utxo to lock to B_spend + utxo_tweak*G, sets + inp.sp_tweak (to psbt_tweak if given, else utxo_tweak), and sets + inp.sp_spend_bip32_derivation. Optionally clears taproot derivation. + """ + master = BIP32Node.from_wallet_key(simulator_fixed_tprv) + mfp = master.fingerprint() + B_spend = master.subkey_for_path(path).sec() + xfp_and_path = mfp + struct.pack("<" + "I" * len(path_ints), *path_ints) + + xonly = _sim_compute_spend_output_xonly(sim_exec, sim_execfile, B_spend, sp_tweak) + amount_bytes = inp.witness_utxo[:8] + inp.witness_utxo = amount_bytes + b"\x22\x51\x20" + xonly + + if clear_taproot: + inp.taproot_bip32_paths = {} + inp.taproot_internal_key = None + + inp.sp_tweak = wrong_tweak if wrong_tweak is not None else sp_tweak + inp.sp_spend_bip32_derivation = {B_spend: xfp_and_path} + + +def _assert_sp_spend_success(sim_exec, sim_execfile, signed): + """Assert a signed SP spend PSBT has correct global shares and output scripts.""" + tp = BasicPSBT().parse(signed) + assert tp.sp_global_ecdh_shares and SCAN_KEY in tp.sp_global_ecdh_shares + assert tp.sp_global_dleq_proofs and SCAN_KEY in tp.sp_global_dleq_proofs + _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + _verify_signatures(sim_exec, sim_execfile, tp, signed) + + # --------------------------------------------------------------------------- # Basic Tests # --------------------------------------------------------------------------- @@ -147,6 +201,7 @@ def sp_hacker(psbt): tp = BasicPSBT().parse(signed) _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + _verify_signatures(sim_exec, sim_execfile, tp, signed) def test_sp_mixed_inputs(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): @@ -162,6 +217,9 @@ def sp_hacker(psbt): tp = BasicPSBT().parse(signed) _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + # Schnorr verification skipped: multi-input taproot sighash covers all inputs' + # sequences, and fake_txn may not write PSBT_IN_SEQUENCE — devtest would + # reconstruct a wrong hashSequence. # --------------------------------------------------------------------------- @@ -318,9 +376,7 @@ def sp_hacker(psbt): # --------------------------------------------------------------------------- -def test_sp_partial_owned_coverage_incomplete( - dev, fake_txn, start_sign, end_sign, cap_story -): +def test_sp_partial_owned_coverage_incomplete(dev, fake_txn, start_sign, end_sign, cap_story): """Scenario (c): some owned + foreign without shares -> coverage incomplete -> save PSBT.""" xp = dev.master_xpub @@ -346,9 +402,7 @@ def sp_hacker(psbt): tp = BasicPSBT().parse(signed) - assert not tp.sp_global_ecdh_shares, ( - "Global ECDH shares must not exist in multi-signer path" - ) + assert not tp.sp_global_ecdh_shares, "Global ECDH shares must not exist in multi-signer path" assert tp.inputs[0].sp_ecdh_shares and SCAN_KEY in tp.inputs[0].sp_ecdh_shares assert tp.inputs[0].sp_dleq_proofs and SCAN_KEY in tp.inputs[0].sp_dleq_proofs @@ -356,18 +410,14 @@ def sp_hacker(psbt): sp_outs = [o for o in tp.outputs if o.sp_v0_info] assert len(sp_outs) == 1 - assert not sp_outs[0].script, ( - "Output script must NOT be set when coverage is incomplete" - ) + assert not sp_outs[0].script, "Output script must NOT be set when coverage is incomplete" for i, inp in enumerate(tp.inputs): assert not inp.part_sigs, f"Input {i} must not have signature" assert not inp.taproot_key_sig, f"Input {i} must not have taproot signature" -def test_sp_partial_owned_coverage_incomplete_refused( - dev, fake_txn, start_sign, end_sign, cap_story -): +def test_sp_partial_owned_coverage_incomplete_refused(dev, fake_txn, start_sign, end_sign, cap_story): """Refuse to contribute SP shares -> CCUserRefused.""" xp = dev.master_xpub @@ -404,59 +454,122 @@ def test_sp_spend_silent_payment_output(dev, fake_txn, start_sign, end_sign, sim """ xp = dev.master_xpub - SP_TWEAK = bytes.fromhex("a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2") - # BIP-352 spend-key path: m/352h/1h/0h/0h/0 (testnet coin=1, account=0, spend=0, index=0) - SP_SPEND_PATH = "352h/1h/0h/0h/0" - SP_SPEND_PATH_INTS = [ - 352 | 0x80000000, - 1 | 0x80000000, - 0 | 0x80000000, - 0 | 0x80000000, - 0, - ] + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + _setup_sp_spend_input( + sim_exec, + sim_execfile, + psbt.inputs[0], + SP_TWEAK, + SP_SPEND_PATH, + SP_SPEND_PATH_INTS, + clear_taproot=True, + ) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + _assert_sp_spend_success(sim_exec, sim_execfile, signed) + + +def test_sp_spend_silent_payment_output_with_taproot(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Spend from SP output with correct proof -> sign (taproot derivation retained).""" + xp = dev.master_xpub def sp_hacker(psbt): _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + _setup_sp_spend_input( + sim_exec, + sim_execfile, + psbt.inputs[0], + SP_TWEAK, + SP_SPEND_PATH, + SP_SPEND_PATH_INTS, + clear_taproot=False, + ) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + _assert_sp_spend_success(sim_exec, sim_execfile, signed) - inp = psbt.inputs[0] - master = BIP32Node.from_wallet_key(simulator_fixed_tprv) - mfp = master.fingerprint() - B_spend = master.subkey_for_path(SP_SPEND_PATH).sec() - xfp_and_path = mfp + struct.pack("<" + "I" * len(SP_SPEND_PATH_INTS), *SP_SPEND_PATH_INTS) +def test_sp_spend_wrong_tweak_rejected(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """SP_TWEAK that does not match the witness UTXO output key must be rejected.""" + xp = dev.master_xpub + WRONG_TWEAK = bytes.fromhex("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") - # Compute SP output key: P_k = B_spend + t_k * G - parsed = ec_pubkey_parse(B_spend) - tweaked = ec_pubkey_tweak_add(parsed, SP_TWEAK) - tweaked_xonly_obj, _ = xonly_pubkey_from_pubkey(tweaked) - output_xonly = xonly_pubkey_serialize(tweaked_xonly_obj) + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + # Witness UTXO uses SP_TWEAK; PSBT carries WRONG_TWEAK — firmware must reject this + _setup_sp_spend_input( + sim_exec, + sim_execfile, + psbt.inputs[0], + SP_TWEAK, + SP_SPEND_PATH, + SP_SPEND_PATH_INTS, + wrong_tweak=WRONG_TWEAK, + ) - # Replace witness UTXO scriptPubKey with the SP output key - amount_bytes = inp.witness_utxo[:8] - inp.witness_utxo = amount_bytes + b"\x22\x51\x20" + output_xonly - print(f"output_xonly: {output_xonly.hex()}") + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + with pytest.raises(CCProtoError, match="SP_TWEAK does not match UTXO output key"): + end_sign(accept=True, finalize=False) - # BIP-376 inputs do not carry standard taproot derivation - inp.taproot_bip32_paths = {} - inp.taproot_internal_key = None - inp.sp_tweak = SP_TWEAK - # sp_spend_bip32_derivation: key=33-byte compressed B_spend, value=mfp+path - inp.sp_spend_bip32_derivation = {B_spend: xfp_and_path} +def test_sp_spend_wrong_purpose_rejected(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """SP_SPEND_BIP32_DERIVATION with a non-352h purpose must be rejected.""" + xp = dev.master_xpub + # BIP-84 path instead of BIP-352 + WRONG_PATH = "84h/1h/0h/0/0" + WRONG_PATH_INTS = [84 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0] + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + _setup_sp_spend_input( + sim_exec, + sim_execfile, + psbt.inputs[0], + SP_TWEAK, + WRONG_PATH, + WRONG_PATH_INTS, + ) psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) - signed = end_sign(accept=True, finalize=False) + with pytest.raises(CCProtoError, match="SP spend key must use 352h path"): + end_sign(accept=True, finalize=False) - tp = BasicPSBT().parse(signed) - assert tp.sp_global_ecdh_shares and SCAN_KEY in tp.sp_global_ecdh_shares - assert tp.sp_global_dleq_proofs and SCAN_KEY in tp.sp_global_dleq_proofs +def test_sp_spend_wrong_coin_type_rejected(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """SP_SPEND_BIP32_DERIVATION with coin type mismatching the network must be rejected.""" + xp = dev.master_xpub + # Simulator is testnet (coin_type=1); use mainnet coin_type=0 to trigger mismatch + WRONG_COIN_PATH = "352h/0h/0h/0h/0" + WRONG_COIN_PATH_INTS = [ + 352 | 0x80000000, + 0 | 0x80000000, + 0 | 0x80000000, + 0 | 0x80000000, + 0, + ] - _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + _setup_sp_spend_input( + sim_exec, + sim_execfile, + psbt.inputs[0], + SP_TWEAK, + WRONG_COIN_PATH, + WRONG_COIN_PATH_INTS, + ) - for i, inp in enumerate(tp.inputs): - assert inp.part_sigs or inp.taproot_key_sig, f"Input {i} missing signature" + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + with pytest.raises(CCProtoError, match="SP spend path coin type does not match network"): + end_sign(accept=True, finalize=False) # --------------------------------------------------------------------------- @@ -484,9 +597,7 @@ def sp_hacker(psbt): # --------------------------------------------------------------------------- -def test_sp_spend_to_labeled_change_address( - dev, fake_txn, start_sign, end_sign, cap_story -): +def test_sp_spend_to_labeled_change_address(dev, fake_txn, start_sign, end_sign, cap_story): """Two SP outputs: output 0 is a send (no label), output 1 is change (label=0 per BIP-352 convention).""" xp = dev.master_xpub @@ -500,9 +611,7 @@ def sp_hacker(psbt): ) psbt.outputs[1].sp_v0_label = b"\x00\x00\x00\x00" - psbt_bytes = fake_txn( - 1, 2, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker - ) + psbt_bytes = fake_txn(1, 2, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) title, story = cap_story() From 280237b81d8a79f502617e15a2023f26dfcd0ee8 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:16:31 -0400 Subject: [PATCH 16/41] SP: add docs/silentpayments.md From a24ea0ff053f2d679615a7e6f1992bd9cc26a3e5 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Thu, 23 Apr 2026 08:50:42 -0400 Subject: [PATCH 17/41] SP: implement bip352 generic format export Include key-value pairs: spscan, deriv, name, xfp, key_exp in bip352 dictionary Add bip352 test block to test_export_coldcard Support 127 character limit for silent payments v0 --- shared/export.py | 18 ++++++++++++++++++ testing/bech32.py | 2 +- testing/sp_helpers.py | 32 ++++++++++++++++++++++++++++++++ testing/test_export.py | 20 ++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/shared/export.py b/shared/export.py index 59c417dbc..966dc0cd0 100644 --- a/shared/export.py +++ b/shared/export.py @@ -13,6 +13,7 @@ from charcodes import KEY_NFC, KEY_CANCEL, KEY_QR from ownership import OWNERSHIP from exceptions import QRTooBigError +from silentpayments import encode_silent_payment_address async def export_by_qr(body, label, type_code, force_bbqr=False): # render as QR and show on-screen @@ -444,6 +445,23 @@ def generate_generic_export(account_num=0): node.derive(0, False).derive(0, False) rv[name]['first'] = chain.address(node, fmt) + # Silent Payments: scan-priv + spend-pub packed as a single bech32m "spscan" string + sp_deriv = "m/352h/%dh/%dh" % (chain.b44_cointype, account_num) + sp_node = sv.derive_path(sp_deriv) + scan_node = sv.derive_path(sp_deriv + "/1h/0") + spend_node = sv.derive_path(sp_deriv + "/0h/0") + + spscan = encode_silent_payment_address(scan_node.privkey(), spend_node.pubkey()) + rv["bip352"] = OrderedDict( + spscan=spscan, + deriv=sp_deriv, + name="p2tr", + xfp=xfp2str(swab32(sp_node.my_fp())), + key_exp="[%s/%s]%s" % (master_xfp_str.lower(), + sp_deriv.replace("m/", ""), + spscan), + ) + sig_deriv = "m/44h/{ct}h/{acc}h".format(ct=chain.b44_cointype, acc=account_num) + "/0/0" return ujson.dumps(rv), sig_deriv, AF_CLASSIC diff --git a/testing/bech32.py b/testing/bech32.py index b33db8716..77ffe95f8 100644 --- a/testing/bech32.py +++ b/testing/bech32.py @@ -79,7 +79,7 @@ def bech32_decode(bech): return (None, None, None) bech = bech.lower() pos = bech.rfind('1') - if pos < 1 or pos + 7 > len(bech) or len(bech) > 90: + if pos < 1 or pos + 7 > len(bech) or len(bech) > 127: return (None, None, None) if not all(x in CHARSET for x in bech[pos+1:]): return (None, None, None) diff --git a/testing/sp_helpers.py b/testing/sp_helpers.py index 0d1bd0a22..bf7c4f987 100644 --- a/testing/sp_helpers.py +++ b/testing/sp_helpers.py @@ -314,3 +314,35 @@ def _sim_negate_if_odd_y(sim_exec, sim_execfile, privkey): }, ) return bytes.fromhex(rv) + + +# --------------------------------------------------------------------------- +# Helpers for test_export.py bip352 assertions +# --------------------------------------------------------------------------- + + +def decode_spscan(s, expected_hrp): + """Decode an spscan/tspscan bech32m string into (scan_priv: bytes32, spend_pub: bytes33).""" + from bech32 import bech32_decode, convertbits, Encoding + + hrp, data, spec = bech32_decode(s) + assert hrp == expected_hrp, f"bad HRP: {hrp!r} != {expected_hrp!r}" + assert spec == Encoding.BECH32M, "must be bech32m" + assert data[0] == 0, "expected version 0" + payload = bytes(convertbits(data[1:], 5, 8, False)) + assert len(payload) == 65, f"expected 65 bytes, got {len(payload)}" + return payload[:32], payload[32:] + + +def derive_sp_keys_for_account(account_num, coin_type): + """Return (scan_priv: bytes32, spend_pub: bytes33) for the given account/coin_type. + + Derives from the simulator's fixed test seed, matching the firmware's SP derivation paths. + """ + from bip32 import BIP32Node + from constants import simulator_fixed_tprv + + root = BIP32Node.from_wallet_key(simulator_fixed_tprv) + scan_node = root.subkey_for_path("352h/%dh/%dh/1h/0" % (coin_type, account_num)) + spend_node = root.subkey_for_path("352h/%dh/%dh/0h/0" % (coin_type, account_num)) + return scan_node.privkey(), spend_node.sec() diff --git a/testing/test_export.py b/testing/test_export.py index 6e37b3ba4..2ad3923cb 100644 --- a/testing/test_export.py +++ b/testing/test_export.py @@ -425,6 +425,26 @@ def test_export_coldcard(way, dev, acct_num, app, pick_menu_item, goto_home, cap else: assert False + # BIP-352 Silent Payments block + from sp_helpers import decode_spscan, derive_sp_keys_for_account + bip352 = obj["bip352"] + ct = 0 if netcode == "BTC" else 1 + acct = int(acct_num or 0) + assert set(bip352.keys()) == {"spscan", "deriv", "name", "xfp", "key_exp"} + assert bip352["deriv"] == "m/352h/%dh/%dh" % (ct, acct) + assert bip352["name"] == "p2tr" + assert len(bip352["xfp"]) == 8 + + hrp_expected = "spscan" if netcode == "BTC" else "tspscan" + scan_priv_enc, spend_pub_enc = decode_spscan(bip352["spscan"], hrp_expected) + exp_scan_priv, exp_spend_pub = derive_sp_keys_for_account(acct, ct) + assert scan_priv_enc == exp_scan_priv + assert spend_pub_enc == exp_spend_pub + + expected_origin = "[%s/352h/%dh/%dh]" % (xfp2str(simulator_fixed_xfp).lower(), ct, acct) + assert bip352["key_exp"].startswith(expected_origin + hrp_expected + "1") + assert bip352["key_exp"].split("]", 1)[1] == bip352["spscan"] + @pytest.mark.parametrize('way', ["sd", "vdisk", "nfc", "qr"]) @pytest.mark.parametrize('testnet', [True, False]) @pytest.mark.parametrize('acct_num', [None, '0', '99', '123']) From c14970981f2fcd725ee9bb8e3ae747cc04941847 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 29 Apr 2026 20:57:12 -0400 Subject: [PATCH 18/41] SP: add more integration tests Mixed inputs SP spend and P2TR Reject non-SIGHASH_ALL Reject psbt v0 send to SP output --- testing/test_silentpayments.py | 56 +++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/testing/test_silentpayments.py b/testing/test_silentpayments.py index ae361f5f1..142b9f970 100644 --- a/testing/test_silentpayments.py +++ b/testing/test_silentpayments.py @@ -222,6 +222,28 @@ def sp_hacker(psbt): # reconstruct a wrong hashSequence. +def test_sp_mixed_sp_spend_and_regular_input(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Regular P2TR input + SP-spend input: both private keys summed for ECDH, both signed""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + _setup_sp_spend_input( + sim_exec, + sim_execfile, + psbt.inputs[1], + SP_TWEAK, + SP_SPEND_PATH, + SP_SPEND_PATH_INTS, + clear_taproot=True, + ) + + psbt_bytes = fake_txn([["p2tr"], ["p2tr"]], 1, xp, psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + signed = end_sign(accept=True, finalize=False) + _assert_sp_spend_success(sim_exec, sim_execfile, signed) + + # --------------------------------------------------------------------------- # Mixed output tests # --------------------------------------------------------------------------- @@ -538,7 +560,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) - with pytest.raises(CCProtoError, match="SP spend key must use 352h path"): + with pytest.raises(CCProtoError, match="SP spend key purpose must use 352h path"): end_sign(accept=True, finalize=False) @@ -592,6 +614,38 @@ def sp_hacker(psbt): end_sign(accept=False, finalize=False) +def test_sp_non_sighash_all_rejected(dev, fake_txn, start_sign, end_sign): + """Non-SIGHASH_ALL on an input with SP outputs must be rejected (BIP-375).""" + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + psbt.inputs[0].sighash = 3 # SIGHASH_SINGLE + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + with pytest.raises(CCProtoError, match="Silent payments require SIGHASH_ALL"): + end_sign(accept=True, finalize=False) + + +def test_sp_psbt_v0_rejected(dev, fake_txn, start_sign, end_sign): + """PSBTv0 with SP outputs is rejected: outpoint fields are PSBTv2-only. + + BIP-352 SP computation requires PSBT_IN_PREVIOUS_TXID and PSBT_IN_OUTPUT_INDEX + (PSBTv2 fields) to derive the input hash. PSBTv0 embeds outpoints only in the + unsigned transaction, so firmware raises when trying to collect them. + """ + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=False, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + with pytest.raises(CCProtoError, match="Missing outpoint for silent payment input"): + end_sign(accept=True, finalize=False) + + # --------------------------------------------------------------------------- # Silent Payments Change Detection Tests # --------------------------------------------------------------------------- From 81fa34a665cfe590b26c9cdb3c536b397bfdc0be Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Fri, 1 May 2026 08:31:13 -0400 Subject: [PATCH 19/41] SP (refactor): test hygiene Remove MockPSBT from verify_sp_outputs Test test_sp_spend_to_labeled_change_address should sign transaction Replace _serialize_psbt with read_psbt Replace single use compute_foreign_share with generate_dleq_proof Remove unnecessary int-byte conversions in test_bip352_vectors.py --- testing/devtest/verify_sp_outputs.py | 144 ++++++--------------------- testing/sp_helpers.py | 93 ++--------------- testing/test_bip352_vectors.py | 19 ++-- testing/test_bip375_vectors.py | 9 +- testing/test_silentpayments.py | 138 +++++++++++++------------ 5 files changed, 123 insertions(+), 280 deletions(-) diff --git a/testing/devtest/verify_sp_outputs.py b/testing/devtest/verify_sp_outputs.py index bd1effc5b..32d23d704 100644 --- a/testing/devtest/verify_sp_outputs.py +++ b/testing/devtest/verify_sp_outputs.py @@ -10,11 +10,7 @@ # import main import ngu -import struct import ujson -from uio import BytesIO -from ubinascii import hexlify as b2a_hex -from ubinascii import unhexlify as a2b_hex from dleq import generate_dleq_proof, verify_dleq_proof from exceptions import FatalPSBTIssue from psbt import psbtObject @@ -28,8 +24,10 @@ _compute_silent_payment_spending_xonly, _negate_if_odd_y, _sum_privkeys, - SilentPaymentsMixin, ) +from ubinascii import hexlify as b2a_hex +from ubinascii import unhexlify as a2b_hex +from uio import BytesIO if isinstance(main.SP_VERIFY, str): with open(main.SP_VERIFY) as f: @@ -40,99 +38,25 @@ mode = params.get("mode") -# --------------------------------------------------------------------------- -# MockPSBT infrastructure for firmware method testing -# --------------------------------------------------------------------------- - - -class MockInput: - def __init__(self): - self.utxo_spk = None - self.taproot_internal_key = None - self.redeem_script = None - self.sighash = None - self.previous_txid = None - self.prevout_idx = None - self.sp_ecdh_shares = {} - self.sp_dleq_proofs = {} - self.subpaths = [] - self.taproot_subpaths = [] - self.sp_tweak = None - self.sp_spend_bip32_derivation = {} - self.sp_idxs = None - self.ik_idx = None - - @property - def is_sp_spend(self): - return bool(self.sp_tweak and self.sp_spend_bip32_derivation) - - -class MockOutput: - def __init__(self): - self.sp_v0_info = None - self.sp_v0_label = None - self.script = None - - -class MockPSBT(SilentPaymentsMixin): - def __init__(self): - self.inputs = [] - self.outputs = [] - self.sp_global_ecdh_shares = {} - self.sp_global_dleq_proofs = {} - self.txn_modifiable = None - self.my_xfp = 0 - - def get(self, x): - return x - - def parse_xfp_path(self, coords): - return coords - - -def _build_mock_psbt(params): - psbt = MockPSBT() - psbt.txn_modifiable = params.get("txn_modifiable") - - global_ecdh = params.get("global_ecdh") or {} - global_dleq = params.get("global_dleq") or {} - psbt.sp_global_ecdh_shares = {a2b_hex(k): a2b_hex(v) for k, v in global_ecdh.items()} - psbt.sp_global_dleq_proofs = {a2b_hex(k): a2b_hex(v) for k, v in global_dleq.items()} - - for d in params.get("inputs", []): - inp = MockInput() - if d.get("utxo_spk"): - inp.utxo_spk = a2b_hex(d["utxo_spk"]) - elif d.get("witness_utxo"): - wu = a2b_hex(d["witness_utxo"]) - # Extract scriptPubKey: 8 bytes value + varint length + script - script_len = wu[8] - inp.utxo_spk = wu[9 : 9 + script_len] - if d.get("taproot_internal_key"): - inp.taproot_internal_key = a2b_hex(d["taproot_internal_key"]) - if d.get("redeem_script"): - inp.redeem_script = a2b_hex(d["redeem_script"]) - inp.sighash = d.get("sighash") - if d.get("previous_txid"): - inp.previous_txid = a2b_hex(d["previous_txid"]) - if d.get("prevout_idx") is not None: - inp.prevout_idx = struct.pack(" Date: Fri, 1 May 2026 17:47:51 -0400 Subject: [PATCH 20/41] SP: improve sp spend without sp outputs and change detection Convert validate_bip376_spend to validate_silent_payment_inputs Use accounts to validate sp spend material and mark output.is_change Introduce reusable sp_derive_path function Fix change detection issue raised by previous test hygiene commit - Signing was restored for test_sp_spend_labeled_change_detected Fix psbt exception in consider_outputs with sp change - Add apply_label_to_spend_key primitive - Match spend public key to labeled spend public key for change New tests: sp spend to non sp output sp spend rejection tests - unknown account, incorrect sp spend derivation path sp change output with foreign keys is allowed but displays warning Changed test: sp spend to label change - fix label spend key derivation, use sp input --- shared/auth.py | 9 +- shared/export.py | 4 +- shared/psbt.py | 17 +- shared/silentpayments.py | 187 +++++++++--- testing/devtest/unit_silentpayments.py | 4 - testing/devtest/verify_sp_outputs.py | 8 + testing/sp_helpers.py | 27 ++ testing/test_silentpayments.py | 404 ++++++++++++++++++++++++- 8 files changed, 584 insertions(+), 76 deletions(-) diff --git a/shared/auth.py b/shared/auth.py index 990a50bbd..fe35bc2f9 100644 --- a/shared/auth.py +++ b/shared/auth.py @@ -418,9 +418,12 @@ async def interact(self): args = self.psbt.consider_inputs(cosign_xfp=ccc_c_xfp) # Silent Payments: Validate and pre-process Silent Payments outputs to make preview useful - if self.psbt.has_silent_payment_outputs(): - with stash.SensitiveValues() as sv: - if not self.psbt.process_silent_payments(sv): + with stash.SensitiveValues() as sv: + if self.psbt.has_silent_payment_inputs(): + self.psbt.validate_silent_payment_inputs(sv) + + if self.psbt.has_silent_payment_outputs(): + if not self.psbt.process_silent_payment_outputs(sv): # Coverage incomplete: shares computed but waiting on other signers # Skip normal approval flow — prompt user to contribute shares, then save del args diff --git a/shared/export.py b/shared/export.py index 966dc0cd0..acbc92f2c 100644 --- a/shared/export.py +++ b/shared/export.py @@ -13,7 +13,7 @@ from charcodes import KEY_NFC, KEY_CANCEL, KEY_QR from ownership import OWNERSHIP from exceptions import QRTooBigError -from silentpayments import encode_silent_payment_address +from silentpayments import encode_silent_payment_address, sp_derive_path async def export_by_qr(body, label, type_code, force_bbqr=False): # render as QR and show on-screen @@ -446,7 +446,7 @@ def generate_generic_export(account_num=0): rv[name]['first'] = chain.address(node, fmt) # Silent Payments: scan-priv + spend-pub packed as a single bech32m "spscan" string - sp_deriv = "m/352h/%dh/%dh" % (chain.b44_cointype, account_num) + sp_deriv = sp_derive_path(chain.b44_cointype, account_num) sp_node = sv.derive_path(sp_deriv) scan_node = sv.derive_path(sp_deriv + "/1h/0") spend_node = sv.derive_path(sp_deriv + "/0h/0") diff --git a/shared/psbt.py b/shared/psbt.py index 3f57046b1..7fba9a1f8 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -49,7 +49,7 @@ AF_P2WSH, AF_P2WSH_P2SH, AF_P2SH, AF_P2TR, AF_P2WPKH, AF_CLASSIC, AF_P2WPKH_P2SH, AFC_SEGWIT, AF_BARE_PK ) -from silentpayments import SilentPaymentsMixin, compute_silent_payment_spending_privkey, validate_bip376_spend +from silentpayments import SilentPaymentsMixin, compute_silent_payment_spending_privkey psbt_tmp256 = bytearray(256) @@ -1145,7 +1145,7 @@ def determine_my_signing_key(self, my_idx, addr_or_pubkey, my_xfp, psbt, parsed_ merkle_root = self.get(self.taproot_merkle_root) if self.is_sp_spend: - validate_bip376_spend(self, addr_or_pubkey, my_xfp, psbt) + pass # Silent Payments inputs are handled in validate_silent_payment_inputs elif len(parsed_subpaths) == 1: # Simple SE-backed key-path spends must not commit to an unknown # script tree. WIF Store is the explicit escape hatch for externally @@ -2144,7 +2144,8 @@ def consider_outputs(self, len_pths, hard_p, prefix_pths, idx_max, cosign_xfp=No self.num_change_outputs += 1 total_change += txo.nValue - if validate_inp_pths: + # Silent Payments: SP change is validated by _detect_sp_change_outputs, skip additional checks here + if validate_inp_pths and not output.sp_v0_info: # Enforce some policy on change outputs: # - need to "look like" they are going to same wallet as inputs came from # - range limit last two path components (numerically) @@ -2997,7 +2998,11 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): # Double-check the change outputs are right. This is slow, but critical because # it detects bad actors, not bugs or mistakes. # - equivalent check already done for p2sh outputs when we re-built the redeem script - change_outs = [n for n,o in enumerate(self.outputs) if o.is_change] + + # SP change is verified at preview time by _detect_sp_change_outputs; + # the subpath/check_pubkey_at_path machinery below doesn't apply to it. + change_outs = [n for n, o in enumerate(self.outputs) + if o.is_change and not o.sp_v0_info] if change_outs: dis.fullscreen('Change Check...') @@ -3040,8 +3045,10 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): "BIP-32 path doesn't match actual address.") # Silent Payment Processing + if self.has_silent_payment_inputs(): + self.validate_silent_payment_inputs(sv) if self.has_silent_payment_outputs(): - if not self.process_silent_payments(sv): + if not self.process_silent_payment_outputs(sv): # Silent Payments: must not sign if output scripts not set for all signers # Defensive re-check - ApproveTransaction::interact should handle this case before reaching signing raise FatalPSBTIssue("Silent Payments: Signing cannot proceed until all signers contribute their shares") diff --git a/shared/silentpayments.py b/shared/silentpayments.py index 7a4ea8eb7..d81c30a0b 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -7,9 +7,11 @@ import chains import ngu import stash +from glob import settings from dleq import generate_dleq_proof, verify_dleq_proof -from exceptions import FatalPSBTIssue +from exceptions import FatalPSBTIssue, FraudulentChangeOutput from precomp_tag_hash import ( + BIP352_LABEL_TAG_H, BIP352_SHARED_SECRET_TAG_H, BIP352_INPUTS_TAG_H, TAP_TWEAK_H, @@ -46,41 +48,34 @@ def encode_silent_payment_address(scan_key, spend_key, version=0): return ngu.codecs.bip352_encode(hrp, scan_key, spend_key, version) -def validate_bip376_spend(input, output_xonly, my_xfp=None, parent=None): - """Validate silent payment spend using PSBT input data - - TODO: replace with test vectors once available - - Raises FatalPSBTIssue if any SP spend validation checks fail - """ - B_spend_coords, val_coords = input.sp_spend_bip32_derivation - xfp_path = input.parse_xfp_path(val_coords) - if my_xfp is not None: - xfp_path = input.handle_zero_xfp(xfp_path, my_xfp, parent) - - sp_path = xfp_path[1:] - if len(sp_path) != 5: - raise FatalPSBTIssue("SP spend path must have 5 components") - if sp_path[0] != (352 | 0x80000000): - raise FatalPSBTIssue("SP spend key purpose must use 352h path") - - expected_coin = chains.current_chain().b44_cointype | 0x80000000 - if sp_path[1] != expected_coin: - raise FatalPSBTIssue("SP spend path coin type does not match network") - if not (sp_path[2] & 0x80000000): - raise FatalPSBTIssue("SP spend path account must be hardened") - if sp_path[3] != 0x80000000: - raise FatalPSBTIssue("SP spend path key type must be 0h") - - B_spend = input.get(B_spend_coords) - if _compute_silent_payment_spending_xonly(B_spend, input.sp_tweak) != output_xonly: - raise FatalPSBTIssue("SP_TWEAK does not match UTXO output key") +def sp_derive_path(coin_type, account): + """BIP-352 base derivation path for a given coin type and account number""" + return "m/352h/%dh/%dh" % (coin_type, account) # ----------------------------------------------------------------------------- # Silent Payments Cryptographic Primitives # ----------------------------------------------------------------------------- +def _apply_label_to_spend_key(B_spend_bytes, b_scan_bytes, label): + """ + Apply BIP-352 label tweak to spend key + + Formula: B_m = B_spend + hash_BIP0352/Label(b_scan || m)*G + + Args: + B_spend_bytes: Base spend public key (33-byte compressed) + b_scan_bytes: Scan private key (32-byte scalar) + label: Label integer (0 for change) + + Returns: + bytes: Labeled spend public key (33-byte compressed) + """ + msg = b_scan_bytes + label.to_bytes(4, 'big') + label_tweak_bytes = ngu.hash.sha256t(BIP352_LABEL_TAG_H, msg, True) + label_tweak_point = ngu.secp256k1.ec_pubkey_tweak_mul(G, label_tweak_bytes) + return ngu.secp256k1.ec_pubkey_combine([B_spend_bytes, label_tweak_point]) + def _combine_pubkeys(pubkeys): """ @@ -294,21 +289,19 @@ class SilentPaymentsMixin: This class assumes it is mixed into psbtObject and has access to psbt as self """ - def process_silent_payments(self, sv): + def process_silent_payment_outputs(self, sv): """ Core SP workflow: validate, compute shares, compute scripts Notes: - - This function is intended to be called during the preview phase, before signing + - This function is intended to be called during the preview phase and again during signing - Single-signer should be able to generate output and preview immediately - Multi-signer should generate shares and prompt user to collect all shares if not complete Returns: bool: True if output scripts were computed and are ready for preview/signing - False if we generated shares but are waiting on others, or if we don't have necessary info to proceed + False if we generated shares but are waiting on others """ - if not self.has_silent_payment_outputs(): - return False self._validate_psbt_structure() self._validate_input_eligibility() self._validate_ecdh_coverage() @@ -319,7 +312,7 @@ def process_silent_payments(self, sv): if self._is_ecdh_coverage_complete(): # Computes scripts, or validates existing ones against recomputed values self._compute_silent_payment_output_scripts() - self._detect_sp_change_outputs() + self._detect_sp_change_outputs(sv) return self._all_sp_outputs_have_scripts() return False @@ -341,6 +334,63 @@ def render_silent_payment_output_string(self, output): return " - silent payments address -\n%s\n" % encode_silent_payment_address(scan_key, spend_key) + def validate_silent_payment_inputs(self, sv): + """ + Validate inputs spending silent payments (BIP-376) + + Raises FatalPSBTIssue on any failure. + """ + coin_type = chains.current_chain().b44_cointype + expected_coin = coin_type | 0x80000000 + + candidate_accounts = self._get_candidate_sp_accounts() + + for i, inp in enumerate(self.inputs): + if not inp.is_sp_spend: + continue + + # Validate path shape and extract B_spend for both our and foreign inputs + B_spend_coords, val_coords = inp.sp_spend_bip32_derivation + xfp_path = inp.parse_xfp_path(val_coords) + xfp_path = inp.handle_zero_xfp(xfp_path, self.my_xfp, self) + + sp_path = xfp_path[1:] + if len(sp_path) != 5: + raise FatalPSBTIssue("Input #%d: SP spend path must have 5 components" % i) + if sp_path[0] != (352 | 0x80000000): + raise FatalPSBTIssue("Input #%d: SP spend key purpose must use 352h path" % i) + if sp_path[1] != expected_coin: + raise FatalPSBTIssue("Input #%d: SP spend path coin type does not match network" % i) + if not (sp_path[2] & 0x80000000): + raise FatalPSBTIssue("Input #%d: SP spend path account must be hardened" % i) + if sp_path[3] != 0x80000000: + raise FatalPSBTIssue("Input #%d: SP spend path key type must be 0h" % i) + if sp_path[4] != 0: + raise FatalPSBTIssue("Input #%d: SP spend path index must be 0" % i) + + B_spend = inp.get(B_spend_coords) + + # For our inputs, validate account is known and B_spend matches derivation from this device + if xfp_path[0] == self.my_xfp: + account = sp_path[2] & ~0x80000000 + if account not in candidate_accounts: + raise FatalPSBTIssue( + "Input #%d: SP spend account not recognized on this device" % i) + + spend_node = sv.derive_path( + sp_derive_path(coin_type, account) + "/0h/0", register=False) + derived = spend_node.pubkey() + del spend_node + if derived != B_spend: + raise FatalPSBTIssue("Input #%d: SP spend pubkey mismatch" % i) + + spk = inp.utxo_spk + if not spk or not _is_p2tr(spk): + raise FatalPSBTIssue("Input #%d: SP spend UTXO is not P2TR" % i) + utxo_xonly = spk[2:34] + if _compute_silent_payment_spending_xonly(B_spend, inp.sp_tweak) != utxo_xonly: + raise FatalPSBTIssue("Input #%d: SP_TWEAK does not match UTXO output key" % i) + # ----------------------------------------------------------------------------- # Input Helper Functions # ----------------------------------------------------------------------------- @@ -613,9 +663,6 @@ def _compute_and_store_proof_entries(self, sv): """ Compute proof entries (ECDH shares and DLEQ proofs) for our inputs, store in PSBT fields - Notes: - Sets self.sp_all_inputs_ours for callers - Returns: bool: True if shares were computed False if we have no signable inputs @@ -644,14 +691,12 @@ def _compute_and_store_proof_entries(self, sv): raise FatalPSBTIssue("No eligible inputs for ECDH computation") return False - self.sp_all_inputs_ours = not has_foreign - scan_keys = self._get_silent_payment_scan_keys() if not scan_keys: return False for scan_key in scan_keys: - if self.sp_all_inputs_ours: + if not has_foreign: # Single-signer: combine all input private keys, one global ECDH share and DLEQ proofs combined_sk = _sum_privkeys(sk for _, sk in input_material) @@ -723,6 +768,10 @@ def _store_proof_entry(self, sk, scan_key, shares, proofs): # Utility Functions # ----------------------------------------------------------------------------- + def has_silent_payment_inputs(self): + """Check if PSBT contains any silent payment inputs""" + return any(inp.is_sp_spend for inp in self.inputs) + def has_silent_payment_outputs(self): """ Check if PSBT contains any silent payment outputs @@ -742,17 +791,59 @@ def _all_sp_outputs_have_scripts(self): return False return True - def _detect_sp_change_outputs(self): + def _detect_sp_change_outputs(self, sv): """ - Mark SP outputs as change if sp_v0_label is present and equals 0 (BIP-352 change convention) + Mark SP outputs as change if they match our accounts - No return value; modifies self.outputs 'is_change' in place + Raises FraudulentChangeOutput if all SP-eligible inputs are ours (single-signer); + multi-signer, a non-matching label=0 output is skipped (may belong to a co-signer). """ - for outp in self.outputs: + has_foreign = False + for inp in self.inputs: + if not self._is_input_eligible(inp): + continue + if inp.sp_idxs: + if self._derive_input_privkey(inp, sv) is None: + has_foreign = True + break + elif self._pubkey_from_input(inp): + has_foreign = True + break + + coin_type = chains.current_chain().b44_cointype + candidate_accounts = self._get_candidate_sp_accounts() + + for out_idx, outp in enumerate(self.outputs): if not outp.sp_v0_info or not outp.sp_v0_label: continue - if int.from_bytes(outp.sp_v0_label, "little") == 0: - outp.is_change = True + if int.from_bytes(outp.sp_v0_label, "little") != 0: + continue + + scan_pub = outp.sp_v0_info[:33] + spend_pub = outp.sp_v0_info[33:66] + + matched = False + for account in candidate_accounts: + base = sp_derive_path(coin_type, account) + scan_node = sv.derive_path(base + "/1h/0", register=False) + spend_node = sv.derive_path(base + "/0h/0", register=False) + label_spend_pub = _apply_label_to_spend_key(spend_node.pubkey(), scan_node.privkey(), 0) + matched = (scan_node.pubkey() == scan_pub) and (label_spend_pub == spend_pub) + del scan_node, spend_node + if matched: + outp.is_change = True + break + + if not matched and not has_foreign: + raise FraudulentChangeOutput(out_idx, "SP change output keys do not match this device") + + def _get_candidate_sp_accounts(self): + """Get all known account numbers from device settings, always include account 0""" + seen = {0} + for _af, acct_num in settings.get('accts', []): + if acct_num: + seen.add(acct_num) + return sorted(seen) def _get_outpoints(self): """ diff --git a/testing/devtest/unit_silentpayments.py b/testing/devtest/unit_silentpayments.py index ec90aa360..bd9ff9abb 100644 --- a/testing/devtest/unit_silentpayments.py +++ b/testing/devtest/unit_silentpayments.py @@ -458,8 +458,6 @@ def _make_sp_output(scan_key): (MY_XFP, 44, 0, 0, 1): TEST_PRIVKEY2, } ) -assert psbt.sp_all_inputs_ours is True - # Foreign input psbt = MockPSBT() inp_ours = _make_eligible_input(pk_ours, TEST_DERIV_OURS, b"\x01" * 32, b"\x00" * 4) @@ -469,8 +467,6 @@ def _make_sp_output(scan_key): outp.sp_v0_info = TEST_SCAN_KEY + TEST_SPEND_KEY psbt.outputs = [outp] psbt._compute_and_store_proof_entries({TEST_DERIV_OURS: TEST_PRIVKEY}) -assert psbt.sp_all_inputs_ours is False - # No signable inputs psbt = MockPSBT() inp = _make_eligible_input(b"\x02" + b"\xbb" * 32, (FOREIGN_XFP, 44, 0, 0, 0), b"\x01" * 32, b"\x00" * 4) diff --git a/testing/devtest/verify_sp_outputs.py b/testing/devtest/verify_sp_outputs.py index 32d23d704..2c17e325c 100644 --- a/testing/devtest/verify_sp_outputs.py +++ b/testing/devtest/verify_sp_outputs.py @@ -16,6 +16,7 @@ from psbt import psbtObject from serializations import SIGHASH_DEFAULT from silentpayments import ( + _apply_label_to_spend_key, _combine_pubkeys, _compute_ecdh_share, _compute_input_hash, @@ -180,6 +181,13 @@ def _load_psbt(params): result = _compute_silent_payment_spending_xonly(B_spend, sp_tweak) RV.write(b2a_hex(result).decode()) +elif mode == "apply_label_to_spend_key": + spend_pub = a2b_hex(params["spend_pub"]) + scan_priv = a2b_hex(params["scan_priv"]) + label = int(params["label"]) + result = _apply_label_to_spend_key(spend_pub, scan_priv, label) + RV.write(b2a_hex(result).decode()) + elif mode == "negate_if_odd_y": privkey = a2b_hex(params["privkey"]) result = _negate_if_odd_y(privkey) diff --git a/testing/sp_helpers.py b/testing/sp_helpers.py index 70c7c1aed..e0b078c9a 100644 --- a/testing/sp_helpers.py +++ b/testing/sp_helpers.py @@ -98,6 +98,19 @@ def _sim_compute_ecdh_share(sim_exec, sim_execfile, privkey, scan_key): return bytes.fromhex(rv) +def _sim_generate_dleq_proof(sim_exec, sim_execfile, privkey, scan_key): + rv = _sim_sp( + sim_exec, + sim_execfile, + "generate_dleq_proof", + { + "privkey": privkey.hex(), + "scan_key": scan_key.hex(), + }, + ) + return bytes.fromhex(rv) + + def _sim_compute_spend_output_xonly(sim_exec, sim_execfile, B_spend, sp_tweak): rv = _sim_sp( sim_exec, @@ -223,6 +236,20 @@ def _sim_sum_privkeys(sim_exec, sim_execfile, privkeys): return bytes.fromhex(rv) +def _sim_apply_label_to_spend_key(sim_exec, sim_execfile, spend_pub, scan_priv, label): + rv = _sim_sp( + sim_exec, + sim_execfile, + "apply_label_to_spend_key", + { + "spend_pub": spend_pub.hex(), + "scan_priv": scan_priv.hex(), + "label": label, + }, + ) + return bytes.fromhex(rv) + + def _sim_negate_if_odd_y(sim_exec, sim_execfile, privkey): rv = _sim_sp( sim_exec, diff --git a/testing/test_silentpayments.py b/testing/test_silentpayments.py index 4310d1d02..8308810a0 100644 --- a/testing/test_silentpayments.py +++ b/testing/test_silentpayments.py @@ -17,9 +17,11 @@ from constants import simulator_fixed_tprv from psbt import BasicPSBT from sp_helpers import ( + _sim_apply_label_to_spend_key, _sim_compute_ecdh_share, _sim_compute_output_script, _sim_compute_spend_output_xonly, + _sim_generate_dleq_proof, _sim_get_ecdh_and_pubkey, _sim_get_outpoints, _sim_verify_dleq, @@ -38,6 +40,7 @@ # BIP-376 SP spend constants (BIP-352 path: m/352h/1h/0h/0h/0, testnet) SP_TWEAK = bytes.fromhex("a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2") +SP_SCAN_PATH = "352h/1h/0h/1h/0" SP_SPEND_PATH = "352h/1h/0h/0h/0" SP_SPEND_PATH_INTS = [ 352 | 0x80000000, @@ -47,6 +50,7 @@ 0, ] +SIMULATOR_DELAY = 0 # seconds to wait for the simulator to process the PSBT and update the story # --------------------------------------------------------------------------- # Helpers @@ -141,8 +145,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) - - time.sleep(0.1) + time.sleep(SIMULATOR_DELAY) title, story = cap_story() assert title == "OK TO SEND?" assert "not well understood script" not in story @@ -160,6 +163,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) tp = BasicPSBT().parse(signed) @@ -175,6 +179,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) tp = BasicPSBT().parse(signed) @@ -191,6 +196,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn([["p2wpkh"], ["p2tr"]], 1, xp, psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) tp = BasicPSBT().parse(signed) @@ -218,6 +224,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn([["p2tr"], ["p2tr"]], 1, xp, psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) _assert_sp_spend_success(sim_exec, sim_execfile, signed) @@ -243,6 +250,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 3, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) tp = BasicPSBT().parse(signed) @@ -268,6 +276,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 2, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) tp = BasicPSBT().parse(signed) @@ -291,6 +300,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 2, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) tp = BasicPSBT().parse(signed) @@ -313,6 +323,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn([["p2wpkh"], ["p2wpkh"]], 1, xp, psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) tp = BasicPSBT().parse(signed) @@ -351,6 +362,7 @@ def sp_hacker(psbt): psbt_hacker=sp_hacker, ) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) tp = BasicPSBT().parse(signed) @@ -394,8 +406,7 @@ def sp_hacker(psbt): psbt_hacker=sp_hacker, ) start_sign(psbt_bytes) - - time.sleep(0.1) + time.sleep(SIMULATOR_DELAY) title, story = cap_story() assert title == "CONTRIBUTE SHARES?" assert "ECDH shares" in story @@ -435,19 +446,240 @@ def sp_hacker(psbt): psbt_hacker=sp_hacker, ) start_sign(psbt_bytes) - - time.sleep(0.1) + time.sleep(SIMULATOR_DELAY) title, _ = cap_story() assert title == "CONTRIBUTE SHARES?" end_sign(accept=False) +# --------------------------------------------------------------------------- +# Multi-signer - re-sign idempotency (Coldcard's own contribution must not +# be regenerated on a second pass, or a fresh DLEQ proof breaks strict PSBT +# merge with another signer's earlier copy of the same field) +# --------------------------------------------------------------------------- + +def _sign_partial_then_act_as_other_signer(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile, + tamper_input0_before_first_sign=None): + """Shared setup: Coldcard signs input 0 first (coverage incomplete), then test + code plays the role of the second signer on input 1, computes the SP output + script, and clears TX_MODIFIABLE. + + Returns (tp, orig_share, orig_proof) where tp is the PSBT ready for Coldcard's + second signing pass, and orig_share/orig_proof are Coldcard's first-pass values + for input 0. + """ + xp = dev.master_xpub + captured = {} + + def sp_hacker(psbt): + # Capture the "other signer" key fake_txn() generated for the foreign + # input; it's only available here, not on the PSBT once parsed back. + captured["foreign_mk"] = psbt._foreign_mk + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + if tamper_input0_before_first_sign: + tamper_input0_before_first_sign(psbt) + + psbt_bytes = fake_txn( + [["p2wpkh"], ["p2wpkh", None, None, False]], + 1, + xp, + psbt_v2=True, + psbt_hacker=sp_hacker, + ) + start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + orig_share = tp.inputs[0].sp_ecdh_shares[SCAN_KEY] + orig_proof = tp.inputs[0].sp_dleq_proofs[SCAN_KEY] + + # Act as the other signer: contribute input 1's share/proof. + foreign_sub = captured["foreign_mk"].subkey_for_path("0/1") + ecdh_share = _sim_compute_ecdh_share(sim_exec, sim_execfile, foreign_sub.privkey(), SCAN_KEY) + proof = bytes.fromhex(_sim_sp( + sim_exec, sim_execfile, "generate_dleq_proof", + {"privkey": foreign_sub.privkey().hex(), "scan_key": SCAN_KEY.hex()}, + )) + tp.inputs[1].sp_ecdh_shares = {SCAN_KEY: ecdh_share} + tp.inputs[1].sp_dleq_proofs = {SCAN_KEY: proof} + + # Resolve the SP output script now that coverage is complete. + ecdh_share_combined, summed_pubkey = _sim_get_ecdh_and_pubkey(sim_exec, sim_execfile, tp, SCAN_KEY) + outpoints = _sim_get_outpoints(sim_exec, sim_execfile, tp) + sp_outs = [o for o in tp.outputs if o.sp_v0_info] + assert len(sp_outs) == 1 + sp_outs[0].script = _sim_compute_output_script( + sim_exec, sim_execfile, outpoints, summed_pubkey, ecdh_share_combined, SPEND_KEY_B, 0 + ) + + tp.txn_modifiable = 0 + + return tp, orig_share, orig_proof + + +def test_sp_multi_signer_resign_preserves_contribution(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Coldcard's second signing pass must not regenerate its own ECDH share / DLEQ + proof on input 0: the DLEQ proof uses fresh randomness, so a naive re-sign would + produce different (but still valid) proof bytes, breaking strict PSBT merge with + the copy the other signer already has. + """ + tp, orig_share, orig_proof = _sign_partial_then_act_as_other_signer( + dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile + ) + input1_share = tp.inputs[1].sp_ecdh_shares[SCAN_KEY] + input1_proof = tp.inputs[1].sp_dleq_proofs[SCAN_KEY] + output_script = [o for o in tp.outputs if o.sp_v0_info][0].script + + start_sign(tp.as_bytes()) + time.sleep(SIMULATOR_DELAY) + resigned = end_sign(accept=True, finalize=False) + + rp = BasicPSBT().parse(resigned) + + assert rp.inputs[0].sp_ecdh_shares[SCAN_KEY] == orig_share, "input 0 ECDH share changed on re-sign" + assert rp.inputs[0].sp_dleq_proofs[SCAN_KEY] == orig_proof, "input 0 DLEQ proof changed on re-sign" + assert rp.inputs[1].sp_ecdh_shares[SCAN_KEY] == input1_share, "input 1 share must be untouched" + assert rp.inputs[1].sp_dleq_proofs[SCAN_KEY] == input1_proof, "input 1 proof must be untouched" + + sp_outs = [o for o in rp.outputs if o.sp_v0_info] + assert len(sp_outs) == 1 + assert sp_outs[0].script == output_script, "output script must not change on re-sign" + + assert rp.inputs[0].part_sigs, "input 0 must be signed" + + assert not rp.sp_global_ecdh_shares, "multi-signer path must never populate global shares" + assert not rp.sp_global_dleq_proofs + + +def test_sp_multi_signer_resign_rejects_tampered_proof(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """A tampered DLEQ proof for our own input must be rejected, not silently + replaced. Note: this may already be caught by _validate_ecdh_coverage once the + output script is set; this test pins that behavior for the re-sign path too. + """ + tp, _, _ = _sign_partial_then_act_as_other_signer( + dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile + ) + proof = bytearray(tp.inputs[0].sp_dleq_proofs[SCAN_KEY]) + proof[0] ^= 0xFF + tp.inputs[0].sp_dleq_proofs[SCAN_KEY] = bytes(proof) + + start_sign(tp.as_bytes()) + time.sleep(SIMULATOR_DELAY) + with pytest.raises(CCProtoError): + end_sign(accept=True, finalize=False) + + +def test_sp_multi_signer_resign_rejects_foreign_share_for_our_input(dev, fake_txn, start_sign, end_sign, + sim_exec, sim_execfile): + """A share/proof from a different key placed on one of Coldcard's own inputs + (before Coldcard has ever contributed) must be rejected rather than kept. + + Note: the foreign DLEQ proof fails against our input pubkey, so this is rejected by + _validate_ecdh_coverage. The share mismatch check in _store_proof_entry is defensive + and cannot be reached from a test without our private key. + """ + xp = dev.master_xpub + + def tamper(psbt): + foreign_sub = psbt._foreign_mk.subkey_for_path("99/99") + ecdh_share = _sim_compute_ecdh_share(sim_exec, sim_execfile, foreign_sub.privkey(), SCAN_KEY) + proof = bytes.fromhex(_sim_sp( + sim_exec, sim_execfile, "generate_dleq_proof", + {"privkey": foreign_sub.privkey().hex(), "scan_key": SCAN_KEY.hex()}, + )) + psbt.inputs[0].sp_ecdh_shares = {SCAN_KEY: ecdh_share} + psbt.inputs[0].sp_dleq_proofs = {SCAN_KEY: proof} + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + tamper(psbt) + + psbt_bytes = fake_txn( + [["p2wpkh"], ["p2wpkh", None, None, False]], + 1, + xp, + psbt_v2=True, + psbt_hacker=sp_hacker, + ) + start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) + with pytest.raises(CCProtoError): + end_sign(accept=True, finalize=False) + + +def test_sp_single_signer_resign_idempotent(dev, fake_txn, start_sign, end_sign): + """Single-signer (all-owned) path: re-signing must not regenerate the global + DLEQ proof either. + + Note: a real single-key, single-input PSBT is fully signed after the first + pass, and firmware refuses to re-sign a completely-signed transaction + (unrelated pre-existing guard in psbt.py, "Transaction looks completely + signed already?"). To exercise the second signing pass at all, we clear the + signature before feeding the PSBT back. This leaves the already-computed + SP fields in place (as a second signer merging back a partially-signed PSBT + would see them) while making the input signable again. + """ + xp = dev.master_xpub + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) + signed = end_sign(accept=True, finalize=False) + tp = BasicPSBT().parse(signed) + orig_proof = tp.sp_global_dleq_proofs[SCAN_KEY] + orig_share = tp.sp_global_ecdh_shares[SCAN_KEY] + + tp.inputs[0].part_sigs = {} + + start_sign(tp.as_bytes()) + time.sleep(SIMULATOR_DELAY) + resigned = end_sign(accept=True, finalize=False) + rp = BasicPSBT().parse(resigned) + + assert rp.sp_global_ecdh_shares[SCAN_KEY] == orig_share + assert rp.sp_global_dleq_proofs[SCAN_KEY] == orig_proof + + # --------------------------------------------------------------------------- # BIP-376 Silent Payments spend sp output test # --------------------------------------------------------------------------- +def test_sp_spend_input_to_non_sp_output(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Spend from SP input to a non SP output. + + Verifies that SP input validation (tweak, path) passes and the tx is signed + without computing ECDH shares (which are only needed for SP outputs). + """ + xp = dev.master_xpub + + def sp_hacker(psbt): + _setup_sp_spend_input( + sim_exec, + sim_execfile, + psbt.inputs[0], + SP_TWEAK, + SP_SPEND_PATH, + SP_SPEND_PATH_INTS, + clear_taproot=True, + ) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) + signed = end_sign(accept=True, finalize=False) + + tp = BasicPSBT().parse(signed) + assert not tp.sp_global_ecdh_shares, "Global ECDH shares must not exist when spending to non-SP outputs" + assert not tp.inputs[0].sp_ecdh_shares, "Per-input ECDH shares must not exist when spending to non-SP outputs" + _verify_signatures(sim_exec, sim_execfile, tp, signed) + + def test_sp_spend_silent_payment_output(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): """Spend from SP output with correct proof -> sign. @@ -471,6 +703,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) _assert_sp_spend_success(sim_exec, sim_execfile, signed) @@ -493,6 +726,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) signed = end_sign(accept=True, finalize=False) _assert_sp_spend_success(sim_exec, sim_execfile, signed) _verify_sp_outputs(sim_exec, sim_execfile, BasicPSBT().parse(signed), SCAN_KEY, [SPEND_KEY_B]) @@ -518,6 +752,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) with pytest.raises(CCProtoError, match="SP_TWEAK does not match UTXO output key"): end_sign(accept=True, finalize=False) @@ -542,6 +777,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) with pytest.raises(CCProtoError, match="SP spend key purpose must use 352h path"): end_sign(accept=True, finalize=False) @@ -572,10 +808,71 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) with pytest.raises(CCProtoError, match="SP spend path coin type does not match network"): end_sign(accept=True, finalize=False) +def test_sp_spend_unknown_account_rejected(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """Path with an account not in settings.get('accts') (and not 0) must be rejected.""" + xp = dev.master_xpub + UNKNOWN_ACCT_PATH = "352h/1h/7h/0h/0" + UNKNOWN_ACCT_PATH_INTS = [ + 352 | 0x80000000, + 1 | 0x80000000, + 7 | 0x80000000, + 0 | 0x80000000, + 0, + ] + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + _setup_sp_spend_input( + sim_exec, + sim_execfile, + psbt.inputs[0], + SP_TWEAK, + UNKNOWN_ACCT_PATH, + UNKNOWN_ACCT_PATH_INTS, + ) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) + with pytest.raises(CCProtoError, match="SP spend account not recognized on this device"): + end_sign(accept=True, finalize=False) + + +def test_sp_spend_tampered_pubkey_rejected(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile): + """PSBT-stated B_spend must match device-derived spend pubkey for the stated path.""" + xp = dev.master_xpub + FAKE_PUBKEY_PATH = "84h/1h/0h/0/0" + + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + master = BIP32Node.from_wallet_key(simulator_fixed_tprv) + mfp = master.fingerprint() + # Tampered: B_spend derived from a non-SP path; xfp+path advertises the legitimate SP path + fake_B_spend = master.subkey_for_path(FAKE_PUBKEY_PATH).sec() + xfp_and_path = mfp + struct.pack("<" + "I" * len(SP_SPEND_PATH_INTS), *SP_SPEND_PATH_INTS) + + # Witness UTXO locked to fake_B_spend + SP_TWEAK*G so tweak math itself passes + xonly = _sim_compute_spend_output_xonly(sim_exec, sim_execfile, fake_B_spend, SP_TWEAK) + inp = psbt.inputs[0] + amount_bytes = inp.witness_utxo[:8] + inp.witness_utxo = amount_bytes + b"\x22\x51\x20" + xonly + inp.taproot_bip32_paths = {} + inp.taproot_internal_key = None + inp.sp_tweak = SP_TWEAK + inp.sp_spend_bip32_derivation = {fake_B_spend: xfp_and_path} + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) + with pytest.raises(CCProtoError, match="SP spend pubkey mismatch"): + end_sign(accept=True, finalize=False) + + # --------------------------------------------------------------------------- # Handle failure test # --------------------------------------------------------------------------- @@ -592,6 +889,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) with pytest.raises(CCProtoError, match="SP_V0_INFO wrong size"): end_sign(accept=True, finalize=False) @@ -606,6 +904,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) with pytest.raises(CCProtoError, match="Silent payments require SIGHASH_ALL"): end_sign(accept=True, finalize=False) @@ -624,6 +923,7 @@ def sp_hacker(psbt): psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=False, psbt_hacker=sp_hacker) start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) with pytest.raises(CCProtoError, match="Missing outpoint for silent payment input"): end_sign(accept=True, finalize=False) @@ -633,27 +933,37 @@ def sp_hacker(psbt): # --------------------------------------------------------------------------- -def test_sp_spend_to_labeled_change_address(dev, fake_txn, start_sign, end_sign, cap_story, sim_exec, sim_execfile): +def test_sp_spend_labeled_change_detected(dev, fake_txn, start_sign, end_sign, cap_story, sim_exec, sim_execfile): """Two SP outputs: output 0 is a send (no label), output 1 is change (label=0 per BIP-352 convention).""" xp = dev.master_xpub root = BIP32Node.from_wallet_key(simulator_fixed_tprv) - sim_scan_pub = root.subkey_for_path("352h/1h/0h/1h/0").sec() - sim_spend_pub = root.subkey_for_path("352h/1h/0h/0h/0").sec() + scan_node = root.subkey_for_path(SP_SCAN_PATH) + scan_pub = scan_node.sec() + spend_pub = root.subkey_for_path(SP_SPEND_PATH).sec() + labeled_spend_pub = _sim_apply_label_to_spend_key(sim_exec, sim_execfile, spend_pub, scan_node.privkey(), 0) def sp_hacker(psbt): + _setup_sp_spend_input( + sim_exec, + sim_execfile, + psbt.inputs[0], + SP_TWEAK, + SP_SPEND_PATH, + SP_SPEND_PATH_INTS, + ) _add_sp_outputs( psbt, [ (0, SCAN_KEY, SPEND_KEY_B), - (1, sim_scan_pub, sim_spend_pub), + (1, scan_pub, labeled_spend_pub), ], ) psbt.outputs[1].sp_v0_label = b"\x00\x00\x00\x00" - psbt_bytes = fake_txn(1, 2, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + psbt_bytes = fake_txn(1, 2, xp, addr_fmt="p2tr", psbt_v2=True, psbt_hacker=sp_hacker) start_sign(psbt_bytes) - + time.sleep(SIMULATOR_DELAY) title, story = cap_story() assert title == "OK TO SEND?" assert "not well understood script" not in story @@ -663,9 +973,74 @@ def sp_hacker(psbt): signed = end_sign(accept=True, finalize=False) tp = BasicPSBT().parse(signed) assert SCAN_KEY in tp.sp_global_ecdh_shares and SCAN_KEY in tp.sp_global_dleq_proofs - assert sim_scan_pub in tp.sp_global_ecdh_shares and sim_scan_pub in tp.sp_global_dleq_proofs + assert scan_pub in tp.sp_global_ecdh_shares and scan_pub in tp.sp_global_dleq_proofs _verify_sp_outputs(sim_exec, sim_execfile, tp, SCAN_KEY, [SPEND_KEY_B]) - _verify_sp_outputs(sim_exec, sim_execfile, tp, sim_scan_pub, [sim_spend_pub]) + _verify_sp_outputs(sim_exec, sim_execfile, tp, scan_pub, [labeled_spend_pub]) + _verify_signatures(sim_exec, sim_execfile, tp, signed) + + +def test_cosigner_change_output_is_allowed_with_warning(dev, fake_txn, start_sign, end_sign, cap_story, sim_exec, sim_execfile): + """label=0 with foreign keys must NOT raise fraud in a multi-signer flow. + + This tests bypasses the normal "coverage incomplete" workflow to simulate this scenario: + When foreign inputs are present, a label=0 SP output + whose scan/spend keys don't belong to this device is treated as a cosigner's change + address and rendered as a normal SP recipient — not marked as change, displays a warning. + """ + xp = dev.master_xpub + + # Fixed deterministic foreign key so the test is reproducible + foreign_mk = BIP32Node.from_master_secret(bytes(range(32))) + foreign_key = foreign_mk.subkey_for_path("0/0") + foreign_pub = foreign_key.sec() + foreign_xfp = foreign_mk.fingerprint() + foreign_priv = foreign_key.privkey() + + # Pre-compute real ECDH shares and DLEQ proofs for the foreign input. + # These must be valid: after preview sets output scripts, _validate_ecdh_coverage + # re-runs and verifies per-input DLEQ proofs. + foreign_shares = { + scan_key: _sim_compute_ecdh_share(sim_exec, sim_execfile, foreign_priv, scan_key) + for scan_key in (SCAN_KEY, SCAN_KEY_2) + } + foreign_proofs = { + scan_key: _sim_generate_dleq_proof(sim_exec, sim_execfile, foreign_priv, scan_key) + for scan_key in (SCAN_KEY, SCAN_KEY_2) + } + + def sp_hacker(psbt): + # Output 0: normal SP send (no label, third-party recipient) + # Output 1: cosigner's SP change (label=0, keys are NOT this device's) + _add_sp_outputs(psbt, [ + (0, SCAN_KEY, SPEND_KEY_B), + (1, SCAN_KEY_2, SPEND_KEY_A), + ]) + psbt.outputs[1].sp_v0_label = b"\x00\x00\x00\x00" + + # Make input 0 foreign: replace the random bip32 entry with the fixed unknown key. + # The firmware will fail to derive a privkey for this XFP → all_sp_inputs_ours=False. + psbt.inputs[0].bip32_paths = {} + psbt.inputs[0].bip32_paths[foreign_pub] = foreign_xfp + struct.pack(' Date: Wed, 3 Jun 2026 18:53:12 -0400 Subject: [PATCH 21/41] WIP: fix (SP): apply sp output sort correctly when scan key is the same for multiple outputs Per BIP-375: sort by spend key then output index in ascending order for each scan key group to determine ordering of the k value - Fix compute_silent_payment_output_scripts to match spec - Update bip375_test_vectors.json to version 1.1.1 --- shared/silentpayments.py | 32 ++++++++------- testing/devtest/unit_silentpayments.py | 19 +++------ testing/test_bip375_vectors.py | 56 ++++++++------------------ 3 files changed, 40 insertions(+), 67 deletions(-) diff --git a/shared/silentpayments.py b/shared/silentpayments.py index d81c30a0b..56491e1cb 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -4,16 +4,17 @@ # # Consolidates cryptographic primitives and PSBT handling logic for Silent Payments # + import chains import ngu import stash -from glob import settings from dleq import generate_dleq_proof, verify_dleq_proof from exceptions import FatalPSBTIssue, FraudulentChangeOutput +from glob import settings from precomp_tag_hash import ( + BIP352_INPUTS_TAG_H, BIP352_LABEL_TAG_H, BIP352_SHARED_SECRET_TAG_H, - BIP352_INPUTS_TAG_H, TAP_TWEAK_H, ) from serializations import SIGHASH_ALL, SIGHASH_DEFAULT @@ -57,6 +58,7 @@ def sp_derive_path(coin_type, account): # Silent Payments Cryptographic Primitives # ----------------------------------------------------------------------------- + def _apply_label_to_spend_key(B_spend_bytes, b_scan_bytes, label): """ Apply BIP-352 label tweak to spend key @@ -71,7 +73,7 @@ def _apply_label_to_spend_key(B_spend_bytes, b_scan_bytes, label): Returns: bytes: Labeled spend public key (33-byte compressed) """ - msg = b_scan_bytes + label.to_bytes(4, 'big') + msg = b_scan_bytes + label.to_bytes(4, "big") label_tweak_bytes = ngu.hash.sha256t(BIP352_LABEL_TAG_H, msg, True) label_tweak_point = ngu.secp256k1.ec_pubkey_tweak_mul(G, label_tweak_bytes) return ngu.secp256k1.ec_pubkey_combine([B_spend_bytes, label_tweak_point]) @@ -374,11 +376,9 @@ def validate_silent_payment_inputs(self, sv): if xfp_path[0] == self.my_xfp: account = sp_path[2] & ~0x80000000 if account not in candidate_accounts: - raise FatalPSBTIssue( - "Input #%d: SP spend account not recognized on this device" % i) + raise FatalPSBTIssue("Input #%d: SP spend account not recognized on this device" % i) - spend_node = sv.derive_path( - sp_derive_path(coin_type, account) + "/0h/0", register=False) + spend_node = sv.derive_path(sp_derive_path(coin_type, account) + "/0h/0", register=False) derived = spend_node.pubkey() del spend_node if derived != B_spend: @@ -724,15 +724,17 @@ def _compute_silent_payment_output_scripts(self): """ outpoints = self._get_outpoints() + # BIP-375: sort by spend key then output index in ascending order for each scan key group to determine + # ordering of the k value + sp_outputs = [(outp.sp_v0_info, out_idx, outp) for out_idx, outp in enumerate(self.outputs) if outp.sp_v0_info] + sp_outputs.sort(key=lambda t: (t[0], t[1])) + # Track k per scan key scan_key_k = {} - for out_idx, outp in enumerate(self.outputs): - if not outp.sp_v0_info: - continue - - scan_key = outp.sp_v0_info[:33] - B_spend = outp.sp_v0_info[33:66] + for sp_info, out_idx, outp in sp_outputs: + scan_key = sp_info[:33] + B_spend = sp_info[33:66] k = scan_key_k.get(scan_key, 0) ecdh_share, summed_pubkey = self._get_ecdh_and_pubkey(scan_key) @@ -819,7 +821,7 @@ def _detect_sp_change_outputs(self, sv): if int.from_bytes(outp.sp_v0_label, "little") != 0: continue - scan_pub = outp.sp_v0_info[:33] + scan_pub = outp.sp_v0_info[:33] spend_pub = outp.sp_v0_info[33:66] matched = False @@ -840,7 +842,7 @@ def _detect_sp_change_outputs(self, sv): def _get_candidate_sp_accounts(self): """Get all known account numbers from device settings, always include account 0""" seen = {0} - for _af, acct_num in settings.get('accts', []): + for _af, acct_num in settings.get("accts", []): if acct_num: seen.add(acct_num) return sorted(seen) diff --git a/testing/devtest/unit_silentpayments.py b/testing/devtest/unit_silentpayments.py index bd9ff9abb..01eb9eb5f 100644 --- a/testing/devtest/unit_silentpayments.py +++ b/testing/devtest/unit_silentpayments.py @@ -61,8 +61,6 @@ # ECDH share computation ecdh_share = _compute_ecdh_share(TEST_PRIVKEY, TEST_SCAN_KEY) -assert len(ecdh_share) == 33 -assert ecdh_share[0] in (0x02, 0x03) # Input hash computation (order-independent) outpoints = [ @@ -77,8 +75,6 @@ ] spk = a2b_hex("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798") ih = _compute_input_hash(outpoints, spk) -assert isinstance(ih, bytes) and len(ih) == 32 -assert int.from_bytes(ih, "big") > 0 assert _compute_input_hash(outpoints[::-1], spk) == ih # Shared secret tweak (different k -> different tweak) @@ -118,8 +114,6 @@ pubkey = ngu.secp256k1.ec_pubkey_tweak_mul(G, TEST_PRIVKEY) proof = generate_dleq_proof(TEST_PRIVKEY, TEST_SCAN_KEY) -assert len(proof) == 64 -assert verify_dleq_proof(pubkey, TEST_SCAN_KEY, ecdh_share, proof) # Tampered proof rejected tampered = bytearray(proof) @@ -200,11 +194,8 @@ # Spending Privkey # --------------------------------------------------------------------------- -result = compute_silent_payment_spending_privkey((1).to_bytes(32, "big"), (42).to_bytes(32, "big")) -assert isinstance(result, bytes) and len(result) == 32 -assert result != (1).to_bytes(32, "big") -assert 0 < int.from_bytes(result, "big") < ngu.secp256k1.curve_order_int() - +# Valid computation is value-tested by BIP-352 receive vectors; only the +# zero-input error path is unique to this unit test. try: compute_silent_payment_spending_privkey(b"\x00" * 32, b"\x00" * 32) assert False, "Should raise" @@ -522,6 +513,7 @@ def _make_sp_output(scan_key): expected = _compute_silent_payment_output_script(outpoints, summed_pk, combined_share, TEST_SPEND_KEY, 0) assert outp.script == expected +# BIP-375: order by spend key when to determine k order when scan key is the same # k counter per scan key (skips non-SP outputs) psbt, scan_key, es, _, pk, _ = _make_mock_psbt_with_global_proofs() spend_key_a = a2b_hex("022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4") @@ -541,9 +533,10 @@ def _make_sp_output(scan_key): ops = [(b"\x01" * 32, b"\x00\x00\x00\x00")] spk_sum = _combine_pubkeys([pk]) +# spend keys sorted ascending: a (022f..) < c (0279..) < b (02c6..) assert sp0.script == _compute_silent_payment_output_script(ops, spk_sum, es, spend_key_a, k=0) -assert sp2.script == _compute_silent_payment_output_script(ops, spk_sum, es, spend_key_b, k=1) -assert sp4.script == _compute_silent_payment_output_script(ops, spk_sum, es, spend_key_c, k=2) +assert sp4.script == _compute_silent_payment_output_script(ops, spk_sum, es, spend_key_c, k=1) +assert sp2.script == _compute_silent_payment_output_script(ops, spk_sum, es, spend_key_b, k=2) assert reg1.script is None assert reg3.script is None diff --git a/testing/test_bip375_vectors.py b/testing/test_bip375_vectors.py index 0f6f9d581..b1944d978 100644 --- a/testing/test_bip375_vectors.py +++ b/testing/test_bip375_vectors.py @@ -90,12 +90,8 @@ def _get(self, substr): ("k values assigned to wrong output indices", "output script mismatch"), ] - @pytest.mark.parametrize( - "desc,expected_err", _SIM_INVALID, ids=[d for d, _ in _SIM_INVALID] - ) - def test_invalid_vectors_sim_validate_sp( - self, sim_exec, sim_execfile, desc, expected_err - ): + @pytest.mark.parametrize("desc,expected_err", _SIM_INVALID, ids=[d for d, _ in _SIM_INVALID]) + def test_invalid_vectors_sim_validate_sp(self, sim_exec, sim_execfile, desc, expected_err): p = BasicPSBT().parse(self._get(desc)["psbt"].encode()) err = _sim_validate_sp(sim_exec, sim_execfile, p) assert err, "Expected validation failure for: %s" % desc @@ -121,24 +117,15 @@ def test_valid_ecdh_computation(self, sim_exec, sim_execfile): eligible_privkeys = [ unhexlify(inp["private_key"]) for inp in vec["supplementary"]["inputs"] - if inp["private_key"] - and _sim_pubkey_from_input( - sim_exec, sim_execfile, p, inp["input_index"] - ) + if inp["private_key"] and _sim_pubkey_from_input(sim_exec, sim_execfile, p, inp["input_index"]) ] for expected in vec["supplementary"]["sp_proofs"]: scan_key = unhexlify(expected["scan_key"]) expected_ecdh = unhexlify(expected["ecdh_share"]) if "input_index" in expected: - ik = next( - k - for k in vec["supplementary"]["inputs"] - if k["input_index"] == expected["input_index"] - ) + ik = next(k for k in vec["supplementary"]["inputs"] if k["input_index"] == expected["input_index"]) privkey = unhexlify(ik["private_key"]) - actual = _sim_compute_ecdh_share( - sim_exec, sim_execfile, privkey, scan_key - ) + actual = _sim_compute_ecdh_share(sim_exec, sim_execfile, privkey, scan_key) else: shares = [ _sim_compute_ecdh_share( @@ -150,9 +137,9 @@ def test_valid_ecdh_computation(self, sim_exec, sim_execfile): for privkey in eligible_privkeys ] actual = _sim_combine_pubkeys(sim_exec, sim_execfile, shares) - assert actual == expected_ecdh, ( - "ECDH mismatch in valid[%d] for scan_key %s" - % (vi, expected["scan_key"][:16]) + assert actual == expected_ecdh, "ECDH mismatch in valid[%d] for scan_key %s" % ( + vi, + expected["scan_key"][:16], ) def test_valid_dleq_verification(self, sim_exec, sim_execfile): @@ -162,12 +149,8 @@ def test_valid_dleq_verification(self, sim_exec, sim_execfile): for scan_key, proof in p.sp_global_dleq_proofs.items(): ecdh_share = p.sp_global_ecdh_shares.get(scan_key) - assert ecdh_share is not None, ( - "valid[%d]: global ECDH share missing for scan key" % vi - ) - _, summed_pubkey = _sim_get_ecdh_and_pubkey( - sim_exec, sim_execfile, p, scan_key - ) + assert ecdh_share is not None, "valid[%d]: global ECDH share missing for scan key" % vi + _, summed_pubkey = _sim_get_ecdh_and_pubkey(sim_exec, sim_execfile, p, scan_key) _sim_verify_dleq( sim_exec, sim_execfile, @@ -185,9 +168,7 @@ def test_valid_dleq_verification(self, sim_exec, sim_execfile): continue for scan_key, proof in inp.sp_dleq_proofs.items(): ecdh_share = inp.sp_ecdh_shares.get(scan_key) - assert ecdh_share is not None, ( - "valid[%d] inp[%d]: ECDH share missing" % (vi, inp_idx) - ) + assert ecdh_share is not None, "valid[%d] inp[%d]: ECDH share missing" % (vi, inp_idx) _sim_verify_dleq( sim_exec, sim_execfile, @@ -202,18 +183,17 @@ def test_valid_output_script_derivation(self, sim_exec, sim_execfile): vec = self.VALID_VECTORS[vi] p = BasicPSBT().parse(vec["psbt"].encode()) sp_outputs = [ - (o.sp_v0_info[:33], o.sp_v0_info[33:66], o.script) - for o in p.outputs + (o.sp_v0_info[:33], o.sp_v0_info[33:66], out_index, o.script) + for out_index, o in enumerate(p.outputs) if o.sp_v0_info and len(o.sp_v0_info) == 66 ] if not sp_outputs: continue + sp_outputs.sort(key=lambda t: (t[0], t[1], t[2])) outpoints = _sim_get_outpoints(sim_exec, sim_execfile, p) scan_key_k = {} - for scan_key, spend_key, script in sp_outputs: - ecdh_share, summed_pubkey = _sim_get_ecdh_and_pubkey( - sim_exec, sim_execfile, p, scan_key - ) + for scan_key, spend_key, _oi, script in sp_outputs: + ecdh_share, summed_pubkey = _sim_get_ecdh_and_pubkey(sim_exec, sim_execfile, p, scan_key) if not ecdh_share: continue if not script: # If script is missing, skip vectors test missing script @@ -230,6 +210,4 @@ def test_valid_output_script_derivation(self, sim_exec, sim_execfile): spend_key, k, ) - assert script == expected, ( - "valid[%d]: output script mismatch at k=%d" % (vi, k) - ) + assert script == expected, "valid[%d]: output script mismatch at k=%d" % (vi, k) From 0c46510284e0aa91cc867beb495913de26b47da0 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Thu, 16 Jul 2026 09:58:47 -0400 Subject: [PATCH 22/41] feat (SP): hide export finalize txn option for silent payment outputs Discourage broadcasting silent payments directly from the device. The wallet coordinator should be responsible for verifying the PSBT and finalizing for broadcast. - Users can restore the default ColdCard behavior by using the Danger Zone -> SP Final Export setting. - USB API was not modified. --- shared/auth.py | 30 +++++++++--- shared/flow.py | 8 +++ shared/nvstore.py | 1 + testing/test_silentpayments.py | 89 ++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 6 deletions(-) diff --git a/shared/auth.py b/shared/auth.py index fe35bc2f9..63feb6045 100644 --- a/shared/auth.py +++ b/shared/auth.py @@ -51,6 +51,10 @@ def psram_wipe(offset, length): for pos in range(offset, offset+length, 256): PSRAM.write(pos, z) +SP_EXPORT_NOTE = '''\ +Silent Payment output detected - finalize signed PSBT on wallet coordinator to broadcast. +Direct broadcast requires opt-in via Danger Zone > SP Final Export.''' + class UserAuthorizedAction: active_request = None @@ -879,6 +883,7 @@ async def done_signing(psbt, tx_req, input_method=None, filename=None, # User authorized PSBT for signing, and we added signatures. # - allow PushTX if enabled (first thing) # - can save final TXN out to SD card/VirtDisk, share by NFC, QR. + # - silent payments should discourage save final txn by default from glob import PSRAM, hsm_active from sffile import SFFile @@ -890,9 +895,15 @@ async def done_signing(psbt, tx_req, input_method=None, filename=None, base_title = "PSBT " + ("Signed" if psbt.sig_added else "Updated") is_complete = psbt.is_complete() + sp_export_hint = None if finalize is not None: # USB case - user can choose whether to attempt finalization is_complete = finalize + elif is_complete and psbt.has_silent_payment_outputs(): + from glob import settings + if not settings.get('spfin', False): + is_complete = False + sp_export_hint = SP_EXPORT_NOTE if psbt.por322: # network txn strips PSBT BIP-32 with paths with pubkey required for verification @@ -906,7 +917,10 @@ async def done_signing(psbt, tx_req, input_method=None, filename=None, noun = "Finalized TX ready for broadcast" else: psbt.serialize(psram) - noun = "Signed BIP-322 PSBT" if psbt.por322 else "Partly Signed PSBT" + # not finalizing: either genuinely partial (needs more sigs) or an SP tx we + # kept as PSBT on purpose - only the latter (sp_export_hint) is fully signed. + noun = ("Signed BIP-322 PSBT" if psbt.por322 else + "Signed PSBT" if sp_export_hint else "Partly Signed PSBT") txid = None data_len = psram.tell() @@ -1025,13 +1039,14 @@ async def done_signing(psbt, tx_req, input_method=None, filename=None, # typical case: save to SD card, show filenames we used assert isinstance(ch, dict) msg = await _save_to_disk(psbt, txid, ch, is_complete, data_len, - output_encoder, filename) + output_encoder, filename, sp_export_hint) input_method = None first_time = False title = base_title -async def _save_to_disk(psbt, txid, save_options, is_complete, data_len, output_encoder, filename=None): +async def _save_to_disk(psbt, txid, save_options, is_complete, data_len, output_encoder, + filename=None, sp_note=None): # Saving a PSBT from PSRAM to something disk-like. # - handle save-to-SD/VirtDisk cases. With re-attempt when no card, etc. assert isinstance(save_options, dict) # from import_export_prompt @@ -1051,10 +1066,10 @@ async def _save_to_disk(psbt, txid, save_options, is_complete, data_len, output_ if match: prefix = base[:-len(match.group(0))] - suffix = '-signed' if is_complete else '-part-%d' % (int(match.group(1)) + 1) + suffix = '-signed' if (is_complete or sp_note) else '-part-%d' % (int(match.group(1)) + 1) else: prefix = base if is_complete else base.replace('-part', '') - suffix = '-signed' if is_complete else '-part' + suffix = '-signed' if (is_complete or sp_note) else '-part' target_fname = prefix + suffix + '.psbt' @@ -1151,7 +1166,7 @@ def _chunk_write(file_d, ofs, chunk=4096): # Done, show the filenames we used. if out_fn: msg = "Updated PSBT is:\n\n%s" % out_fn - if out2_fn: + if out2_fn or sp_note: msg += '\n\n' else: # del_after is probably set @@ -1159,6 +1174,9 @@ def _chunk_write(file_d, ofs, chunk=4096): if out2_fn: msg += 'Finalized transaction (ready for broadcast):\n\n%s' % out2_fn + elif sp_note: + # in place of the finalized-txn line: explain why it was not produced + msg += sp_note return msg diff --git a/shared/flow.py b/shared/flow.py index 088953463..5711a821f 100644 --- a/shared/flow.py +++ b/shared/flow.py @@ -357,6 +357,14 @@ async def goto_home(*a): warnings, funds can be stolen by specially crafted PSBT or MitM. Keep blocked unless you intend to sign special transactions.'''), + ToggleMenuItem("SP Final Export", "spfin", ["Default: PSBT", "Allow Final"], + story='''\ +Silent Payment outputs are computed on-device. A coordinator requires a signed \ +PSBT to verify the computation. By default, Silent Payment transactions \ +export as PSBT for the coordinator to finalize. + +Enable only if you intend to broadcast Silent Payment \ +transactions directly from this device.'''), ToggleMenuItem('Testnet Mode', 'chain', ['Bitcoin', 'Testnet4', 'Regtest'], value_map=['BTC', 'XTN', 'XRT'], on_change=change_which_chain, diff --git a/shared/nvstore.py b/shared/nvstore.py index 2c543bcd0..a2dcc7fbc 100644 --- a/shared/nvstore.py +++ b/shared/nvstore.py @@ -70,6 +70,7 @@ # sssp = (complex) If present, a (single signer) spending-policy is defined (maybe disabled) # lfr = (string) If present, the reason why Spending Policy blocked last transaction # wifs = (list) List of tuples (public/private key) +# spfin = (bool) allow finalized/broadcast export of Silent Payment txns (default: PSBT only) # Stored w/ key=00 for access before login # _skip_pin = hard code a PIN value (dangerous, only for debug) diff --git a/testing/test_silentpayments.py b/testing/test_silentpayments.py index 8308810a0..176128eb1 100644 --- a/testing/test_silentpayments.py +++ b/testing/test_silentpayments.py @@ -1063,3 +1063,92 @@ def sp_hacker(psbt): time.sleep(SIMULATOR_DELAY) with pytest.raises(CCProtoError, match="SP change output keys do not match this device"): end_sign(accept=True, finalize=False) + + +# --------------------------------------------------------------------------- +# Finalized/broadcast export policy for SP-output transactions +# --------------------------------------------------------------------------- + + +def _one_sp_output_psbt(dev, fake_txn): + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + return fake_txn(1, 1, dev.master_xpub, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + + +def _sp_sign_microsd(open_microsd, microsd_path, goto_home, pick_menu_item, + cap_story, need_keypress, psbt_bytes): + # Sign an SP-output PSBT via the air-gapped microSD flow (finalize=None path), + # approve, and let the first-pass auto-echo save to SD. Returns the save-summary + # story and the files that ended up on the card. + import os + from glob import glob as _glob + + name = 'sptest' + for f in _glob(microsd_path(name + '*')): + os.remove(f) + with open_microsd(name + '.psbt', 'wb') as sd: + sd.write(psbt_bytes) + + goto_home() + pick_menu_item('Ready To Sign') + time.sleep(0.1) + title, story = cap_story() + if 'OK TO SEND' not in title: + pick_menu_item(name + '.psbt') + time.sleep(0.1) + title, story = cap_story() + assert title == 'OK TO SEND?' + need_keypress('y') + + time.sleep(0.1) + title, story = cap_story() + assert 'Updated PSBT' in story + + txn = _glob(microsd_path(name + '*-final.txn')) + signed = _glob(microsd_path(name + '*-signed.psbt')) + part = _glob(microsd_path(name + '*-part.psbt')) + return story, txn, (signed or part) + + +def test_sp_export_defaults_to_psbt(dev, fake_txn, settings_remove, open_microsd, + microsd_path, goto_home, pick_menu_item, cap_story, need_keypress): + # Default (spfin unset): SP-output tx exports the signed PSBT, no broadcast tx, + # and the policy note replaces the finalized-transaction line. + settings_remove('spfin') + psbt_bytes = _one_sp_output_psbt(dev, fake_txn) + + story, txn, psbt_out = _sp_sign_microsd(open_microsd, microsd_path, goto_home, + pick_menu_item, cap_story, need_keypress, psbt_bytes) + + assert not txn, "no finalized broadcast tx by default" + assert psbt_out and 'signed.psbt' in psbt_out[0] + assert 'Finalized transaction' not in story + assert 'SP Final Export' in story, "policy note should be shown" + + tp = BasicPSBT().parse(open(psbt_out[0], 'rb').read()) + assert any(o.sp_v0_info for o in tp.outputs), "PSBT retains SP metadata for verification" + + +def test_sp_export_final_allowed(dev, fake_txn, settings_set, settings_remove, open_microsd, + microsd_path, goto_home, pick_menu_item, cap_story, need_keypress): + # With the opt-in setting, the current finalized-export behavior is restored. + settings_set('spfin', 1) + try: + psbt_bytes = _one_sp_output_psbt(dev, fake_txn) + story, txn, _ = _sp_sign_microsd(open_microsd, microsd_path, goto_home, + pick_menu_item, cap_story, need_keypress, psbt_bytes) + assert txn, "finalized broadcast tx written when allowed" + assert 'Finalized transaction' in story + assert 'SP Final Export' not in story + finally: + settings_remove('spfin') + + +def test_sp_export_usb_finalize_unchanged(dev, fake_txn, start_sign, end_sign, settings_remove): + # USB STXN_FINALIZE is honored despite SP outputs and spfin unset (USB path untouched). + settings_remove('spfin') + psbt_bytes = _one_sp_output_psbt(dev, fake_txn) + start_sign(psbt_bytes, finalize=True) + time.sleep(SIMULATOR_DELAY) + end_sign(accept=True, finalize=True) # asserts a non-PSBT finalized tx is returned From 5d996ef3d5b3009faab62bd08e1a27616641e7bb Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Mon, 3 Aug 2026 16:42:44 -0400 Subject: [PATCH 23/41] fix (SP): add dleq.py and silentpayments.py to manifest If shared files are not included in manifest bundling fails and will brick the device before PIN entry. --- shared/manifest.py | 2 ++ stm32/COLDCARD_MK4/mpconfigboard.mk | 1 + stm32/COLDCARD_Q1/mpconfigboard.mk | 1 + unix/variant/mpconfigvariant.mk | 1 + 4 files changed, 5 insertions(+) diff --git a/shared/manifest.py b/shared/manifest.py index 76cd5828d..00449910e 100644 --- a/shared/manifest.py +++ b/shared/manifest.py @@ -16,6 +16,7 @@ 'countdowns.py', 'descriptor.py', 'desc_utils.py', + 'dleq.py', 'drv_entro.py', 'exceptions.py', 'export.py', @@ -51,6 +52,7 @@ 'selftest.py', 'serializations.py', 'sffile.py', + 'silentpayments.py', 'stash.py', 'tapsigner.py', 'trick_pins.py', diff --git a/stm32/COLDCARD_MK4/mpconfigboard.mk b/stm32/COLDCARD_MK4/mpconfigboard.mk index fcbc0fc33..166434266 100644 --- a/stm32/COLDCARD_MK4/mpconfigboard.mk +++ b/stm32/COLDCARD_MK4/mpconfigboard.mk @@ -23,6 +23,7 @@ NGU_NEEDS_CIFRA = 1 # Include libngu secp256k1 features required by Edge NGU_INCL_SCHNORR = 1 NGU_INCL_MUSIG = 1 +NGU_INCL_SILENTPAYMENTS = 1 USER_C_MODULES = boards/$(BOARD)/c-modules # the bulk of the COLDCARD-specific code diff --git a/stm32/COLDCARD_Q1/mpconfigboard.mk b/stm32/COLDCARD_Q1/mpconfigboard.mk index 030204f2c..22dafef03 100644 --- a/stm32/COLDCARD_Q1/mpconfigboard.mk +++ b/stm32/COLDCARD_Q1/mpconfigboard.mk @@ -19,6 +19,7 @@ NGU_NEEDS_CIFRA = 1 # Include libngu secp256k1 features required by Edge NGU_INCL_SCHNORR = 1 NGU_INCL_MUSIG = 1 +NGU_INCL_SILENTPAYMENTS = 1 USER_C_MODULES = boards/$(BOARD)/c-modules # the bulk of the COLDCARD-specific code diff --git a/unix/variant/mpconfigvariant.mk b/unix/variant/mpconfigvariant.mk index 4144848e9..0dc9aba75 100644 --- a/unix/variant/mpconfigvariant.mk +++ b/unix/variant/mpconfigvariant.mk @@ -44,6 +44,7 @@ FROZEN_MANIFEST += $(CC_TOP)/unix/variant/manifest.py NGU_NEEDS_CIFRA = 1 NGU_INCL_SCHNORR = 1 NGU_INCL_MUSIG = 1 +NGU_INCL_SILENTPAYMENTS = 1 USER_C_MODULES = $(CC_TOP)/external/c-modules From 11200231c845da132465169a2376411f06529239 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Tue, 15 Sep 2026 12:39:16 -0400 Subject: [PATCH 24/41] fix (SP): preserve explicit sighash and finalize output flags Keep an explicitly supplied sighash type when signing PSBTs with silent payment outputs so later signers can see it. Clear the Inputs and Outputs Modifiable bits when deriving SP output scripts, and reject resolved scripts while either bit remains set. Leave the SIGHASH_SINGLE modifiable bit to the sighash check. Enforce SIGHASH_ALL or SIGHASH_DEFAULT on every input, including foreign inputs without a UTXO, and cover these cases in the signing and unit tests. --- shared/psbt.py | 8 +++++- shared/silentpayments.py | 31 +++++++++++++---------- testing/devtest/unit_silentpayments.py | 34 ++++++++++++++++++++++++++ testing/test_silentpayments.py | 7 +++++- 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/shared/psbt.py b/shared/psbt.py index 7fba9a1f8..98ae9b591 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -3047,7 +3047,8 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): # Silent Payment Processing if self.has_silent_payment_inputs(): self.validate_silent_payment_inputs(sv) - if self.has_silent_payment_outputs(): + has_sp_outputs = self.has_silent_payment_outputs() + if has_sp_outputs: if not self.process_silent_payment_outputs(sv): # Silent Payments: must not sign if output scripts not set for all signers # Defensive re-check - ApproveTransaction::interact should handle this case before reaching signing @@ -3077,6 +3078,7 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): # but in other cases, no more signatures are possible continue + explicit_sighash = inp.sighash is not None inp.handle_none_sighash() if self.por322: assert inp.sighash in [SIGHASH_ALL, SIGHASH_DEFAULT], "POR sighash not ALL/DEFAULT" @@ -3087,6 +3089,10 @@ def _sign_it(self, alternate_secret, my_xfp, musig_session): else: drop_sighash = (inp.sighash == SIGHASH_ALL) + # BIP-375: retain explicit sighash so other signers see the SIGHASH_ALL intent + if has_sp_outputs and explicit_sighash: + drop_sighash = False + schnorrsig = False tr_sh = [] to_sign = [] diff --git a/shared/silentpayments.py b/shared/silentpayments.py index 56491e1cb..d3292109d 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -554,10 +554,11 @@ def _validate_psbt_structure(self): "Input #%d DLEQ proof wrong size (%d bytes, expected 64)" % (i, len(proof)) ) - # TX_MODIFIABLE must be cleared when output scripts are finalized + # BIP-375: Inputs/Outputs Modifiable must be cleared when output scripts are finalized. + # The SIGHASH_SINGLE bit is left to the SIGHASH_ALL check in _validate_input_eligibility. for outp in self.outputs: - if outp.sp_v0_info and outp.script: - if self.txn_modifiable is not None and self.txn_modifiable != 0: + if outp.sp_v0_info and self.resolve_script(outp.script): + if self.txn_modifiable is not None and self.txn_modifiable & 0b11: raise FatalPSBTIssue("TX_MODIFIABLE not cleared but SP output script is set") def _validate_input_eligibility(self): @@ -567,6 +568,17 @@ def _validate_input_eligibility(self): Raises FatalPSBTIssue if any input constraints are violated """ for i, inp in enumerate(self.inputs): + # SIGHASH_ALL required when SP outputs present + # Checked for every input, including foreign ones without a UTXO + if inp.sighash is not None and inp.sighash not in ( + SIGHASH_ALL, + SIGHASH_DEFAULT, + ): + raise FatalPSBTIssue( + "BIP-375 violation: Input #%d uses sighash 0x%x. " + "Silent payments require SIGHASH_ALL." % (i, inp.sighash) + ) + if not inp.utxo_spk: continue @@ -579,16 +591,6 @@ def _validate_input_eligibility(self): "Silent payment outputs cannot be mixed with Segwit v>1 inputs." % (i, witness_version) ) - # SIGHASH_ALL required when SP outputs present - if inp.sighash is not None and inp.sighash not in ( - SIGHASH_ALL, - SIGHASH_DEFAULT, - ): - raise FatalPSBTIssue( - "BIP-375 violation: Input #%d uses sighash 0x%x. " - "Silent payments require SIGHASH_ALL." % (i, inp.sighash) - ) - def _validate_ecdh_coverage(self): """ Validate ECDH share coverage and DLEQ proof correctness (BIP-375) @@ -749,6 +751,9 @@ def _compute_silent_payment_output_scripts(self): outp.script = computed scan_key_k[scan_key] = k + 1 + # Clear TX_MODIFIABLE when output scripts are finalized + if self.txn_modifiable is not None and self.txn_modifiable != 0: + self.txn_modifiable &= ~0b11 def _store_proof_entry(self, sk, scan_key, shares, proofs): """ diff --git a/testing/devtest/unit_silentpayments.py b/testing/devtest/unit_silentpayments.py index 01eb9eb5f..8835fb112 100644 --- a/testing/devtest/unit_silentpayments.py +++ b/testing/devtest/unit_silentpayments.py @@ -245,6 +245,7 @@ def __init__(self): self.my_xfp = MY_XFP self.sp_global_ecdh_shares = {} self.sp_global_dleq_proofs = {} + self.txn_modifiable = None def get(self, x): return x @@ -540,6 +541,39 @@ def _make_sp_output(scan_key): assert reg1.script is None assert reg3.script is None +# --------------------------------------------------------------------------- +# Mixin: TX_MODIFIABLE and sighash +# --------------------------------------------------------------------------- + +# Resolved SP output: Inputs/Outputs Modifiable must be cleared +psbt = MockPSBT() +outp = _make_sp_output(TEST_SCAN_KEY) +outp.script = b"\x51\x20" + b"\xcd" * 32 +psbt.outputs = [outp] +for flags in (0b01, 0b10, 0b111): + psbt.txn_modifiable = flags + try: + psbt._validate_psbt_structure() + assert False, "Should raise for TX_MODIFIABLE 0x%x" % flags + except FatalPSBTIssue as e: + assert "TX_MODIFIABLE not cleared" in str(e) + +# SIGHASH_SINGLE bit alone is left to the SIGHASH_ALL check +psbt.txn_modifiable = 0b100 +psbt._validate_psbt_structure() + +# SIGHASH_ALL enforced on every input, including a foreign input without a UTXO +inp = MockInput() +psbt.inputs = [inp] +inp.sighash = 1 # SIGHASH_ALL +psbt._validate_input_eligibility() +inp.sighash = 3 # SIGHASH_SINGLE +try: + psbt._validate_input_eligibility() + assert False, "Should raise for SIGHASH_SINGLE" +except FatalPSBTIssue as e: + assert "require SIGHASH_ALL" in str(e) + # --------------------------------------------------------------------------- # Mixin: Simple Methods # --------------------------------------------------------------------------- diff --git a/testing/test_silentpayments.py b/testing/test_silentpayments.py index 176128eb1..c48854961 100644 --- a/testing/test_silentpayments.py +++ b/testing/test_silentpayments.py @@ -459,11 +459,14 @@ def sp_hacker(psbt): # merge with another signer's earlier copy of the same field) # --------------------------------------------------------------------------- +SIGHASH_ALL = 1 + + def _sign_partial_then_act_as_other_signer(dev, fake_txn, start_sign, end_sign, sim_exec, sim_execfile, tamper_input0_before_first_sign=None): """Shared setup: Coldcard signs input 0 first (coverage incomplete), then test code plays the role of the second signer on input 1, computes the SP output - script, and clears TX_MODIFIABLE. + script, clears TX_MODIFIABLE, and sets SIGHASH_ALL on input 0. Returns (tp, orig_share, orig_proof) where tp is the PSBT ready for Coldcard's second signing pass, and orig_share/orig_proof are Coldcard's first-pass values @@ -515,6 +518,7 @@ def sp_hacker(psbt): ) tp.txn_modifiable = 0 + tp.inputs[0].sighash = SIGHASH_ALL return tp, orig_share, orig_proof @@ -548,6 +552,7 @@ def test_sp_multi_signer_resign_preserves_contribution(dev, fake_txn, start_sign assert sp_outs[0].script == output_script, "output script must not change on re-sign" assert rp.inputs[0].part_sigs, "input 0 must be signed" + assert rp.inputs[0].sighash == SIGHASH_ALL, "explicit SIGHASH_ALL must be retained" assert not rp.sp_global_ecdh_shares, "multi-signer path must never populate global shares" assert not rp.sp_global_dleq_proofs From 0af4357ce553532b7d5737b8b86380079d28ace8 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Fri, 25 Sep 2026 15:14:07 -0400 Subject: [PATCH 25/41] fix (SP): only trust a NUMS internal key claim that matches the prevout _is_input_eligible treated any P2TR input with PSBT_IN_TAP_INTERNAL_KEY set to NUMS H as ineligible. A PSBT could make that claim for a key-path spendable input to drop it from ECDH coverage, so the signer would compute an output script the recipient cannot find. Only treat the input as ineligible when H tweaked by PSBT_IN_TAP_MERKLE_ROOT reproduces the prevout output key. The bip375 v1.1.1 'P2TR input with NUMS internal key cannot derive sp output' vector uses the raw H as its prevout output key, which no internal key of H can produce under BIP-341, so it now fails with a DLEQ error instead. The updated vectors build a real NUMS script-path output and add a vector for a false claim. --- shared/silentpayments.py | 8 +++++++- testing/devtest/unit_silentpayments.py | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/shared/silentpayments.py b/shared/silentpayments.py index d3292109d..f43d40bd9 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -444,7 +444,13 @@ def _is_input_eligible(self, input): if input.taproot_internal_key: tap_ik = self.get(input.taproot_internal_key) if tap_ik == NUMS_H: - return False + # Only trust the NUMS claim if it reproduces the prevout output key, + # otherwise an eligible key-path input could be excluded from ECDH + # TODO: derive the merkle root from PSBT_IN_TAP_LEAF_SCRIPT control blocks when + # PSBT_IN_TAP_MERKLE_ROOT is absent; until then such a NUMS input fails closed + mr =self.get(input.taproot_merkle_root) if input.taproot_merkle_root else None + if chains.taptweak(NUMS_H, mr) == spk[2:34]: + return False if _is_p2sh(spk): if input.redeem_script: diff --git a/testing/devtest/unit_silentpayments.py b/testing/devtest/unit_silentpayments.py index 8835fb112..32d487749 100644 --- a/testing/devtest/unit_silentpayments.py +++ b/testing/devtest/unit_silentpayments.py @@ -8,6 +8,7 @@ from ubinascii import unhexlify as a2b_hex from uhashlib import sha256 +from chains import taptweak from dleq import generate_dleq_proof, verify_dleq_proof from exceptions import FatalPSBTIssue from silentpayments import ( @@ -219,6 +220,7 @@ def __init__(self): self.prevout_idx = None self.witness_utxo = None self.taproot_internal_key = None + self.taproot_merkle_root = None self.sp_tweak = None self.sp_spend_bip32_derivation = None self.utxo_spk = None @@ -626,6 +628,16 @@ def _make_sp_output(scan_key): # P2TR with NUMS output key is still valid P2TR shape (ineligibility is checked separately) assert _is_p2tr(b"\x51\x20" + NUMS_H) is True +# NUMS internal key claim only makes a P2TR input ineligible when it reproduces the prevout +psbt = MockPSBT() +inp = MockInput() +inp.taproot_internal_key = NUMS_H +inp.taproot_merkle_root = b"\x42" * 32 +inp.utxo_spk = b"\x51\x20" + taptweak(NUMS_H, inp.taproot_merkle_root) +assert psbt._is_input_eligible(inp) is False +inp.utxo_spk = b"\x51\x20" + taptweak(NUMS_H) # claimed merkle root does not match +assert psbt._is_input_eligible(inp) is True + # --------------------------------------------------------------------------- # _combine_pubkeys edge cases # --------------------------------------------------------------------------- From 5d199c6ed204a8d0b1965573f91740a9f6c10dbe Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 30 Sep 2026 17:20:35 -0400 Subject: [PATCH 26/41] fix (SP): select the input pubkey that matches the prevout script _pubkey_from_input took the first 33 byte BIP32_DERIVATION key, so a decoy derivation ahead of the matching key made valid PSBTs fail DLEQ verification, and a pubkey that does not match the prevout script was accepted and fed into the summed key and output script derivation. - Pick the derivation whose hash160 matches the P2PKH, P2WPKH or P2SH-P2WPKH program; return None if none does - Reject an eligible input whose derivations do not include the prevout key - Make the unit mock and the cosigner change test commit their prevout to the derivation pubkey, as a real input does --- shared/silentpayments.py | 30 +++++++++++++++++++++++--- testing/devtest/unit_silentpayments.py | 3 ++- testing/test_bip375_vectors.py | 2 +- testing/test_silentpayments.py | 3 +++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/shared/silentpayments.py b/shared/silentpayments.py index f43d40bd9..75d340185 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -17,7 +17,7 @@ BIP352_SHARED_SECRET_TAG_H, TAP_TWEAK_H, ) -from serializations import SIGHASH_ALL, SIGHASH_DEFAULT +from serializations import SIGHASH_ALL, SIGHASH_DEFAULT, hash160 from ubinascii import unhexlify as a2b_hex from utils import keypath_to_str @@ -461,13 +461,32 @@ def _is_input_eligible(self, input): return False return True + def _committed_key_hash(self, input): + """ + Hash160 of the public key a non-taproot eligible input's prevout commits to + + Returns: + bytes: 20-byte key hash, or None if the script type carries none + """ + spk = input.utxo_spk + if _is_p2wpkh(spk): + return spk[2:22] + if _is_p2pkh(spk): + return spk[3:23] + if _is_p2sh(spk) and input.redeem_script: + rs = self.get(input.redeem_script) + if _is_p2wpkh(rs): + return rs[2:22] + return None + def _pubkey_from_input(self, input): """ Extract the contributing public key from an input Note: P2TR: use PSBT_IN_WITNESS_UTXO to fetch x-only compressed pubkey - non-taproot: use BIP32 derivation pubkey from subpaths + non-taproot: use the BIP32 derivation pubkey that matches the prevout script, + skipping any decoy derivations Returns: bytes: Input public key (33-byte compressed) or None if not found @@ -479,9 +498,10 @@ def _pubkey_from_input(self, input): if spk and _is_p2tr(spk): return b"\x02" + spk[2:34] if input.subpaths: + key_hash = self._committed_key_hash(input) for pk_coords, _ in input.subpaths: pk = self.get(pk_coords) - if len(pk) == 33: + if len(pk) == 33 and hash160(pk) == key_hash: return pk return None @@ -597,6 +617,10 @@ def _validate_input_eligibility(self): "Silent payment outputs cannot be mixed with Segwit v>1 inputs." % (i, witness_version) ) + # A derivation pubkey that does not match the prevout script must not reach the ECDH sum + if inp.subpaths and not _is_p2tr(spk) and self._is_input_eligible(inp) and not self._pubkey_from_input(inp): + raise FatalPSBTIssue("Input #%d: BIP32_DERIVATION pubkey does not match prevout script" % i) + def _validate_ecdh_coverage(self): """ Validate ECDH share coverage and DLEQ proof correctness (BIP-375) diff --git a/testing/devtest/unit_silentpayments.py b/testing/devtest/unit_silentpayments.py index 32d487749..b38b62f98 100644 --- a/testing/devtest/unit_silentpayments.py +++ b/testing/devtest/unit_silentpayments.py @@ -11,6 +11,7 @@ from chains import taptweak from dleq import generate_dleq_proof, verify_dleq_proof from exceptions import FatalPSBTIssue +from serializations import hash160 from silentpayments import ( _compute_ecdh_share, _compute_input_hash, @@ -264,7 +265,7 @@ def _path_to_privkey(self, xfp_path, sv): def _make_eligible_input(pk, deriv, txid, vout_bytes): inp = MockInput() - inp.utxo_spk = P2WPKH_SPK + inp.utxo_spk = b"\x00\x14" + hash160(pk) # the prevout must commit to the derivation pubkey inp.subpaths = [(pk, deriv)] inp.previous_txid = txid inp.prevout_idx = vout_bytes diff --git a/testing/test_bip375_vectors.py b/testing/test_bip375_vectors.py index b1944d978..e53b4fcad 100644 --- a/testing/test_bip375_vectors.py +++ b/testing/test_bip375_vectors.py @@ -119,7 +119,7 @@ def test_valid_ecdh_computation(self, sim_exec, sim_execfile): for inp in vec["supplementary"]["inputs"] if inp["private_key"] and _sim_pubkey_from_input(sim_exec, sim_execfile, p, inp["input_index"]) ] - for expected in vec["supplementary"]["sp_proofs"]: + for expected in vec["supplementary"].get("sp_proofs", []): scan_key = unhexlify(expected["scan_key"]) expected_ecdh = unhexlify(expected["ecdh_share"]) if "input_index" in expected: diff --git a/testing/test_silentpayments.py b/testing/test_silentpayments.py index c48854961..552c8dd78 100644 --- a/testing/test_silentpayments.py +++ b/testing/test_silentpayments.py @@ -15,6 +15,7 @@ from bip32 import BIP32Node from ckcc_protocol.protocol import CCProtoError from constants import simulator_fixed_tprv +from helpers import hash160 from psbt import BasicPSBT from sp_helpers import ( _sim_apply_label_to_spend_key, @@ -1026,6 +1027,8 @@ def sp_hacker(psbt): # The firmware will fail to derive a privkey for this XFP → all_sp_inputs_ours=False. psbt.inputs[0].bip32_paths = {} psbt.inputs[0].bip32_paths[foreign_pub] = foreign_xfp + struct.pack(' Date: Fri, 25 Sep 2026 15:14:45 -0400 Subject: [PATCH 27/41] test (SP): update BIP-375 test vectors to v1.3.1 Import bip375-test-generator v1.3.1 vectors, including NUMS prevout claims, derivation mismatch cases, decoy-first derivations, and Signer workflow steps. Map the new invalid vectors to simulator errors and account for the valid bare OP_2 vector with no SP proofs. --- testing/bip375_test_vectors.json | 1769 +++++++++++++++++++++++------- testing/test_bip375_vectors.py | 9 +- 2 files changed, 1390 insertions(+), 388 deletions(-) diff --git a/testing/bip375_test_vectors.json b/testing/bip375_test_vectors.json index 922eeebe1..8a58e3553 100644 --- a/testing/bip375_test_vectors.json +++ b/testing/bip375_test_vectors.json @@ -1,77 +1,135 @@ { "description": "BIP-375 Test Vectors", - "version": "1.1.1", + "version": "1.3.1", "notes": [ "Generated by https://github.com/macgyver13/bip375-test-generator/", "Each vector includes: base64-encoded psbt and description", - "Supplementary material (inputs, outputs, sp_proofs) is included for diagnostics and should not be used for validation", + "Supplementary material (hex, inputs, outputs, sp_proofs) is included for diagnostics and should not be used for validation", "'checks' overrides the validation sequence, e.g. skip structure checks to test input eligibility" ], "invalid": [ { "description": "psbt structure: missing PSBT_OUT_SP_V0_INFO field when PSBT_OUT_SP_V0_LABEL set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgImjPUplZ8wrI96VHHKTGdTalHw5bForwPu1HFe3McuABCgQBAAAAAA==", - "supplementary": {} + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDA0MWZ04xLnQHpSq5jI2/aAbRMT5OsRKl39Iml2eMiwwIgfd311m6QKccuNVB0fZJjffaj5C4W9UJpdPi+uF0mIcABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIBe/gYp0DI0Tuy5Y5sq4rrsiY8+rt5QENxNV46aiiaG0AQoEAQAAAAA=", + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100c0d0c599d38c4b9d01e94aae63236fda01b44c4f93ac44a977f489a5d9e322c302207dddf5d66e9029c72e3550747d92637df6a3e42e16f5426974f8beb85d2621c00101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021000103081873010000000000010422512017bf818a740c8d13bb2e58e6cab8aebb2263cfabb79404371355e3a6a289a1b4010a040100000000", + "task": "fail_deserialize" + } }, { "description": "psbt structure: incorrect byte length for PSBT_OUT_SP_V0_INFO field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUECekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84AA=", - "supplementary": {} + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUECekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84AA=", + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010941027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce000", + "task": "fail_deserialize" + } }, { "description": "psbt structure: incorrect byte length for PSBT_IN_SP_ECDH_SHARE field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GggA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QoiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", - "supplementary": {} + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GggA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QoiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682003eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "task": "fail_deserialize" + } }, { "description": "psbt structure: incorrect byte length for PSBT_IN_SP_DLEQ field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4Gg/ihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", - "supplementary": {} + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4Gg/ihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0683f8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3200001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "task": "fail_deserialize" + } }, { "description": "psbt structure: PSBT_GLOBAL_TX_MODIFIABLE field is non-zero when PSBT_OUT_SCRIPT set for sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAQABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", - "supplementary": {} + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEBAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010101fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159" + } + ], + "task": "fail_sign" + } }, { "description": "psbt structure: missing PSBT_OUT_SCRIPT field when sending to non-sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAA=", - "supplementary": {} + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCTDMtMl1wmVr6/9mlBKycpeg3DlJS0y+DuhXpHwOpobgIgNKBkNH18RgAxoQYT8IBMqDwncNq+uFh3IH0rf6qmXv0BAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAAA", + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100930ccb4c975c2656bebff669412b27297a0dc39494b4cbe0ee857a47c0ea686e022034a064347d7c460031a10613f0804ca83c2770dabeb85877207d2b7faaa65efd0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308187301000000000000", + "task": "fail_deserialize" + } + }, + { + "description": "psbt structure: incorrect byte length for PSBT_OUT_SP_V0_LABEL field", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCPK7BV068xhdltYVI7x1UGydVRKIUnGQwguF9HPd5W8gIgZ0ErvfZD1lcvsUUFisMo7xFFAZvsjC9aImux76km008BAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g1EDnWvzdUxpZHjer0m5K8r8Pb/LhkYMCNWHo/FcTj0oBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRILLXUKYOxNBb0sIicfCP4hsA4nEdOCMEi7lloivEFz0vAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA+qPIovitxbaze/LKBAHKHTwCkdvXAe9BRkXEmzGSz3vAQoBAQAiAgNelfRXHtom4PY2PqXFlHlK1N0hXqEmYvE8mpkG1aqTrgwAAAAAAAAAAAAAAAEBAwhw8wUAAAAAAAEEFgAU10OzS4cowqNfapTI2vQRh0WtlpsA", + "supplementary": { + "hex": "70736274ff0102040200000001040101010501020106010001fb04020000000001011f20a10700000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4830450221008f2bb055d3af3185d96d61523bc75506c9d551288527190c20b85f473dde56f2022067412bbdf643d6572fb145058ac328ef1145019bec8c2f5a226bb1efa926d34f0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20d440e75afcdd531a591e37abd26e4af2bf0f6ff2e19183023561e8fc57138f4a010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308a0860100000000000104225120b2d750a60ec4d05bd2c22271f08fe21b00e2711d3823048bb965a22bc4173d2f010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803ea8f228be2b716dacdefcb2810072874f00a476f5c07bd051917126cc64b3def010a0101002202035e95f4571eda26e0f6363ea5c594794ad4dd215ea12662f13c9a9906d5aa93ae0c00000000000000000000000101030870f30500000000000104160014d743b34b8728c2a35f6a94c8daf4118745ad969b00", + "task": "fail_deserialize" + } }, { "description": "ecdh coverage: only one ineligible P2SH multisig input when PSBT_OUT_SCRIPT set for sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiDNOBpFUI/j2cq2O34PcEoPVp2/1VqYEC2eozruYht19AEPBAAAAAABAFMCAAAAAXyoMfPUiQn+aMsOqqoR+Hc97n6McwhTN1kOJLsGOQ20AAAAAAD/////AaCGAQAAAAAAF6kU2OZohxTu7Qqi7dSJqhyjwXFwHk2HAAAAAAEER1IhAr5Ar99ismPLfe4rmF0cOP5BsZlNKwUHU0PRcsIY6rHEIQJ6R5JT0AogWhCpQ483IBm582TgqDaAC/g529KOfOa5VVKuARAE/v///wABAwiQXwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFMCAAAAAXyoMfPUiQn+aMsOqqoR+Hc97n6McwhTN1kOJLsGOQ20AAAAAAD/////AaCGAQAAAAAAF6kU2OZohxTu7Qqi7dSJqhyjwXFwHk2HAAAAAAEER1IhAr5Ar99ismPLfe4rmF0cOP5BsZlNKwUHU0PRcsIY6rHEIQJ6R5JT0AogWhCpQ483IBm582TgqDaAC/g529KOfOa5VVKuAQ4gzTgaRVCP49nKtjt+D3BKD1adv9VamBAtnqM67mIbdfQBDwQAAAAAARAE/v///wABAwiQXwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001005302000000017ca831f3d48909fe68cb0eaaaa11f8773dee7e8c73085337590e24bb06390db40000000000ffffffff01a08601000000000017a914d8e6688714eeed0aa2edd489aa1ca3c171701e4d8700000000010447522102be40afdf62b263cb7dee2b985d1c38fe41b1994d2b05075343d172c218eab1c421027a479253d00a205a10a9438f372019b9f364e0a836800bf839dbd28e7ce6b95552ae010e20cd381a45508fe3d9cab63b7e0f704a0f569dbfd55a98102d9ea33aee621b75f4010f0400000000011004feffffff00010308905f0100000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "", "public_key": "", - "prevout_txid": "cd381a45508fe3d9cab63b7e0f704a0f569dbfd55a98102d9ea33aee621b75f4", + "prevout_txid": "f4751b62ee3aa39e2d10985ad5bf9d560f4a700f7e3bb6cad9e38f50451a38cd", "prevout_index": 0, - "prevout_scriptpubkey": "a914d8e6688714eeed0aa2edd489aa1ca3c171701e4d87", "amount": 100000, "non_witness_utxo": "02000000017ca831f3d48909fe68cb0eaaaa11f8773dee7e8c73085337590e24bb06390db40000000000ffffffff01a08601000000000017a914d8e6688714eeed0aa2edd489aa1ca3c171701e4d8700000000", "sequence": 4294967294, "signed": false } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: missing PSBT_IN_SP_ECDH_SHARE field for input 0 when PSBT_OUT_SCRIPT set for sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBHxAnAAAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0BAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////AAEBHxAnAAAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABDiCT02M2J+tY6dwwP275yxvoDBZhNzq+im1o30frVfCaGwEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff0001011f10270000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a0103040100000022060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000010e2093d3633627eb58e9dc303f6ef9cb1be80c1661373abe8a6d68df47eb55f09a1b010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba60001030818730100000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false }, @@ -79,11 +137,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "1b9af055eb47df686d8abe3a3761160ce81bcbf96e3f30dce958eb273663d393", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 10000, - "witness_utxo": "10270000000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff0110270000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "10270000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": false } @@ -95,23 +153,25 @@ "dleq_proof": "f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6", "input_index": 1 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: missing PSBT_IN_SP_DLEQ field for input when PSBT_IN_SP_ECDH_SHARE set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b0001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -123,23 +183,25 @@ "dleq_proof": null, "input_index": 0 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: missing PSBT_GLOBAL_SP_DLEQ field when PSBT_GLOBAL_SP_ECDH_SHARE set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWwABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff010204020000000104010101050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b01fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e01220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff0001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -149,23 +211,25 @@ "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b" } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: invalid proof in PSBT_IN_SP_DLEQ field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAbvHreDwFl9ZoVl4787j95b7SgVKV9D4XAVEk1EXcy9rdKkne51lhePEhbl1NuRdP/dpjNON8kDEQjAjOE3TeDwABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAbvHreDwFl9ZoVl4787j95b7SgVKV9D4XAVEk1EXcy9rdKkne51lhePEhbl1NuRdP/dpjNON8kDEQjAjOE3TeDwABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068406ef1eb783c0597d668565e3bf3b8fde5bed2815295f43e17015124d445dccbdadd2a49dee7596178f1216e5d4db9174ffdda6334e37c9031108c08ce1374de0f0001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -177,23 +241,25 @@ "dleq_proof": "6ef1eb783c0597d668565e3bf3b8fde5bed2815295f43e17015124d445dccbdadd2a49dee7596178f1216e5d4db9174ffdda6334e37c9031108c08ce1374de0f", "input_index": 0 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: invalid proof in PSBT_GLOBAL_SP_DLEQ field", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQOfI/UQrlNiKKmoskrQ0ZI+gB8n+CARyozeA0LUjKETQm9iLP+6G0S1DhsRlf7t4Xi0vFL/PkYV0P+EqyCUPldkAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAJB3pqpkrBSuehqk/mjAKs4gbJ6scjSQYa52A5ALkibgIgbxQypXj44zCvC5ACVnRryfTlKqLozHkCncjnajwpSwYBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA58j9RCuU2IoqaiyStDRkj6AHyf4IBHKjN4DQtSMoRNCb2Is/7obRLUOGxGV/u3heLS8Uv8+RhXQ/4SrIJQ+V2QH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiBvYUyrFsgMJqaWcuL4qucLwIi1IC6p3v9qznjNp/ticgIgEFWHj/1ZZ1Bg62CgC/ozTJyyQfuhKEwRJJDRANnsfC4BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff010204020000000104010101050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b2208027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840e7c8fd442b94d88a2a6a2c92b434648fa007c9fe080472a33780d0b5232844d09bd88b3fee86d12d4386c4657fbb785e2d2f14bfcf9185743fe12ac8250f95d901fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e01220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff0001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -204,25 +270,69 @@ "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", "dleq_proof": "2430479d2da1310a024d2aab8e4c7b49d76cd51f45ee8127c159b0393a675b6f75c581ebe3d0817ddaf3bb598cfd7a022f1a87ed479664f6b947a47db5941cb2" } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: missing PSBT_IN_BIP32_DERIVATION field for input when PSBT_IN_SP_DLEQ set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAkHemqmSsFK56GqT+aMAqziBsnqxyNJBhrnYDkAuSJuAiBvFDKlePjjMK8LkAJWdGvJ9OUqoujMeQKdyOdqPClLBgEBAwQBAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAAAEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": false + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "task": "fail_sign" + } + }, + { + "description": "ecdh coverage: P2TR input with NUMS internal key claim not matching prevout missing ECDH share", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIAQP555Em+hjM5d56gUd0fxeXJSOfwE/DZ0FbUrp9fwSAiBrB60FrDGbSTgwJplbvoqCRDG2HefJzrfbsFfJiiC6AgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABASughgEAAAAAACJRIHLEmErsS65L2Z+1y2N/3wve4uoYRI7Ujt2bdAdXl6YdAQ4grwOsOauGq8T2eHpf40SY+UqBhFFDS837fY8CqgRabKcBDwQAAAAAARAE/v///wEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARggm8GHmFvK4bSi5pfd8JB+lR6bivNWZXMueZHkf+InJkUAAQMIuPkCAAAAAAABBCJRIAKsXITa4/9Ix30hgMWvlIWeTU6GMOiCav/3I1MzLJa6AQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4730440220040fe79e449be863339779ea051dd1fc5e5c948e7f013f0d9d056d4ae9f5fc1202206b07ad05ac319b49383026995bbe8a824431b61de7c9ceb7dbb057c98a20ba020101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001012ba08601000000000022512072c4984aec4bae4bd99fb5cb637fdf0bdee2ea18448ed48edd9b74075797a61d010e20af03ac39ab86abc4f6787a5fe34498f94a818451434bcdfb7d8f02aa045a6ca7010f0400000000011004feffffff01172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac00118209bc187985bcae1b4a2e697ddf0907e951e9b8af35665732e7991e47fe227264500010308b8f9020000000000010422512002ac5c84dae3ff48c77d2180c5af94859e4d4e8630e8826afff72353332c96ba010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true + }, + { + "input_index": 1, + "private_key": "0f31b97d707a7f76eb099f41f372dbe12f2ef7a685ced8b6309eefc4e7b60afc", + "public_key": "0272c4984aec4bae4bd99fb5cb637fdf0bdee2ea18448ed48edd9b74075797a61d", + "prevout_txid": "a76c5a04aa028f7dfbcd4b435184814af99844e35f7a78f6c4ab86ab39ac03af", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "02000000012b9037ff41dd174e5522f0f4045c3f40436232af2600d4da5c9ea13cc3cab4b50000000000ffffffff01a08601000000000022512072c4984aec4bae4bd99fb5cb637fdf0bdee2ea18448ed48edd9b74075797a61d00000000", + "witness_utxo": "a08601000000000022512072c4984aec4bae4bd99fb5cb637fdf0bdee2ea18448ed48edd9b74075797a61d", + "sequence": 4294967294, + "signed": false } ], "sp_proofs": [ @@ -232,23 +342,33 @@ "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", "input_index": 0 } - ] + ], + "outputs": [ + { + "output_index": 0, + "amount": 195000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "512002ac5c84dae3ff48c77d2180c5af94859e4d4e8630e8826afff72353332c96ba" + } + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: output 1 missing ECDH share for scan key with one input / three sp outputs (different scan keys)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9ADQMAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwIQLChkR0sISqyB9uMKxe30ZnOTzmBNgI0/SZoJhOi1JJdCIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwQPCxHVHD/ROzjgpsjvwu4Mpxdzr2dLMVHmiSFJJcS1fIFojJ4Hi3UIhabKsoa1d+k6JJfrSWNrGvG2vILnyRElEiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEDCJBfAQAAAAAAAQQiUSDTlxRqgoZbVOsSuepx1oJP6rD5KkgTf3p5OmhZazNnpAEJQgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3gPycOClYyGDtqsBB06HfmgA2wD1x8XS+vu2j5wo1IVFJAABAwgQJwAAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUIDUteMQTkAMq2RgWppf8dA2OuQnPBNcIhSZLBR8jheJewC4MTBh7chX5l8hIWnW0WRtsKEd7laESO5lpItMVSGC/gAAQMIIE4AAAAAAAABBCJRINLSQezkGFFKoY45kuyVPE1K1exwSmk+IQa6IsOwWnqDAQlCArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwAhJoHj8J6uOKjy8/7NfdVvxYbPoCjoqzP3KpD4QKbSJcAA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQMBBgEAAfsEAgAAAAABAR9ADQMAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwIQLChkR0sISqyB9uMKxe30ZnOTzmBNgI0/SZoJhOi1JJdCIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwQPCxHVHD/ROzjgpsjvwu4Mpxdzr2dLMVHmiSFJJcS1fIFojJ4Hi3UIhabKsoa1d+k6JJfrSWNrGvG2vILnyRElEiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEDCJBfAQAAAAAAAQQiUSBg9n1lOOjDNhoPtXryD47AzuIAMtDb3yc6UykBnOW/TgEJQgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3gPycOClYyGDtqsBB06HfmgA2wD1x8XS+vu2j5wo1IVFJAABAwgQJwAAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUIDUteMQTkAMq2RgWppf8dA2OuQnPBNcIhSZLBR8jheJewC4MTBh7chX5l8hIWnW0WRtsKEd7laESO5lpItMVSGC/gAAQMIIE4AAAAAAAABBCJRIM//VLPkWViKpOGXLVboPI42pZ2WjLKZ3vuvBMJDlKnuAQlCArlFYVfpRu8H90tU+gm+Sn6Tjcr7+ye0s3LFc8BZ8SqwAhJoHj8J6uOKjy8/7NfdVvxYbPoCjoqzP3KpD4QKbSJcAA==", "supplementary": { + "hex": "70736274ff0102040200000001040101010501030106010001fb04020000000001011f400d0300000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20fd2df4f58b5abf9b91ff1a1e43e2e3523f50c6aa19d5c22360141ec48c9a8021010f0400000000011004feffffff221d02b9456157e946ef07f74b54fa09be4a7e938dcafbfb27b4b372c573c059f12ab02102c2864474b084aac81f6e30ac5edf4667393ce604d808d3f499a0984e8b524974221d03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de210376892327c4e780aeeed4ce1bc92bb0122b7b7910d96f0ad5148b496f9c3e92fb221e02b9456157e946ef07f74b54fa09be4a7e938dcafbfb27b4b372c573c059f12ab040f0b11d51c3fd13b38e0a6c8efc2ee0ca71773af674b3151e689214925c4b57c81688c9e078b750885a6cab286b577e93a2497eb49636b1af1b6bc82e7c911251221e03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de4098f14ac45af6459ab0c84d47da5364cfb144ff90bdac732f9cabc6db000dcf1a95e3b31f7b70a04298a51b6fd4516c81d716c9954f8af10c3d59809aee2bbd3800010308905f010000000000010422512060f67d6538e8c3361a0fb57af20f8ec0cee20032d0dbdf273a5329019ce5bf4e01094203651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de03f270e0a5632183b6ab01074e877e6800db00f5c7c5d2fafbb68f9c28d48545240001030810270000000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e290109420352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf800010308204e0000000000000104225120cfff54b3e459588aa4e1972d56e83c8e36a59d968cb299defbaf04c24394a9ee01094202b9456157e946ef07f74b54fa09be4a7e938dcafbfb27b4b372c573c059f12ab00212681e3f09eae38a8f2f3fecd7dd56fc586cfa028e8ab33f72a90f840a6d225c00", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "21809a8cc41e146023c2d519aac6503f52e3e2431e1aff919bbf5a8bf5f42dfd", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 200000, - "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01400d0300000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "400d0300000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false } @@ -266,23 +386,25 @@ "dleq_proof": "f0b11d51c3fd13b38e0a6c8efc2ee0ca71773af674b3151e689214925c4b57c81688c9e078b750885a6cab286b577e93a2497eb49636b1af1b6bc82e7c911251", "input_index": 0 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: input 1 missing ECDH share for output 1 with two inputs / two sp outputs (different scan keys)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0BAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94hAnUEQAf+LQMNV3wymRzyo+deU1BCRbPL5bMFOufF8iBaIh4DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp95AOLnjgGtJvr7vxs7gZcKwZv2wCuzs8ei1sqr0fPBBeyma4KJW7Xy2yCcC63E31zv1eSccQoTQBuO1nXCpuWfYiQABAwiQXwEAAAAAAAEEIlEg9Jwu8ZtnBhG4bd7+iQzvlCaKgq4zHkb+GVHWxuNyPLEBCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRID2h4XbGT7RZU+xG4FA2NLx+jjQ6do2+77sKPojMSkyaAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQIBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIdA2UdLAc/ywKk2C3aU/HVAdd6A1BmZ5hUZHOyEmts0afeIQN2iSMnxOeAru7UzhvJK7ASK3t5ENlvCtUUi0lvnD6S+yIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIiHgNlHSwHP8sCpNgt2lPx1QHXegNQZmeYVGRzshJrbNGn3kCY8UrEWvZFmrDITUfaU2TPsUT/kL2scy+cq8bbAA3PGpXjsx97cKBCmKUbb9RRbIHXFsmVT4rxDD1ZgJruK704AAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABDiDnbAFxCDpMX7Sv4vbWHwCkcwG50B+NLkd4CrdULjd8CAEPBAAAAAABEAT+////Ih0DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94hAnUEQAf+LQMNV3wymRzyo+deU1BCRbPL5bMFOufF8iBaIh4DZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp95AOLnjgGtJvr7vxs7gZcKwZv2wCuzs8ei1sqr0fPBBeyma4KJW7Xy2yCcC63E31zv1eSccQoTQBuO1nXCpuWfYiQABAwiQXwEAAAAAAAEEIlEgUYxvb4GbCpCxtzrI2r6I+6L7jU21kKWeh5y2htZLPwoBCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIJPCrCoXvlxLW2ZvyHz2ESYroSl4aKSY4YV32/tFpEJwAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", "supplementary": { + "hex": "70736274ff0102040200000001040102010501020106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec2103091fd48039177f44d7b79e96168849c62eb3f87800c46767c50a8f38f98efd15221d03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de210376892327c4e780aeeed4ce1bc92bb0122b7b7910d96f0ad5148b496f9c3e92fb221e0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec40be1a723aef55e8981b99599a9bc12b38f87eba0158cc7066890f2269cade463b77341a97d29271964d01c0241cc322fd5390c29b99160f826f329365898cbf02221e03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de4098f14ac45af6459ab0c84d47da5364cfb144ff90bdac732f9cabc6db000dcf1a95e3b31f7b70a04298a51b6fd4516c81d716c9954f8af10c3d59809aee2bbd380001011fa0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a0103040100000022060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000010e20e76c0171083a4c5fb4afe2f6d61f00a47301b9d01f8d2e47780ab7542e377c08010f0400000000011004feffffff221d03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de210275044007fe2d030d577c32991cf2a3e75e53504245b3cbe5b3053ae7c5f2205a221e03651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de4038b9e3806b49bebeefc6cee065c2b066fdb00aececf1e8b5b2aaf47cf0417b299ae0a256ed7cb6c82702eb7137d73bf579271c4284d006e3b59d70a9b967d88900010308905f0100000000000104225120518c6f6f819b0a90b1b73ac8dabe88fba2fb8d4db590a59e879cb686d64b3f0a01094203651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de03f270e0a5632183b6ab01074e877e6800db00f5c7c5d2fafbb68f9c28d485452400010308905f010000000000010422512093c2ac2a17be5c4b5b666fc87cf611262ba1297868a498e18577dbfb45a442700109420352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf800", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false }, @@ -290,11 +412,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "087c372e54b70a78472e8d1fd0b90173a4001fd6f6e2afb45f4c3a0871016ce7", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 100000, - "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": false } @@ -318,23 +440,25 @@ "dleq_proof": "38b9e3806b49bebeefc6cee065c2b066fdb00aececf1e8b5b2aaf47cf0417b299ae0a256ed7cb6c82702eb7137d73bf579271c4284d006e3b59d70a9b967d889", "input_index": 1 } - ] + ], + "task": "fail_sign" } }, { "description": "ecdh coverage: input 1 missing ECDH share for scan key with two inputs / one sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9QwwAAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gvp1lyDkV+wkkirvfyoyj7ubONQxVT2Xo1Sbl31J6tSIBDwQAAAAAAQEfUMMAAAAAAAAWABRGM9WcrRNDR5ly4MmWkh0KXa22XSIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR9QwwAAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g6xHhra18MFGah0Q1Mm7jehlliBwKVcouqa/tQZZIthYBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQEfUMMAAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeaiIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAAQ4g245T4MzJHLEs15uROavlPi9D3Liqq6r37/AsHsiwHCgBDwQAAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgzeOdiwW0lvjxjyCyfQr5oyMzCeBHIhnggT/ztdN4fikBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001011f50c30000000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20eb11e1adad7c30519a874435326ee37a1965881c0a55ca2ea9afed419648b616010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001011f50c30000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a22060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000010e20db8e53e0ccc91cb12cd79b9139abe53e2f43dcb8aaabaaf7eff02c1ec8b01c28010f0400000000011004feffffff0001030818730100000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "16b6489641edafa92eca550a1c8865197ae36e323544879a51307cadade111eb", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 50000, - "witness_utxo": "50c3000000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff0150c30000000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "50c30000000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false }, @@ -342,11 +466,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "281cb0c81e2cf0eff7aaabaab8dc432f3ee5ab39919bd72cb11cc9cce0538edb", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 50000, - "witness_utxo": "50c30000000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff0150c30000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "50c30000000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": false } @@ -358,27 +482,30 @@ "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", "input_index": 0 } - ] + ], + "task": "fail_sign" } }, { "description": "input eligibility: segwit version greater than 1 in transaction inputs with sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABZSFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHLzeIUvuENyYHLyUHbw53Vg7UwuBHFm7mpibHW/2znWAiAhKq5fCVdONB9YhvX/8y9XFuq5AwpKU3nmAWtqTULcJAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABZSFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQD/G0d7SFEcnvURdIK0VbinRBzrmgXCDZ4gwhD+Z4IEJAIgJ32Cr+1Q28AA/sbFs+Rp61l2dsYw+TpBveyIolGGf00BAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g0w9eTlaTsy1vWnieNwu2RHFBjAHb48ufI2BmfBwTOaUBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIPGzmH+N0VjGTWFO/Otm7DX662b5nu+5arlL2tCh6dqAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001652141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100ff1b477b48511c9ef5117482b455b8a7441ceb9a05c20d9e20c210fe678204240220277d82afed50dbc000fec6c5b3e469eb597676c630f93a41bdec88a251867f4d0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20d30f5e4e5693b32d6f5a789e370bb64471418c01dbe3cb9f2360667c1c1339a5010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120f1b3987f8dd158c64d614efceb66ec35faeb66f99eefb96ab94bdad0a1e9da80010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "a539131c7c6660239fcbe3db018c417144b60b379e785a6f2db393564e5e0fd3", "prevout_index": 0, - "prevout_scriptpubkey": "5214229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000165214229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001652141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001652141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } - ] + ], + "task": "fail_sign" }, "checks": [ "input_eligibility" @@ -386,47 +513,50 @@ }, { "description": "input eligibility: non-SIGHASH_ALL signature on input with sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHLzeIUvuENyYHLyUHbw53Vg7UwuBHFm7mpibHW/2znWAiAhKq5fCVdONB9YhvX/8y9XFuq5AwpKU3nmAWtqTULcJAEBAwQCAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCn5fOU3u8TEXv+eTvdTjZkLeUMYSSBzSsy5pItW+GG9gIgKi3cqMSD7vNlhvYOLy5eRW3NQNOGU1HEnjPxXFg0XK4CAQMEAgAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100a7e5f394deef13117bfe793bdd4e36642de50c612481cd2b32e6922d5be186f602202a2ddca8c483eef36586f60e2f2e5e456dcd40d3865351c49e33f15c58345cae0201030402000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } - ] + ], + "task": "fail_sign" } }, { "description": "output scripts: P2TR input with NUMS internal key cannot derive sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAQMEAQAAAAEQBP7///8BFyBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wCIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIHCUAAAAAAAABBCJRICdoyIruoiMiW6OthOeGNS+YKdLT6TeKOToL/1mvh83QAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABASsQJwAAAAAAACJRICG+i0nY1uxr8GEwJe9oKFeYqXr2DtXaB7tet9ZpYewfAQMEAQAAAAEOIH+QX5ugy7b4HNdKHstiYMqtPm+AQQ5JLIv1XAj9zv6iAQ8EAAAAAAEQBP7///9BFNMsopJrMi8UXXbPyLBj7jj06YS1J1xwXHfzaeotwZjXywLWLIhtqqDoD+Oihy6ICzLHNSrQOqcQ70op/TJd8D5BdOvTC5iMb90n5znTaWSj5nvrmsw9N0hd1L9Iy5QYvoe/x32ScF6OyZcN7h1d+TXOTBJBP8nlOygqhfF6r1NwXwEiFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wCMg0yyikmsyLxRdds/IsGPuOPTphLUnXHBcd/Np6i3BmNeswAEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARggywLWLIhtqqDoD+Oihy6ICzLHNSrQOqcQ70op/TJd8D4iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCECbjDxKE9sZsCbdlTvcg3YzT5FQSlRC8an2PA0VXz4haIiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAtIsQmB3MHSlSbLN97CFCvZVEy4chvXZ2NNcfyDarw4O5rsxx2tiOonGJ7oE3poZ6yBpxC3ZiLcQqabgqlFQZYAAEDCBwlAAAAAAAAAQQiUSA7AHWSopMU/w1Qnp3Ta6olUu/AqwawM7/S9iQIV9ABBwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001012b102700000000000022512021be8b49d8d6ec6bf0613025ef68285798a97af60ed5da07bb5eb7d66961ec1f01030401000000010e207f905f9ba0cbb6f81cd74a1ecb6260caad3e6f80410e492c8bf55c08fdcefea2010f0400000000011004feffffff4114d32ca2926b322f145d76cfc8b063ee38f4e984b5275c705c77f369ea2dc198d7cb02d62c886daaa0e80fe3a2872e880b32c7352ad03aa710ef4a29fd325df03e4174ebd30b988c6fdd27e739d36964a3e67beb9acc3d37485dd4bf48cb9418be87bfc77d92705e8ec9970dee1d5df935ce4c12413fc9e53b282a85f17aaf53705f012215c050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac02320d32ca2926b322f145d76cfc8b063ee38f4e984b5275c705c77f369ea2dc198d7acc001172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0011820cb02d62c886daaa0e80fe3a2872e880b32c7352ad03aa710ef4a29fd325df03e221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06821026e30f1284f6c66c09b7654ef720dd8cd3e454129510bc6a7d8f034557cf885a2221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068402d22c4260773074a549b2cdf7b0850af655132e1c86f5d9d8d35c7f20daaf0e0ee6bb31c76b623a89c627ba04de9a19eb2069c42dd988b710a9a6e0aa5150658000103081c2500000000000001042251203b007592a29314ff0d509e9dd36baa2552efc0ab06b033bfd2f6240857d00107010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", - "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "private_key": "9dab08c8eb0a4d9984ba709d580d009608f7b117dd4620eb4209c1d67a6c29d0", + "public_key": "02d32ca2926b322f145d76cfc8b063ee38f4e984b5275c705c77f369ea2dc198d7", + "prevout_txid": "a2fecefd085cf58b2c490e41806f3eadca6062cb1e4ad71cf8b6cba09b5f907f", "prevout_index": 0, - "prevout_scriptpubkey": "512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", "amount": 10000, - "witness_utxo": "102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "non_witness_utxo": "020000000113f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d020000000000ffffffff01102700000000000022512021be8b49d8d6ec6bf0613025ef68285798a97af60ed5da07bb5eb7d66961ec1f00000000", + "witness_utxo": "102700000000000022512021be8b49d8d6ec6bf0613025ef68285798a97af60ed5da07bb5eb7d66961ec1f", "sequence": 4294967294, - "signed": false + "signed": true } ], "sp_proofs": [ { "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", - "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", - "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "ecdh_share": "026e30f1284f6c66c09b7654ef720dd8cd3e454129510bc6a7d8f034557cf885a2", + "dleq_proof": "2d22c4260773074a549b2cdf7b0850af655132e1c86f5d9d8d35c7f20daaf0e0ee6bb31c76b623a89c627ba04de9a19eb2069c42dd988b710a9a6e0aa5150658", "input_index": 0 } ], @@ -435,25 +565,27 @@ "output_index": 0, "amount": 9500, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51202768c88aeea223225ba3ad84e786352f9829d2d3e9378a393a0bff59af87cdd0" + "script": "51203b007592a29314ff0d509e9dd36baa2552efc0ab06b033bfd2f6240857d00107" } - ] + ], + "task": "fail_sign" } }, { "description": "output scripts: PSBT_OUT_SCRIPT does not match derived sp output", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIM3jnYsFtJb48Y8gsn0K+aMjMwngRyIZ4IE/87XTeH4pAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIM3jnYsFtJb48Y8gsn0K+aMjMwngRyIZ4IE/87XTeH4pAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false } @@ -473,23 +605,25 @@ "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", "script": "5120cde39d8b05b496f8f18f20b27d0af9a3233309e0472219e0813ff3b5d3787e29" } - ] + ], + "task": "fail_sign" } }, { "description": "output scripts: two sp outputs (same scan / different spend keys) not sorted lexicographically by spend key", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCID9iBcRocGpGJF8XE6u4uLmjp7/YOsdF98ByDUQxtM38AiBxWKv7gg8r9a1nRfVvwHCcmVzMrP4XCY2KobYfjJ/y/wEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgdUe4Fj1bvFSYQL5MwUaq0JUgc2e565RwbeZwjUCPk/kBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgCi4D5lDNIleEbx2x1q254/iwluzMvIXshHEAXvx9nfYYAAQMIECcAAAAAAAABBCJRIGziw1OV8XDyS20tgNCkDEb0a6S0hD9qsxGpNLMcXYTcAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA6r4Yq7amM+SU5r33DN10dpfsGsSHvCh8DGp9zgv1T27AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIExYL+wZvNCU5oIsqPD7MiK6sIG6J64r3IOIgwa67SNWAiAfxZx06/JBydKQqMxQ8qOYD8DANBNXtltjINXNPOpPBAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgPajcATlIcUBND7sqMXcLxrF+r7rr33jiwy48KFZTJ1kBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgCi4D5lDNIleEbx2x1q254/iwluzMvIXshHEAXvx9nfYYAAQMIECcAAAAAAAABBCJRINcZ2dcurhCyj8MgCzL61dlJboWOixbkdXjXyMFEkzsEAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA6r4Yq7amM+SU5r33DN10dpfsGsSHvCh8DGp9zgv1T27AA==", "supplementary": { + "hex": "70736274ff0102040200000001040101010501020106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402204c582fec19bcd094e6822ca8f0fb3222bab081ba27ae2bdc83888306baed235602201fc59c74ebf241c9d290a8cc50f2a3980fc0c0341357b65b6320d5cd3cea4f040101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308905f01000000000001042251203da8dc01394871404d0fbb2a31770bc6b17eafbaebdf78e2c32e3c2856532759010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068028b80f994334895e11bc76c75ab6e78fe2c25bb332f217b211c4017bf1f677d860001030810270000000000000104225120d719d9d72eae10b28fc3200b32fad5d9496e858e8b16e47578d7c8c144933b04010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803aaf862aeda98cf92539af7dc3375d1da5fb06b121ef0a1f031a9f7382fd53dbb00", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -507,31 +641,33 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068028b80f994334895e11bc76c75ab6e78fe2c25bb332f217b211c4017bf1f677d86", - "script": "51207547b8163d5bbc549840be4cc146aad095207367b9eb94706de6708d408f93f9" + "script": "51203da8dc01394871404d0fbb2a31770bc6b17eafbaebdf78e2c32e3c2856532759" }, { "output_index": 1, "amount": 10000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803aaf862aeda98cf92539af7dc3375d1da5fb06b121ef0a1f031a9f7382fd53dbb", - "script": "51206ce2c35395f170f24b6d2d80d0a40c46f46ba4b4843f6ab311a934b31c5d84dc" + "script": "5120d719d9d72eae10b28fc3200b32fad5d9496e858e8b16e47578d7c8c144933b04" } - ] + ], + "task": "fail_sign" } }, { "description": "output scripts: k values assigned to wrong output indices with three sp outputs (same scan / spend keys)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFg36hg2U7tRrGNQq+bDhHvokGogZdwwSNbSCOp8DkyCAiAQ+0/6sv7Vqmy2KAqTxHnPsE5Gyp7fF6owXNFnSiQsSQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwiQXwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIECcAAAAAAAABBCJRIJcUQsifBHhuCCcorhFu6rgC8/qelf2w03U6aEAgIAbeAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCBAnAAAAAAAAAQQiUSA/y66kkIf44D2d79Ory9bejAMrWD+Fpl0FeIHExEPNwAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQMBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDmsaUAuR12tiR/luLlnUQZ6/oZayCC6yzQGczKmeec6wIgVp/snmnIG0ZomQT4uGSrck/xFnuR58NgeHpzOZqLvNMBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIkF8BAAAAAAABBCJRIGRvSUygu5vOrRS4235MaURWH68jLnzMw2vdWGlfdJFZAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCBAnAAAAAAAAAQQiUSBnO3Y1anIQCkUV5BRRrprC+6ap0dft7SIJEBvVLxrrVwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwgQJwAAAAAAAAEEIlEgpRVl2ozof5Td+ErkDvaYxXSb8mLkE+ryjVDYvYtTJ8UBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff0102040200000001040101010501030106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100e6b1a500b91d76b6247f96e2e59d4419ebfa196b2082eb2cd019ccca99e79ceb0220569fec9e69c81b46689904f8b864ab724ff1167b91e7c360787a73399a8bbcd30101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308905f0100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce0390001030810270000000000000104225120673b76356a72100a4515e41451ae9ac2fba6a9d1d7eded2209101bd52f1aeb57010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce0390001030810270000000000000104225120a51565da8ce87f94ddf84ae40ef698c5749bf262e413eaf28d50d8bd8b5327c5010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -549,41 +685,53 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "5120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159" }, { "output_index": 1, "amount": 10000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + "script": "5120673b76356a72100a4515e41451ae9ac2fba6a9d1d7eded2209101bd52f1aeb57" }, { "output_index": 2, "amount": 10000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + "script": "5120a51565da8ce87f94ddf84ae40ef698c5749bf262e413eaf28d50d8bd8b5327c5" } - ] + ], + "task": "fail_sign" } - } - ], - "valid": [ + }, { - "description": "can finalize: one P2PKH input single-signer", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIDnBDcvHz0XG2UNW/1DBK42GqVUM8DcXPZzr94cU5nx1AiBxlVpC7SBTJDIHI8TwFCXc6J9CX4NwKEy0J2z9tt6jrAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEg4UDSh7RbRs1OqvpDdwYVcLq+g9G4vJUKdKn+oJIz16YBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "description": "input derivation: P2WPKH BIP32_DERIVATION pubkey does not match prevout script", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQEfoIYBAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeagEDBAEAAAAiBgOP2dET3ewN0gEXd2Lkd4xhYmldb10sk0cPUzds3/SWdQgAAACAAQAAAAEOIOdsAXEIOkxftK/i9tYfAKRzAbnQH40uR3gKt1QuN3wIAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDuLp0zF+YxhYSFGAkyZmFfq97oLcJgtDvLwcFAmu71lEiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEBat7GdOafv5+XHkteHj5E99rNK/LstiMM8SSinTIp8a971N0pUKC9lwV6FYLVmZ/MPZfalQ/zv109HhpUR9oolAAEDCLj5AgAAAAAAAQQiUSDK5a4XZIhLnDP78jGCuuHrX/eVKk0kl0sH/v3Vr+f1MQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001011fa0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a010304010000002206038fd9d113ddec0dd201177762e4778c6162695d6f5d2c93470f53376cdff49675080000008001000000010e20e76c0171083a4c5fb4afe2f6d61f00a47301b9d01f8d2e47780ab7542e377c08010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103b8ba74cc5f98c61612146024c999857eaf7ba0b70982d0ef2f0705026bbbd651221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068405ab7b19d39a7efe7e5c792d7878f913df6b34afcbb2d88c33c4928a74c8a7c6bdef5374a54282f65c15e8560b56667f30f65f6a543fcefd74f47869511f68a2500010308b8f90200000000000104225120cae5ae1764884b9c33fbf23182bae1eb5ff7952a4d24974b07fefdd5afe7f531010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "522748eb17764d28ca494815ec8d49e7d30d52bc73422c7c86eb74e397057294", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "76a9141e2ad7872d329413a56df0968be338222783163b88ac", "amount": 100000, - "non_witness_utxo": "0200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, - "signed": true + "signed": false + }, + { + "input_index": 1, + "private_key": "92f9d1f434a6c0fe23770ca8eec0b27163b5635a9d43717a4db48683b797041d", + "public_key": "038fd9d113ddec0dd201177762e4778c6162695d6f5d2c93470f53376cdff49675", + "prevout_txid": "087c372e54b70a78472e8d1fd0b90173a4001fd6f6e2afb45f4c3a0871016ce7", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", + "sequence": 4294967294, + "signed": false } ], "sp_proofs": [ @@ -592,93 +740,109 @@ "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", "input_index": 0 + }, + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03b8ba74cc5f98c61612146024c999857eaf7ba0b70982d0ef2f0705026bbbd651", + "dleq_proof": "5ab7b19d39a7efe7e5c792d7878f913df6b34afcbb2d88c33c4928a74c8a7c6bdef5374a54282f65c15e8560b56667f30f65f6a543fcefd74f47869511f68a25", + "input_index": 1 } ], "outputs": [ { "output_index": 0, - "amount": 95000, + "amount": 195000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6" + "script": "5120cae5ae1764884b9c33fbf23182bae1eb5ff7952a4d24974b07fefdd5afe7f531" } - ] + ], + "task": "fail_sign" } }, { - "description": "can finalize: two inputs single-signer using global ECDH share", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQLTJicjNSYH6E/K92UfjS1jfgIK6obfrYDTBs1PSM/MYiIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQMZTtx+UaBipW9w58JGERbyQOgh2tzgGDp5dsdzsMKvfVOC18XhXP1EZ3nGqY60ZtEnjvLZUY5Nsi67qTZFzkrkAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAXBfzaBiZu2zKxaYZ3s39nu25F1JLr/OZWqIDufxOOtgIgPc3jI53ZBjavZPskEspB45fJWKAwd3z/nIlAucd310wBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgA4mx4K7v1/q2Ce+rAYv7AWrP8hu4EPPEjDi6ckQYDpUCIBUP7GDiVvQMR1dN/RKaCOr3rB2Xq+4x9AaZ+Hk1RhnzASIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAARAE/v///wABAwgYcwEAAAAAAAEEIlEgEz1qT1CQlbV5T3SR+8PxLDxFvC2bYK8luLunBMgHKq8BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "description": "input derivation: P2PKH BIP32_DERIVATION pubkey does not match prevout script", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQBVAgAAAAHPmI7XeVJdVEXLmqFQS10faaA/SyRQoHYDNdRfLoolpAAAAAAA/////wGghgEAAAAAABl2qRQ3IfpzwjBcsviOhIkta9a5dyYeaoisAAAAAAEDBAEAAAAiBgOP2dET3ewN0gEXd2Lkd4xhYmldb10sk0cPUzds3/SWdQgAAACAAQAAAAEOIHZaNDWqtg2RrSQnRFJLMo0gq2YNRT5yddYNi5dXSBHhAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDuLp0zF+YxhYSFGAkyZmFfq97oLcJgtDvLwcFAmu71lEiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEBat7GdOafv5+XHkteHj5E99rNK/LstiMM8SSinTIp8a971N0pUKC9lwV6FYLVmZ/MPZfalQ/zv109HhpUR9oolAAEDCLj5AgAAAAAAAQQiUSDMv9KwHk7y/2bj3db5FzKWCe7rNVYtKwAtYiWC2+JlawEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021000100550200000001cf988ed779525d5445cb9aa1504b5d1f69a03f4b2450a0760335d45f2e8a25a40000000000ffffffff01a0860100000000001976a9143721fa73c2305cb2f88e84892d6bd6b977261e6a88ac00000000010304010000002206038fd9d113ddec0dd201177762e4778c6162695d6f5d2c93470f53376cdff49675080000008001000000010e20765a3435aab60d91ad242744524b328d20ab660d453e7275d60d8b97574811e1010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103b8ba74cc5f98c61612146024c999857eaf7ba0b70982d0ef2f0705026bbbd651221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068405ab7b19d39a7efe7e5c792d7878f913df6b34afcbb2d88c33c4928a74c8a7c6bdef5374a54282f65c15e8560b56667f30f65f6a543fcefd74f47869511f68a2500010308b8f90200000000000104225120ccbfd2b01e4ef2ff66e3ddd6f917329609eeeb35562d2b002d622582dbe2656b010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, - "signed": true + "signed": false }, { "input_index": 1, - "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", - "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "private_key": "92f9d1f434a6c0fe23770ca8eec0b27163b5635a9d43717a4db48683b797041d", + "public_key": "038fd9d113ddec0dd201177762e4778c6162695d6f5d2c93470f53376cdff49675", + "prevout_txid": "e1114857978b0dd675723e450d66ab208d324b52442724ad910db6aa35345a76", "prevout_index": 0, - "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", "amount": 100000, - "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "non_witness_utxo": "0200000001cf988ed779525d5445cb9aa1504b5d1f69a03f4b2450a0760335d45f2e8a25a40000000000ffffffff01a0860100000000001976a9143721fa73c2305cb2f88e84892d6bd6b977261e6a88ac00000000", "sequence": 4294967294, - "signed": true + "signed": false } ], "sp_proofs": [ { "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", - "ecdh_share": "02d3262723352607e84fcaf7651f8d2d637e020aea86dfad80d306cd4f48cfcc62", - "dleq_proof": "c653b71f946818a95bdc39f0918445bc903a0876b738060e9e5db1dcec30abdf54e0b5f178573f5119de71aa63ad19b449e3bcb65463936c8baeea4d917392b9" + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + }, + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03b8ba74cc5f98c61612146024c999857eaf7ba0b70982d0ef2f0705026bbbd651", + "dleq_proof": "5ab7b19d39a7efe7e5c792d7878f913df6b34afcbb2d88c33c4928a74c8a7c6bdef5374a54282f65c15e8560b56667f30f65f6a543fcefd74f47869511f68a25", + "input_index": 1 } ], "outputs": [ { "output_index": 0, - "amount": 95000, + "amount": 195000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120133d6a4f509095b5794f7491fbc3f12c3c45bc2d9b60af25b8bba704c8072aaf" + "script": "5120ccbfd2b01e4ef2ff66e3ddd6f917329609eeeb35562d2b002d622582dbe2656b" } - ] + ], + "task": "fail_sign" } }, { - "description": "can finalize: two inputs single-signer using per-input ECDH shares", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIBcF/NoGJm7bMrFphnezf2e7bkXUkuv85laogO5/E462AiA9zeMjndkGNq9k+yQSykHjl8lYoDB3fP+ciUC5x3fXTAEiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgA4mx4K7v1/q2Ce+rAYv7AWrP8hu4EPPEjDi6ckQYDpUCIBUP7GDiVvQMR1dN/RKaCOr3rB2Xq+4x9AaZ+Hk1RhnzAQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDNNLO907e1EZCJ2B/xZrB3oDBKiQzpWJxUo7cz1D6bCsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEA3wAwLQqBz9rZfDEtuVuBndLOAwd894otkCxIe4LO0z3hQ30VuC12OGXXd/yUmLIOB4g+FLNhwveP2qDKmMlvMAAEDCBhzAQAAAAAAAQQiUSATPWpPUJCVtXlPdJH7w/EsPEW8LZtgryW4u6cEyAcqrwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "description": "input derivation: P2SH-P2WPKH BIP32_DERIVATION pubkey does not match prevout script", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQBTAgAAAAGFNcjf6kodjm3vHXkBFOJcl9LHhBHA5Kb9GADb8enj2QAAAAAA/////wGghgEAAAAAABepFJ5mEl14gLfj9LtmDTzxiIHqE4S5hwAAAAABASCghgEAAAAAABepFJ5mEl14gLfj9LtmDTzxiIHqE4S5hwEDBAEAAAABBBYAFDch+nPCMFyy+I6EiS1r1rl3Jh5qIgYDj9nRE93sDdIBF3di5HeMYWJpXW9dLJNHD1M3bN/0lnUIAAAAgAEAAAABDiAGlw+JzAopeHrPyL+p4esaFkrW2plbeoDFULkWf1wEwQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA7i6dMxfmMYWEhRgJMmZhX6ve6C3CYLQ7y8HBQJru9ZRIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAWrexnTmn7+flx5LXh4+RPfazSvy7LYjDPEkop0yKfGve9TdKVCgvZcFehWC1ZmfzD2X2pUP879dPR4aVEfaKJQABAwi4+QIAAAAAAAEEIlEgBrhGBywjb8Uuiok20iUSu/mvKH/Wm+XA51IaQPewdQ0BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001005302000000018535c8dfea4a1d8e6def1d790114e25c97d2c78411c0e4a6fd1800dbf1e9e3d90000000000ffffffff01a08601000000000017a9149e66125d7880b7e3f4bb660d3cf18881ea1384b98700000000010120a08601000000000017a9149e66125d7880b7e3f4bb660d3cf18881ea1384b9870103040100000001041600143721fa73c2305cb2f88e84892d6bd6b977261e6a2206038fd9d113ddec0dd201177762e4778c6162695d6f5d2c93470f53376cdff49675080000008001000000010e2006970f89cc0a29787acfc8bfa9e1eb1a164ad6da995b7a80c550b9167f5c04c1010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103b8ba74cc5f98c61612146024c999857eaf7ba0b70982d0ef2f0705026bbbd651221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068405ab7b19d39a7efe7e5c792d7878f913df6b34afcbb2d88c33c4928a74c8a7c6bdef5374a54282f65c15e8560b56667f30f65f6a543fcefd74f47869511f68a2500010308b8f9020000000000010422512006b846072c236fc52e8a8936d22512bbf9af287fd69be5c0e7521a40f7b0750d010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, - "signed": true + "signed": false }, { "input_index": 1, - "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", - "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "private_key": "92f9d1f434a6c0fe23770ca8eec0b27163b5635a9d43717a4db48683b797041d", + "public_key": "038fd9d113ddec0dd201177762e4778c6162695d6f5d2c93470f53376cdff49675", + "prevout_txid": "c1045c7f16b950c5807a5b99dad64a161aebe1a9bfc8cf7a78290acc890f9706", "prevout_index": 0, - "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", "amount": 100000, - "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "non_witness_utxo": "02000000018535c8dfea4a1d8e6def1d790114e25c97d2c78411c0e4a6fd1800dbf1e9e3d90000000000ffffffff01a08601000000000017a9149e66125d7880b7e3f4bb660d3cf18881ea1384b98700000000", + "witness_utxo": "a08601000000000017a9149e66125d7880b7e3f4bb660d3cf18881ea1384b987", "sequence": 4294967294, - "signed": true + "signed": false } ], "sp_proofs": [ @@ -690,135 +854,377 @@ }, { "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", - "ecdh_share": "0334d2cef74eded4464227607fc59ac1de80c12a2433a56271528edccf50fa6c2b", - "dleq_proof": "37c00c0b42a073f6b65f0c4b6e56e06774b380c1df3de28b640b121ee0b3b4cf7850df456e0b5d8e1975ddff25262c8381e20f852cd870bde3f6a832a6325bcc", + "ecdh_share": "03b8ba74cc5f98c61612146024c999857eaf7ba0b70982d0ef2f0705026bbbd651", + "dleq_proof": "5ab7b19d39a7efe7e5c792d7878f913df6b34afcbb2d88c33c4928a74c8a7c6bdef5374a54282f65c15e8560b56667f30f65f6a543fcefd74f47869511f68a25", "input_index": 1 } ], "outputs": [ { "output_index": 0, - "amount": 95000, + "amount": 195000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120133d6a4f509095b5794f7491fbc3f12c3c45bc2d9b60af25b8bba704c8072aaf" + "script": "512006b846072c236fc52e8a8936d22512bbf9af287fd69be5c0e7521a40f7b0750d" } - ] + ], + "task": "fail_sign" } }, { - "description": "can finalize: two inputs / two sp outputs with mixed global and per-input ECDH shares", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQECAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQNmz8f9zgbgjtSbGzlSuNFRqPfgdf5fbdWN1o+dre7KlCIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQF6riwhtSFD+nRyflhqR+Ze2HKjQhQr8BqeL3zx0nvVAUOaStT+1sIbl54eT8B5203R/ieMXen/v9vjBYX8bBuMAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfQA0DAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEA1k6e8CREAEbpyjkwLrh7LfYN/FHJwKkX1oLzz4EFkIwCIB6+EqXx/SGW8u+11Tr+V850W5Af6ImXitWa7+FKT1A3AQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECED+9Fz2cSNWMUCJCbQUni8oXuajiKCZmkBobALngS3mUkiHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDAXaQQSHz67DeP6+avUAXjrmyGI2gYsOVbIUAX61Bz7e9AF5V1tdzaqQY0kayLg/0GJNQXek0t1JlMRkDWuMzeAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH0ANAwAAAAAAFgAUE5NQEXxXeUGphYArue3vwROTK8ciAgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3EcwRAIgWoJ5pshwRPECyFkwyJ7C/wGUKGJBraOMeFTy6DZR1fICICvMZkqflwTVcxLbwryDaGcIDyLEdYuR27ktF6HkEeqpAQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDpqibG5hqmVUz4XvtZFALVBuw1zkHHv4q4rfvsKDKa88iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDDSmopQLvppzVsHMb/41jdREHbWIl8upnCEut1KF59oeyhHHksl6OASTNFqyJN6dlMKzbuhSauI1KBcaMjHeczAAEDCJBfAQAAAAAAAQQiUSCA65gxi89t1hGsF6lksJFzbATK6t8ubodOXO+Gx8YFFwEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwiQXwEAAAAAAAEEIlEgELYvxakKvKAWeWHb/0zq6aoyTvssfyRmJ+i1oz3jfIQBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4A", + "description": "input pubkey mismatch: global ECDH share computed from decoy pubkey not matching prevout script", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAvdzdBE1pUOuor1gyv0Iy+MKMlgF8u3zI/BFddmCM/KQIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhASw1DOEMBDKlGMv8axU8cDwGVuY1wt6iezLZInpjSEc6cu47IeRoJoxzcPud19zcxlnCex0i5FI9m2B9dtRXa4wH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFDch+nPCMFyy+I6EiS1r1rl3Jh5qIgYDj9nRE93sDdIBF3di5HeMYWJpXW9dLJNHD1M3bN/0lnUIAAAAgAEAAAABDiDnbAFxCDpMX7Sv4vbWHwCkcwG50B+NLkd4CrdULjd8CAEPBAAAAAABEAT+////AAEDCLj5AgAAAAAAAQQiUSDK5a4XZIhLnDP78jGCuuHrX/eVKk0kl0sH/v3Vr+f1MQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", "supplementary": { + "hex": "70736274ff010204020000000104010201050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102f773741135a543aea2bd60cafd08cbe30a325805f2edf323f04575d98233f2902208027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068404b0d433843010ca94632ff1ac54f1c0f0195b98d70b7a89eccb6489e98d211ce9cbb8ec8791a09a31cdc3ee775f7373196709ec748b9148f66d81f5db515dae301fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff0001011fa0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a2206038fd9d113ddec0dd201177762e4778c6162695d6f5d2c93470f53376cdff49675080000008001000000010e20e76c0171083a4c5fb4afe2f6d61f00a47301b9d01f8d2e47780ab7542e377c08010f0400000000011004feffffff00010308b8f90200000000000104225120cae5ae1764884b9c33fbf23182bae1eb5ff7952a4d24974b07fefdd5afe7f531010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", - "amount": 200000, - "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, - "signed": true + "signed": false }, { "input_index": 1, - "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", - "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "private_key": "92f9d1f434a6c0fe23770ca8eec0b27163b5635a9d43717a4db48683b797041d", + "public_key": "038fd9d113ddec0dd201177762e4778c6162695d6f5d2c93470f53376cdff49675", + "prevout_txid": "087c372e54b70a78472e8d1fd0b90173a4001fd6f6e2afb45f4c3a0871016ce7", "prevout_index": 0, - "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", - "amount": 200000, - "witness_utxo": "400d030000000000160014139350117c577941a985802bb9edefc113932bc7", + "amount": 100000, + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, - "signed": true + "signed": false } ], "sp_proofs": [ { - "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", - "ecdh_share": "0366cfc7fdce06e08ed49b1b3952b8d151a8f7e075fe5f6dd58dd68f9dadeeca94", - "dleq_proof": "5eab8b086d4850fe9d1c9f961a91f997b61ca8d0850afc06a78bdf3c749ef54050e692b53fb5b086e5e78793f01e76d3747f89e3177a7feff6f8c1617f1b06e3" - }, - { - "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", - "ecdh_share": "03fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949", - "dleq_proof": "c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde", - "input_index": 0 - }, - { - "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", - "ecdh_share": "03a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf", - "dleq_proof": "c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de733", - "input_index": 1 + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02f773741135a543aea2bd60cafd08cbe30a325805f2edf323f04575d98233f290", + "dleq_proof": "4b0d433843010ca94632ff1ac54f1c0f0195b98d70b7a89eccb6489e98d211ce9cbb8ec8791a09a31cdc3ee775f7373196709ec748b9148f66d81f5db515dae3" } ], "outputs": [ { "output_index": 0, - "amount": 90000, - "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", - "script": "512080eb98318bcf6dd611ac17a964b091736c04caeadf2e6e874e5cef86c7c60517" - }, - { - "output_index": 1, - "amount": 90000, - "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", - "script": "512010b62fc5a90abca0167961dbff4ceae9aa324efb2c7f246627e8b5a33de37c84" + "amount": 195000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120cae5ae1764884b9c33fbf23182bae1eb5ff7952a4d24974b07fefdd5afe7f531" } - ] + ], + "task": "fail_sign" } + } + ], + "valid": [ + { + "description": "input eligibility: bare OP_2 script is not a segwit v2 witness program", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAQqghgEAAAAAAAFSIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDcMWh5PnuQZH/WqW0Qf2ESQ99LPO5aj2579frPvx4hHQIgSdaCpC/YrSZfLRuypQYRZHvFWqDqYGrMUrcIyqLnSiABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4gnhmdIQaZa5GIOEUxnr6A65UD13HxCWiRFHluW7k94pQBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIFKLoa04yfp7F3C33FvBdXXbvicIEfts7oll3uQvUd5OAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001010aa0860100000000000152220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100dc3168793e7b90647fd6a96d107f611243df4b3cee5a8f6e7bf5facfbf1e211d022049d682a42fd8ad265f2d1bb2a50611647bc55aa0ea606acc52b708caa2e74a200101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e209e199d2106996b91883845319ebe80eb9503d771f109689114796e5bb93de294010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120528ba1ad38c9fa7b1770b7dc5bc17575dbbe270811fb6cee8965dee42f51de4e010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "94e23db95b6e7914916809f171d70395eb80be9e31453888916b9906219d199e", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a086010000000000015200000000", + "witness_utxo": "a0860100000000000152", + "sequence": 4294967294, + "signed": true + } + ], + "task": "deserialize" + }, + "checks": [ + "input_eligibility" + ] }, { - "description": "can finalize: one input / one sp output with both global and per-input ECDH shares", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBACIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQCf7kMXWHHjjEVIA/9GD0o0KtIOAYslUGTTGQW1CZ84xvUKH6TWUUsCBevDvTVDP9XhDaw0o+e2PIbeaRHZAgI4AAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfQA0DAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiA3eo+fWjPY+iVcM7OSJtO88CKd+tlgRw74AWpxQvIzWAIgCBvWlIh63us2Ia9aLeTw05yxNpLQQb99vM00oysFQekBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQAATg9RmG+hyXvKQSPSMkR+J9fNDF9fAwKzGDvZfG1K//3qW2DObYl34Orq1eqJz7c2aNceU2suxyGEXG7JnB18AAQMIkF8BAAAAAAABBCJRINxNRNnjYeXnQ2V5x44lklVB4in9wVOtWYmtiuawYkx4AQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAA==", + "description": "can finalize: one P2PKH input single-signer", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCKz65hp7Ug/wQxkrbclMyEJpEkQIMSdkyI3dldqY0pVQIgIIfDsRj5aZKk2iQTz/6RcPJQ4n48FMtd7z5jjDDX6oABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4gUidI6xd2TSjKSUgV7I1J59MNUrxzQix8hut045cFcpQBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIGHMBAAAAAAABBCJRIOFA0oe0W0bNTqr6Q3cGFXC6voPRuLyVCnSp/qCSM9emAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAAQdrSDBFAiEAis+uYae1IP8EMZK23JTMhCaRJECDEnZMiN3ZXamNKVUCICCHw7EY+WmSpNokE8/+kXDyUOJ+PBTLXe8+Y4ww1+qAASECyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8BDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEg4UDSh7RbRs1OqvpDdwYVcLq+g9G4vJUKdKn+oJIz16YBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA" + }, "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb0402000000000100550200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4830450221008acfae61a7b520ff043192b6dc94cc84269124408312764c88ddd95da98d295502202087c3b118f96992a4da2413cffe9170f250e27e3c14cb5def3e638c30d7ea800101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20522748eb17764d28ca494815ec8d49e7d30d52bc73422c7c86eb74e397057294010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "94720597e374eb867c2c4273bc520dd3e7498dec154849ca284d7617eb482752", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", - "amount": 200000, - "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "non_witness_utxo": "0200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000", "sequence": 4294967294, "signed": true } ], "sp_proofs": [ { - "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", - "ecdh_share": "030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e", - "dleq_proof": "27fb90c5d61c78e3115200ffd183d28d0ab4838062c9541934c6416d4267ce31bd4287e9359452c0817af0ef4d50cff578436b0d28f9ed8f21b79a447640808e" + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 } ], "outputs": [ { "output_index": 0, - "amount": 90000, - "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", - "script": "5120dc4d44d9e361e5e7436579c78e25925541e229fdc153ad5989ad8ae6b0624c78" + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6" } - ] + ], + "task": "finalize" } }, { - "description": "can finalize: three sp outputs (different scan keys) with multiple global ECDH shares", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEDAQYBACIHAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQLC2d9g7mmlqGYE3ZpigsIu+OLJJ22m5ZWlRj83Gq3uJCIHAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQLcfS7KxWiwEVF1ujzVSW/0xLbZCUItvMrrjyUvpU+L0CIHA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQJwvvXAapqFX8Y7/yvQvi1wAzyCC2FTQTyNbtpR8lobKSIIAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQOyCQr97WIHO4GBWbH8TzEfkcQyJomRYwgMBswMeSBc7wL6gFoDTN1616AYRqw1Qix5Jq7VxsYeAMqrknwsC99IiCAMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEDqQ0cOXhvjKRtIoLy1P1WVLGSGDnY177pQA8yt7XfdEo4hZpew9SO+IX7Gh1B3l8zOvFzZQ2KvG0bYA2Qr1flAIggDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAG9/lTtSioG//mwAJrk49gPxHYWR1r98hJEz+PG0QTfJHQah1UU14ZU+5yhEY5tPlUvOPjKujVS6DM8UBvwy9PwABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLg3ekbsHGTj/QlvLhIwW7hrrfzKDP2b9X3JYim55whAIgfn3H3eyoVVwXfr7/yUnqTDNSD+W+7Hun4nJ+NPvUjf0BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////AAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0iAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAPmSLe+tUsYSCQS6pacAUymDbsHD2uFsoGjAFrJrBNLYAiBw+V8k+cklbkGWlGnDUqz6yOiUMjUC6s0WPJSi42nuHwEiBgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwgAAACAAQAAAAEQBP7///8AAQMIkF8BAAAAAAABBCJRIKFPr9x+36QEQnF0sSasoOmZMTP+F+JCCurtIO9U/DjcAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCJBfAQAAAAAAAQQiUSB99fJJWUQ0FLvv6J0tqJSGSlYotoAzuSPoaGvcw96dlAEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwiQXwEAAAAAAAEEIlEgsvEqf1cMxQV4QPpjk/cfBpABQgiBgYEMNLuIdh2SlQ0BCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAA", + "description": "can finalize: two inputs single-signer using global ECDH share", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAtMmJyM1JgfoT8r3ZR+NLWN+Agrqht+tgNMGzU9Iz8xiIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAxlO3H5RoGKlb3DnwkYRFvJA6CHa3OAYOnl2x3Owwq99U4LXxeFc/URnecapjrRm0SeO8tlRjk2yLrupNkXOSuQH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEA7BqWeJn9r3jg2rH/VnzzA3wMo9G7Im8q7sP98KfSmdcCIBHdNztMi7HrfRAkJSDvxy+E7Un3b0H78IdNp0bjoGOoASIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBIgYC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtwIAAAAgAEAAAABDiC81IWnCcsl0TRjoYMtshlMbJ2f5yuWmfT+Qsgr7ZPTJgEPBAAAAAABEAT+////AAEDCBhzAQAAAAAAAQQiUSCZu9KYLwKAvNwmQx1rKc9nkRilu7tgkU1v+s+rvFy0WwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAtMmJyM1JgfoT8r3ZR+NLWN+Agrqht+tgNMGzU9Iz8xiIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAxlO3H5RoGKlb3DnwkYRFvJA6CHa3OAYOnl2x3Owwq99U4LXxeFc/URnecapjrRm0SeO8tlRjk2yLrupNkXOSuQH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOwEIbAJIMEUCIQDsGpZ4mf2veODasf9WfPMDfAyj0bsibyruw/3wp9KZ1wIgEd03O0yLset9ECQlIO/HL4TtSfdvQfvwh02nRuOgY6gBIQLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8AAQEfoIYBAAAAAAAWABSmklEcB5V1vzdW2rxWrXHUKEppDgEIbAJIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBIQL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AEOILzUhacJyyXRNGOhgy2yGUxsnZ/nK5aZ9P5CyCvtk9MmAQ8EAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRIJm70pgvAoC83CZDHWspz2eRGKW7u2CRTW/6z6u8XLRbAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==" + }, "supplementary": { + "hex": "70736274ff010204020000000104010201050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102d3262723352607e84fcaf7651f8d2d637e020aea86dfad80d306cd4f48cfcc622208027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840c653b71f946818a95bdc39f0918445bc903a0876b738060e9e5db1dcec30abdf54e0b5f178573f5119de71aa63ad19b449e3bcb65463936c8baeea4d917392b901fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100ec1a967899fdaf78e0dab1ff567cf3037c0ca3d1bb226f2aeec3fdf0a7d299d7022011dd373b4c8bb1eb7d10242520efc72f84ed49f76f41fbf0874da746e3a063a801220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff0001011fa086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e220202f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc483045022100de9701a8fbc2b51470a79f95742d3cffdbaeed62fce924a0a0d5d705605153c5022045df0f887a3923ba4b316293b60cd9ff101d89952a7db069c4795633327c3ca201220602f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc080000008001000000010e20bcd485a709cb25d13463a1832db2194c6c9d9fe72b9699f4fe42c82bed93d326010f0400000000011004feffffff000103081873010000000000010422512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", - "amount": 500000, - "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "26d393ed2bc842fef499962be79f9d6c4c19b22d83a16334d125cb09a785d4bc", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e00000000", + "witness_utxo": "a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02d3262723352607e84fcaf7651f8d2d637e020aea86dfad80d306cd4f48cfcc62", + "dleq_proof": "c653b71f946818a95bdc39f0918445bc903a0876b738060e9e5db1dcec30abdf54e0b5f178573f5119de71aa63ad19b449e3bcb65463936c8baeea4d917392b9" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b" + } + ], + "task": "finalize" + } + }, + { + "description": "can finalize: two inputs single-signer using per-input ECDH shares", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQDsGpZ4mf2veODasf9WfPMDfAyj0bsibyruw/3wp9KZ1wIgEd03O0yLset9ECQlIO/HL4TtSfdvQfvwh02nRuOgY6gBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBAQMEAQAAACIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAAQ4gvNSFpwnLJdE0Y6GDLbIZTGydn+crlpn0/kLIK+2T0yYBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQM00s73Tt7URkInYH/FmsHegMEqJDOlYnFSjtzPUPpsKyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQDfADAtCoHP2tl8MS25W4Gd0s4DB3z3ii2QLEh7gs7TPeFDfRW4LXY4Zdd3/JSYsg4HiD4Us2HC94/aoMqYyW8wAAQMIGHMBAAAAAAABBCJRIJm70pgvAoC83CZDHWspz2eRGKW7u2CRTW/6z6u8XLRbAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQhsAkgwRQIhAOwalniZ/a944Nqx/1Z88wN8DKPRuyJvKu7D/fCn0pnXAiAR3Tc7TIux630QJCUg78cvhO1J929B+/CHTadG46BjqAEhAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQEfoIYBAAAAAAAWABSmklEcB5V1vzdW2rxWrXHUKEppDgEIbAJIMEUCIQDelwGo+8K1FHCnn5V0LTz/267tYvzpJKCg1dcFYFFTxQIgRd8PiHo5I7pLMWKTtgzZ/xAdiZUqfbBpxHlWMzJ8PKIBIQL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AEOILzUhacJyyXRNGOhgy2yGUxsnZ/nK5aZ9P5CyCvtk9MmAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDNNLO907e1EZCJ2B/xZrB3oDBKiQzpWJxUo7cz1D6bCsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEA3wAwLQqBz9rZfDEtuVuBndLOAwd894otkCxIe4LO0z3hQ30VuC12OGXXd/yUmLIOB4g+FLNhwveP2qDKmMlvMAAEDCBhzAQAAAAAAAQQiUSCZu9KYLwKAvNwmQx1rKc9nkRilu7tgkU1v+s+rvFy0WwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=" + }, + "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100ec1a967899fdaf78e0dab1ff567cf3037c0ca3d1bb226f2aeec3fdf0a7d299d7022011dd373b4c8bb1eb7d10242520efc72f84ed49f76f41fbf0874da746e3a063a801220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001011fa086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e220202f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc483045022100de9701a8fbc2b51470a79f95742d3cffdbaeed62fce924a0a0d5d705605153c5022045df0f887a3923ba4b316293b60cd9ff101d89952a7db069c4795633327c3ca20101030401000000220602f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc080000008001000000010e20bcd485a709cb25d13463a1832db2194c6c9d9fe72b9699f4fe42c82bed93d326010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068210334d2cef74eded4464227607fc59ac1de80c12a2433a56271528edccf50fa6c2b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0684037c00c0b42a073f6b65f0c4b6e56e06774b380c1df3de28b640b121ee0b3b4cf7850df456e0b5d8e1975ddff25262c8381e20f852cd870bde3f6a832a6325bcc000103081873010000000000010422512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "26d393ed2bc842fef499962be79f9d6c4c19b22d83a16334d125cb09a785d4bc", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e00000000", + "witness_utxo": "a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + }, + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "0334d2cef74eded4464227607fc59ac1de80c12a2433a56271528edccf50fa6c2b", + "dleq_proof": "37c00c0b42a073f6b65f0c4b6e56e06774b380c1df3de28b640b121ee0b3b4cf7850df456e0b5d8e1975ddff25262c8381e20f852cd870bde3f6a832a6325bcc", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "512099bbd2982f0280bcdc26431d6b29cf679118a5bbbb60914d6ffacfabbc5cb45b" + } + ], + "task": "finalize" + } + }, + { + "description": "can finalize: two inputs / two sp outputs with mixed global and per-input ECDH shares", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQIBBgEAIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghA2bPx/3OBuCO1JsbOVK40VGo9+B1/l9t1Y3Wj52t7sqUIggDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAXquLCG1IUP6dHJ+WGpH5l7YcqNCFCvwGp4vfPHSe9UBQ5pK1P7WwhuXnh5PwHnbTdH+J4xd6f+/2+MFhfxsG4wH7BAIAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiAKK+ZG0anqXBVNlCNCmskJl9/09NFCJp/mC8dvxE42HAIgCANa6s/ngmX6X6JTanzM6oXez4bcGYlSGOAMQI1gw7ABAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQP70XPZxI1YxQIkJtBSeLyhe5qOIoJmaQGhsAueBLeZSSIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMBdpBBIfPrsN4/r5q9QBeOubIYjaBiw5VshQBfrUHPt70AXlXW13NqpBjSRrIuD/QYk1Bd6TS3UmUxGQNa4zN4AAQEfQA0DAAAAAAAWABSmklEcB5V1vzdW2rxWrXHUKEppDiICAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cSDBFAiEA1c3ZMOY2lwfrZ4b1q8L00OgVt4cmVi2tA1VpGbbQIjgCIF8zRs9QoCxciaScoUlqFfUE49+mFdDTyCBi0nGS0uE5AQEDBAEAAAAiBgL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AgAAACAAQAAAAEOIITULym/Ww9KyMHgbIoBNLUz+CwKAffuThNSpATHWvsuAQ8EAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDpqibG5hqmVUz4XvtZFALVBuw1zkHHv4q4rfvsKDKa88iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDDSmopQLvppzVsHMb/41jdREHbWIl8upnCEut1KF59oeyhHHksl6OASTNFqyJN6dlMKzbuhSauI1KBcaMjHeczAAEDCJBfAQAAAAAAAQQiUSCxKAm+EU5RY5SZU7O++G4xbRcMZzZlTdRqkb2+RLxVEAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwiQXwEAAAAAAAEEIlEge2sCToSJVp8gv7oB/byYmecZMBVcHiDoeJIGlPmxpggBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4A", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQIBBgEAIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghA2bPx/3OBuCO1JsbOVK40VGo9+B1/l9t1Y3Wj52t7sqUIggDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAXquLCG1IUP6dHJ+WGpH5l7YcqNCFCvwGp4vfPHSe9UBQ5pK1P7WwhuXnh5PwHnbTdH+J4xd6f+/2+MFhfxsG4wH7BAIAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOwEIawJHMEQCIAor5kbRqepcFU2UI0KayQmX3/T00UImn+YLx2/ETjYcAiAIA1rqz+eCZfpfolNqfMzqhd7PhtwZiVIY4AxAjWDDsAEhAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQP70XPZxI1YxQIkJtBSeLyhe5qOIoJmaQGhsAueBLeZSSIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMBdpBBIfPrsN4/r5q9QBeOubIYjaBiw5VshQBfrUHPt70AXlXW13NqpBjSRrIuD/QYk1Bd6TS3UmUxGQNa4zN4AAQEfQA0DAAAAAAAWABSmklEcB5V1vzdW2rxWrXHUKEppDgEIbAJIMEUCIQDVzdkw5jaXB+tnhvWrwvTQ6BW3hyZWLa0DVWkZttAiOAIgXzNGz1CgLFyJpJyhSWoV9QTj36YV0NPIIGLScZLS4TkBIQL1tZ+l5JIiHr9VunitRCYFvq6VFmuh66MlDQu6rH4u3AEOIITULym/Ww9KyMHgbIoBNLUz+CwKAffuThNSpATHWvsuAQ8EAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDpqibG5hqmVUz4XvtZFALVBuw1zkHHv4q4rfvsKDKa88iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEDDSmopQLvppzVsHMb/41jdREHbWIl8upnCEut1KF59oeyhHHksl6OASTNFqyJN6dlMKzbuhSauI1KBcaMjHeczAAEDCJBfAQAAAAAAAQQiUSCxKAm+EU5RY5SZU7O++G4xbRcMZzZlTdRqkb2+RLxVEAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwiQXwEAAAAAAAEEIlEge2sCToSJVp8gv7oB/byYmecZMBVcHiDoeJIGlPmxpggBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4A" + }, + "supplementary": { + "hex": "70736274ff010204020000000104010201050102010601002207033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28210366cfc7fdce06e08ed49b1b3952b8d151a8f7e075fe5f6dd58dd68f9dadeeca942208033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28405eab8b086d4850fe9d1c9f961a91f997b61ca8d0850afc06a78bdf3c749ef54050e692b53fb5b086e5e78793f01e76d3747f89e3177a7feff6f8c1617f1b06e301fb04020000000001011f400d0300000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402200a2be646d1a9ea5c154d9423429ac90997dff4f4d142269fe60bc76fc44e361c022008035aeacfe78265fa5fa2536a7cccea85decf86dc19895218e00c408d60c3b00101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20fd2df4f58b5abf9b91ff1a1e43e2e3523f50c6aa19d5c22360141ec48c9a8021010f0400000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde0001011f400d030000000000160014a692511c079575bf3756dabc56ad71d4284a690e220202f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc483045022100d5cdd930e6369707eb6786f5abc2f4d0e815b78726562dad03556919b6d0223802205f3346cf50a02c5c89a49ca1496a15f504e3dfa615d0d3c82062d27192d2e1390101030401000000220602f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc080000008001000000010e2084d42f29bf5b0f4ac8c1e06c8a0134b533f82c0a01f7ee4e1352a404c75afb2e010f0400000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de73300010308905f0100000000000104225120b12809be114e5163949953b3bef86e316d170c6736654dd46a91bdbe44bc5510010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd400010308905f01000000000001042251207b6b024e8489569f20bfba01fdbc9899e71930155c1e20e878920694f9b1a60801094202a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e00", + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "21809a8cc41e146023c2d519aac6503f52e3e2431e1aff919bbf5a8bf5f42dfd", + "prevout_index": 0, + "amount": 200000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01400d0300000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "400d0300000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + }, + { + "input_index": 1, + "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", + "prevout_txid": "2efb5ac704a452134eeef7010a2cf833b534018a6ce0c1c84a0f5bbf292fd484", + "prevout_index": 0, + "amount": 200000, + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01400d030000000000160014a692511c079575bf3756dabc56ad71d4284a690e00000000", + "witness_utxo": "400d030000000000160014a692511c079575bf3756dabc56ad71d4284a690e", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "0366cfc7fdce06e08ed49b1b3952b8d151a8f7e075fe5f6dd58dd68f9dadeeca94", + "dleq_proof": "5eab8b086d4850fe9d1c9f961a91f997b61ca8d0850afc06a78bdf3c749ef54050e692b53fb5b086e5e78793f01e76d3747f89e3177a7feff6f8c1617f1b06e3" + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949", + "dleq_proof": "c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde", + "input_index": 0 + }, + { + "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", + "ecdh_share": "03a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf", + "dleq_proof": "c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de733", + "input_index": 1 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "5120b12809be114e5163949953b3bef86e316d170c6736654dd46a91bdbe44bc5510" + }, + { + "output_index": 1, + "amount": 90000, + "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", + "script": "51207b6b024e8489569f20bfba01fdbc9899e71930155c1e20e878920694f9b1a608" + } + ], + "task": "finalize" + } + }, + { + "description": "can finalize: one input / one sp output with both global and per-input ECDH shares", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAwoYubtBmbiTMOsX+O5ax4bghT3NLzzN8XRLl85O3gU+IggDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAJ/uQxdYceOMRUgD/0YPSjQq0g4BiyVQZNMZBbUJnzjG9QofpNZRSwIF68O9NUM/1eENrDSj57Y8ht5pEdkCAjgH7BAIAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEAyFvlr5bhqKf1YcXDSFBg36YAz/htqrTzO6OY5lBittkCIBPq0/BHmz/uJrpIh+BRh2ZjzRP8fmHmDS6WBkIym0HkAQEDBAEAAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIP0t9PWLWr+bkf8aHkPi41I/UMaqGdXCI2AUHsSMmoAhAQ8EAAAAAAEQBP7///8iHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCEDChi5u0GZuJMw6xf47lrHhuCFPc0vPM3xdEuXzk7eBT4iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAAE4PUZhvocl7ykEj0jJEfifXzQxfXwMCsxg72XxtSv/96ltgzm2Jd+Dq6tXqic+3NmjXHlNrLschhFxuyZwdfAAEDCJBfAQAAAAAAAQQiUSAqcL4BPYeh6B6gH736DPH/CNUqaNGMExqMyWAfhKagrAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AA=", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAwoYubtBmbiTMOsX+O5ax4bghT3NLzzN8XRLl85O3gU+IggDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAJ/uQxdYceOMRUgD/0YPSjQq0g4BiyVQZNMZBbUJnzjG9QofpNZRSwIF68O9NUM/1eENrDSj57Y8ht5pEdkCAjgH7BAIAAAAAAQEfQA0DAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOwEIbAJIMEUCIQDIW+WvluGop/VhxcNIUGDfpgDP+G2qtPM7o5jmUGK22QIgE+rT8EebP+4mukiH4FGHZmPNE/x+YeYNLpYGQjKbQeQBIQLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwEOIP0t9PWLWr+bkf8aHkPi41I/UMaqGdXCI2AUHsSMmoAhAQ8EAAAAAAEQBP7///8iHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCEDChi5u0GZuJMw6xf47lrHhuCFPc0vPM3xdEuXzk7eBT4iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAAE4PUZhvocl7ykEj0jJEfifXzQxfXwMCsxg72XxtSv/96ltgzm2Jd+Dq6tXqic+3NmjXHlNrLschhFxuyZwdfAAEDCJBfAQAAAAAAAQQiUSAqcL4BPYeh6B6gH736DPH/CNUqaNGMExqMyWAfhKagrAEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AA=" + }, + "supplementary": { + "hex": "70736274ff010204020000000104010101050101010601002207033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e2208033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284027fb90c5d61c78e3115200ffd183d28d0ab4838062c9541934c6416d4267ce31bd4287e9359452c0817af0ef4d50cff578436b0d28f9ed8f21b79a447640808e01fb04020000000001011f400d0300000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100c85be5af96e1a8a7f561c5c3485060dfa600cff86daab4f33ba398e65062b6d9022013ead3f0479b3fee26ba4887e051876663cd13fc7e61e60d2e960642329b41e40101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20fd2df4f58b5abf9b91ff1a1e43e2e3523f50c6aa19d5c22360141ec48c9a8021010f0400000000011004feffffff221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840001383d4661be8725ef29048f48c911f89f5f34317d7c0c0acc60ef65f1b52bfff7a96d8339b625df83abab57aa273edcd9a35c794dacbb1c861171bb267075f00010308905f01000000000001042251202a70be013d87a1e81ea01fbdfa0cf1ff08d52a68d18c131a8cc9601f84a6a0ac010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd400", + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "21809a8cc41e146023c2d519aac6503f52e3e2431e1aff919bbf5a8bf5f42dfd", + "prevout_index": 0, + "amount": 200000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01400d0300000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "400d0300000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", + "ecdh_share": "030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e", + "dleq_proof": "27fb90c5d61c78e3115200ffd183d28d0ab4838062c9541934c6416d4267ce31bd4287e9359452c0817af0ef4d50cff578436b0d28f9ed8f21b79a447640808e" + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 90000, + "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", + "script": "51202a70be013d87a1e81ea01fbdfa0cf1ff08d52a68d18c131a8cc9601f84a6a0ac" + } + ], + "task": "finalize" + } + }, + { + "description": "can finalize: three sp outputs (different scan keys) with multiple global ECDH shares", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQMBBgEAIgcCqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhAsLZ32DuaaWoZgTdmmKCwi744sknbabllaVGPzcare4kIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAtx9LsrFaLARUXW6PNVJb/TEttkJQi28yuuPJS+lT4vQIgcDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhAnC+9cBqmoVfxjv/K9C+LXADPIILYVNBPI1u2lHyWhspIggCqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBA7IJCv3tYgc7gYFZsfxPMR+RxDImiZFjCAwGzAx5IFzvAvqAWgNM3XrXoBhGrDVCLHkmrtXGxh4AyquSfCwL30iIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQOpDRw5eG+MpG0igvLU/VZUsZIYOdjXvulADzK3td90SjiFml7D1I74hfsaHUHeXzM68XNlDYq8bRtgDZCvV+UAiCAOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEAb3+VO1KKgb/+bAAmuTj2A/EdhZHWv3yEkTP48bRBN8kdBqHVRTXhlT7nKERjm0+VS84+Mq6NVLoMzxQG/DL0/AfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQC42QsRZqzXY8+uqHOJGaBPRdBVbSvLD2Z/C6PEGO5f2QIgI64RGn6itGrUpKOIKuT++973rl0BtM22H1aXmv9SahgBIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABEAT+////AAEBH6CGAQAAAAAAFgAUNyH6c8IwXLL4joSJLWvWuXcmHmoiAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAJfXTGL5WdOu1bnHpXDy1zyq0MCrseRy1E/UxirCYuS5AiAX2VXEZF+Fr+z2aKPQRlXWdZPyNXYrGm9SKYcXYECqoAEiBgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwgAAACAAQAAAAEOIOdsAXEIOkxftK/i9tYfAKRzAbnQH40uR3gKt1QuN3wIAQ8EAAAAAAEQBP7///8AAQMIkF8BAAAAAAABBCJRIE6KUf3Rq9Uk/FLWkolTgu5u3MSNN3228eZRXyNALkgnAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCJBfAQAAAAAAAQQiUSB+MV8kXPlXXxNDwxcP/O42rUbTO1ZfCji5lDx8AqzXawEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwiQXwEAAAAAAAEEIlEgPK1PnUbiURy2iCuvYOjtgGIgsUFRPWkE2s0r6qE3w5UBCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAA", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQMBBgEAIgcCqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhAsLZ32DuaaWoZgTdmmKCwi744sknbabllaVGPzcare4kIgcDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAtx9LsrFaLARUXW6PNVJb/TEttkJQi28yuuPJS+lT4vQIgcDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhAnC+9cBqmoVfxjv/K9C+LXADPIILYVNBPI1u2lHyWhspIggCqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBA7IJCv3tYgc7gYFZsfxPMR+RxDImiZFjCAwGzAx5IFzvAvqAWgNM3XrXoBhGrDVCLHkmrtXGxh4AyquSfCwL30iIIAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQOpDRw5eG+MpG0igvLU/VZUsZIYOdjXvulADzK3td90SjiFml7D1I74hfsaHUHeXzM68XNlDYq8bRtgDZCvV+UAiCAOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEAb3+VO1KKgb/+bAAmuTj2A/EdhZHWv3yEkTP48bRBN8kdBqHVRTXhlT7nKERjm0+VS84+Mq6NVLoMzxQG/DL0/AfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQhsAkgwRQIhALjZCxFmrNdjz66oc4kZoE9F0FVtK8sPZn8Lo8QY7l/ZAiAjrhEafqK0atSko4gq5P773veuXQG0zbYfVpea/1JqGAEhAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQ4g1EDnWvzdUxpZHjer0m5K8r8Pb/LhkYMCNWHo/FcTj0oBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFDch+nPCMFyy+I6EiS1r1rl3Jh5qAQhsAkgwRQIhAJfXTGL5WdOu1bnHpXDy1zyq0MCrseRy1E/UxirCYuS5AiAX2VXEZF+Fr+z2aKPQRlXWdZPyNXYrGm9SKYcXYECqoAEhAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7AQ4g52wBcQg6TF+0r+L21h8ApHMBudAfjS5HeAq3VC43fAgBDwQAAAAAARAE/v///wABAwiQXwEAAAAAAAEEIlEgTopR/dGr1ST8UtaSiVOC7m7cxI03fbbx5lFfI0AuSCcBCUIDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSgDEmZYHj6EHLuU3mLqc1WDojLEyIj6bt7y7C+HB4n8HdQAAQMIkF8BAAAAAAABBCJRIH4xXyRc+VdfE0PDFw/87jatRtM7Vl8KOLmUPHwCrNdrAQlCAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQAkpI124g1AvPXy4aXD/+s9wqizuI15pIbVTJ2eqo+hiOAAEDCJBfAQAAAAAAAQQiUSA8rU+dRuJRHLaIK69g6O2AYiCxQVE9aQTazSvqoTfDlQEJQgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobAP4FHOETJ10ySH/F6WvQQtjNzSNevv/c4kbxcsMskywwAA=" + }, + "supplementary": { + "hex": "70736274ff01020402000000010401020105010301060100220702a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102c2d9df60ee69a5a86604dd9a6282c22ef8e2c9276da6e595a5463f371aadee242207033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282102dc7d2ecac568b0115175ba3cd5496ff4c4b6d909422dbccaeb8f252fa54f8bd02207038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c210270bef5c06a9a855fc63bff2bd0be2d70033c820b6153413c8d6eda51f25a1b29220802a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040ec8242bf7b5881cee060566c7f13cc47e4710c89a26458c20301b3031e48173bc0bea01680d3375eb5e80611ab0d508b1e49abb571b1878032aae49f0b02f7d22208033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840ea43470e5e1be3291b48a0bcb53f55952c64860e7635efba5003ccaded77dd128e216697b0f523be217ec687507797cccebc5cd94362af1b46d803642bd5f9402208038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c401bdfe54ed4a2a06fff9b0009ae4e3d80fc47616475afdf21244cfe3c6d104df24741a875514d78654fb9ca1118e6d3e552f38f8caba3552e8333c501bf0cbd3f01fb04020000000001011f20a10700000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100b8d90b1166acd763cfaea8738919a04f45d0556d2bcb0f667f0ba3c418ee5fd9022023ae111a7ea2b46ad4a4a3882ae4fefbdef7ae5d01b4cdb61f56979aff526a1801220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20d440e75afcdd531a591e37abd26e4af2bf0f6ff2e19183023561e8fc57138f4a010f0400000000011004feffffff0001011fa0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a22020243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb48304502210097d74c62f959d3aed5b9c7a570f2d73caad0c0abb1e472d44fd4c62ac262e4b9022017d955c4645f85afecf668a3d04655d67593f235762b1a6f522987176040aaa00122060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000010e20e76c0171083a4c5fb4afe2f6d61f00a47301b9d01f8d2e47780ab7542e377c08010f0400000000011004feffffff00010308905f01000000000001042251204e8a51fdd1abd524fc52d692895382ee6edcc48d377db6f1e6515f23402e4827010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd400010308905f01000000000001042251207e315f245cf9575f1343c3170ffcee36ad46d33b565f0a38b9943c7c02acd76b01094202a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e00010308905f01000000000001042251203cad4f9d46e2511cb6882baf60e8ed806220b141513d6904dacd2beaa137c395010942038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c000", + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "4a8f1357fce86135028391e1f26f0fbff24a6ed2ab371e591a53ddfc5ae740d4", + "prevout_index": 0, + "amount": 500000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff0120a10700000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "20a10700000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, @@ -826,11 +1232,11 @@ "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "087c372e54b70a78472e8d1fd0b90173a4001fd6f6e2afb45f4c3a0871016ce7", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 100000, - "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": true } @@ -857,37 +1263,83 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", - "script": "5120a14fafdc7edfa404427174b126aca0e9993133fe17e2420aeaed20ef54fc38dc" + "script": "51204e8a51fdd1abd524fc52d692895382ee6edcc48d377db6f1e6515f23402e4827" }, { "output_index": 1, "amount": 90000, "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", - "script": "51207df5f24959443414bbefe89d2da894864a5628b68033b923e8686bdcc3de9d94" + "script": "51207e315f245cf9575f1343c3170ffcee36ad46d33b565f0a38b9943c7c02acd76b" }, { "output_index": 2, "amount": 90000, "sp_v0_info": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c0", - "script": "5120b2f12a7f570cc5057840fa6393f71f06900142088181810c34bb88761d92950d" + "script": "51203cad4f9d46e2511cb6882baf60e8ed806220b141513d6904dacd2beaa137c395" } - ] + ], + "task": "finalize" + } + }, + { + "description": "can finalize: one P2TR input signed with SIGHASH_DEFAULT", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABASughgEAAAAAACJRIOr+wb8f+Gc4KaZp0ODVHmm4+HjCR3lPlLOIEAxKsoGoAQMEAAAAAAEOIBju6I1/yremcDAUdu9RuwYVT/2r7gE0V7N7s0GwUlsLAQ8EAAAAAAEQBP7///8BE0Dy/VdTtEk8Bo7qOC1qbZzruIxMcN5cnWn6zEfPWxL7fqzH/X2QFbNBLaXwlV/Jq1OFBE8Ha6ukSjA5QQgp3YtUARcgyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCECk3pXhhJkdtDAvHvJiFCBD2dK6sF9p/psij0ude8Q1H4iHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEC7hR+N0QAzvYyyhCJd2xRdt7U9XefG6uFTgLQD82RsaBQF5qYVLY+hw+UEHqLlfuBkcjmxsDLKgfxdKrPZYBY+AAEDCBhzAQAAAAAAAQQiUSBh3waWykfLBeW4dLLG6ABA0uPZoqmtDn7azwlY9VVz6wEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABASughgEAAAAAACJRIOr+wb8f+Gc4KaZp0ODVHmm4+HjCR3lPlLOIEAxKsoGoAQhCAUDy/VdTtEk8Bo7qOC1qbZzruIxMcN5cnWn6zEfPWxL7fqzH/X2QFbNBLaXwlV/Jq1OFBE8Ha6ukSjA5QQgp3YtUAQ4gGO7ojX/Kt6ZwMBR271G7BhVP/avuATRXs3uzQbBSWwsBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQKTeleGEmR20MC8e8mIUIEPZ0rqwX2n+myKPS517xDUfiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQLuFH43RADO9jLKEIl3bFF23tT1d58bq4VOAtAPzZGxoFAXmphUtj6HD5QQeouV+4GRyObGwMsqB/F0qs9lgFj4AAQMIGHMBAAAAAAABBCJRIGHfBpbKR8sF5bh0ssboAEDS49miqa0OftrPCVj1VXPrAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==" + }, + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001012ba086010000000000225120eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a801030400000000010e2018eee88d7fcab7a670301476ef51bb06154ffdabee013457b37bb341b0525b0b010f0400000000011004feffffff011340f2fd5753b4493c068eea382d6a6d9cebb88c4c70de5c9d69facc47cf5b12fb7eacc7fd7d9015b3412da5f0955fc9ab5385044f076baba44a3039410829dd8b54011720c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102937a5786126476d0c0bc7bc98850810f674aeac17da7fa6c8a3d2e75ef10d47e221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840bb851f8dd10033bd8cb284225ddb145db7b53d5de7c6eae15380b403f3646c681405e6a6152d8fa1c3e5041ea2e57ee0647239b1b032ca81fc5d2ab3d960163e000103081873010000000000010422512061df0696ca47cb05e5b874b2c6e80040d2e3d9a2a9ad0e7edacf0958f55573eb010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "inputs": [ + { + "input_index": 0, + "private_key": "2c0141a983cc711ec6a59cd7bccad7a159c43dab09d6e783e91facc865134da5", + "public_key": "02eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a8", + "prevout_txid": "0b5b52b041b37bb3573401eeabfd4f1506bb51ef76143070a6b7ca7f8de8ee18", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "020000000113f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d020000000000ffffffff01a086010000000000225120eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a800000000", + "witness_utxo": "a086010000000000225120eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a8", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "02937a5786126476d0c0bc7bc98850810f674aeac17da7fa6c8a3d2e75ef10d47e", + "dleq_proof": "bb851f8dd10033bd8cb284225ddb145db7b53d5de7c6eae15380b403f3646c681405e6a6152d8fa1c3e5041ea2e57ee0647239b1b032ca81fc5d2ab3d960163e", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "512061df0696ca47cb05e5b874b2c6e80040d2e3d9a2a9ad0e7edacf0958f55573eb" + } + ], + "task": "finalize" } }, { "description": "can finalize: one P2WPKH input / two mixed outputs - labeled sp output and BIP 32 change", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCspcmETsmSLIHmcIF+My2i3RXSxdOpRiq21l5TtoKJXgIgTfMs6jgucsQ8BYQE/a5wWVHmuj3jPYM8g6lbsBg4CscBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRICJoz1KZWfMKyPelRxykxnU2pR8OWxaK8D7tRxXtzHLgAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA+qPIovitxbaze/LKBAHKHTwCkdvXAe9BRkXEmzGSz3vAQoEAQAAAAABAwhw8wUAAAAAAAEEFgAUOMGPNd2AY+OApw/+tPmP9O80gXciAgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwwAAAAAAAAAAAAAAAEA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCPK7BV068xhdltYVI7x1UGydVRKIUnGQwguF9HPd5W8gIgZ0ErvfZD1lcvsUUFisMo7xFFAZvsjC9aImux76km008BAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g1EDnWvzdUxpZHjer0m5K8r8Pb/LhkYMCNWHo/FcTj0oBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRILLXUKYOxNBb0sIicfCP4hsA4nEdOCMEi7lloivEFz0vAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA+qPIovitxbaze/LKBAHKHTwCkdvXAe9BRkXEmzGSz3vAQoEAQAAAAAiAgNelfRXHtom4PY2PqXFlHlK1N0hXqEmYvE8mpkG1aqTrgwAAAAAAAAAAAAAAAEBAwhw8wUAAAAAAAEEFgAU10OzS4cowqNfapTI2vQRh0WtlpsA", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQhsAkgwRQIhAI8rsFXTrzGF2W1hUjvHVQbJ1VEohScZDCC4X0c93lbyAiBnQSu99kPWVy+xRQWKwyjvEUUBm+yML1oia7HvqSbTTwEhAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQ4g1EDnWvzdUxpZHjer0m5K8r8Pb/LhkYMCNWHo/FcTj0oBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRILLXUKYOxNBb0sIicfCP4hsA4nEdOCMEi7lloivEFz0vAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA+qPIovitxbaze/LKBAHKHTwCkdvXAe9BRkXEmzGSz3vAQoEAQAAAAAiAgNelfRXHtom4PY2PqXFlHlK1N0hXqEmYvE8mpkG1aqTrgwAAAAAAAAAAAAAAAEBAwhw8wUAAAAAAAEEFgAU10OzS4cowqNfapTI2vQRh0WtlpsA" + }, "supplementary": { + "hex": "70736274ff0102040200000001040101010501020106010001fb04020000000001011f20a10700000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4830450221008f2bb055d3af3185d96d61523bc75506c9d551288527190c20b85f473dde56f2022067412bbdf643d6572fb145058ac328ef1145019bec8c2f5a226bb1efa926d34f0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20d440e75afcdd531a591e37abd26e4af2bf0f6ff2e19183023561e8fc57138f4a010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308a0860100000000000104225120b2d750a60ec4d05bd2c22271f08fe21b00e2711d3823048bb965a22bc4173d2f010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803ea8f228be2b716dacdefcb2810072874f00a476f5c07bd051917126cc64b3def010a0401000000002202035e95f4571eda26e0f6363ea5c594794ad4dd215ea12662f13c9a9906d5aa93ae0c00000000000000000000000101030870f30500000000000104160014d743b34b8728c2a35f6a94c8daf4118745ad969b00", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "4a8f1357fce86135028391e1f26f0fbff24a6ed2ab371e591a53ddfc5ae740d4", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 500000, - "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff0120a10700000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "20a10700000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -906,30 +1358,35 @@ "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06803ea8f228be2b716dacdefcb2810072874f00a476f5c07bd051917126cc64b3def", "sp_v0_label": 1, - "script": "51202268cf529959f30ac8f7a5471ca4c67536a51f0e5b168af03eed4715edcc72e0" + "script": "5120b2d750a60ec4d05bd2c22271f08fe21b00e2711d3823048bb965a22bc4173d2f" }, { "output_index": 1, "amount": 390000, - "script": "001438c18f35dd8063e380a70ffeb4f98ff4ef348177" + "script": "0014d743b34b8728c2a35f6a94c8daf4118745ad969b" } - ] + ], + "task": "finalize" } }, { "description": "can finalize: one input / two sp outputs - output 0 has no label / output 1 uses label=0 convention for sp change", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR/gkwQAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICJa45kPVF365uoUKpN0arSqgSfjyBNY63wha08anrtiAiBl42BSGRArJQdeOVXz80zjvPKjXR4QFd1dw7/tPs81qQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts0hA84eNnXZDZkmSfqd2xH5AlSbs7AvVvbonMCgTIuMN92UIh0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts1ADolhPR9rJTbbj6kkIA2zpvjvyhciVWTVaxEuUIZbTTAuBY+m9hwp4jZqSnJp1FVaXGHWVVnb+/rJ4urf5TY31SIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIKBIDZZnnBk25au9SLqw4B/6yx7n0cnhaC8VQBaZZYXZAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA7RDRzNcY/UF5V4mirKA8xi0pqoUSS/zecNmih9U74ybAAEDCDDmAgAAAAAAAQQiUSDkKhgUiNj/9ucWH3FfXvD0fcbISAhIqtaERxvz6ljzUgEJQgJfDsGzjZmEp+ti8VvkAwIEEPFC7fTWnjY/VhWv0qa2zQLOCzIZpapd+PIc45PpYs3afVFUbaTTXDjtAYilludg8wEKBAAAAAAA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR/gkwQAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFB2CeL9erskEbcJ/ZjL+pgC0nxcDrLBEMLU8/EJ61yYAiBeYmSIxVqzZbFYt+8gUlTszHEFFvbNOzksUNGJgWmDsQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiDXHS3QFsrGYSyer5hVH2eAhRu3czlByBTq+trO3jDcPQEPBAAAAAABEAT+////Ih0CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts0hA84eNnXZDZkmSfqd2xH5AlSbs7AvVvbonMCgTIuMN92UIh0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts1ADolhPR9rJTbbj6kkIA2zpvjvyhciVWTVaxEuUIZbTTAuBY+m9hwp4jZqSnJp1FVaXGHWVVnb+/rJ4urf5TY31SIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIBM/6m8cjln0UbKW1K2xPs7sf8M9vFNq5NY3WropOE+LAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA7RDRzNcY/UF5V4mirKA8xi0pqoUSS/zecNmih9U74ybAAEDCDDmAgAAAAAAAQQiUSBgK8NLBuQ1Rvh+VIKxETqr+cn+KSUJmpItXCPYS7zqxgEJQgJfDsGzjZmEp+ti8VvkAwIEEPFC7fTWnjY/VhWv0qa2zQLOCzIZpapd+PIc45PpYs3afVFUbaTTXDjtAYilludg8wEKBAAAAAAA", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR/gkwQAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQhrAkcwRAIgUHYJ4v16uyQRtwn9mMv6mALSfFwOssEQwtTz8QnrXJgCIF5iZIjFWrNlsVi37yBSVOzMcQUW9s07OSxQ0YmBaYOxASECyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8BDiDXHS3QFsrGYSyer5hVH2eAhRu3czlByBTq+trO3jDcPQEPBAAAAAABEAT+////Ih0CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts0hA84eNnXZDZkmSfqd2xH5AlSbs7AvVvbonMCgTIuMN92UIh0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4CXw7Bs42ZhKfrYvFb5AMCBBDxQu301p42P1YVr9Kmts1ADolhPR9rJTbbj6kkIA2zpvjvyhciVWTVaxEuUIZbTTAuBY+m9hwp4jZqSnJp1FVaXGHWVVnb+/rJ4urf5TY31SIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoIYBAAAAAAABBCJRIBM/6m8cjln0UbKW1K2xPs7sf8M9vFNq5NY3WropOE+LAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA7RDRzNcY/UF5V4mirKA8xi0pqoUSS/zecNmih9U74ybAAEDCDDmAgAAAAAAAQQiUSBgK8NLBuQ1Rvh+VIKxETqr+cn+KSUJmpItXCPYS7zqxgEJQgJfDsGzjZmEp+ti8VvkAwIEEPFC7fTWnjY/VhWv0qa2zQLOCzIZpapd+PIc45PpYs3afVFUbaTTXDjtAYilludg8wEKBAAAAAAA" + }, "supplementary": { + "hex": "70736274ff0102040200000001040101010501020106010001fb04020000000001011fe0930400000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4730440220507609e2fd7abb2411b709fd98cbfa9802d27c5c0eb2c110c2d4f3f109eb5c9802205e626488c55ab365b158b7ef205254eccc710516f6cd3b392c50d189816983b10101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20d71d2dd016cac6612c9eaf98551f6780851bb7733941c814eafadacede30dc3d010f0400000000011004feffffff221d025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd2103ce1e3675d90d992649fa9ddb11f902549bb3b02f56f6e89cc0a04c8b8c37dd94221d028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656821025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050221e025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd400e89613d1f6b2536db8fa924200db3a6f8efca17225564d56b112e50865b4d302e058fa6f61c29e2366a4a7269d4555a5c61d65559dbfbfac9e2eadfe53637d5221e028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568407940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb00010308a0860100000000000104225120133fea6f1c8e59f451b296d4adb13eceec7fc33dbc536ae4d6375aba29384f8b010942028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b0001030830e60200000000000104225120602bc34b06e43546f87e5482b1113aabf9c9fe2925099a922d5c23d84bbceac6010942025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd02ce0b3219a5aa5df8f21ce393e962cdda7d51546da4d35c38ed0188a596e760f3010a040000000000", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "3ddc30decedafaea14c8413973b71b8580671f5598af9e2c61c6ca16d02d1dd7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 300000, - "witness_utxo": "e093040000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01e0930400000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "e0930400000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -953,32 +1410,37 @@ "output_index": 0, "amount": 100000, "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803b44347335c63f505e55e268ab280f318b4a6aa14492ff379c3668a1f54ef8c9b", - "script": "5120a0480d96679c1936e5abbd48bab0e01ffacb1ee7d1c9e1682f154016996585d9" + "script": "5120133fea6f1c8e59f451b296d4adb13eceec7fc33dbc536ae4d6375aba29384f8b" }, { "output_index": 1, "amount": 190000, "sp_v0_info": "025f0ec1b38d9984a7eb62f15be403020410f142edf4d69e363f5615afd2a6b6cd02ce0b3219a5aa5df8f21ce393e962cdda7d51546da4d35c38ed0188a596e760f3", "sp_v0_label": 0, - "script": "5120e42a181488d8fff6e7161f715f5ef0f47dc6c8480848aad684471bf3ea58f352" + "script": "5120602bc34b06e43546f87e5482b1113aabf9c9fe2925099a922d5c23d84bbceac6" } - ] + ], + "task": "finalize" } }, { "description": "can finalize: three sp outputs (same scan key) - output 0 uses label=1, outputs 1 and 2 uses label=2 (same spend key)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEDAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+AGgYAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIFaplAuaU3aICoTcvxrXSZnHH6i4SXpbYSuzopSyB0k4AiA98iUFQysKS0I3s2sHC3R8ZpycvK7JZiE0PcjMfiNnYgEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWghAlWBv6pzMVb2uY5xom9w/XazZ4ZJ9isfxed7jpq45hBQIh4Ci3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWhAeUCBnrbp8ljBWDh8CmTMFvUXx+9ECRIszqqU9OL/U3bEJHv8Fw2bJjsOPSBrZoyH6Us03ur6AKF5KwR614h1uwABAwihhgEAAAAAAAEEIlEgG/+hD9qiUCwvDJKF/grxmlD4UV47bfv1behQ2ZkBRAABCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgD1DFYje5hqzo5clspnDdC3Gaghh3s9ZG0I7DlJwcPgjQBCgQBAAAAAAEDCDLmAgAAAAAAAQQiUSCITaZwjIK5tWyYvTvm5fU4lLsb/ZC/rPiUAlVw9r1TBQEJQgKLeQ4Jh/3p8NEjmOtr4wxzdnk8ZHhloqAvLvyWDZZlaAMhk60Mh1+sUkNzgCKQCnckxhdd2smUQWWqtFeq35xPPAEKBAIAAAAAAQMIooYBAAAAAAABBCJRINKR0zkoDgyG4scIpZH46OL4ktEqfP6FELZneZtxExyGAQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoAyGTrQyHX6xSQ3OAIpAKdyTGF13ayZRBZaq0V6rfnE88AQoEAgAAAAA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQMBBgEAAfsEAgAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCUWfs0hcwTRkOekp3AdPHTla2+gwarlNndhIFCaNDsOAIgOAjuJjqIA6Fy5rMVCyyiJMlhF6GfDplTlH+lICupcGUBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4gcOBrhlWVxMJzHTP1pq0oD7hwNVRmYpiAyl3NjpAH4ZoBDwQAAAAAARAE/v///yIdAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoIQJVgb+qczFW9rmOcaJvcP12s2eGSfYrH8Xne46auOYQUCIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoYYBAAAAAAABBCJRIJPaXrkneTYjgSVQ+GmdZjtxlvDMnUiEWLtoH+srb/y6AQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA9QxWI3uYas6OXJbKZw3QtxmoIYd7PWRtCOw5ScHD4I0AQoEAQAAAAABAwgy5gIAAAAAAAEEIlEg/euuKHi5JCPRfXT0zBQOHpmABZeNccGDE5KAQF4w5AYBCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgDIZOtDIdfrFJDc4AikAp3JMYXXdrJlEFlqrRXqt+cTzwBCgQCAAAAAAEDCKKGAQAAAAAAAQQiUSD04wY25I9qev6YT6CyVFslfqroyqFuxIGT2zSJJpWHWwEJQgKLeQ4Jh/3p8NEjmOtr4wxzdnk8ZHhloqAvLvyWDZZlaAMhk60Mh1+sUkNzgCKQCnckxhdd2smUQWWqtFeq35xPPAEKBAIAAAAA", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQMBBgEAAfsEAgAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQhsAkgwRQIhAJRZ+zSFzBNGQ56SncB08dOVrb6DBquU2d2EgUJo0Ow4AiA4CO4mOogDoXLmsxULLKIkyWEXoZ8OmVOUf6UgK6lwZQEhAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQ4gcOBrhlWVxMJzHTP1pq0oD7hwNVRmYpiAyl3NjpAH4ZoBDwQAAAAAARAE/v///yIdAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoIQJVgb+qczFW9rmOcaJvcP12s2eGSfYrH8Xne46auOYQUCIeAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoQHlAgZ626fJYwVg4fApkzBb1F8fvRAkSLM6qlPTi/1N2xCR7/BcNmyY7Dj0ga2aMh+lLNN7q+gCheSsEeteIdbsAAQMIoYYBAAAAAAABBCJRIJPaXrkneTYjgSVQ+GmdZjtxlvDMnUiEWLtoH+srb/y6AQlCAot5DgmH/enw0SOY62vjDHN2eTxkeGWioC8u/JYNlmVoA9QxWI3uYas6OXJbKZw3QtxmoIYd7PWRtCOw5ScHD4I0AQoEAQAAAAABAwgy5gIAAAAAAAEEIlEg/euuKHi5JCPRfXT0zBQOHpmABZeNccGDE5KAQF4w5AYBCUICi3kOCYf96fDRI5jra+MMc3Z5PGR4ZaKgLy78lg2WZWgDIZOtDIdfrFJDc4AikAp3JMYXXdrJlEFlqrRXqt+cTzwBCgQCAAAAAAEDCKKGAQAAAAAAAQQiUSD04wY25I9qev6YT6CyVFslfqroyqFuxIGT2zSJJpWHWwEJQgKLeQ4Jh/3p8NEjmOtr4wxzdnk8ZHhloqAvLvyWDZZlaAMhk60Mh1+sUkNzgCKQCnckxhdd2smUQWWqtFeq35xPPAEKBAIAAAAA" + }, "supplementary": { + "hex": "70736274ff0102040200000001040101010501030106010001fb04020000000001011f801a0600000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4830450221009459fb3485cc1346439e929dc074f1d395adbe8306ab94d9dd84814268d0ec3802203808ee263a8803a172e6b3150b2ca224c96117a19f0e9953947fa5202ba970650101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e2070e06b865595c4c2731d33f5a6ad280fb870355466629880ca5dcd8e9007e19a010f0400000000011004feffffff221d028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656821025581bfaa733156f6b98e71a26f70fd76b3678649f62b1fc5e77b8e9ab8e61050221e028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568407940819eb6e9f258c158387c0a64cc16f517c7ef4409122cceaa94f4e2ff5376c4247bfc170d9b263b0e3d206b668c87e94b34deeafa00a1792b047ad78875bb00010308a186010000000000010422512093da5eb927793623812550f8699d663b7196f0cc9d488458bb681feb2b6ffcba010942028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803d431588dee61ab3a39725b299c3742dc66a0861decf591b423b0e527070f8234010a04010000000001030832e60200000000000104225120fdebae2878b92423d17d74f4cc140e1e998005978d71c183139280405e30e406010942028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c010a040200000000010308a2860100000000000104225120f4e30636e48f6a7afe984fa0b2545b257eaae8caa16ec48193db34892695875b010942028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c010a040200000000", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "9ae107908ecd5dca80986266543570b80f28ada6f5331d73c2c49555866be070", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 400000, - "witness_utxo": "801a060000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01801a0600000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "801a0600000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -997,39 +1459,44 @@ "amount": 100001, "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d96656803d431588dee61ab3a39725b299c3742dc66a0861decf591b423b0e527070f8234", "sp_v0_label": 1, - "script": "51201bffa10fdaa2502c2f0c9285fe0af19a50f8515e3b6dfbf56de850d999014400" + "script": "512093da5eb927793623812550f8699d663b7196f0cc9d488458bb681feb2b6ffcba" }, { "output_index": 1, "amount": 190002, "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c", "sp_v0_label": 2, - "script": "5120884da6708c82b9b56c98bd3be6e5f53894bb1bfd90bfacf894025570f6bd5305" + "script": "5120fdebae2878b92423d17d74f4cc140e1e998005978d71c183139280405e30e406" }, { "output_index": 2, "amount": 100002, "sp_v0_info": "028b790e0987fde9f0d12398eb6be30c7376793c647865a2a02f2efc960d966568032193ad0c875fac5243738022900a7724c6175ddac9944165aab457aadf9c4f3c", "sp_v0_label": 2, - "script": "5120d291d339280e0c86e2c708a591f8e8e2f892d12a7cfe8510b667799b71131c86" + "script": "5120f4e30636e48f6a7afe984fa0b2545b257eaae8caa16ec48193db34892695875b" } - ] + ], + "task": "finalize" } }, { "description": "can finalize: two inputs using per-input ECDH shares - only eligible inputs contribute shares (P2SH excluded)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLTLcGPIp7P5Ia4ABZbNd4jlRA4dY+8e4bzsjCrJQMogIgNw2OmoWgzI3SWwuwgfMaotzFugoiSOqGCoFlHKNKDGgBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4g0iImLyaHKbt8hMVYEppdaYYYXO9TXsFJwN9g3UqSwgQBDwQAAAAAAQBTAgAAAAFA5vqmEmjxehAQHWJVNYKIKuSFi+4TNj24D98oH4Jf/AAAAAAA/////wHwSQIAAAAAABepFPRfjMomjsJuS76JkXDxOCUNfPVehwAAAAABBEdSIQKHfKAvFEBZvYLQDhs5muN094pSzvehyjfyjXiLNA0veSEDTIekSHL14fAG002IoAlZKCvUU150d8PWjDFlmR6hs5ZSrgEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCECYototkRuaocCWXPZOvsZTkIKEPOhzLOK3YLUZKiUpCgiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDCJBfAQAAAAAAAQQiUSAybfUP4KB7estyBwvrO2Muua0VumlcweWqaqAHthRv2AEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIHX/+DN7oavaEJzJjnIcVUgz9mY0VLyglR21zhcuA3LjAiAFXY5F4lr2Gu+QPcbwd9LpuW0Ut5Op7+w5K5bqn1Hf7gEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAFMCAAAAAUDm+qYSaPF6EBAdYlU1gogq5IWL7hM2PbgP3ygfgl/8AAAAAAD/////AfBJAgAAAAAAF6kU9F+MyiaOwm5LvomRcPE4JQ189V6HAAAAACICAod8oC8UQFm9gtAOGzma43T3ilLO96HKN/KNeIs0DS95SDBFAiEAqSSjxsVMq0LZrsVrZN4OgTZn7OqQUi0BVLG9SX4ez+YCIGft7MnVjKeYvO1u7T6P8a78F3wXYOtCur6uou2iCI3PASICA0yHpEhy9eHwBtNNiKAJWSgr1FNedHfD1owxZZkeobOWRzBEAiAFkbOcu2+fEK7M5arMpm9mZybWJUb4KIZG0kEVrZeVlQIgI77PzicSbG9Gn2gR0KGOTzipSLOk7Gg1PusWVdZmbOkBAQRHUiECh3ygLxRAWb2C0A4bOZrjdPeKUs73oco38o14izQNL3khA0yHpEhy9eHwBtNNiKAJWSgr1FNedHfD1owxZZkeobOWUq4BDiDSIiYvJocpu3yExVgSml1phhhc71NewUnA32DdSpLCBAEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAmKLaLZEbmqHAllz2Tr7GU5CChDzocyzit2C1GSolKQoIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwiQXwEAAAAAAAEEIlEgFlXRMkKnFHnfSR7Zw5s8dapbHNjQFr+Ms1SnTXd0Hd4BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQhrAkcwRAIgdf/4M3uhq9oQnMmOchxVSDP2ZjRUvKCVHbXOFy4DcuMCIAVdjkXiWvYa75A9xvB30um5bRS3k6nv7DkrluqfUd/uASECyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8BDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAFMCAAAAAUDm+qYSaPF6EBAdYlU1gogq5IWL7hM2PbgP3ygfgl/8AAAAAAD/////AfBJAgAAAAAAF6kU9F+MyiaOwm5LvomRcPE4JQ189V6HAAAAAAEH2gBIMEUCIQCpJKPGxUyrQtmuxWtk3g6BNmfs6pBSLQFUsb1Jfh7P5gIgZ+3sydWMp5i87W7tPo/xrvwXfBdg60K6vq6i7aIIjc8BRzBEAiAFkbOcu2+fEK7M5arMpm9mZybWJUb4KIZG0kEVrZeVlQIgI77PzicSbG9Gn2gR0KGOTzipSLOk7Gg1PusWVdZmbOkBR1IhAod8oC8UQFm9gtAOGzma43T3ilLO96HKN/KNeIs0DS95IQNMh6RIcvXh8AbTTYigCVkoK9RTXnR3w9aMMWWZHqGzllKuAQ4g0iImLyaHKbt8hMVYEppdaYYYXO9TXsFJwN9g3UqSwgQBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQJii2i2RG5qhwJZc9k6+xlOQgoQ86HMs4rdgtRkqJSkKCIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMIkF8BAAAAAAABBCJRIBZV0TJCpxR530ke2cObPHWqWxzY0Ba/jLNUp013dB3eAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==" + }, "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf473044022075fff8337ba1abda109cc98e721c554833f6663454bca0951db5ce172e0372e30220055d8e45e25af61aef903dc6f077d2e9b96d14b793a9efec392b96ea9f51dfee0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010053020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000220202877ca02f144059bd82d00e1b399ae374f78a52cef7a1ca37f28d788b340d2f79483045022100a924a3c6c54cab42d9aec56b64de0e813667ecea90522d0154b1bd497e1ecfe6022067edecc9d58ca798bced6eed3e8ff1aefc177c1760eb42babeaea2eda2088dcf012202034c87a44872f5e1f006d34d88a00959282bd4535e7477c3d68c3165991ea1b39647304402200591b39cbb6f9f10aecce5aacca66f666726d62546f8288646d24115ad979595022023becfce27126c6f469f6811d0a18e4f38a948b3a4ec68353eeb1655d6666ce901010447522102877ca02f144059bd82d00e1b399ae374f78a52cef7a1ca37f28d788b340d2f7921034c87a44872f5e1f006d34d88a00959282bd4535e7477c3d68c3165991ea1b39652ae010e20d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102628b68b6446e6a87025973d93afb194e420a10f3a1ccb38add82d464a894a428221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010308905f01000000000001042251201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, @@ -1037,13 +1504,12 @@ "input_index": 1, "private_key": "", "public_key": "", - "prevout_txid": "d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204", + "prevout_txid": "04c2924add60dfc049c15e53ef5c1886695d9a1258c5847cbb2987262f2622d2", "prevout_index": 0, - "prevout_scriptpubkey": "a914f45f8cca268ec26e4bbe899170f138250d7cf55e87", "amount": 150000, "non_witness_utxo": "020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000", "sequence": 4294967294, - "signed": false + "signed": true } ], "sp_proofs": [ @@ -1059,25 +1525,30 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "51201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde" } - ] + ], + "task": "finalize" } }, { "description": "can finalize: two inputs using global ECDH share - only eligible inputs contribute shares (P2SH excluded)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBACIHAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIIAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQCQwR50toTEKAk0qq45Me0nXbNUfRe6BJ8FZsDk6Z1tvdcWB6+PQgX3a87tZjP16Ai8ah+1HlmT2uUekfbWUHLIAAQ4gGKcXZjsLqxSxKhp3EyP/HkB53VMuXdE+KOoQgccAmEoBDwQAAAAAAQEfoIYBAAAAAAAWABQimnLTSmRb00lru/ULu4HJBj9PlCICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/SDBFAiEAi0y3BjyKez+SGuAAWWzXeI5UQOHWPvHuG87IwqyUDKICIDcNjpqFoMyN0lsLsIHzGqLcxboKIkjqhgqBZRyjSgxoASIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///wABDiDSIiYvJocpu3yExVgSml1phhhc71NewUnA32DdSpLCBAEPBAAAAAABAFMCAAAAAUDm+qYSaPF6EBAdYlU1gogq5IWL7hM2PbgP3ygfgl/8AAAAAAD/////AfBJAgAAAAAAF6kU9F+MyiaOwm5LvomRcPE4JQ189V6HAAAAAAEER1IhAod8oC8UQFm9gtAOGzma43T3ilLO96HKN/KNeIs0DS95IQNMh6RIcvXh8AbTTYigCVkoK9RTXnR3w9aMMWWZHqGzllKuARAE/v///wABAwiQXwEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAJDBHnS2hMQoCTSqrjkx7Sdds1R9F7oEnwVmwOTpnW291xYHr49CBfdrzu1mM/XoCLxqH7UeWZPa5R6R9tZQcsgH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOyICAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/RzBEAiB1//gze6Gr2hCcyY5yHFVIM/ZmNFS8oJUdtc4XLgNy4wIgBV2OReJa9hrvkD3G8HfS6bltFLeTqe/sOSuW6p9R3+4BIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////AAEAUwIAAAABQOb6phJo8XoQEB1iVTWCiCrkhYvuEzY9uA/fKB+CX/wAAAAAAP////8B8EkCAAAAAAAXqRT0X4zKJo7Cbku+iZFw8TglDXz1XocAAAAAIgICh3ygLxRAWb2C0A4bOZrjdPeKUs73oco38o14izQNL3lIMEUCIQCpJKPGxUyrQtmuxWtk3g6BNmfs6pBSLQFUsb1Jfh7P5gIgZ+3sydWMp5i87W7tPo/xrvwXfBdg60K6vq6i7aIIjc8BIgIDTIekSHL14fAG002IoAlZKCvUU150d8PWjDFlmR6hs5ZHMEQCIAWRs5y7b58Qrszlqsymb2ZnJtYlRvgohkbSQRWtl5WVAiAjvs/OJxJsb0afaBHQoY5POKlIs6TsaDU+6xZV1mZs6QEBBEdSIQKHfKAvFEBZvYLQDhs5muN094pSzvehyjfyjXiLNA0veSEDTIekSHL14fAG002IoAlZKCvUU150d8PWjDFlmR6hs5ZSrgEOINIiJi8mhym7fITFWBKaXWmGGFzvU17BScDfYN1KksIEAQ8EAAAAAAEQBP7///8AAQMIkF8BAAAAAAABBCJRIBZV0TJCpxR530ke2cObPHWqWxzY0Ba/jLNUp013dB3eAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAJDBHnS2hMQoCTSqrjkx7Sdds1R9F7oEnwVmwOTpnW291xYHr49CBfdrzu1mM/XoCLxqH7UeWZPa5R6R9tZQcsgH7BAIAAAAAAQEfoIYBAAAAAAAWABQeKteHLTKUE6Vt8JaL4zgiJ4MWOwEIawJHMEQCIHX/+DN7oavaEJzJjnIcVUgz9mY0VLyglR21zhcuA3LjAiAFXY5F4lr2Gu+QPcbwd9LpuW0Ut5Op7+w5K5bqn1Hf7gEhAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///wABAFMCAAAAAUDm+qYSaPF6EBAdYlU1gogq5IWL7hM2PbgP3ygfgl/8AAAAAAD/////AfBJAgAAAAAAF6kU9F+MyiaOwm5LvomRcPE4JQ189V6HAAAAAAEH2gBIMEUCIQCpJKPGxUyrQtmuxWtk3g6BNmfs6pBSLQFUsb1Jfh7P5gIgZ+3sydWMp5i87W7tPo/xrvwXfBdg60K6vq6i7aIIjc8BRzBEAiAFkbOcu2+fEK7M5arMpm9mZybWJUb4KIZG0kEVrZeVlQIgI77PzicSbG9Gn2gR0KGOTzipSLOk7Gg1PusWVdZmbOkBR1IhAod8oC8UQFm9gtAOGzma43T3ilLO96HKN/KNeIs0DS95IQNMh6RIcvXh8AbTTYigCVkoK9RTXnR3w9aMMWWZHqGzllKuAQ4g0iImLyaHKbt8hMVYEppdaYYYXO9TXsFJwN9g3UqSwgQBDwQAAAAAARAE/v///wABAwiQXwEAAAAAAAEEIlEgFlXRMkKnFHnfSR7Zw5s8dapbHNjQFr+Ms1SnTXd0Hd4BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA" + }, "supplementary": { + "hex": "70736274ff010204020000000104010201050101010601002207027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b2208027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068402430479d2da1310a024d2aab8e4c7b49d76cd51f45ee8127c159b0393a675b6f75c581ebe3d0817ddaf3bb598cfd7a022f1a87ed479664f6b947a47db5941cb201fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf473044022075fff8337ba1abda109cc98e721c554833f6663454bca0951db5ce172e0372e30220055d8e45e25af61aef903dc6f077d2e9b96d14b793a9efec392b96ea9f51dfee01220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff00010053020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000220202877ca02f144059bd82d00e1b399ae374f78a52cef7a1ca37f28d788b340d2f79483045022100a924a3c6c54cab42d9aec56b64de0e813667ecea90522d0154b1bd497e1ecfe6022067edecc9d58ca798bced6eed3e8ff1aefc177c1760eb42babeaea2eda2088dcf012202034c87a44872f5e1f006d34d88a00959282bd4535e7477c3d68c3165991ea1b39647304402200591b39cbb6f9f10aecce5aacca66f666726d62546f8288646d24115ad979595022023becfce27126c6f469f6811d0a18e4f38a948b3a4ec68353eeb1655d6666ce901010447522102877ca02f144059bd82d00e1b399ae374f78a52cef7a1ca37f28d788b340d2f7921034c87a44872f5e1f006d34d88a00959282bd4535e7477c3d68c3165991ea1b39652ae010e20d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204010f0400000000011004feffffff00010308905f01000000000001042251201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, @@ -1085,13 +1556,12 @@ "input_index": 1, "private_key": "", "public_key": "", - "prevout_txid": "d222262f268729bb7c84c558129a5d6986185cef535ec149c0df60dd4a92c204", + "prevout_txid": "04c2924add60dfc049c15e53ef5c1886695d9a1258c5847cbb2987262f2622d2", "prevout_index": 0, - "prevout_scriptpubkey": "a914f45f8cca268ec26e4bbe899170f138250d7cf55e87", "amount": 150000, "non_witness_utxo": "020000000140e6faa61268f17a10101d62553582882ae4858bee13363db80fdf281f825ffc0000000000ffffffff01f04902000000000017a914f45f8cca268ec26e4bbe899170f138250d7cf55e8700000000", "sequence": 4294967294, - "signed": false + "signed": true } ], "sp_proofs": [ @@ -1106,37 +1576,42 @@ "output_index": 0, "amount": 90000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "51201655d13242a71479df491ed9c39b3c75aa5b1cd8d016bf8cb354a74d77741dde" } - ] + ], + "task": "finalize" } }, { "description": "can finalize: two mixed input types - only eligible inputs contribute ECDH shares (NUMS internal key excluded)", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASsQJwAAAAAAACJRIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARAE/v///wEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAAAEOIL6dZcg5FfsJJIq738qMo+7mzjUMVU9l6NUm5d9SerUiAQ8EAAAAAAEBH6CGAQAAAAAAFgAURjPVnK0TQ0eZcuDJlpIdCl2ttl0iAgJDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFu0gwRQIhAPRhsN/2Q/wKVsFSIUU2OBYiEkh+UGpZ4GnXXtHwq4T2AiBSxx6U6TEuqKkAH80mNyvnCZfdwqpinFqBFtxR9bfpogEBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgcJQAAAAAAAAEEIlEgBXZyJSSDmoybydLZc46Yu0DdLsUCO9x9p/cGI818hfsBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABASsQJwAAAAAAACJRICG+i0nY1uxr8GEwJe9oKFeYqXr2DtXaB7tet9ZpYewfAQ4gf5Bfm6DLtvgc10oey2Jgyq0+b4BBDkksi/VcCP3O/qIBDwQAAAAAARAE/v///0EU0yyikmsyLxRdds/IsGPuOPTphLUnXHBcd/Np6i3BmNfLAtYsiG2qoOgP46KHLogLMsc1KtA6pxDvSin9Ml3wPkEFOScrenQKes5AMDDn/ar06CwQzyxJYJtq1S4XnXP8cGrRiaIfQgBg15MfR5azciZnamg8g9yiiQ7BcMS84OFaASIVwFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAIyDTLKKSazIvFF12z8iwY+449OmEtSdccFx382nqLcGY16zAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsABGCDLAtYsiG2qoOgP46KHLogLMsc1KtA6pxDvSin9Ml3wPgABAR+ghgEAAAAAABYAFDch+nPCMFyy+I6EiS1r1rl3Jh5qIgICQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbtHMEQCIEvgsV24URpQm0VnL8iNevy7bOFlEP7lL+UK0MIV+AO0AiANj93lbxA3Wm80S+AYlQrYIVTG31A3j6d9poXzrUU2jwEBAwQBAAAAIgYCQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsIAAAAgAEAAAABDiDnbAFxCDpMX7Sv4vbWHwCkcwG50B+NLkd4CrdULjd8CAEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAuV6etywGNj7MVToDBS5elCZS0I1aEHqn8ExcGFEAOY3Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA9/o4HeILO0WcbkJsYhPUF1MI8kgqROMyhCMmJNTa/Vcymb868WqzAsViY2OjfUSHB/fnoevqBke8zUhiA7srpgABAwgcJQAAAAAAAAEEIlEgLqIeHn2vtNQ7Mym1q9E4igU+7PPZwNHiakJEeFE284ABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABASsQJwAAAAAAACJRICG+i0nY1uxr8GEwJe9oKFeYqXr2DtXaB7tet9ZpYewfAQiIA0EFOScrenQKes5AMDDn/ar06CwQzyxJYJtq1S4XnXP8cGrRiaIfQgBg15MfR5azciZnamg8g9yiiQ7BcMS84OFaASIg0yyikmsyLxRdds/IsGPuOPTphLUnXHBcd/Np6i3BmNesIcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wAEOIH+QX5ugy7b4HNdKHstiYMqtPm+AQQ5JLIv1XAj9zv6iAQ8EAAAAAAEQBP7///8AAQEfoIYBAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeagEIawJHMEQCIEvgsV24URpQm0VnL8iNevy7bOFlEP7lL+UK0MIV+AO0AiANj93lbxA3Wm80S+AYlQrYIVTG31A3j6d9poXzrUU2jwEhAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7AQ4g52wBcQg6TF+0r+L21h8ApHMBudAfjS5HeAq3VC43fAgBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQLlenrcsBjY+zFU6AwUuXpQmUtCNWhB6p/BMXBhRADmNyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQPf6OB3iCztFnG5CbGIT1BdTCPJIKkTjMoQjJiTU2v1XMpm/OvFqswLFYmNjo31Ehwf356Hr6gZHvM1IYgO7K6YAAQMIHCUAAAAAAAABBCJRIC6iHh59r7TUOzMptavROIoFPuzz2cDR4mpCRHhRNvOAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==" + }, "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001012b102700000000000022512021be8b49d8d6ec6bf0613025ef68285798a97af60ed5da07bb5eb7d66961ec1f010e207f905f9ba0cbb6f81cd74a1ecb6260caad3e6f80410e492c8bf55c08fdcefea2010f0400000000011004feffffff4114d32ca2926b322f145d76cfc8b063ee38f4e984b5275c705c77f369ea2dc198d7cb02d62c886daaa0e80fe3a2872e880b32c7352ad03aa710ef4a29fd325df03e410539272b7a740a7ace403030e7fdaaf4e82c10cf2c49609b6ad52e179d73fc706ad189a21f420060d7931f4796b37226676a683c83dca2890ec170c4bce0e15a012215c050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac02320d32ca2926b322f145d76cfc8b063ee38f4e984b5275c705c77f369ea2dc198d7acc001172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0011820cb02d62c886daaa0e80fe3a2872e880b32c7352ad03aa710ef4a29fd325df03e0001011fa0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a22020243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb47304402204be0b15db8511a509b45672fc88d7afcbb6ce16510fee52fe50ad0c215f803b402200d8fdde56f10375a6f344be018950ad82154c6df50378fa77da685f3ad45368f010103040100000022060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000010e20e76c0171083a4c5fb4afe2f6d61f00a47301b9d01f8d2e47780ab7542e377c08010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6000103081c2500000000000001042251202ea21e1e7dafb4d43b3329b5abd1388a053eecf3d9c0d1e26a4244785136f380010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", - "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "private_key": "9dab08c8eb0a4d9984ba709d580d009608f7b117dd4620eb4209c1d67a6c29d0", + "public_key": "02d32ca2926b322f145d76cfc8b063ee38f4e984b5275c705c77f369ea2dc198d7", + "prevout_txid": "a2fecefd085cf58b2c490e41806f3eadca6062cb1e4ad71cf8b6cba09b5f907f", "prevout_index": 0, - "prevout_scriptpubkey": "512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", "amount": 10000, - "witness_utxo": "102700000000000022512050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "non_witness_utxo": "020000000113f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d020000000000ffffffff01102700000000000022512021be8b49d8d6ec6bf0613025ef68285798a97af60ed5da07bb5eb7d66961ec1f00000000", + "witness_utxo": "102700000000000022512021be8b49d8d6ec6bf0613025ef68285798a97af60ed5da07bb5eb7d66961ec1f", "sequence": 4294967294, - "signed": false + "signed": true }, { "input_index": 1, "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "087c372e54b70a78472e8d1fd0b90173a4001fd6f6e2afb45f4c3a0871016ce7", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 100000, - "witness_utxo": "a0860100000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "a0860100000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": true } @@ -1154,25 +1629,30 @@ "output_index": 0, "amount": 9500, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51200576722524839a8c9bc9d2d9738e98bb40dd2ec5023bdc7da7f70623cd7c85fb" + "script": "51202ea21e1e7dafb4d43b3329b5abd1388a053eecf3d9c0d1e26a4244785136f380" } - ] + ], + "task": "finalize" } }, { "description": "can finalize: three sp outputs (same scan key) - each output has distinct k value", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEEAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+AGgYAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIA3+9XB4r8pV2yK0ze42yxF/h2HkeAgptCHRBkisr62PAiBk5vWJD0/QW3emSnGDHJiGTZyYTJ7x/r6afFC08VkHIQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgMm31D+Cge3rLcgcL6ztjLrmtFbppXMHlqmqgB7YUb9gBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIoIYBAAAAAAABBCJRID/LrqSQh/jgPZ3v06vL1t6MAytYP4WmXQV4gcTEQ83AAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCKCGAQAAAAAAAQQiUSCXFELInwR4bggnKK4Rbuq4AvP6npX9sNN1OmhAICAG3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwiQXwEAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQQBBgEAAfsEAgAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIH2bvrz6uqFt0Kqa+PjltDT3VIfbiiHm1QtEnjAT9WsrAiAlq8iYSKvhCgxaq6TPG5n553yKIkS2xy6zrFdRfncXuAEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiBw4GuGVZXEwnMdM/WmrSgPuHA1VGZimIDKXc2OkAfhmgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgpL1hojWVPFX7Ib8SF+ZZlw+BcVUweVNwtqhuui4/buABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIoIYBAAAAAAABBCJRIEZ7FHQz3K03MqLFl4fZe6tlntq7U2+lo3EHQLVhS4t1AQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCKCGAQAAAAAAAQQiUSCkZ5TVNLTq9lSGWuFY2oR7xga4HYq3jhMySv5KWUnbhQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwiQXwEAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQA", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQQBBgEAAfsEAgAAAAABAR+AGgYAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQhrAkcwRAIgfZu+vPq6oW3Qqpr4+OW0NPdUh9uKIebVC0SeMBP1aysCICWryJhIq+EKDFqrpM8bmfnnfIoiRLbHLrOsV1F+dxe4ASECyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8BDiBw4GuGVZXEwnMdM/WmrSgPuHA1VGZimIDKXc2OkAfhmgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgpL1hojWVPFX7Ib8SF+ZZlw+BcVUweVNwtqhuui4/buABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIoIYBAAAAAAABBCJRIEZ7FHQz3K03MqLFl4fZe6tlntq7U2+lo3EHQLVhS4t1AQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCKCGAQAAAAAAAQQiUSCkZ5TVNLTq9lSGWuFY2oR7xga4HYq3jhMySv5KWUnbhQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwiQXwEAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQA" + }, "supplementary": { + "hex": "70736274ff0102040200000001040101010501040106010001fb04020000000001011f801a0600000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402207d9bbebcfabaa16dd0aa9af8f8e5b434f75487db8a21e6d50b449e3013f56b2b022025abc89848abe10a0c5aaba4cf1b99f9e77c8a2244b6c72eb3ac57517e7717b80101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e2070e06b865595c4c2731d33f5a6ad280fb870355466629880ca5dcd8e9007e19a010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308a0860100000000000104225120a4bd61a235953c55fb21bf1217e659970f81715530795370b6a86eba2e3f6ee0010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900010308a0860100000000000104225120467b147433dcad3732a2c59787d97bab659edabb536fa5a3710740b5614b8b75010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900010308a0860100000000000104225120a46794d534b4eaf654865ae158da847bc606b81d8ab78e13324afe4a5949db85010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900010308905f010000000000010422512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da400", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "9ae107908ecd5dca80986266543570b80f28ada6f5331d73c2c49555866be070", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 400000, - "witness_utxo": "801a060000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01801a0600000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "801a0600000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -1190,42 +1670,47 @@ "output_index": 0, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "5120a4bd61a235953c55fb21bf1217e659970f81715530795370b6a86eba2e3f6ee0" }, { "output_index": 1, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + "script": "5120467b147433dcad3732a2c59787d97bab659edabb536fa5a3710740b5614b8b75" }, { "output_index": 2, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + "script": "5120a46794d534b4eaf654865ae158da847bc606b81d8ab78e13324afe4a5949db85" }, { "output_index": 3, "amount": 90000, "script": "512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da4" } - ] + ], + "task": "finalize" } }, { "description": "can finalize: three sp outputs (same scan key) / two regular outputs - k values assigned independently of output index", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEGAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR8goQcAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQD333KAYwDd2+SyTNcz9TsypkayNsKUYFfeR65QOyqxaAIgTGlAW3e+2vOyB+3ll0m7o9VMRhWoi7025Ugkr3fJ5zEBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQMIoIYBAAAAAAABBCJRIDJt9Q/goHt6y3IHC+s7Yy65rRW6aVzB5apqoAe2FG/YAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCFDDAAAAAAAAAQQiUSCcaj0jgY6CDtHQz965Y2V8jsMne32bhlx411V/Xe3WogABAwighgEAAAAAAAEEIlEgP8uupJCH+OA9ne/Tq8vW3owDK1g/haZdBXiBxMRDzcABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIUMMAAAAAAAABBCJRIHnvVoij+n/vw5InRVsfHC8IxwCHQk1qAPhMMUIayo2kAAEDCKCGAQAAAAAAAQQiUSCXFELInwR4bggnKK4Rbuq4AvP6npX9sNN1OmhAICAG3gEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwjILAEAAAAAAAEEIlEgb8UG+AUqn1qKqbmQ1emU9JXd7W1HusRMqs2t2NiZHNAA", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQYBBgEAAfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCICcgzDtRc5g6XoCKbBZuU04tEOEjpGhrAqg+sdM9G3B6AiBdslMBO2N4nLRYrOIxjHkT9mvR6OIXHye1MrEw+uWDNQEBAwQBAAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgcjuJtcY4edW50HowRRu91I43rAOOZvcm83ykCrJkq3IBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIUMMAAAAAAAABBCJRIJxqPSOBjoIO0dDP3rljZXyOwyd7fZuGXHjXVX9d7daiAAEDCKCGAQAAAAAAAQQiUSCvFHbuA/XpiJDsVJYDYaxJHFbjCpPrKYD8MiuYN6dYugEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwhQwwAAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQAAQMIoIYBAAAAAAABBCJRIJ5nNdGxGWsLGu/g5NEOytKTdJZLn1mSBdF8qrYcp4VFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCMgsAQAAAAAAAQQiUSBvxQb4BSqfWoqpuZDV6ZT0ld3tbUe6xEyqza3Y2Jkc0AA=", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQYBBgEAAfsEAgAAAAABAR8goQcAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQhrAkcwRAIgJyDMO1FzmDpegIpsFm5TTi0Q4SOkaGsCqD6x0z0bcHoCIF2yUwE7Y3ictFis4jGMeRP2a9Ho4hcfJ7UysTD65YM1ASECyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8BDiDUQOda/N1TGlkeN6vSbkryvw9v8uGRgwI1Yej8VxOPSgEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwighgEAAAAAAAEEIlEgcjuJtcY4edW50HowRRu91I43rAOOZvcm83ykCrJkq3IBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkAAQMIUMMAAAAAAAABBCJRIJxqPSOBjoIO0dDP3rljZXyOwyd7fZuGXHjXVX9d7daiAAEDCKCGAQAAAAAAAQQiUSCvFHbuA/XpiJDsVJYDYaxJHFbjCpPrKYD8MiuYN6dYugEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQABAwhQwwAAAAAAAAEEIlEgee9WiKP6f+/DkidFWx8cLwjHAIdCTWoA+EwxQhrKjaQAAQMIoIYBAAAAAAABBCJRIJ5nNdGxGWsLGu/g5NEOytKTdJZLn1mSBdF8qrYcp4VFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AAEDCMgsAQAAAAAAAQQiUSBvxQb4BSqfWoqpuZDV6ZT0ld3tbUe6xEyqza3Y2Jkc0AA=" + }, "supplementary": { + "hex": "70736274ff0102040200000001040101010501060106010001fb04020000000001011f20a10700000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402202720cc3b5173983a5e808a6c166e534e2d10e123a4686b02a83eb1d33d1b707a02205db253013b63789cb458ace2318c7913f66bd1e8e2171f27b532b130fae583350101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20d440e75afcdd531a591e37abd26e4af2bf0f6ff2e19183023561e8fc57138f4a010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee3202100010308a0860100000000000104225120723b89b5c63879d5b9d07a30451bbdd48e37ac038e66f726f37ca40ab264ab72010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce0390001030850c300000000000001042251209c6a3d23818e820ed1d0cfdeb963657c8ec3277b7d9b865c78d7557f5dedd6a200010308a0860100000000000104225120af1476ee03f5e98890ec54960361ac491c56e30a93eb2980fc322b9837a758ba010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce0390001030850c3000000000000010422512079ef5688a3fa7fefc39227455b1f1c2f08c70087424d6a00f84c31421aca8da400010308a08601000000000001042251209e6735d1b1196b0b1aefe0e4d10ecad29374964b9f599205d17caab61ca78545010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900010308c82c01000000000001042251206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd000", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "4a8f1357fce86135028391e1f26f0fbff24a6ed2ab371e591a53ddfc5ae740d4", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 500000, - "witness_utxo": "20a1070000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff0120a10700000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "20a10700000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true } @@ -1243,7 +1728,7 @@ "output_index": 0, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120326df50fe0a07b7acb72070beb3b632eb9ad15ba695cc1e5aa6aa007b6146fd8" + "script": "5120723b89b5c63879d5b9d07a30451bbdd48e37ac038e66f726f37ca40ab264ab72" }, { "output_index": 1, @@ -1254,7 +1739,7 @@ "output_index": 2, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "51203fcbaea49087f8e03d9defd3abcbd6de8c032b583f85a65d057881c4c443cdc0" + "script": "5120af1476ee03f5e98890ec54960361ac491c56e30a93eb2980fc322b9837a758ba" }, { "output_index": 3, @@ -1265,42 +1750,47 @@ "output_index": 4, "amount": 100000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120971442c89f04786e082728ae116eeab802f3fa9e95fdb0d3753a6840202006de" + "script": "51209e6735d1b1196b0b1aefe0e4d10ecad29374964b9f599205d17caab61ca78545" }, { "output_index": 5, "amount": 77000, "script": "51206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd0" } - ] + ], + "task": "finalize" } }, { "description": "in progress: two P2TR inputs, neither is signed", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AQMEAQAAAAEQBP7///8BFyDIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvyIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gK5A3/0HdF05VIvD0BFw/QENiMq8mANTaXJ6hPMPKtLUBDwQAAAAAAQErECcAAAAAAAAiUSBDoNQOneCIJ5QWF1K65CupCVJ4QgnwY0MPCvJWNUqFuwEDBAEAAAABEAT+////ARcgQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsiHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEC5Xp63LAY2PsxVOgMFLl6UJlLQjVoQeqfwTFwYUQA5jciHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaED3+jgd4gs7RZxuQmxiE9QXUwjySCpE4zKEIyYk1Nr9VzKZvzrxarMCxWJjY6N9RIcH9+eh6+oGR7zNSGIDuyumAAEDCLj5AgAAAAAAAQQiUSDLH766UNBuv/tpC9qdX/Oc4vrbT87clmMu/xukHMDAewEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAStADQMAAAAAACJRIOr+wb8f+Gc4KaZp0ODVHmm4+HjCR3lPlLOIEAxKsoGoAQMEAQAAAAEOII8FdrO+JFR/LnHnx5E/usrGtDeRW7vskxyrz2lTxHduAQ8EAAAAAAEQBP7///8BFyDIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvyIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQKTeleGEmR20MC8e8mIUIEPZ0rqwX2n+myKPS517xDUfiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQLuFH43RADO9jLKEIl3bFF23tT1d58bq4VOAtAPzZGxoFAXmphUtj6HD5QQeouV+4GRyObGwMsqB/F0qs9lgFj4AAQErECcAAAAAAAAiUSByxJhK7EuuS9mftctjf98L3uLqGESO1I7dm3QHV5emHQEDBAEAAAABDiBK7+9qIrqY39KfGZyZ5uRg6lkyVeZUs7+YLAU/Zl6MNAEPBAAAAAABEAT+////ARcgQ6DUDp3giCeUFhdSuuQrqQlSeEIJ8GNDDwryVjVKhbsiHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCEDqyW+QCj++wxirIYxCPsMh/4IwcZ7wf2zwvtouIX3yhUiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaEDmalcdRGkQ4vvQ2EKCAsY6u1QmOGRDP70nIxFZc2vFlkZhZSkeUq+TMI9trZUVvluEWN/MmPHV/1+iGC5Lo3TnAAEDCLj5AgAAAAAAAQQiUSDt0WY14OrJfJ2zc3tD6kg1WVtBWfEASCMpWHOUAeiILwEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAStADQMAAAAAACJRIOr+wb8f+Gc4KaZp0ODVHmm4+HjCR3lPlLOIEAxKsoGoAQMEAQAAAAEOII8FdrO+JFR/LnHnx5E/usrGtDeRW7vskxyrz2lTxHduAQ8EAAAAAAEQBP7///8BE0H0bmbAbil+cc5EFPqPkPwQk9mSDUf4dxVqsFEFw84EyOObQdNQJibQGHfsRg0zU4EGw7AsBJbtGtmaKsE51XNoAQEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghApN6V4YSZHbQwLx7yYhQgQ9nSurBfaf6bIo9LnXvENR+Ih4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAu4UfjdEAM72MsoQiXdsUXbe1PV3nxurhU4C0A/NkbGgUBeamFS2PocPlBB6i5X7gZHI5sbAyyoH8XSqz2WAWPgABASsQJwAAAAAAACJRIHLEmErsS65L2Z+1y2N/3wve4uoYRI7Ujt2bdAdXl6YdAQMEAQAAAAEOIErv72oiupjf0p8ZnJnm5GDqWTJV5lSzv5gsBT9mXow0AQ8EAAAAAAEQBP7///8BE0EBEFz/OSaUDU1S949X1JV02VgDoq6nh+8L2ioapKWkXoboEVENOguuBRQ8Ud5Z1pUZmu/JO/JpJ970Af+bLuNgAQEXIEOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA6slvkAo/vsMYqyGMQj7DIf+CMHGe8H9s8L7aLiF98oVIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA5mpXHURpEOL70NhCggLGOrtUJjhkQz+9JyMRWXNrxZZGYWUpHlKvkzCPba2VFb5bhFjfzJjx1f9fohguS6N05wABAwi4+QIAAAAAAAEEIlEg7dFmNeDqyXyds3N7Q+pINVlbQVnxAEgjKVhzlAHoiC8BCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA" + }, "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001012b400d030000000000225120eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a801030401000000010e208f0576b3be24547f2e71e7c7913fbacac6b437915bbbec931cabcf6953c4776e010f0400000000011004feffffff011720c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682102937a5786126476d0c0bc7bc98850810f674aeac17da7fa6c8a3d2e75ef10d47e221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840bb851f8dd10033bd8cb284225ddb145db7b53d5de7c6eae15380b403f3646c681405e6a6152d8fa1c3e5041ea2e57ee0647239b1b032ca81fc5d2ab3d960163e0001012b102700000000000022512072c4984aec4bae4bd99fb5cb637fdf0bdee2ea18448ed48edd9b74075797a61d01030401000000010e204aefef6a22ba98dfd29f199c99e6e460ea593255e654b3bf982c053f665e8c34010f0400000000011004feffffff01172043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103ab25be4028fefb0c62ac863108fb0c87fe08c1c67bc1fdb3c2fb68b885f7ca15221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe06840e66a571d446910e2fbd0d8428202c63abb54263864433fbd27231159736bc596466165291e52af93308f6dad9515be5b8458dfcc98f1d5ff5fa2182e4ba374e700010308b8f90200000000000104225120edd16635e0eac97c9db3737b43ea4835595b4159f10048232958739401e8882f010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", - "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "private_key": "2c0141a983cc711ec6a59cd7bccad7a159c43dab09d6e783e91facc865134da5", + "public_key": "02eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a8", + "prevout_txid": "6e77c45369cfab1c93ecbb5b9137b4c6caba3f91c7e7712e7f5424beb376058f", "prevout_index": 0, - "prevout_scriptpubkey": "5120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "amount": 100000, - "witness_utxo": "a086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "amount": 200000, + "non_witness_utxo": "020000000113f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d020000000000ffffffff01400d030000000000225120eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a800000000", + "witness_utxo": "400d030000000000225120eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a8", "sequence": 4294967294, "signed": false }, { "input_index": 1, - "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", - "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "2b9037ff41dd174e5522f0f4045c3f40436232af2600d4da5c9ea13cc3cab4b5", + "private_key": "0f31b97d707a7f76eb099f41f372dbe12f2ef7a685ced8b6309eefc4e7b60afc", + "public_key": "0272c4984aec4bae4bd99fb5cb637fdf0bdee2ea18448ed48edd9b74075797a61d", + "prevout_txid": "348c5e663f052c98bfb354e6553259ea60e4e6999c199fd2df98ba226aefef4a", "prevout_index": 0, - "prevout_scriptpubkey": "512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", "amount": 10000, - "witness_utxo": "102700000000000022512043a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", + "non_witness_utxo": "02000000012b9037ff41dd174e5522f0f4045c3f40436232af2600d4da5c9ea13cc3cab4b50000000000ffffffff01102700000000000022512072c4984aec4bae4bd99fb5cb637fdf0bdee2ea18448ed48edd9b74075797a61d00000000", + "witness_utxo": "102700000000000022512072c4984aec4bae4bd99fb5cb637fdf0bdee2ea18448ed48edd9b74075797a61d", "sequence": 4294967294, "signed": false } @@ -1308,14 +1798,14 @@ "sp_proofs": [ { "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", - "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", - "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "ecdh_share": "02937a5786126476d0c0bc7bc98850810f674aeac17da7fa6c8a3d2e75ef10d47e", + "dleq_proof": "bb851f8dd10033bd8cb284225ddb145db7b53d5de7c6eae15380b403f3646c681405e6a6152d8fa1c3e5041ea2e57ee0647239b1b032ca81fc5d2ab3d960163e", "input_index": 0 }, { "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", - "ecdh_share": "02e57a7adcb018d8fb3154e80c14b97a50994b42356841ea9fc13170614400e637", - "dleq_proof": "f7fa381de20b3b459c6e426c6213d4175308f2482a44e33284232624d4dafd573299bf3af16ab302c5626363a37d448707f7e7a1ebea0647bccd486203bb2ba6", + "ecdh_share": "03ab25be4028fefb0c62ac863108fb0c87fe08c1c67bc1fdb3c2fb68b885f7ca15", + "dleq_proof": "e66a571d446910e2fbd0d8428202c63abb54263864433fbd27231159736bc596466165291e52af93308f6dad9515be5b8458dfcc98f1d5ff5fa2182e4ba374e7", "input_index": 1 } ], @@ -1324,25 +1814,30 @@ "output_index": 0, "amount": 195000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", - "script": "5120cb1fbeba50d06ebffb690bda9d5ff39ce2fadb4fcedc96632eff1ba41cc0c07b" + "script": "5120edd16635e0eac97c9db3737b43ea4835595b4159f10048232958739401e8882f" } - ] + ], + "task": "sign" } }, { "description": "in progress: one P2TR input / one sp output with no ECDH shares when PSBT_OUT_SCRIPT field is not set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQEBAQYBAAABDiAT8Qa2S1e1sTdvn2xHGQ9AzAazvty4qrqXhQqz1/Z9AgEPBAAAAAABASughgEAAAAAACJRIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/ARAE/v///wEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABASughgEAAAAAACJRIOr+wb8f+Gc4KaZp0ODVHmm4+HjCR3lPlLOIEAxKsoGoAQ4gGO7ojX/Kt6ZwMBR271G7BhVP/avuATRXs3uzQbBSWwsBDwQAAAAAARAE/v///wEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABASughgEAAAAAACJRIOr+wb8f+Gc4KaZp0ODVHmm4+HjCR3lPlLOIEAxKsoGoAQ4gGO7ojX/Kt6ZwMBR271G7BhVP/avuATRXs3uzQbBSWwsBDwQAAAAAARAE/v///wEXIMgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==" + }, "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001012ba086010000000000225120eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a8010e2018eee88d7fcab7a670301476ef51bb06154ffdabee013457b37bb341b0525b0b010f0400000000011004feffffff011720c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf000103081873010000000000010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", - "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "13f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d02", + "private_key": "", + "public_key": "02eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a8", + "prevout_txid": "0b5b52b041b37bb3573401eeabfd4f1506bb51ef76143070a6b7ca7f8de8ee18", "prevout_index": 0, - "prevout_scriptpubkey": "5120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", "amount": 100000, - "witness_utxo": "a086010000000000225120c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "non_witness_utxo": "020000000113f106b64b57b5b1376f9f6c47190f40cc06b3bedcb8aaba97850ab3d7f67d020000000000ffffffff01a086010000000000225120eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a800000000", + "witness_utxo": "a086010000000000225120eafec1bf1ff8673829a669d0e0d51e69b8f878c247794f94b388100c4ab281a8", "sequence": 4294967294, "signed": false } @@ -1354,35 +1849,40 @@ "amount": 95000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" } - ] + ], + "task": "sign" } }, { "description": "in progress: two inputs / one sp output, input 1 missing ECDH share when PSBT_OUT_SCRIPT field is not set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQIBBQEBAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQ4gvp1lyDkV+wkkirvfyoyj7ubONQxVT2Xo1Sbl31J6tSIBDwQAAAAAAQEf8EkCAAAAAAAWABRGM9WcrRNDR5ly4MmWkh0KXa22XSIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAARAE/v///wABAwhADQMAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQEf8EkCAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeaiIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAAQ4gSQv/chrf7ISJdgPfb7uyrbjEZTqaQrLW0VICyiQN4LEBDwQAAAAAARAE/v///wABAwhADQMAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQPspP8Rtyji4PYM5iIpQ6b/VbnZX2J7+amdCEvIctUKWyIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQIoTs5hVRfcr1uiXFK65CbPjVKhCqbuLVs0O3tId+KGZWYsxIopJ4L1+lc4QU/fFsorLVDpocHYA486Jgi7jICEAAQEf8EkCAAAAAAAWABQ3IfpzwjBcsviOhIkta9a5dyYeaiIGAkOg1A6d4IgnlBYXUrrkK6kJUnhCCfBjQw8K8lY1SoW7CAAAAIABAAAAAQ4gSQv/chrf7ISJdgPfb7uyrbjEZTqaQrLW0VICyiQN4LEBDwQAAAAAARAE/v///wABAwhADQMAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=" + }, "supplementary": { + "hex": "70736274ff0102040200000001040102010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001011ff0490200000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a22060243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb080000008001000000010e20490bff721adfec84897603df6fbbb2adb8c4653a9a42b2d6d15202ca240de0b1010f0400000000011004feffffff00010308400d030000000000010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", "inputs": [ { "input_index": 0, "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false }, { "input_index": 1, - "private_key": "586b0810bbc3c7266971aeb7f8778b41707e092a1aeaf0d953b211f956e35541", + "private_key": "", "public_key": "0243a0d40e9de0882794161752bae42ba90952784209f063430f0af256354a85bb", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "b1e00d24ca0252d1d6b2429a3a65c4b8adb2bb6fdf03768984ecdf1a72ff0b49", "prevout_index": 0, - "prevout_scriptpubkey": "00144633d59cad1343479972e0c996921d0a5dadb65d", "amount": 150000, - "witness_utxo": "f0490200000000001600144633d59cad1343479972e0c996921d0a5dadb65d", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01f0490200000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a00000000", + "witness_utxo": "f0490200000000001600143721fa73c2305cb2f88e84892d6bd6b977261e6a", "sequence": 4294967294, "signed": false } @@ -1401,23 +1901,28 @@ "amount": 200000, "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" } - ] + ], + "task": "sign" } }, { "description": "in progress: one input / two sp outputs, input 0 missing ECDH share for output 0 when PSBT_OUT_SCRIPT field is not set", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQEBBQECAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR9ADQMAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIAAQMIkF8BAAAAAAABCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIENYHfbIefmqrcU2YN6xVrnxIr0a7KczIDvOh/zx84buAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR9ADQMAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIAAQMIkF8BAAAAAAABCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIGMlBrk4zY0hMZ/eTlk5KyP5juuXb0OS1jPxg+Iut/qxAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQIBBgEAAfsEAgAAAAABAR9ADQMAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g/S309Ytav5uR/xoeQ+LjUj9QxqoZ1cIjYBQexIyagCEBDwQAAAAAARAE/v///yIdA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsIQMJH9SAORd/RNe3npYWiEnGLrP4eADEZ2fFCo84+Y79FSIeA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsQL4acjrvVeiYG5lZmpvBKzj4froBWMxwZokPImnK3kY7dzQal9KScZZNAcAkHMMi/VOQwpuZFg+CbzKTZYmMvwIAAQMIkF8BAAAAAAABCUIDZR0sBz/LAqTYLdpT8dUB13oDUGZnmFRkc7ISa2zRp94D8nDgpWMhg7arAQdOh35oANsA9cfF0vr7to+cKNSFRSQAAQMIkF8BAAAAAAABBCJRIGMlBrk4zY0hMZ/eTlk5KyP5juuXb0OS1jPxg+Iut/qxAQlCA1LXjEE5ADKtkYFqaX/HQNjrkJzwTXCIUmSwUfI4XiXsAuDEwYe3IV+ZfISFp1tFkbbChHe5WhEjuZaSLTFUhgv4AA==" + }, "supplementary": { + "hex": "70736274ff0102040200000001040101010501020106010001fb04020000000001011f400d0300000000001600141e2ad7872d329413a56df0968be338222783163b01030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20fd2df4f58b5abf9b91ff1a1e43e2e3523f50c6aa19d5c22360141ec48c9a8021010f0400000000011004feffffff221d0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec2103091fd48039177f44d7b79e96168849c62eb3f87800c46767c50a8f38f98efd15221e0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec40be1a723aef55e8981b99599a9bc12b38f87eba0158cc7066890f2269cade463b77341a97d29271964d01c0241cc322fd5390c29b99160f826f329365898cbf0200010308905f01000000000001094203651d2c073fcb02a4d82dda53f1d501d77a0350666798546473b2126b6cd1a7de03f270e0a5632183b6ab01074e877e6800db00f5c7c5d2fafbb68f9c28d485452400010308905f0100000000000104225120632506b938cd8d21319fde4e59392b23f98eeb976f4392d633f183e22eb7fab10109420352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf800", "inputs": [ { "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "private_key": "", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "21809a8cc41e146023c2d519aac6503f52e3e2431e1aff919bbf5a8bf5f42dfd", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 200000, - "witness_utxo": "400d030000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01400d0300000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "400d0300000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": false } @@ -1440,119 +1945,123 @@ "output_index": 1, "amount": 90000, "sp_v0_info": "0352d78c41390032ad91816a697fc740d8eb909cf04d70885264b051f2385e25ec02e0c4c187b7215f997c8485a75b4591b6c28477b95a1123b996922d3154860bf8", - "script": "512043581df6c879f9aaadc53660deb156b9f122bd1aeca733203bce87fcf1f386ee" + "script": "5120632506b938cd8d21319fde4e59392b23f98eeb976f4392d633f183e22eb7fab1" } - ] + ], + "task": "sign" } }, { "description": "in progress: large PSBT with nine mixed inputs / six outputs - some inputs signed", - "psbt": "cHNidP8B+wQCAAAAAQIEAgAAAAEEAQkBBQEGAQYBAAABDiAYpxdmOwurFLEqGncTI/8eQHndUy5d0T4o6hCBxwCYSgEPBAAAAAABAR+ghgEAAAAAABYAFCKactNKZFvTSWu79Qu7gckGP0+UIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCLNThMVlDzsjgXC0oPt/Sorr8CiDHHC50NMY3FUceJxgIgMZmwKWN19OdCfS+4KMjLfkHblItuYaaIKCeY8x+RIogBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQP70XPZxI1YxQIkJtBSeLyhe5qOIoJmaQGhsAueBLeZSSIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQNzctF59PYo2oLMvU5CF72wgJ8UF8mr6qNfqAXUitZVTCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMBdpBBIfPrsN4/r5q9QBeOubIYjaBiw5VshQBfrUHPt70AXlXW13NqpBjSRrIuD/QYk1Bd6TS3UmUxGQNa4zN4iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAAE4PUZhvocl7ykEj0jJEfifXzQxfXwMCsxg72XxtSv/96ltgzm2Jd+Dq6tXqic+3NmjXHlNrLschhFxuyZwdfIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxApoctTrEZ/ir3CVP3UqIiNrVKO1f3DlEfEL2LQv9Wtaz2NlCTxIDqnxN3Z4SUW1kxisKSfZFariRM+2g/QYijpwABDiC+nWXIORX7CSSKu9/KjKPu5s41DFVPZejVJuXfUnq1IgEPBAAAAAABAR+ghgEAAAAAABYAFBOTUBF8V3lBqYWAK7nt78ETkyvHIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxHMEQCIGBe6cE9y5EoaPHeTsHHUaxLRis49eXxBj+EHthVABbpAiBHqaafS5jOmNbyz3jQjoWlVWhRC3tc+65oAn9FjH5+BQEBAwQBAAAAIgYC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtwIAAAAgAEAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhA6aomxuYaplVM+F77WRQC1QbsNc5Bx7+KuK377CgymvPIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAvaue4qsmg+cnwTqtIQGIXLfLjjZ8vbsMbQEu1ooaqvwIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhArHT7S+kvDFqCOsUhfp17X3VTKeprhjQxKF9qT8ww4XVIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAw0pqKUC76ac1bBzG/+NY3URB21iJfLqZwhLrdShefaHsoRx5LJejgEkzRasiTenZTCs27oUmriNSgXGjIx3nMyIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQDNKztgQbrqkKH2spWzKJnlfLSpzl4TPa3NNozcHV/SZ4SDA5AvkBDbNdMTvJpBXBvUvp/pujnZFHoWDeDBRqEMiHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEDYQaNzrSiWuXK4z+oWNP8Uow+A2Ez9bvGIkzl7jzRsgFGcmxYaciRNDptk5UNsmM6d1OF6Byj8mXtce885zstoAAEOINBBx0LKNkRy0aGMeo6uB+bpBKnqG4XxmFJfuD7yduNDAQ8EAAAAAAEBH6CGAQAAAAAAFgAUIwf8d0yhdLQq2oFLwubkRP89gwwiAgJlXvXa8F0o0cpzuo4hEwDbK3BBZzcYPg+ow1XuTBy6xkcwRAIgKTOk1x6k+7U8mzjYjLK+bqIQKQBrzEx5rJgFGKrIYxkCICj9GcotjGhqD9CjsK6gmpqVgMw4oisFIgS+RXXwNa0/AQEDBAEAAAAiBgJlXvXa8F0o0cpzuo4hEwDbK3BBZzcYPg+ow1XuTBy6xggAAACAAgAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECED33Bv8m1nL+UMb1aiyh5xdOdQVckgu9M34afWvygm9twiHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCEDv7hiU765b1i4xGnkQs/Pn3ilQTqVQjvo5oZ2Ty+nvT8iHQOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobCEDhgSqjP8wnd30mx82b4nCaWFlh/xB22CFQPlDFTb2ZG8iHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEED9LowiubZy07ueJtS22i3D8SVFWpaf2OKywbp5EHatcbOMAfkhjD1ndv2JXS8wZ0hJltheJoOQwrQz5sSyGJHxIh4DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAUt/78AlfKbHeJMnWjVSdHFS85pAEVP43/RD1yQPf7oX3utinKtqOUs2QkvUdnpC1p+TzbKBN+Y53+60TRzBbxyIeA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsQJPh5dSIi8HP4C7s+p3qFE6thPI6EPwaMBEDweVjk1J7Y0F8bEpa9FNZ/4tuF5r3OXjk1i6GLu3Soob1J45Ms0AAAQ4gUiYs1dQCvzJhbQf8Ayhqj3/nivesQR3/9BZV3cEBHm8BDwQAAAAAAQEfoIYBAAAAAAAWABRwGLzpZSiNi/DM8+DsSLbx27/lSCICAwOg9FKNJk6OlSVmNLlEFOJ0j3KWJwT+V+iwosxE0jg9SDBFAiEA2yW73RvPhQMJZj64j7uw62ETCVeF1/bVM42du8cFAycCIHmV0Cb1bqmeBz39CnlsbnT8Ye0I7NJGcM7zQNrVCueaAQEDBAEAAAAiBgMDoPRSjSZOjpUlZjS5RBTidI9ylicE/lfosKLMRNI4PQgAAACAAwAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEDgCmZjHPCsTnbdVV+wwEexl7NISRHljAGVxhSo+kiicwiHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCECmAuscmThS/ggzENbaaeN9ybBd+sCbxuBtS3oEScvWOsiHQOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobCEDon2fH6U+Q/cINaaZCVS3ijX3RwZve4K0qeqC6LteBqYiHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEEA4HOPBrJ/H9qUVNkViUphHaOj70BQHAjn0yxOxZ5PHTMXtZ3yKfqzBc+mI01Oj8onH4hQdt6S0FFxUmeyDfzauIh4DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAOOA0Y7ZFDb0FEGWoEqbyYxCH95UeRqyE5m2oEXVXF8CTGA5NSYJ7jAl8pwk/6S05P5Wl162EmkGALcTkVYq96SIeA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsQHMqoJV6nbLHWeOayl0BZ+8T0qNKQ8gS6cydcS1Fj3sihdp1EesW9h+WANIL5OlN/dK8OuN/2UP8NJR9/D/cZ5cAAQ4g4pjq8k/hymi0Hktrg8w9kc7ZnG541bmSz7FXcbVFcGQBDwQAAAAAAQEfoIYBAAAAAAAWABSTMrsCDLA9SetNBHEsHMCOKwbY2CICA6iRG+taSP4RnLAVCIzww6EYzwJnckSJctG3DHZKxZQSRzBEAiBr1hL2RzkhB3F8V6+V7oRzl08sMjurcHnoGRbsuQIcjgIgWlToLfcW0eQKehOGkN9w6tSjzILOEImugKMj+1/ui1UBAQMEAQAAACIGA6iRG+taSP4RnLAVCIzww6EYzwJnckSJctG3DHZKxZQSCAAAAIAEAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQK+9HOMbzJ/FySxQHmIlZzfK9GSEIlL/QQ1NbYROCcIGCIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQJ+t8HEr81+Yqtq09K6JzOjdFIgZB+RkD6/57zF29xrXSIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQPKiLzbbR9SkekMddPaYBqL0pmR6rv3+UsvOUg+OFjJoSIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQApYSScQKCC3tsrWvPsDGiOjcxKth9I/HLWoNZvi1f85tqKi/jfNDVPuNH8T5rNSV2my54nwaZy5hViOrC2vEN0iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEB3sVcjNtm9Ti9zQR649qliNaEw9ETL6wekifRHkh43SJ1x/T2yigu6o1uIw3t1eezb9s4WOHANuB38hr95zRvnIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAXQ3oon8NUogCzzNUoa9Qe88P7UGdpkHJwIB811Tgevh5C1EccF1fv2MwWrIq/gSX+s8HC1r+r87jppAFR3Z3VgABDiAXMIM+y1vgE2LXFJUiYESEIW4cexjPMT0c8VQ++F3ztgEPBAAAAAABASughgEAAAAAACJRINFVcTxSDOLYJ2FkIV1lmrYjxfcwb4ZSwXVuJoM+iG4BAQMEAQAAAAEQBP7///8BFyDRVXE8Ugzi2CdhZCFdZZq2I8X3MG+GUsF1biaDPohuASIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQJPKhWksVprePCmMvx/3xEpKfZL1N0U9npjz0+48yWiBCIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQOAK2mzYNpFhVErHPlnsYQBAibXXOW3Yud6ASi8sGjMuyIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQJAdhVQXsveqIExJQTu9vRoGiYxbvc9M1N6f9eT9GWOqSIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQI8iPeJ5ht2HkqA9nVtmIyPoaXgw66u2c2OIH+cshkgq5hoJJo0IO4NUz8K601wUjuspGvYi3UYGNGBjMq8bgpciHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAQOuBcEOQymDdsP+4dxfDQQ4n08gr0k0bUjq0yTWFdbyj8oKMYRFEw6laoYgGbLeDCY32zxBjAsHS1hUiuiyDJIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxA8FWZBzhUTQmbFZKQ5/VELLkSJiYBdKqdjByDELfLAc4rlMxdK4/fgWZ+Avt5bbDlwnh33g1BoqDnCbAURbrylgABDiDpNTLg7aOcTTnaLT+R0UUpvENfwu+5GW4l+6rEtOibgQEPBAAAAAABASughgEAAAAAACJRINAOFftian7+6FxbzmdtY2tgSJFOmjSs4LTLxEvJSAd6AQMEAQAAAAEQBP7///8BFyDQDhX7Ymp+/uhcW85nbWNrYEiRTpo0rOC0y8RLyUgHeiIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQIVP83+lq5wNj/RVCZG0wnCEyuDJVQOPdf4jjf5eWB5piIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQIPqjoMMa52ledpVG4wqngqvTH7aBuXChOqNcwh39E4ACIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQPzE/j0desB487LwOqsL3JtKQMsb/fDrWzDv4uxAYZSfCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQEMg6fYP08Km9zeqzlRsI7DH126EFZwK0onB30wPilAOUSCfKW+dfSI6HSkr1B0mb6rLG+hDvs9LcG6xXbpwKAYiHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEDkB0puyJPquAbV35p07SV+eF/zeGQ9uqeTPHgTp7X2yQyoK2JTnzmzjCxy/lz4HCKl5kH2c2RPbEhrPbV3RkRjIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAOynhLPaT8nITn3RFLyvMwrzQdDLc6PsQc1TBRYoSpHyFRNLWyh4zvOBXi2UIz4pZNGc/n8Q1pfhKIqVLWty8/AABDiC2Nou8Mwzd/p4lUO2338Fa50ysm8x9ln/oHm8n+Fl7HQEPBAAAAAABAFMCAAAAAf6hTz0WmysEANsUmWIhsxGCu56GyhaekbnHvZP5xz6IAAAAAAD/////AaCGAQAAAAAAF6kUDfEBNX9z5mWFAM9W86Ey17uK+92HAAAAAAEBIKCGAQAAAAAAF6kUDfEBNX9z5mWFAM9W86Ey17uK+92HIgICBQDxZ89mnn2sOeauzaHyjGa3jscJfu/vJdVPe+eF5/ZHMEQCIA134+usWENCsMr5fopp9YcHxKsAzK2+hsRKoYe1Zfv/AiBubgVutYtmJeL++r0axbRapqEto5ypCKEaIcY396JcMAEBAwQBAAAAAQQWABTGvIEF7G22DE2lOsNc2iBAaekOiiIGAgUA8WfPZp59rDnmrs2h8oxmt47HCX7v7yXVT3vnhef2CAAAAIAHAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQL+eEHN37Rv2yypveVslVjC0bNhIWZWWQgCJOJAMUOECCIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQJvAnsjWnWTyolDxte3432S6rM5YX9/DDRBBsWN0MvGqiIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQIGEUUMbBlE7N7LePYYFsdn+6Q2jyH36bFpd5x28jz0zCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQIgHJVFmLD7r7lRfGIuNr8aClzovIY58oH/I5C/1ehE0YwRJ/XAxd9ehLQyc7QJIRNwbng7K1nWH3VxHlDGzahoiHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAWtYFI97r/eD5DEPGFUD/pJBfbpDuWbIOiGEMiyx8gQky50ECuahrqTnREvceGJYqXVkTOGgGVVkwrn8PGBqKSIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxASrNr3WnrHNDUsK6uQD3OTbUijFujopHccl3iM4LRc20mXXvDP4NpClylYJcZ8Z6BlS1MjV4oj9DLjGQREEuAowABDiADvOulN51z2ur+Z3lysD3PfvMLfxDqqDrQS8C/ANiy9wEPBAAAAAABAFUCAAAAASo0rBsNt3qBmMHikALMR7v81u2DCWAwTSyaOrVISGtdAAAAAAD/////AaCGAQAAAAAAGXapFFab8xHmijg3Z7Q/gwQt+r5gCT7eiKwAAAAAIgIDGZ0vFV8y67FnrrDMym5a+3NAiY3xt6uZNlAPbUORkCpHMEQCIGIn/SRuyIcF32NUW0i+PRLD1KVITUtOxDRAmsuEETxaAiA8y8m0eI77f7hg2oVYqUx+TEJa11XoaOLY8Fz7RhJflwEBAwQBAAAAIgYDGZ0vFV8y67FnrrDMym5a+3NAiY3xt6uZNlAPbUORkCoIAAAAgAgAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhAvPBdbCLIHY3YWqnTme6rBoYB8lLznCAD3b1sXtSwAgtIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAvoc7ZMlmKJ/ooQQuVXqZ0ebWkAztp8smeTiZ2e7oKVWIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhAwDg/RcQ3FatfBc6qRQdcxV3AJvD3/y6hXakjnerNNlwIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAmSJWWP7eeowkN+s4Ib3J03AKvIlui23O+E4pNHt4vCsD5tozg25PQHZzkMNmRM4Bazax1UaWNUD6UdCwQH221yIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQKCUjFF9cJdsDjnKZ6vxnnIXBA2+Fyu5ZTQTPm/6OUHBZZQW9UBmK3Vh77cAZLTXGpsXtjvFY/Yw20Qi8nPg3xIiHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEDuCqplynPMxUezHCt+0q4xpPTM2upz8q3SRjDWCO3prqXYCGiBhuvKQrh376sT815g8hDU9iBgL4UPwHMcIB6RAAEDCDB1AAAAAAAAAQQiUSAa+l2IGIzvm5Gz8QArEeD56UrTmBl4xNEqBgVWTAgSMwEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwgwdQAAAAAAAAEEIlEgyr9+Sg3kJOybut1/ckLM52c+FwH0nWoZqXBV2jMrEyQBCUIDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSgDEmZYHj6EHLuU3mLqc1WDojLEyIj6bt7y7C+HB4n8HdQAAQMIIE4AAAAAAAABBCJRIEqtyeClkNIeDBnLICTycUD5sZwqEoLVDqfF9F6wP9SiAQlCAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQAkpI124g1AvPXy4aXD/+s9wqizuI15pIbVTJ2eqo+hiOAAEDCCBOAAAAAAAAAQQiUSAvpDcA6h0o/XrU3LMys+XloNjLVCWPZmHE3gN31ygE5QEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwgQJwAAAAAAAAEEIlEgUZhvruMZQ2tRs4QJwbMA9DluKzLjzJoSripL4TXab24BCUIDjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwD+BRzhEyddMkh/xelr0ELYzc0jXr7/3OJG8XLDLJMsMAAAQMIUMMAAAAAAAABBCJRIG/FBvgFKp9aiqm5kNXplPSV3e1tR7rETKrNrdjYmRzQAA==", + "psbt": "cHNidP8BAgQCAAAAAQQBCQEFAQYBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCv5P5xeJJvJzjL4P4lgkWxL6PpXSHLT5RBhFoQysegEQIgTxC0f3slWNuXTK683/KVbOk8hyAZLZKir+WzNLjK69sBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQP70XPZxI1YxQIkJtBSeLyhe5qOIoJmaQGhsAueBLeZSSIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQNzctF59PYo2oLMvU5CF72wgJ8UF8mr6qNfqAXUitZVTCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMBdpBBIfPrsN4/r5q9QBeOubIYjaBiw5VshQBfrUHPt70AXlXW13NqpBjSRrIuD/QYk1Bd6TS3UmUxGQNa4zN4iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAAE4PUZhvocl7ykEj0jJEfifXzQxfXwMCsxg72XxtSv/96ltgzm2Jd+Dq6tXqic+3NmjXHlNrLschhFxuyZwdfIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxApoctTrEZ/ir3CVP3UqIiNrVKO1f3DlEfEL2LQv9Wtaz2NlCTxIDqnxN3Z4SUW1kxisKSfZFariRM+2g/QYijpwABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDW86lMNwk1Pl44m6LOVIhTgtjQk7SuDogcw67bVIQT5gIgYCeNhb9SMCp7OvVc3DvDb9hcT+L/G8pXhnqcD4F4I5EBAQMEAQAAACIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAAQ4gvNSFpwnLJdE0Y6GDLbIZTGydn+crlpn0/kLIK+2T0yYBDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQOmqJsbmGqZVTPhe+1kUAtUG7DXOQce/irit++woMprzyIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQL2rnuKrJoPnJ8E6rSEBiFy3y442fL27DG0BLtaKGqr8CIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQKx0+0vpLwxagjrFIX6de191Uynqa4Y0MShfak/MMOF1SIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMNKailAu+mnNWwcxv/jWN1EQdtYiXy6mcIS63UoXn2h7KEceSyXo4BJM0WrIk3p2UwrNu6FJq4jUoFxoyMd5zMiHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAzSs7YEG66pCh9rKVsyiZ5Xy0qc5eEz2tzTaM3B1f0meEgwOQL5AQ2zXTE7yaQVwb1L6f6bo52RR6Fg3gwUahDIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxA2EGjc60olrlyuM/qFjT/FKMPgNhM/W7xiJM5e480bIBRnJsWGnIkTQ6bZOVDbJjOndThegco/Jl7XHvPOc7LaAABAR+ghgEAAAAAABYAFNTckD9xFmAu41jsjt8yhOb/ApTjIgICZV712vBdKNHKc7qOIRMA2ytwQWc3GD4PqMNV7kwcusZHMEQCIFa6M2IBK4Lky66GLs4o83KwxU+Py57U4jt+4aJAxH3LAiAu7+Lw7ChjJdmPYrBo8OHbbyBrFE5zcAQHGFAikkIZlgEBAwQBAAAAIgYCZV712vBdKNHKc7qOIRMA2ytwQWc3GD4PqMNV7kwcusYIAAAAgAIAAAABDiCinXdnRAJ1ylMq9gkfClxWMpiVAg07C9iK/0O0EyAjnAEPBAAAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhA99wb/JtZy/lDG9WosoecXTnUFXJILvTN+Gn1r8oJvbcIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghA7+4YlO+uW9YuMRp5ELPz594pUE6lUI76OaGdk8vp70/Ih0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhA4YEqoz/MJ3d9JsfNm+JwmlhZYf8QdtghUD5QxU29mRvIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBA/S6MIrm2ctO7nibUttotw/ElRVqWn9jissG6eRB2rXGzjAH5IYw9Z3b9iV0vMGdISZbYXiaDkMK0M+bEshiR8SIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQFLf+/AJXymx3iTJ1o1UnRxUvOaQBFT+N/0Q9ckD3+6F97rYpyrajlLNkJL1HZ6Qtafk82ygTfmOd/utE0cwW8ciHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobECT4eXUiIvBz+Au7Pqd6hROrYTyOhD8GjARA8HlY5NSe2NBfGxKWvRTWf+Lbhea9zl45NYuhi7t0qKG9SeOTLNAAAEBH6CGAQAAAAAAFgAU+20I37FPAB3JjPF8TXMisHvwdU8iAgMDoPRSjSZOjpUlZjS5RBTidI9ylicE/lfosKLMRNI4PUgwRQIhAPHJiHGnvcXpQWKgXdwlAwwjacuoChhT69OCAab/R2+bAiAwcmvl+cqFlnOAO2HBh/ue/BCqK5wRQJQK4Zh0SQCEwQEBAwQBAAAAIgYDA6D0Uo0mTo6VJWY0uUQU4nSPcpYnBP5X6LCizETSOD0IAAAAgAMAAAABDiAef87nvuWNqIGXxAlZpi4GA4Ca3jUTdJPfLPqPhVMEuwEPBAAAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhA4ApmYxzwrE523VVfsMBHsZezSEkR5YwBlcYUqPpIonMIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghApgLrHJk4Uv4IMxDW2mnjfcmwXfrAm8bgbUt6BEnL1jrIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhA6J9nx+lPkP3CDWmmQlUt4o190cGb3uCtKnqgui7XgamIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAOBzjwayfx/alFTZFYlKYR2jo+9AUBwI59MsTsWeTx0zF7Wd8in6swXPpiNNTo/KJx+IUHbektBRcVJnsg382riIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQDjgNGO2RQ29BRBlqBKm8mMQh/eVHkashOZtqBF1VxfAkxgOTUmCe4wJfKcJP+ktOT+VpdethJpBgC3E5FWKvekiHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEBzKqCVep2yx1njmspdAWfvE9KjSkPIEunMnXEtRY97IoXadRHrFvYflgDSC+TpTf3SvDrjf9lD/DSUffw/3GeXAAEBH6CGAQAAAAAAFgAUCxhF9MgNq+LF3IpWf75BCnjkhsgiAgOokRvrWkj+EZywFQiM8MOhGM8CZ3JEiXLRtwx2SsWUEkgwRQIhAI6xqpQossxTVOjJ83WXR+mBcUUOwma2NYGtuLN5GZEtAiAcyk5nPjaUGgBKCzcPQaiPJ7ekQ4qeni8aJ+XSWucuoAEBAwQBAAAAIgYDqJEb61pI/hGcsBUIjPDDoRjPAmdyRIly0bcMdkrFlBIIAAAAgAQAAAABDiDTEVrd/vujHd9xq1Vn1DXMWPSAbUX6hlqLBw7J+HQZBwEPBAAAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhAr70c4xvMn8XJLFAeYiVnN8r0ZIQiUv9BDU1thE4JwgYIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAn63wcSvzX5iq2rT0ronM6N0UiBkH5GQPr/nvMXb3GtdIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhA8qIvNttH1KR6Qx109pgGovSmZHqu/f5Sy85SD44WMmhIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAClhJJxAoILe2yta8+wMaI6NzEq2H0j8ctag1m+LV/zm2oqL+N80NU+40fxPms1JXabLnifBpnLmFWI6sLa8Q3SIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQHexVyM22b1OL3NBHrj2qWI1oTD0RMvrB6SJ9EeSHjdInXH9PbKKC7qjW4jDe3V57Nv2zhY4cA24HfyGv3nNG+ciHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEBdDeiifw1SiALPM1Shr1B7zw/tQZ2mQcnAgHzXVOB6+HkLURxwXV+/YzBasir+BJf6zwcLWv6vzuOmkAVHdndWAAEBK6CGAQAAAAAAIlEgGjS87lYb/TgrBcYrc+fQV+BLJFCahT9ESfIsqm0OhG4BAwQBAAAAAQ4gsfKZWK5flwWjVkpKKhVMX8xeQKsZPQWZb+cyax1JLHUBDwQAAAAAARAE/v///wEXINFVcTxSDOLYJ2FkIV1lmrYjxfcwb4ZSwXVuJoM+iG4BIh0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhAtOvNHx/MNCZRobaIn3Rgh6t4oG6YxtYOUjVfcwhq89BIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghA4EeOFGirI0VPmoQOr6NTIn51itibDUZPEMjp0X7jdTYIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhAwuoUVrbqo11D0MnMeSakbdYFTeWHd2u293jEMxdQWnDIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAkUfsswO+1fGc1E9rL9XFwITZh4wTWIEz/iE55PS4Gip+aHl47w9fuh8IuA5oqmPAg2iVyZ90eVyDBK6u3tqnnCIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQLAaU3hGnhl6TxinGOR+QRXRcZ3JfTpRBNT/fzgslKHn75HUsYKss1c/sCONBN9dZ6XZzD2Qr3ByM8tANy9AF30iHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEDFsYp5T1xwq+v5SUWkUy11rU+505qFMoZ8z3tuzV0Y99+nO5fWj8coAgwX40auxYWWXuNpjY35sk1Ky692EpK9AAEBK6CGAQAAAAAAIlEgfTKY0wGe2IurqJuIUjc4K+eI+I7wWV/RsNi2dhQviLEBAwQBAAAAAQ4ggaf+HByEkKbZqp54stts5AIi2Vdd+t0LcYrtx/7ylXgBDwQAAAAAARAE/v///wEXINAOFftian7+6FxbzmdtY2tgSJFOmjSs4LTLxEvJSAd6Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhApheaYZhpdG4rVMmS5ZPguk+yKK5Wn7pwBqdCWrq3J6oIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAivDgwzCNZXFRJLBt/XdUMmgIDrRIf29mMe5dGIkQ19GIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhAx1EON+FS1KjP6LgJKHcCZAkLnM1CQpwTJoe/rPFM/qgIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAmK4MWCsRIC+6pcaLy1jusCiBstfPtUd2fMrZAClJJFO8qudjj3M62b8tbhRJ5mkK213/Kzb+98iLQMro6iE8YiIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQO+bRaceeOkQeR7ZHCXqzooqFLkHERHCqEjtG7eFYlaN0uwzkO+WYwqGzKCPbPTrGeirQO3J5Bxlq69WEHlZ/i8iHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEBViSkIcecXvMP8hiPSuRXNBTi+BZlElqWPsSYRIw6IFtAp5OtPX+GrqYZmWJmzxi253E+zgG/t09ZuY0J6KKNDAAEAUwIAAAAB/qFPPRabKwQA2xSZYiGzEYK7nobKFp6Ruce9k/nHPogAAAAAAP////8BoIYBAAAAAAAXqRQN8QE1f3PmZYUAz1bzoTLXu4r73YcAAAAAAQEgoIYBAAAAAAAXqRQN8QE1f3PmZYUAz1bzoTLXu4r73YciAgIFAPFnz2aefaw55q7NofKMZreOxwl+7+8l1U9754Xn9kgwRQIhAKZMJkhm1w5287C/XiW4OCEp4+eAaZ7VpRZnwKZS9lcQAiB4tjElCNeC7Y7dhwpvvOKw2FWL0RrwDQzrfdUJVXx2LgEBAwQBAAAAAQQWABTGvIEF7G22DE2lOsNc2iBAaekOiiIGAgUA8WfPZp59rDnmrs2h8oxmt47HCX7v7yXVT3vnhef2CAAAAIAHAAAAAQ4gtjaLvDMM3f6eJVDtt9/BWudMrJvMfZZ/6B5vJ/hZex0BDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQL+eEHN37Rv2yypveVslVjC0bNhIWZWWQgCJOJAMUOECCIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQJvAnsjWnWTyolDxte3432S6rM5YX9/DDRBBsWN0MvGqiIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQIGEUUMbBlE7N7LePYYFsdn+6Q2jyH36bFpd5x28jz0zCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQIgHJVFmLD7r7lRfGIuNr8aClzovIY58oH/I5C/1ehE0YwRJ/XAxd9ehLQyc7QJIRNwbng7K1nWH3VxHlDGzahoiHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAWtYFI97r/eD5DEPGFUD/pJBfbpDuWbIOiGEMiyx8gQky50ECuahrqTnREvceGJYqXVkTOGgGVVkwrn8PGBqKSIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxASrNr3WnrHNDUsK6uQD3OTbUijFujopHccl3iM4LRc20mXXvDP4NpClylYJcZ8Z6BlS1MjV4oj9DLjGQREEuAowABAFUCAAAAASo0rBsNt3qBmMHikALMR7v81u2DCWAwTSyaOrVISGtdAAAAAAD/////AaCGAQAAAAAAGXapFFab8xHmijg3Z7Q/gwQt+r5gCT7eiKwAAAAAIgIDGZ0vFV8y67FnrrDMym5a+3NAiY3xt6uZNlAPbUORkCpIMEUCIQCzDdEyhS9PQmbxovcFoD3AnB7vfkWfXzye2nOIiWRfbAIgdQUKwZNNI4CZ640jTYpR0c8twn88Fgh3awc1vjbpgpkBAQMEAQAAACIGAxmdLxVfMuuxZ66wzMpuWvtzQImN8bermTZQD21DkZAqCAAAAIAIAAAAAQ4gA7zrpTedc9rq/md5crA9z37zC38Q6qg60EvAvwDYsvcBDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQLzwXWwiyB2N2Fqp05nuqwaGAfJS85wgA929bF7UsAILSIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQL6HO2TJZiif6KEELlV6mdHm1pAM7afLJnk4mdnu6ClViIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQMA4P0XENxWrXwXOqkUHXMVdwCbw9/8uoV2pI53qzTZcCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQJkiVlj+3nqMJDfrOCG9ydNwCryJbottzvhOKTR7eLwrA+baM4NuT0B2c5DDZkTOAWs2sdVGljVA+lHQsEB9ttciHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKECglIxRfXCXbA45ymer8Z5yFwQNvhcruWU0Ez5v+jlBwWWUFvVAZit1Ye+3AGS01xqbF7Y7xWP2MNtEIvJz4N8SIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxA7gqqZcpzzMVHsxwrftKuMaT0zNrqc/Kt0kYw1gjt6a6l2AhogYbrykK4d++rE/NeYPIQ1PYgYC+FD8BzHCAekQABAwgwdQAAAAAAAAEEIlEg0DpVy+lu6guDVcj8mfcHzTuArbEvJ1Sr2sca6q2pb5oBCUIDM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSgDEmZYHj6EHLuU3mLqc1WDojLEyIj6bt7y7C+HB4n8HdQAAQMIMHUAAAAAAAABBCJRINC/hV+FqORuS7w3pIN3AK7XI2sW+FkiJn4/d+h3z3IRAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCCBOAAAAAAAAAQQiUSAMpTyiR7FQPi5lL/ullrkxB+OXTEB4HobftREwPDvZdQEJQgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEAJKSNduINQLz18uGlw//rPcKos7iNeaSG1UydnqqPoYjgABAwggTgAAAAAAAAEEIlEgMFJ/AYKwZvAEE8Fo/n/umIEDckG8GYpuowLJnAUka7wBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4AAQMIECcAAAAAAAABBCJRIDYlIYJgbyj1laGqxm4agdGcpajLdVBEfcXqa/I4z9pGAQlCA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsA/gUc4RMnXTJIf8Xpa9BC2M3NI16+/9ziRvFywyyTLDAAAEDCFDDAAAAAAAAAQQiUSBvxQb4BSqfWoqpuZDV6ZT0ld3tbUe6xEyqza3Y2Jkc0AA=", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBCQEFAQYBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCv5P5xeJJvJzjL4P4lgkWxL6PpXSHLT5RBhFoQysegEQIgTxC0f3slWNuXTK683/KVbOk8hyAZLZKir+WzNLjK69sBAQMEAQAAACIGAsgXu3Uhr8NeqW87+ycObrUN3/pVYGJ7lh/sAPKZZQi/CAAAAIAAAAAAAQ4g907dH3W0uz5ddJwVv9tmNI9oBam01F/u4aLiAfUDu3EBDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQP70XPZxI1YxQIkJtBSeLyhe5qOIoJmaQGhsAueBLeZSSIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQMKGLm7QZm4kzDrF/juWseG4IU9zS88zfF0S5fOTt4FPiIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQNzctF59PYo2oLMvU5CF72wgJ8UF8mr6qNfqAXUitZVTCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMBdpBBIfPrsN4/r5q9QBeOubIYjaBiw5VshQBfrUHPt70AXlXW13NqpBjSRrIuD/QYk1Bd6TS3UmUxGQNa4zN4iHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAAE4PUZhvocl7ykEj0jJEfifXzQxfXwMCsxg72XxtSv/96ltgzm2Jd+Dq6tXqic+3NmjXHlNrLschhFxuyZwdfIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxApoctTrEZ/ir3CVP3UqIiNrVKO1f3DlEfEL2LQv9Wtaz2NlCTxIDqnxN3Z4SUW1kxisKSfZFariRM+2g/QYijpwABAR+ghgEAAAAAABYAFKaSURwHlXW/N1bavFatcdQoSmkOIgIC9bWfpeSSIh6/Vbp4rUQmBb6ulRZroeujJQ0Luqx+LtxIMEUCIQDW86lMNwk1Pl44m6LOVIhTgtjQk7SuDogcw67bVIQT5gIgYCeNhb9SMCp7OvVc3DvDb9hcT+L/G8pXhnqcD4F4I5EBAQMEAQAAACIGAvW1n6XkkiIev1W6eK1EJgW+rpUWa6HroyUNC7qsfi7cCAAAAIABAAAAAQ4gvNSFpwnLJdE0Y6GDLbIZTGydn+crlpn0/kLIK+2T0yYBDwQAAAAAARAE/v///yIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQOmqJsbmGqZVTPhe+1kUAtUG7DXOQce/irit++woMprzyIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQL2rnuKrJoPnJ8E6rSEBiFy3y442fL27DG0BLtaKGqr8CIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQKx0+0vpLwxagjrFIX6de191Uynqa4Y0MShfak/MMOF1SIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQMNKailAu+mnNWwcxv/jWN1EQdtYiXy6mcIS63UoXn2h7KEceSyXo4BJM0WrIk3p2UwrNu6FJq4jUoFxoyMd5zMiHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEAzSs7YEG66pCh9rKVsyiZ5Xy0qc5eEz2tzTaM3B1f0meEgwOQL5AQ2zXTE7yaQVwb1L6f6bo52RR6Fg3gwUahDIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxA2EGjc60olrlyuM/qFjT/FKMPgNhM/W7xiJM5e480bIBRnJsWGnIkTQ6bZOVDbJjOndThegco/Jl7XHvPOc7LaAABAR+ghgEAAAAAABYAFNTckD9xFmAu41jsjt8yhOb/ApTjIgICZV712vBdKNHKc7qOIRMA2ytwQWc3GD4PqMNV7kwcusZHMEQCIFa6M2IBK4Lky66GLs4o83KwxU+Py57U4jt+4aJAxH3LAiAu7+Lw7ChjJdmPYrBo8OHbbyBrFE5zcAQHGFAikkIZlgEBAwQBAAAAIgYCZV712vBdKNHKc7qOIRMA2ytwQWc3GD4PqMNV7kwcusYIAAAAgAIAAAABDiCinXdnRAJ1ylMq9gkfClxWMpiVAg07C9iK/0O0EyAjnAEPBAAAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhA99wb/JtZy/lDG9WosoecXTnUFXJILvTN+Gn1r8oJvbcIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghA7+4YlO+uW9YuMRp5ELPz594pUE6lUI76OaGdk8vp70/Ih0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhA4YEqoz/MJ3d9JsfNm+JwmlhZYf8QdtghUD5QxU29mRvIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBA/S6MIrm2ctO7nibUttotw/ElRVqWn9jissG6eRB2rXGzjAH5IYw9Z3b9iV0vMGdISZbYXiaDkMK0M+bEshiR8SIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQFLf+/AJXymx3iTJ1o1UnRxUvOaQBFT+N/0Q9ckD3+6F97rYpyrajlLNkJL1HZ6Qtafk82ygTfmOd/utE0cwW8ciHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobECT4eXUiIvBz+Au7Pqd6hROrYTyOhD8GjARA8HlY5NSe2NBfGxKWvRTWf+Lbhea9zl45NYuhi7t0qKG9SeOTLNAAAEBH6CGAQAAAAAAFgAU+20I37FPAB3JjPF8TXMisHvwdU8iAgMDoPRSjSZOjpUlZjS5RBTidI9ylicE/lfosKLMRNI4PUgwRQIhAPHJiHGnvcXpQWKgXdwlAwwjacuoChhT69OCAab/R2+bAiAwcmvl+cqFlnOAO2HBh/ue/BCqK5wRQJQK4Zh0SQCEwQEBAwQBAAAAIgYDA6D0Uo0mTo6VJWY0uUQU4nSPcpYnBP5X6LCizETSOD0IAAAAgAMAAAABDiAef87nvuWNqIGXxAlZpi4GA4Ca3jUTdJPfLPqPhVMEuwEPBAAAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhA4ApmYxzwrE523VVfsMBHsZezSEkR5YwBlcYUqPpIonMIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghApgLrHJk4Uv4IMxDW2mnjfcmwXfrAm8bgbUt6BEnL1jrIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhA6J9nx+lPkP3CDWmmQlUt4o190cGb3uCtKnqgui7XgamIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAOBzjwayfx/alFTZFYlKYR2jo+9AUBwI59MsTsWeTx0zF7Wd8in6swXPpiNNTo/KJx+IUHbektBRcVJnsg382riIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQDjgNGO2RQ29BRBlqBKm8mMQh/eVHkashOZtqBF1VxfAkxgOTUmCe4wJfKcJP+ktOT+VpdethJpBgC3E5FWKvekiHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEBzKqCVep2yx1njmspdAWfvE9KjSkPIEunMnXEtRY97IoXadRHrFvYflgDSC+TpTf3SvDrjf9lD/DSUffw/3GeXAAEBH6CGAQAAAAAAFgAUCxhF9MgNq+LF3IpWf75BCnjkhsgiAgOokRvrWkj+EZywFQiM8MOhGM8CZ3JEiXLRtwx2SsWUEkgwRQIhAI6xqpQossxTVOjJ83WXR+mBcUUOwma2NYGtuLN5GZEtAiAcyk5nPjaUGgBKCzcPQaiPJ7ekQ4qeni8aJ+XSWucuoAEBAwQBAAAAIgYDqJEb61pI/hGcsBUIjPDDoRjPAmdyRIly0bcMdkrFlBIIAAAAgAQAAAABDiDTEVrd/vujHd9xq1Vn1DXMWPSAbUX6hlqLBw7J+HQZBwEPBAAAAAABEAT+////Ih0CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRAhAr70c4xvMn8XJLFAeYiVnN8r0ZIQiUv9BDU1thE4JwgYIh0DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bSghAn63wcSvzX5iq2rT0ronM6N0UiBkH5GQPr/nvMXb3GtdIh0DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGwhA8qIvNttH1KR6Qx109pgGovSmZHqu/f5Sy85SD44WMmhIh4CqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRBAClhJJxAoILe2yta8+wMaI6NzEq2H0j8ctag1m+LV/zm2oqL+N80NU+40fxPms1JXabLnifBpnLmFWI6sLa8Q3SIeAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oQHexVyM22b1OL3NBHrj2qWI1oTD0RMvrB6SJ9EeSHjdInXH9PbKKC7qjW4jDe3V57Nv2zhY4cA24HfyGv3nNG+ciHgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobEBdDeiifw1SiALPM1Shr1B7zw/tQZ2mQcnAgHzXVOB6+HkLURxwXV+/YzBasir+BJf6zwcLWv6vzuOmkAVHdndWAAEBK6CGAQAAAAAAIlEgGjS87lYb/TgrBcYrc+fQV+BLJFCahT9ESfIsqm0OhG4BAwQBAAAAAQ4gsfKZWK5flwWjVkpKKhVMX8xeQKsZPQWZb+cyax1JLHUBDwQAAAAAARAE/v///wETQYv6bvGC8LNByfgK1XIywrL18N6Hm6PPOREKz6QvS/z7ZKU60Ia5MWjeoI02TZ8uEspzsqpe+pCE78ydUzjbpzkBARcg0VVxPFIM4tgnYWQhXWWatiPF9zBvhlLBdW4mgz6IbgEiHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEC0680fH8w0JlGhtoifdGCHq3igbpjG1g5SNV9zCGrz0EiHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCEDgR44UaKsjRU+ahA6vo1MifnWK2JsNRk8QyOnRfuN1NgiHQOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobCEDC6hRWtuqjXUPQycx5JqRt1gVN5Yd3a7b3eMQzF1BacMiHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEECRR+yzA77V8ZzUT2sv1cXAhNmHjBNYgTP+ITnk9LgaKn5oeXjvD1+6Hwi4DmiqY8CDaJXJn3R5XIMErq7e2qecIh4DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAsBpTeEaeGXpPGKcY5H5BFdFxncl9OlEE1P9/OCyUoefvkdSxgqyzVz+wI40E311npdnMPZCvcHIzy0A3L0AXfSIeA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsQMWxinlPXHCr6/lJRaRTLXWtT7nTmoUyhnzPe27NXRj336c7l9aPxygCDBfjRq7FhZZe42mNjfmyTUrLr3YSkr0AAQEroIYBAAAAAAAiUSB9MpjTAZ7Yi6uom4hSNzgr54j4jvBZX9Gw2LZ2FC+IsQEDBAEAAAABDiCBp/4cHISQptmqnniy22zkAiLZV1363Qtxiu3H/vKVeAEPBAAAAAABEAT+////ARNB4urcB+YqH5ofTpiVPlTxWKwnF+WJbvKha1Joww5wVOChubPTPmDCIySswy2qbD2ErgI6fNRbnzYeCzPkaG0rYgEBFyDQDhX7Ymp+/uhcW85nbWNrYEiRTpo0rOC0y8RLyUgHeiIdAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQIQKYXmmGYaXRuK1TJkuWT4LpPsiiuVp+6cAanQlq6tyeqCIdAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oIQIrw4MMwjWVxUSSwbf13VDJoCA60SH9vZjHuXRiJENfRiIdA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsIQMdRDjfhUtSoz+i4CSh3AmQJC5zNQkKcEyaHv6zxTP6oCIeAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQQJiuDFgrESAvuqXGi8tY7rAogbLXz7VHdnzK2QApSSRTvKrnY49zOtm/LW4USeZpCttd/ys2/vfIi0DK6OohPGIiHgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKEDvm0WnHnjpEHke2Rwl6s6KKhS5BxERwqhI7Ru3hWJWjdLsM5DvlmMKhsygj2z06xnoq0DtyeQcZauvVhB5Wf4vIh4DjtMiDnM0T5Hi0zOR4+FpHbOdrwbkI34ZftDQB78nKGxAVYkpCHHnF7zD/IYj0rkVzQU4vgWZRJalj7EmESMOiBbQKeTrT1/hq6mGZliZs8YtudxPs4Bv7dPWbmNCeiijQwABAFMCAAAAAf6hTz0WmysEANsUmWIhsxGCu56GyhaekbnHvZP5xz6IAAAAAAD/////AaCGAQAAAAAAF6kUDfEBNX9z5mWFAM9W86Ey17uK+92HAAAAAAEBIKCGAQAAAAAAF6kUDfEBNX9z5mWFAM9W86Ey17uK+92HIgICBQDxZ89mnn2sOeauzaHyjGa3jscJfu/vJdVPe+eF5/ZIMEUCIQCmTCZIZtcOdvOwv14luDghKePngGme1aUWZ8CmUvZXEAIgeLYxJQjXgu2O3YcKb7zisNhVi9Ea8A0M633VCVV8di4BAQMEAQAAAAEEFgAUxryBBexttgxNpTrDXNogQGnpDooiBgIFAPFnz2aefaw55q7NofKMZreOxwl+7+8l1U9754Xn9ggAAACABwAAAAEOILY2i7wzDN3+niVQ7bffwVrnTKybzH2Wf+gebyf4WXsdAQ8EAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEC/nhBzd+0b9ssqb3lbJVYwtGzYSFmVlkIAiTiQDFDhAgiHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCECbwJ7I1p1k8qJQ8bXt+N9kuqzOWF/fww0QQbFjdDLxqoiHQOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobCECBhFFDGwZROzey3j2GBbHZ/ukNo8h9+mxaXecdvI89MwiHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEECIByVRZiw+6+5UXxiLja/Ggpc6LyGOfKB/yOQv9XoRNGMESf1wMXfXoS0MnO0CSETcG54OytZ1h91cR5Qxs2oaIh4DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAFrWBSPe6/3g+QxDxhVA/6SQX26Q7lmyDohhDIssfIEJMudBArmoa6k50RL3HhiWKl1ZEzhoBlVZMK5/DxgaikiIeA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsQEqza91p6xzQ1LCurkA9zk21Ioxbo6KR3HJd4jOC0XNtJl17wz+DaQpcpWCXGfGegZUtTI1eKI/Qy4xkERBLgKMAAQBVAgAAAAEqNKwbDbd6gZjB4pACzEe7/NbtgwlgME0smjq1SEhrXQAAAAAA/////wGghgEAAAAAABl2qRRWm/MR5oo4N2e0P4MELfq+YAk+3oisAAAAACICAxmdLxVfMuuxZ66wzMpuWvtzQImN8bermTZQD21DkZAqSDBFAiEAsw3RMoUvT0Jm8aL3BaA9wJwe735Fn188ntpziIlkX2wCIHUFCsGTTSOAmeuNI02KUdHPLcJ/PBYId2sHNb426YKZAQEDBAEAAAAiBgMZnS8VXzLrsWeusMzKblr7c0CJjfG3q5k2UA9tQ5GQKggAAACACAAAAAEOIAO866U3nXPa6v5neXKwPc9+8wt/EOqoOtBLwL8A2LL3AQ8EAAAAAAEQBP7///8iHQKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVECEC88F1sIsgdjdhaqdOZ7qsGhgHyUvOcIAPdvWxe1LACC0iHQMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKCEC+hztkyWYon+ihBC5VepnR5taQDO2nyyZ5OJnZ7ugpVYiHQOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobCEDAOD9FxDcVq18FzqpFB1zFXcAm8Pf/LqFdqSOd6s02XAiHgKp8frCzEV2hPM96QBz/iDSLJR8khY7hisU0Kuh30cVEECZIlZY/t56jCQ36zghvcnTcAq8iW6Lbc74Tik0e3i8KwPm2jODbk9AdnOQw2ZEzgFrNrHVRpY1QPpR0LBAfbbXIh4DM2HT/3LzTmtOenvvluW4FR5mqXmtznU8OcWDy+V2bShAoJSMUX1wl2wOOcpnq/GechcEDb4XK7llNBM+b/o5QcFllBb1QGYrdWHvtwBktNcamxe2O8Vj9jDbRCLyc+DfEiIeA47TIg5zNE+R4tMzkePhaR2zna8G5CN+GX7Q0Ae/JyhsQO4KqmXKc8zFR7McK37SrjGk9Mza6nPyrdJGMNYI7emupdgIaIGG68pCuHfvqxPzXmDyENT2IGAvhQ/AcxwgHpEAAQMIMHUAAAAAAAABBCJRINA6VcvpbuoLg1XI/Jn3B807gK2xLydUq9rHGuqtqW+aAQlCAzNh0/9y805rTnp775bluBUeZql5rc51PDnFg8vldm0oAxJmWB4+hBy7lN5i6nNVg6IyxMiI+m7e8uwvhweJ/B3UAAEDCDB1AAAAAAAAAQQiUSDQv4Vfhajkbku8N6SDdwCu1yNrFvhZIiZ+P3fod89yEQEJQgMzYdP/cvNOa056e++W5bgVHmapea3OdTw5xYPL5XZtKAMSZlgePoQcu5TeYupzVYOiMsTIiPpu3vLsL4cHifwd1AABAwggTgAAAAAAAAEEIlEgDKU8okexUD4uZS/7pZa5MQfjl0xAeB6G37URMDw72XUBCUICqfH6wsxFdoTzPekAc/4g0iyUfJIWO4YrFNCrod9HFRACSkjXbiDUC89fLhpcP/6z3CqLO4jXmkhtVMnZ6qj6GI4AAQMIIE4AAAAAAAABBCJRIDBSfwGCsGbwBBPBaP5/7piBA3JBvBmKbqMCyZwFJGu8AQlCAqnx+sLMRXaE8z3pAHP+INIslHySFjuGKxTQq6HfRxUQAkpI124g1AvPXy4aXD/+s9wqizuI15pIbVTJ2eqo+hiOAAEDCBAnAAAAAAAAAQQiUSA2JSGCYG8o9ZWhqsZuGoHRnKWoy3VQRH3F6mvyOM/aRgEJQgOO0yIOczRPkeLTM5Hj4Wkds52vBuQjfhl+0NAHvycobAP4FHOETJ10ySH/F6WvQQtjNzSNevv/c4kbxcsMskywwAABAwhQwwAAAAAAAAEEIlEgb8UG+AUqn1qKqbmQ1emU9JXd7W1HusRMqs2t2NiZHNAA" + }, "supplementary": { + "hex": "70736274ff0102040200000001040109010501060106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf483045022100afe4fe7178926f2738cbe0fe258245b12fa3e95d21cb4f9441845a10cac7a01102204f10b47f7b2558db974caebcdff2956ce93c8720192d92a2afe5b334b8caebdb0101030401000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103fbd173d9c48d58c5022426d05278bca17b9a8e2282666901a1b00b9e04b79949221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821030a18b9bb4199b89330eb17f8ee5ac786e0853dcd2f3ccdf1744b97ce4ede053e221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c21037372d179f4f628da82ccbd4e4217bdb0809f1417c9abeaa35fa805d48ad6554c221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040c05da410487cfaec378febe6af5005e3ae6c86236818b0e55b214017eb5073edef40179575b5dcdaa9063491ac8b83fd0624d4177a4d2dd4994c4640d6b8ccde221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840001383d4661be8725ef29048f48c911f89f5f34317d7c0c0acc60ef65f1b52bfff7a96d8339b625df83abab57aa273edcd9a35c794dacbb1c861171bb267075f221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40a6872d4eb119fe2af70953f752a22236b54a3b57f70e511f10bd8b42ff56b5acf6365093c480ea9f13776784945b59318ac2927d915aae244cfb683f4188a3a70001011fa086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e220202f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc483045022100d6f3a94c3709353e5e389ba2ce54885382d8d093b4ae0e881cc3aedb548413e6022060278d85bf52302a7b3af55cdc3bc36fd85c4fe2ff1bca57867a9c0f817823910101030401000000220602f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc080000008001000000010e20bcd485a709cb25d13463a1832db2194c6c9d9fe72b9699f4fe42c82bed93d326010f0400000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103a6a89b1b986a995533e17bed64500b541bb0d739071efe2ae2b7efb0a0ca6bcf221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282102f6ae7b8aac9a0f9c9f04eab484062172df2e38d9f2f6ec31b404bb5a286aabf0221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c2102b1d3ed2fa4bc316a08eb1485fa75ed7dd54ca7a9ae18d0c4a17da93f30c385d5221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040c34a6a2940bbe9a7356c1cc6ffe358dd4441db58897cba99c212eb75285e7da1eca11c792c97a380493345ab224de9d94c2b36ee8526ae23528171a3231de733221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840334aced8106ebaa4287daca56cca26795f2d2a739784cf6b734da3370757f499e120c0e40be40436cd74c4ef26905706f52fa7fa6e8e76451e8583783051a843221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40d841a373ad2896b972b8cfea1634ff14a30f80d84cfd6ef18893397b8f346c80519c9b161a72244d0e9b64e5436c98ce9dd4e17a0728fc997b5c7bcf39cecb680001011fa086010000000000160014d4dc903f7116602ee358ec8edf3284e6ff0294e3220202655ef5daf05d28d1ca73ba8e211300db2b70416737183e0fa8c355ee4c1cbac6473044022056ba3362012b82e4cbae862ece28f372b0c54f8fcb9ed4e23b7ee1a240c47dcb02202eefe2f0ec286325d98f62b068f0e1db6f206b144e73700407185022924219960101030401000000220602655ef5daf05d28d1ca73ba8e211300db2b70416737183e0fa8c355ee4c1cbac6080000008002000000010e20a29d7767440275ca532af6091f0a5c56329895020d3b0bd88aff43b41320239c010f0400000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102103df706ff26d672fe50c6f56a2ca1e7174e75055c920bbd337e1a7d6bf2826f6dc221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282103bfb86253beb96f58b8c469e442cfcf9f78a5413a95423be8e686764f2fa7bd3f221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c21038604aa8cff309dddf49b1f366f89c269616587fc41db608540f9431536f6646f221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040fd2e8c22b9b672d3bb9e26d4b6da2dc3f125455a969fd8e2b2c1ba791076ad71b38c01f9218c3d6776fd895d2f3067484996d85e268390c2b433e6c4b21891f1221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284052dffbf0095f29b1de24c9d68d549d1c54bce6900454fe37fd10f5c903dfee85f7bad8a72ada8e52cd9092f51d9e90b5a7e4f36ca04df98e77fbad1347305bc7221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c4093e1e5d4888bc1cfe02eecfa9dea144ead84f23a10fc1a301103c1e56393527b63417c6c4a5af45359ff8b6e179af73978e4d62e862eedd2a286f5278e4cb3400001011fa086010000000000160014fb6d08dfb14f001dc98cf17c4d7322b07bf0754f22020303a0f4528d264e8e95256634b94414e2748f72962704fe57e8b0a2cc44d2383d483045022100f1c98871a7bdc5e94162a05ddc25030c2369cba80a1853ebd38201a6ff476f9b022030726be5f9ca859673803b61c187fb9efc10aa2b9c1140940ae19874490084c1010103040100000022060303a0f4528d264e8e95256634b94414e2748f72962704fe57e8b0a2cc44d2383d080000008003000000010e201e7fcee7bee58da88197c40959a62e0603809ade35137493df2cfa8f855304bb010f0400000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151021038029998c73c2b139db75557ec3011ec65ecd212447963006571852a3e92289cc221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282102980bac7264e14bf820cc435b69a78df726c177eb026f1b81b52de811272f58eb221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c2103a27d9f1fa53e43f70835a6990954b78a35f747066f7b82b4a9ea82e8bb5e06a6221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df47151040381ce3c1ac9fc7f6a51536456252984768e8fbd014070239f4cb13b16793c74cc5ed677c8a7eacc173e988d353a3f289c7e2141db7a4b4145c5499ec837f36ae221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284038e03463b6450dbd051065a812a6f2631087f7951e46ac84e66da811755717c093180e4d49827b8c097ca7093fe92d393f95a5d7ad849a41802dc4e4558abde9221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40732aa0957a9db2c759e39aca5d0167ef13d2a34a43c812e9cc9d712d458f7b2285da7511eb16f61f9600d20be4e94dfdd2bc3ae37fd943fc34947dfc3fdc67970001011fa0860100000000001600140b1845f4c80dabe2c5dc8a567fbe410a78e486c8220203a8911beb5a48fe119cb015088cf0c3a118cf026772448972d1b70c764ac594124830450221008eb1aa9428b2cc5354e8c9f3759747e98171450ec266b63581adb8b37919912d02201cca4e673e36941a004a0b370f41a88f27b7a4438a9e9e2f1a27e5d25ae72ea00101030401000000220603a8911beb5a48fe119cb015088cf0c3a118cf026772448972d1b70c764ac59412080000008004000000010e20d3115addfefba31ddf71ab5567d435cc58f4806d45fa865a8b070ec9f8741907010f0400000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102bef4738c6f327f1724b1407988959cdf2bd19210894bfd043535b61138270818221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821027eb7c1c4afcd7e62ab6ad3d2ba2733a3745220641f91903ebfe7bcc5dbdc6b5d221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c2103ca88bcdb6d1f5291e90c75d3da601a8bd29991eabbf7f94b2f39483e3858c9a1221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510400a584927102820b7b6cad6bcfb031a23a37312ad87d23f1cb5a8359be2d5ff39b6a2a2fe37cd0d53ee347f13e6b3525769b2e789f0699cb985588eac2daf10dd221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284077b1572336d9bd4e2f73411eb8f6a96235a130f444cbeb07a489f447921e37489d71fd3db28a0bbaa35b88c37b7579ecdbf6ce1638700db81dfc86bf79cd1be7221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c405d0de8a27f0d528802cf3354a1af507bcf0fed419da641c9c0807cd754e07af8790b511c705d5fbf63305ab22afe0497facf070b5afeafcee3a69005477677560001012ba0860100000000002251201a34bcee561bfd382b05c62b73e7d057e04b24509a853f4449f22caa6d0e846e01030401000000010e20b1f29958ae5f9705a3564a4a2a154c5fcc5e40ab193d05996fe7326b1d492c75010f0400000000011004feffffff011720d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102d3af347c7f30d0994686da227dd1821eade281ba631b583948d57dcc21abcf41221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282103811e3851a2ac8d153e6a103abe8d4c89f9d62b626c35193c4323a745fb8dd4d8221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c21030ba8515adbaa8d750f432731e49a91b7581537961dddaedbdde310cc5d4169c3221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510409147ecb303bed5f19cd44f6b2fd5c5c084d9878c13588133fe2139e4f4b81a2a7e687978ef0f5fba1f08b80e68aa63c0836895c99f74795c8304aeaededaa79c221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840b01a5378469e197a4f18a718e47e4115d1719dc97d3a5104d4ff7f382c94a1e7ef91d4b182acb3573fb0238d04df5d67a5d9cc3d90af707233cb40372f40177d221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40c5b18a794f5c70abebf94945a4532d75ad4fb9d39a8532867ccf7b6ecd5d18f7dfa73b97d68fc728020c17e346aec585965ee3698d8df9b24d4acbaf761292bd0001012ba0860100000000002251207d3298d3019ed88baba89b885237382be788f88ef0595fd1b0d8b676142f88b101030401000000010e2081a7fe1c1c8490a6d9aa9e78b2db6ce40222d9575dfadd0b718aedc7fef29578010f0400000000011004feffffff011720d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102985e698661a5d1b8ad53264b964f82e93ec8a2b95a7ee9c01a9d096aeadc9ea8221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821022bc3830cc23595c54492c1b7f5dd50c9a0203ad121fdbd98c7b9746224435f46221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c21031d4438df854b52a33fa2e024a1dc0990242e7335090a704c9a1efeb3c533faa0221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715104098ae0c582b11202fbaa5c68bcb58eeb02881b2d7cfb547767ccad90029492453bcaae7638f733ad9bf2d6e1449e6690adb5dff2b36fef7c88b40cae8ea213c62221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840ef9b45a71e78e910791ed91c25eace8a2a14b9071111c2a848ed1bb78562568dd2ec3390ef96630a86cca08f6cf4eb19e8ab40edc9e41c65abaf56107959fe2f221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c405589290871e717bcc3fc8623d2b915cd0538be05994496a58fb12611230e8816d029e4eb4f5fe1aba986665899b3c62db9dc4fb3806fedd3d66e63427a28a343000100530200000001fea14f3d169b2b0400db14996221b31182bb9e86ca169e91b9c7bd93f9c73e880000000000ffffffff01a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd8700000000010120a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd872202020500f167cf669e7dac39e6aecda1f28c66b78ec7097eefef25d54f7be785e7f6483045022100a64c264866d70e76f3b0bf5e25b8382129e3e780699ed5a51667c0a652f65710022078b6312508d782ed8edd870a6fbce2b0d8558bd11af00d0ceb7dd509557c762e01010304010000000104160014c6bc8105ec6db60c4da53ac35cda204069e90e8a2206020500f167cf669e7dac39e6aecda1f28c66b78ec7097eefef25d54f7be785e7f6080000008007000000010e20b6368bbc330cddfe9e2550edb7dfc15ae74cac9bcc7d967fe81e6f27f8597b1d010f0400000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102fe7841cddfb46fdb2ca9bde56c9558c2d1b36121665659080224e24031438408221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2821026f027b235a7593ca8943c6d7b7e37d92eab339617f7f0c344106c58dd0cbc6aa221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c21020611450c6c1944ecdecb78f61816c767fba4368f21f7e9b169779c76f23cf4cc221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715104088072551662c3eebee545f188b8dafc682973a2f218e7ca07fc8e42ff57a1134630449fd703177d7a12d0c9ced024844dc1b9e0ecad67587dd5c479431b36a1a221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d284016b58148f7baff783e4310f185503fe92417dba43b966c83a2184322cb1f20424cb9d040ae6a1aea4e7444bdc786258a975644ce1a0195564c2b9fc3c606a292221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c404ab36bdd69eb1cd0d4b0aeae403dce4db5228c5ba3a291dc725de23382d1736d265d7bc33f83690a5ca5609719f19e81952d4c8d5e288fd0cb8c6411104b80a30001005502000000012a34ac1b0db77a8198c1e29002cc47bbfcd6ed830960304d2c9a3ab548486b5d0000000000ffffffff01a0860100000000001976a914569bf311e68a383767b43f83042dfabe60093ede88ac00000000220203199d2f155f32ebb167aeb0ccca6e5afb7340898df1b7ab9936500f6d4391902a483045022100b30dd132852f4f4266f1a2f705a03dc09c1eef7e459f5f3c9eda738889645f6c022075050ac1934d238099eb8d234d8a51d1cf2dc27f3c1608776b0735be36e982990101030401000000220603199d2f155f32ebb167aeb0ccca6e5afb7340898df1b7ab9936500f6d4391902a080000008008000000010e2003bceba5379d73daeafe677972b03dcf7ef30b7f10eaa83ad04bc0bf00d8b2f7010f0400000000011004feffffff221d02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715102102f3c175b08b207637616aa74e67baac1a1807c94bce70800f76f5b17b52c0082d221d033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d282102fa1ced932598a27fa28410b955ea67479b5a4033b69f2c99e4e26767bba0a556221d038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c210300e0fd1710dc56ad7c173aa9141d731577009bc3dffcba8576a48e77ab34d970221e02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df4715104099225658fede7a8c2437eb3821bdc9d3700abc896e8b6dcef84e29347b78bc2b03e6da33836e4f40767390c36644ce016b36b1d546963540fa51d0b0407db6d7221e033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d2840a0948c517d70976c0e39ca67abf19e7217040dbe172bb96534133e6ffa3941c1659416f540662b7561efb70064b4d71a9b17b63bc563f630db4422f273e0df12221e038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c40ee0aaa65ca73ccc547b31c2b7ed2ae31a4f4ccdaea73f2add24630d608ede9aea5d808688186ebca42b877efab13f35e60f210d4f620602f850fc0731c201e910001030830750000000000000104225120d03a55cbe96eea0b8355c8fc99f707cd3b80adb12f2754abdac71aeaada96f9a010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd40001030830750000000000000104225120d0bf855f85a8e46e4bbc37a4837700aed7236b16f85922267e3f77e877cf7211010942033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd400010308204e00000000000001042251200ca53ca247b1503e2e652ffba596b93107e3974c40781e86dfb511303c3bd97501094202a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e00010308204e000000000000010422512030527f0182b066f00413c168fe7fee9881037241bc198a6ea302c99c05246bbc01094202a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e000103081027000000000000010422512036252182606f28f595a1aac66e1a81d19ca5a8cb7550447dc5ea6bf238cfda46010942038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c00001030850c300000000000001042251206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd000", "inputs": [ { "input_index": 0, - "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "private_key": "", "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", - "prevout_txid": "18a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", "prevout_index": 0, - "prevout_scriptpubkey": "0014229a72d34a645bd3496bbbf50bbb81c9063f4f94", "amount": 100000, - "witness_utxo": "a086010000000000160014229a72d34a645bd3496bbbf50bbb81c9063f4f94", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", "sequence": 4294967294, "signed": true }, { "input_index": 1, - "private_key": "295c2eedddd8331d20b5d4cf9e69bb523ed85cb0bf35ab12e04fea66fe6d4a4a", + "private_key": "", "public_key": "02f5b59fa5e492221ebf55ba78ad442605beae95166ba1eba3250d0bbaac7e2edc", - "prevout_txid": "be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab522", + "prevout_txid": "26d393ed2bc842fef499962be79f9d6c4c19b22d83a16334d125cb09a785d4bc", "prevout_index": 0, - "prevout_scriptpubkey": "0014139350117c577941a985802bb9edefc113932bc7", "amount": 100000, - "witness_utxo": "a086010000000000160014139350117c577941a985802bb9edefc113932bc7", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e00000000", + "witness_utxo": "a086010000000000160014a692511c079575bf3756dabc56ad71d4284a690e", "sequence": 4294967294, "signed": true }, { "input_index": 2, - "private_key": "e6db4a04e2fc29745ea1a9dcf1fed7449c8228ffe0503d8171e64126d5399800", + "private_key": "", "public_key": "02655ef5daf05d28d1ca73ba8e211300db2b70416737183e0fa8c355ee4c1cbac6", - "prevout_txid": "d041c742ca364472d1a18c7a8eae07e6e904a9ea1b85f198525fb83ef276e343", + "prevout_txid": "9c232013b443ff8ad80b3b0d02959832565c0a1f09f62a53ca75024467779da2", "prevout_index": 0, - "prevout_scriptpubkey": "00142307fc774ca174b42ada814bc2e6e444ff3d830c", "amount": 100000, - "witness_utxo": "a0860100000000001600142307fc774ca174b42ada814bc2e6e444ff3d830c", + "non_witness_utxo": "0200000001d041c742ca364472d1a18c7a8eae07e6e904a9ea1b85f198525fb83ef276e3430000000000ffffffff01a086010000000000160014d4dc903f7116602ee358ec8edf3284e6ff0294e300000000", + "witness_utxo": "a086010000000000160014d4dc903f7116602ee358ec8edf3284e6ff0294e3", "sequence": 4294967294, "signed": true }, { "input_index": 3, - "private_key": "f5208ed67b0019ba4e306aff029d247931e0dfacd1fe6e69091bc6bc70a42619", + "private_key": "", "public_key": "0303a0f4528d264e8e95256634b94414e2748f72962704fe57e8b0a2cc44d2383d", - "prevout_txid": "52262cd5d402bf32616d07fc03286a8f7fe78af7ac411dfff41655ddc1011e6f", + "prevout_txid": "bb0453858ffa2cdf93741335de9a8003062ea65909c49781a88de5bee7ce7f1e", "prevout_index": 0, - "prevout_scriptpubkey": "00147018bce965288d8bf0ccf3e0ec48b6f1dbbfe548", "amount": 100000, - "witness_utxo": "a0860100000000001600147018bce965288d8bf0ccf3e0ec48b6f1dbbfe548", + "non_witness_utxo": "020000000152262cd5d402bf32616d07fc03286a8f7fe78af7ac411dfff41655ddc1011e6f0000000000ffffffff01a086010000000000160014fb6d08dfb14f001dc98cf17c4d7322b07bf0754f00000000", + "witness_utxo": "a086010000000000160014fb6d08dfb14f001dc98cf17c4d7322b07bf0754f", "sequence": 4294967294, "signed": true }, { "input_index": 4, - "private_key": "0c19c34dc1005feb5ca60104d20472f7f2f97bd4d521264618196bf71155b20a", + "private_key": "", "public_key": "03a8911beb5a48fe119cb015088cf0c3a118cf026772448972d1b70c764ac59412", - "prevout_txid": "e298eaf24fe1ca68b41e4b6b83cc3d91ced99c6e78d5b992cfb15771b5457064", + "prevout_txid": "071974f8c90e078b5a86fa456d80f458cc35d46755ab71df1da3fbfedd5a11d3", "prevout_index": 0, - "prevout_scriptpubkey": "00149332bb020cb03d49eb4d04712c1cc08e2b06d8d8", "amount": 100000, - "witness_utxo": "a0860100000000001600149332bb020cb03d49eb4d04712c1cc08e2b06d8d8", + "non_witness_utxo": "0200000001e298eaf24fe1ca68b41e4b6b83cc3d91ced99c6e78d5b992cfb15771b54570640000000000ffffffff01a0860100000000001600140b1845f4c80dabe2c5dc8a567fbe410a78e486c800000000", + "witness_utxo": "a0860100000000001600140b1845f4c80dabe2c5dc8a567fbe410a78e486c8", "sequence": 4294967294, "signed": true }, { "input_index": 5, - "private_key": "5aaa151cbdeb566911784d166b01ce57f35993b98f96846efec1cfefcc0d8f56", - "public_key": "02d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", - "prevout_txid": "1730833ecb5be01362d7149522604484216e1c7b18cf313d1cf1543ef85df3b6", + "private_key": "2b8676a5f410a07ce7f4e9899f14a2e3d5528dadf05a164ea566fc192299d01a", + "public_key": "021a34bcee561bfd382b05c62b73e7d057e04b24509a853f4449f22caa6d0e846e", + "prevout_txid": "752c491d6b32e76f99053d19ab405ecc5f4c152a4a4a56a305975fae5899f2b1", "prevout_index": 0, - "prevout_scriptpubkey": "5120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", "amount": 100000, - "witness_utxo": "a086010000000000225120d155713c520ce2d8276164215d659ab623c5f7306f8652c1756e26833e886e01", + "non_witness_utxo": "02000000011730833ecb5be01362d7149522604484216e1c7b18cf313d1cf1543ef85df3b60000000000ffffffff01a0860100000000002251201a34bcee561bfd382b05c62b73e7d057e04b24509a853f4449f22caa6d0e846e00000000", + "witness_utxo": "a0860100000000002251201a34bcee561bfd382b05c62b73e7d057e04b24509a853f4449f22caa6d0e846e", "sequence": 4294967294, "signed": false }, { "input_index": 6, - "private_key": "d92c1506167b3a00a21f4d90d7b5ccb4713c00194aa66f9c7deb162c467f9643", - "public_key": "02d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", - "prevout_txid": "e93532e0eda39c4d39da2d3f91d14529bc435fc2efb9196e25fbaac4b4e89b81", + "private_key": "de6b1726d3f5997e5db395ead26fba223c64f20be9ccde470bb7530a9d301445", + "public_key": "027d3298d3019ed88baba89b885237382be788f88ef0595fd1b0d8b676142f88b1", + "prevout_txid": "7895f2fec7ed8a710bddfa5d57d92202e46cdbb2789eaad9a690841c1cfea781", "prevout_index": 0, - "prevout_scriptpubkey": "5120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", "amount": 100000, - "witness_utxo": "a086010000000000225120d00e15fb626a7efee85c5bce676d636b6048914e9a34ace0b4cbc44bc948077a", + "non_witness_utxo": "0200000001e93532e0eda39c4d39da2d3f91d14529bc435fc2efb9196e25fbaac4b4e89b810000000000ffffffff01a0860100000000002251207d3298d3019ed88baba89b885237382be788f88ef0595fd1b0d8b676142f88b100000000", + "witness_utxo": "a0860100000000002251207d3298d3019ed88baba89b885237382be788f88ef0595fd1b0d8b676142f88b1", "sequence": 4294967294, "signed": false }, { "input_index": 7, - "private_key": "d8bc8d0e1233a97133f3573d6dceb6736e8b6d2e4839925145022ea3efdad8f8", + "private_key": "", "public_key": "020500f167cf669e7dac39e6aecda1f28c66b78ec7097eefef25d54f7be785e7f6", - "prevout_txid": "b6368bbc330cddfe9e2550edb7dfc15ae74cac9bcc7d967fe81e6f27f8597b1d", + "prevout_txid": "1d7b59f8276f1ee87f967dcc9bac4ce75ac1dfb7ed50259efedd0c33bc8b36b6", "prevout_index": 0, - "prevout_scriptpubkey": "a9140df101357f73e6658500cf56f3a132d7bb8afbdd87", "amount": 100000, + "non_witness_utxo": "0200000001fea14f3d169b2b0400db14996221b31182bb9e86ca169e91b9c7bd93f9c73e880000000000ffffffff01a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd8700000000", "witness_utxo": "a08601000000000017a9140df101357f73e6658500cf56f3a132d7bb8afbdd87", "sequence": 4294967294, "signed": true }, { "input_index": 8, - "private_key": "81e30f5b5d049bdf5c5bea9c3329bf57cc8b473240182a9f2a6eee07435bd54a", + "private_key": "", "public_key": "03199d2f155f32ebb167aeb0ccca6e5afb7340898df1b7ab9936500f6d4391902a", - "prevout_txid": "03bceba5379d73daeafe677972b03dcf7ef30b7f10eaa83ad04bc0bf00d8b2f7", + "prevout_txid": "f7b2d800bfc04bd03aa8ea107f0bf37ecf3db0727967feeada739d37a5ebbc03", "prevout_index": 0, - "prevout_scriptpubkey": "76a914569bf311e68a383767b43f83042dfabe60093ede88ac", "amount": 100000, "non_witness_utxo": "02000000012a34ac1b0db77a8198c1e29002cc47bbfcd6ed830960304d2c9a3ab548486b5d0000000000ffffffff01a0860100000000001976a914569bf311e68a383767b43f83042dfabe60093ede88ac00000000", "sequence": 4294967294, @@ -1652,38 +2161,38 @@ }, { "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", - "ecdh_share": "03802b69b360da4585512b1cf967b184010226d75ce5b762e77a0128bcb068ccbb", - "dleq_proof": "103ae05c10e43298376c3fee1dc5f0d04389f4f20af49346d48ead324d615d6f28fca0a318445130ea56a862019b2de0c2637db3c418c0b074b58548ae8b20c9", + "ecdh_share": "03811e3851a2ac8d153e6a103abe8d4c89f9d62b626c35193c4323a745fb8dd4d8", + "dleq_proof": "b01a5378469e197a4f18a718e47e4115d1719dc97d3a5104d4ff7f382c94a1e7ef91d4b182acb3573fb0238d04df5d67a5d9cc3d90af707233cb40372f40177d", "input_index": 5 }, { "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", - "ecdh_share": "024f2a15a4b15a6b78f0a632fc7fdf112929f64bd4dd14f67a63cf4fb8f325a204", - "dleq_proof": "8f223de27986dd8792a03d9d5b662323e8697830ebabb67363881fe72c86482ae61a09268d083b8354cfc2bad35c148eeb291af622dd460634606332af1b8297", + "ecdh_share": "02d3af347c7f30d0994686da227dd1821eade281ba631b583948d57dcc21abcf41", + "dleq_proof": "9147ecb303bed5f19cd44f6b2fd5c5c084d9878c13588133fe2139e4f4b81a2a7e687978ef0f5fba1f08b80e68aa63c0836895c99f74795c8304aeaededaa79c", "input_index": 5 }, { "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", - "ecdh_share": "02407615505ecbdea881312504eef6f4681a26316ef73d33537a7fd793f4658ea9", - "dleq_proof": "f055990738544d099b159290e7f5442cb91226260174aa9d8c1c8310b7cb01ce2b94cc5d2b8fdf81667e02fb796db0e5c27877de0d41a2a0e709b01445baf296", + "ecdh_share": "030ba8515adbaa8d750f432731e49a91b7581537961dddaedbdde310cc5d4169c3", + "dleq_proof": "c5b18a794f5c70abebf94945a4532d75ad4fb9d39a8532867ccf7b6ecd5d18f7dfa73b97d68fc728020c17e346aec585965ee3698d8df9b24d4acbaf761292bd", "input_index": 5 }, { "scan_key": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28", - "ecdh_share": "020faa3a0c31ae7695e769546e30aa782abd31fb681b970a13aa35cc21dfd13800", - "dleq_proof": "e4074a6ec893eab806d5df9a74ed257e785ff378643dbaa7933c7813a7b5f6c90ca82b62539f39b38c2c72fe5cf81c22a5e641f673644f6c486b3db577464463", + "ecdh_share": "022bc3830cc23595c54492c1b7f5dd50c9a0203ad121fdbd98c7b9746224435f46", + "dleq_proof": "ef9b45a71e78e910791ed91c25eace8a2a14b9071111c2a848ed1bb78562568dd2ec3390ef96630a86cca08f6cf4eb19e8ab40edc9e41c65abaf56107959fe2f", "input_index": 6 }, { "scan_key": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510", - "ecdh_share": "02153fcdfe96ae70363fd1542646d309c2132b8325540e3dd7f88e37f9796079a6", - "dleq_proof": "4320e9f60fd3c2a6f737aace546c23b0c7d76e84159c0ad289c1df4c0f8a500e51209f296f9d7d223a1d292bd41d266faacb1be843becf4b706eb15dba702806", + "ecdh_share": "02985e698661a5d1b8ad53264b964f82e93ec8a2b95a7ee9c01a9d096aeadc9ea8", + "dleq_proof": "98ae0c582b11202fbaa5c68bcb58eeb02881b2d7cfb547767ccad90029492453bcaae7638f733ad9bf2d6e1449e6690adb5dff2b36fef7c88b40cae8ea213c62", "input_index": 6 }, { "scan_key": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c", - "ecdh_share": "03f313f8f475eb01e3cecbc0eaac2f726d29032c6ff7c3ad6cc3bf8bb10186527c", - "dleq_proof": "3b29e12cf693f272139f74452f2bccc2bcd07432dce8fb107354c1458a12a47c8544d2d6ca1e33bce0578b6508cf8a5934673f9fc435a5f84a22a54b5adcbcfc", + "ecdh_share": "031d4438df854b52a33fa2e024a1dc0990242e7335090a704c9a1efeb3c533faa0", + "dleq_proof": "5589290871e717bcc3fc8623d2b915cd0538be05994496a58fb12611230e8816d029e4eb4f5fe1aba986665899b3c62db9dc4fb3806fedd3d66e63427a28a343", "input_index": 6 }, { @@ -1728,39 +2237,525 @@ "output_index": 0, "amount": 30000, "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", - "script": "51201afa5d88188cef9b91b3f1002b11e0f9e94ad3981978c4d12a0605564c081233" + "script": "5120d03a55cbe96eea0b8355c8fc99f707cd3b80adb12f2754abdac71aeaada96f9a" }, { "output_index": 1, "amount": 30000, "sp_v0_info": "033361d3ff72f34e6b4e7a7bef96e5b8151e66a979adce753c39c583cbe5766d28031266581e3e841cbb94de62ea735583a232c4c888fa6edef2ec2f870789fc1dd4", - "script": "5120cabf7e4a0de424ec9bbadd7f7242cce7673e1701f49d6a19a97055da332b1324" + "script": "5120d0bf855f85a8e46e4bbc37a4837700aed7236b16f85922267e3f77e877cf7211" }, { "output_index": 2, "amount": 20000, "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", - "script": "51204aadc9e0a590d21e0c19cb2024f27140f9b19c2a1282d50ea7c5f45eb03fd4a2" + "script": "51200ca53ca247b1503e2e652ffba596b93107e3974c40781e86dfb511303c3bd975" }, { "output_index": 3, "amount": 20000, "sp_v0_info": "02a9f1fac2cc457684f33de90073fe20d22c947c92163b862b14d0aba1df471510024a48d76e20d40bcf5f2e1a5c3ffeb3dc2a8b3b88d79a486d54c9d9eaa8fa188e", - "script": "51202fa43700ea1d28fd7ad4dcb332b3e5e5a0d8cb54258f6661c4de0377d72804e5" + "script": "512030527f0182b066f00413c168fe7fee9881037241bc198a6ea302c99c05246bbc" }, { "output_index": 4, "amount": 10000, "sp_v0_info": "038ed3220e73344f91e2d33391e3e1691db39daf06e4237e197ed0d007bf27286c03f81473844c9d74c921ff17a5af410b6337348d7afbff73891bc5cb0cb24cb0c0", - "script": "512051986faee319436b51b38409c1b300f4396e2b32e3cc9a12ae2a4be135da6f6e" + "script": "512036252182606f28f595a1aac66e1a81d19ca5a8cb7550447dc5ea6bf238cfda46" }, { "output_index": 5, "amount": 50000, "script": "51206fc506f8052a9f5a8aa9b990d5e994f495dded6d47bac44caacdadd8d8991cd0" } + ], + "task": "sign" + } + }, + { + "description": "can finalize: P2WPKH with decoy BIP32_DERIVATION before the matching key", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7IgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9HMEQCIG9hTKsWyAwmppZy4viq5wvAiLUgLqne/2rOeM2n+2JyAiAQVYeP/VlnUGDrYKAL+jNMnLJB+6EoTBEkkNEA2ex8LgEBAwQBAAAAIgYCpRa89dF+FVVFALBtY95Srqd8dFqTvkLq2/Sunj4dEqAIAAAAgP8AAAAiBgLIF7t1Ia/DXqlvO/snDm61Dd/6VWBie5Yf7ADymWUIvwgAAACAAAAAAAEOIPdO3R91tLs+XXScFb/bZjSPaAWptNRf7uGi4gH1A7txAQ8EAAAAAAEQBP7///8iHQJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaCED7KT/Ebco4uD2DOYiKUOm/1W52V9ie/mpnQhLyHLVClsiHgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaECKE7OYVUX3K9bolxSuuQmz41SoQqm7i1bNDt7SHfihmVmLMSKKSeC9fpXOEFP3xbKKy1Q6aHB2AOPOiYIu4yAhAAEDCBhzAQAAAAAAAQQiUSBkb0lMoLubzq0UuNt+TGlEVh+vIy58zMNr3VhpX3SRWQEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFB4q14ctMpQTpW3wlovjOCIngxY7AQhrAkcwRAIgb2FMqxbIDCamlnLi+KrnC8CItSAuqd7/as54zaf7YnICIBBVh4/9WWdQYOtgoAv6M0ycskH7oShMESSQ0QDZ7HwuASECyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8BDiD3Tt0fdbS7Pl10nBW/22Y0j2gFqbTUX+7houIB9QO7cQEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEgZG9JTKC7m86tFLjbfkxpRFYfryMufMzDa91YaV90kVkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA" + }, + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb04020000000001011fa0860100000000001600141e2ad7872d329413a56df0968be338222783163b220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf47304402206f614cab16c80c26a69672e2f8aae70bc088b5202ea9deff6ace78cda7fb627202201055878ffd59675060eb60a00bfa334c9cb241fba1284c112490d100d9ec7c2e0101030401000000220602a516bcf5d17e15554500b06d63de52aea77c745a93be42eadbf4ae9e3e1d12a00800000080ff000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20f74edd1f75b4bb3e5d749c15bfdb66348f6805a9b4d45feee1a2e201f503bb71010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "71bb03f501e2a2e1ee5fd4b4a905688f3466dbbf159c745d3ebbb4751fdd4ef7", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a0860100000000001600141e2ad7872d329413a56df0968be338222783163b00000000", + "witness_utxo": "a0860100000000001600141e2ad7872d329413a56df0968be338222783163b", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120646f494ca0bb9bcead14b8db7e4c6944561faf232e7cccc36bdd58695f749159" + } + ], + "task": "finalize" + } + }, + { + "description": "can finalize: P2PKH with decoy BIP32_DERIVATION before the matching key", + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAIgICyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL9IMEUCIQCKz65hp7Ug/wQxkrbclMyEJpEkQIMSdkyI3dldqY0pVQIgIIfDsRj5aZKk2iQTz/6RcPJQ4n48FMtd7z5jjDDX6oABAQMEAQAAACIGAqUWvPXRfhVVRQCwbWPeUq6nfHRak75C6tv0rp4+HRKgCAAAAID/AAAAIgYCyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8IAAAAgAAAAAABDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEg4UDSh7RbRs1OqvpDdwYVcLq+g9G4vJUKdKn+oJIz16YBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAAfsEAgAAAAABAFUCAAAAAfTCEtWu0ef2/2M/LOCcZHxXvt2TAxTZjed1A9WOlAszAAAAAAD/////AaCGAQAAAAAAGXapFB4q14ctMpQTpW3wlovjOCIngxY7iKwAAAAAAQdrSDBFAiEAis+uYae1IP8EMZK23JTMhCaRJECDEnZMiN3ZXamNKVUCICCHw7EY+WmSpNokE8/+kXDyUOJ+PBTLXe8+Y4ww1+qAASECyBe7dSGvw16pbzv7Jw5utQ3f+lVgYnuWH+wA8pllCL8BDiBSJ0jrF3ZNKMpJSBXsjUnn0w1SvHNCLHyG63TjlwVylAEPBAAAAAABEAT+////Ih0Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghA+yk/xG3KOLg9gzmIilDpv9VudlfYnv5qZ0IS8hy1QpbIh4Cekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAihOzmFVF9yvW6JcUrrkJs+NUqEKpu4tWzQ7e0h34oZlZizEiikngvX6VzhBT98WyistUOmhwdgDjzomCLuMgIQABAwgYcwEAAAAAAAEEIlEg4UDSh7RbRs1OqvpDdwYVcLq+g9G4vJUKdKn+oJIz16YBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA" + }, + "supplementary": { + "hex": "70736274ff0102040200000001040101010501010106010001fb0402000000000100550200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000220202c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf4830450221008acfae61a7b520ff043192b6dc94cc84269124408312764c88ddd95da98d295502202087c3b118f96992a4da2413cffe9170f250e27e3c14cb5def3e638c30d7ea800101030401000000220602a516bcf5d17e15554500b06d63de52aea77c745a93be42eadbf4ae9e3e1d12a00800000080ff000000220602c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf080000008000000000010e20522748eb17764d28ca494815ec8d49e7d30d52bc73422c7c86eb74e397057294010f0400000000011004feffffff221d027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0682103eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b221e027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068408a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee320210001030818730100000000000104225120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6010942027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce03900", + "inputs": [ + { + "input_index": 0, + "private_key": "7e31eeeb1aa2597b6d63b357541461d75ddae76b7603d24619f5ebed9e88ec31", + "public_key": "02c817bb7521afc35ea96f3bfb270e6eb50ddffa5560627b961fec00f2996508bf", + "prevout_txid": "94720597e374eb867c2c4273bc520dd3e7498dec154849ca284d7617eb482752", + "prevout_index": 0, + "amount": 100000, + "non_witness_utxo": "0200000001f4c212d5aed1e7f6ff633f2ce09c647c57bedd930314d98de77503d58e940b330000000000ffffffff01a0860100000000001976a9141e2ad7872d329413a56df0968be338222783163b88ac00000000", + "sequence": 4294967294, + "signed": true + } + ], + "sp_proofs": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "ecdh_share": "03eca4ff11b728e2e0f60ce6222943a6ff55b9d95f627bf9a99d084bc872d50a5b", + "dleq_proof": "8a13b3985545f72bd6e89714aeb909b3e354a842a9bb8b56cd0eded21df8a199598b31228a49e0bd7e95ce1053f7c5b28acb543a68707600e3ce89822ee32021", + "input_index": 0 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039", + "script": "5120e140d287b45b46cd4eaafa4377061570babe83d1b8bc950a74a9fea09233d7a6" + } + ], + "task": "finalize" + } + } + ], + "workflows": [ + { + "psbt": "", + "description": "Single-input P2WPKH to silent payment workflow (global-share): Creator adds inputs and SP outputs", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "prevout_txid": "617a421b840f772798bddc2286aadb05e47722a3e17d7df02fdcc000d731f9c0", + "prevout_index": 0, + "sequence": 4294967294 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 95000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + } + ], + "task": "create" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABDiDA+THXAMDcL/B9feGjInfkBduqhiLcvZgndw+EG0J6YQEPBAAAAAABEAT+////AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABDiDA+THXAMDcL/B9feGjInfkBduqhiLcvZgndw+EG0J6YQEPBAAAAAABEAT+////AAEDCBhzAQAAAAAAAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "description": "Single-input P2WPKH to silent payment workflow (global-share): Updater adds UTXO and BIP32 derivation data", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "public_key": "02e7ab2537b5d49e970309aae06e9e49f36ce1c9febbd44ec8e0d1cca0b4f9c319", + "witness_utxo": "a086010000000000160014d0c4a3ef09e997b6e99e397e518fe3e41a118ca1", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a086010000000000160014d0c4a3ef09e997b6e99e397e518fe3e41a118ca100000000", + "master_fingerprint": "73c5da0a", + "derivation_path": [ + 2147483732, + 2147483649, + 2147483648, + 0, + 0 + ] + } + ], + "task": "update" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAwgYcwEAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "transaction_id": "3b508bc0ded7d279823abacc5f8b5e218616829fed93e3dc7f33b84dae4ada75" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAwgYcwEAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "description": "Single-input P2WPKH to silent payment workflow (global-share): Signer adds the ECDH shares and DLEQ proofs, computes the silent payment output scripts, signs every eligible input", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "a9c4134b73560f43fc5c081e5c1daa7ce068adc806d80e1f37cb658e0fea4c8d" + } + ], + "task": "sign", + "dleq_aux_rand": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "aux_rand": "9a684bfd1bf67b76a4ea0422fb4a9947f4935263df55f351d7220a9d538faf3a" + } + ] + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAylSyo8o6g37bbrUnjjfGpNDehukHrc7H6xkkwckN2EGIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAJ3LCFKc+Lc4IppMOwehTbOueVq72Kx1tpkeZIM+UfZWRcZk7H//xvRI3CIWe63g2ApFsYIibTFzSle+qWiljOwH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoSICAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZSDBFAiEAiRbWpFNivV39l2zSAjQ+TuEuZ0sosH5wsiF45/otaMwCIAIXlqCwHdSEzFGdVSLkBHa6cJBdHCyO8p8UIGp/DaypASIGAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZGHPF2gpUAACAAQAAgAAAAIAAAAAAAAAAAAEOIMD5MdcAwNwv8H194aMid+QF26qGIty9mCd3D4QbQnphAQ8EAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRICTunhAal3RlYRPQo7kLMXOvGFybNFOLadMNt2k4+SGuAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "transaction_id": "3b508bc0ded7d279823abacc5f8b5e218616829fed93e3dc7f33b84dae4ada75" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAylSyo8o6g37bbrUnjjfGpNDehukHrc7H6xkkwckN2EGIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAJ3LCFKc+Lc4IppMOwehTbOueVq72Kx1tpkeZIM+UfZWRcZk7H//xvRI3CIWe63g2ApFsYIibTFzSle+qWiljOwH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoSICAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZSDBFAiEAiRbWpFNivV39l2zSAjQ+TuEuZ0sosH5wsiF45/otaMwCIAIXlqCwHdSEzFGdVSLkBHa6cJBdHCyO8p8UIGp/DaypASIGAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZGHPF2gpUAACAAQAAgAAAAIAAAAAAAAAAAAEOIMD5MdcAwNwv8H194aMid+QF26qGIty9mCd3D4QbQnphAQ8EAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRICTunhAal3RlYRPQo7kLMXOvGFybNFOLadMNt2k4+SGuAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "description": "Single-input P2WPKH to silent payment workflow (global-share): Input Finalizer builds the final scriptwitness", + "supplementary": { + "task": "finalize" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAylSyo8o6g37bbrUnjjfGpNDehukHrc7H6xkkwckN2EGIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAJ3LCFKc+Lc4IppMOwehTbOueVq72Kx1tpkeZIM+UfZWRcZk7H//xvRI3CIWe63g2ApFsYIibTFzSle+qWiljOwH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoQEIbAJIMEUCIQCJFtakU2K9Xf2XbNICND5O4S5nSyiwfnCyIXjn+i1ozAIgAheWoLAd1ITMUZ1VIuQEdrpwkF0cLI7ynxQgan8NrKkBIQLnqyU3tdSelwMJquBunknzbOHJ/rvUTsjg0cygtPnDGQEOIMD5MdcAwNwv8H194aMid+QF26qGIty9mCd3D4QbQnphAQ8EAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRICTunhAal3RlYRPQo7kLMXOvGFybNFOLadMNt2k4+SGuAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "transaction_id": "3b508bc0ded7d279823abacc5f8b5e218616829fed93e3dc7f33b84dae4ada75" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAylSyo8o6g37bbrUnjjfGpNDehukHrc7H6xkkwckN2EGIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAJ3LCFKc+Lc4IppMOwehTbOueVq72Kx1tpkeZIM+UfZWRcZk7H//xvRI3CIWe63g2ApFsYIibTFzSle+qWiljOwH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoQEIbAJIMEUCIQCJFtakU2K9Xf2XbNICND5O4S5nSyiwfnCyIXjn+i1ozAIgAheWoLAd1ITMUZ1VIuQEdrpwkF0cLI7ynxQgan8NrKkBIQLnqyU3tdSelwMJquBunknzbOHJ/rvUTsjg0cygtPnDGQEOIMD5MdcAwNwv8H194aMid+QF26qGIty9mCd3D4QbQnphAQ8EAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRICTunhAal3RlYRPQo7kLMXOvGFybNFOLadMNt2k4+SGuAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "description": "Single-input P2WPKH to silent payment workflow (global-share): Extractor produces the raw transaction", + "supplementary": { + "task": "extract" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAQEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAylSyo8o6g37bbrUnjjfGpNDehukHrc7H6xkkwckN2EGIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhAJ3LCFKc+Lc4IppMOwehTbOueVq72Kx1tpkeZIM+UfZWRcZk7H//xvRI3CIWe63g2ApFsYIibTFzSle+qWiljOwH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoQEIbAJIMEUCIQCJFtakU2K9Xf2XbNICND5O4S5nSyiwfnCyIXjn+i1ozAIgAheWoLAd1ITMUZ1VIuQEdrpwkF0cLI7ynxQgan8NrKkBIQLnqyU3tdSelwMJquBunknzbOHJ/rvUTsjg0cygtPnDGQEOIMD5MdcAwNwv8H194aMid+QF26qGIty9mCd3D4QbQnphAQ8EAAAAAAEQBP7///8AAQMIGHMBAAAAAAABBCJRICTunhAal3RlYRPQo7kLMXOvGFybNFOLadMNt2k4+SGuAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "transaction_id": "3b508bc0ded7d279823abacc5f8b5e218616829fed93e3dc7f33b84dae4ada75", + "tx": "02000000000101c0f931d700c0dc2ff07d7de1a32277e405dbaa8622dcbd9827770f841b427a610000000000feffffff01187301000000000022512024ee9e101a9774656113d0a3b90b3173af185c9b34538b69d30db76938f921ae024830450221008916d6a45362bd5dfd976cd202343e4ee12e674b28b07e70b22178e7fa2d68cc0220021796a0b01dd484cc519d5522e40476ba70905d1c2c8ef29f14206a7f0daca9012102e7ab2537b5d49e970309aae06e9e49f36ce1c9febbd44ec8e0d1cca0b4f9c31900000000" + } + }, + { + "psbt": "", + "description": "Two-input P2WPKH to silent payment workflow (global-share): Creator adds inputs and SP outputs", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "prevout_txid": "617a421b840f772798bddc2286aadb05e47722a3e17d7df02fdcc000d731f9c0", + "prevout_index": 0, + "sequence": 4294967294 + }, + { + "input_index": 1, + "prevout_txid": "dfe871f835c88bc1cd5ba1f55be8bbab77ed73a93f51120dddebcdf0d280d895", + "prevout_index": 0, + "sequence": 4294967294 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 190000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + } + ], + "task": "create" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABDiDA+THXAMDcL/B9feGjInfkBduqhiLcvZgndw+EG0J6YQEPBAAAAAABEAT+////AAEOIJXYgNLwzevdDRJRP6lz7Xeru+hb9aFbzcGLyDX4cejfAQ8EAAAAAAEQBP7///8AAQMIMOYCAAAAAAABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABDiDA+THXAMDcL/B9feGjInfkBduqhiLcvZgndw+EG0J6YQEPBAAAAAABEAT+////AAEOIJXYgNLwzevdDRJRP6lz7Xeru+hb9aFbzcGLyDX4cejfAQ8EAAAAAAEQBP7///8AAQMIMOYCAAAAAAABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "description": "Two-input P2WPKH to silent payment workflow (global-share): Updater adds UTXO and BIP32 derivation data", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "public_key": "02e7ab2537b5d49e970309aae06e9e49f36ce1c9febbd44ec8e0d1cca0b4f9c319", + "witness_utxo": "a086010000000000160014d0c4a3ef09e997b6e99e397e518fe3e41a118ca1", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a086010000000000160014d0c4a3ef09e997b6e99e397e518fe3e41a118ca100000000", + "master_fingerprint": "73c5da0a", + "derivation_path": [ + 2147483732, + 2147483649, + 2147483648, + 0, + 0 + ] + }, + { + "input_index": 1, + "public_key": "03eeed205a69022fed4a62a02457f3699b19c06bf74bf801acc6d9ae84bc16a9e1", + "witness_utxo": "a0860100000000001600146fa016500a3c6a737ebb260e2ddca78ba9234558", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600146fa016500a3c6a737ebb260e2ddca78ba923455800000000", + "master_fingerprint": "73c5da0a", + "derivation_path": [ + 2147483732, + 2147483649, + 2147483648, + 0, + 1 + ] + } + ], + "task": "update" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFG+gFlAKPGpzfrsmDi3cp4upI0VYIgYD7u0gWmkCL+1KYqAkV/NpmxnAa/dL+AGsxtmuhLwWqeEYc8XaClQAAIABAACAAAAAgAAAAAABAAAAAQ4gldiA0vDN690NElE/qXPtd6u76Fv1oVvNwYvINfhx6N8BDwQAAAAAARAE/v///wABAwgw5gIAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "transaction_id": "1ef33a458c1a8408009884a292e696c00f21e380f6aa6cf548011f53d158e6de" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFG+gFlAKPGpzfrsmDi3cp4upI0VYIgYD7u0gWmkCL+1KYqAkV/NpmxnAa/dL+AGsxtmuhLwWqeEYc8XaClQAAIABAACAAAAAgAAAAAABAAAAAQ4gldiA0vDN690NElE/qXPtd6u76Fv1oVvNwYvINfhx6N8BDwQAAAAAARAE/v///wABAwgw5gIAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "description": "Two-input P2WPKH to silent payment workflow (global-share): Signer adds the ECDH shares and DLEQ proofs, computes the silent payment output scripts, signs every eligible input", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "a9c4134b73560f43fc5c081e5c1daa7ce068adc806d80e1f37cb658e0fea4c8d" + }, + { + "input_index": 1, + "private_key": "4f9fb140e0586691de963613549631e2048ab4030d74f4d98405686dd30a9d75" + } + ], + "task": "sign", + "dleq_aux_rand": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "aux_rand": "9a684bfd1bf67b76a4ea0422fb4a9947f4935263df55f351d7220a9d538faf3a" + } ] + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAmcOzf/PYeb50isRkiio5eVa07QCBzxkbX4DJQwH/4eRIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA+Zz2pHZ6ZB86WLG51PiJstSsyTp0kNq5r8HtT4qvCjjdUmr4iDUAiAAVx0jzsT2+ymUPNFFMs6It2Wx+UZs2TQH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoSICAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZRzBEAiBSY20zBuplGPvfTyQ5p7jq1UMrLefHtCfhamw5qzk96wIgP/lU5A3A/y8VJPVEGwmA79NTqTNrIlkBmyQGUVXiKBIBIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFG+gFlAKPGpzfrsmDi3cp4upI0VYIgID7u0gWmkCL+1KYqAkV/NpmxnAa/dL+AGsxtmuhLwWqeFIMEUCIQCymbbzv+dZll5k+bwL8twlLK+JEM9KXpBpl18UExjPNwIgOXWPp6qDtBUOmLae2cbUQnYT4/0KEWF+rOX8yiT04jkBIgYD7u0gWmkCL+1KYqAkV/NpmxnAa/dL+AGsxtmuhLwWqeEYc8XaClQAAIABAACAAAAAgAAAAAABAAAAAQ4gldiA0vDN690NElE/qXPtd6u76Fv1oVvNwYvINfhx6N8BDwQAAAAAARAE/v///wABAwgw5gIAAAAAAAEEIlEgQR/Q1fcGFdKAXOVfN/x5gNJki6BFaTzD5fcxsppcDGkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "transaction_id": "1ef33a458c1a8408009884a292e696c00f21e380f6aa6cf548011f53d158e6de" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAmcOzf/PYeb50isRkiio5eVa07QCBzxkbX4DJQwH/4eRIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA+Zz2pHZ6ZB86WLG51PiJstSsyTp0kNq5r8HtT4qvCjjdUmr4iDUAiAAVx0jzsT2+ymUPNFFMs6It2Wx+UZs2TQH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoSICAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZRzBEAiBSY20zBuplGPvfTyQ5p7jq1UMrLefHtCfhamw5qzk96wIgP/lU5A3A/y8VJPVEGwmA79NTqTNrIlkBmyQGUVXiKBIBIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFG+gFlAKPGpzfrsmDi3cp4upI0VYIgID7u0gWmkCL+1KYqAkV/NpmxnAa/dL+AGsxtmuhLwWqeFIMEUCIQCymbbzv+dZll5k+bwL8twlLK+JEM9KXpBpl18UExjPNwIgOXWPp6qDtBUOmLae2cbUQnYT4/0KEWF+rOX8yiT04jkBIgYD7u0gWmkCL+1KYqAkV/NpmxnAa/dL+AGsxtmuhLwWqeEYc8XaClQAAIABAACAAAAAgAAAAAABAAAAAQ4gldiA0vDN690NElE/qXPtd6u76Fv1oVvNwYvINfhx6N8BDwQAAAAAARAE/v///wABAwgw5gIAAAAAAAEEIlEgQR/Q1fcGFdKAXOVfN/x5gNJki6BFaTzD5fcxsppcDGkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "description": "Two-input P2WPKH to silent payment workflow (global-share): Input Finalizer builds the final scriptwitness", + "supplementary": { + "task": "finalize" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAmcOzf/PYeb50isRkiio5eVa07QCBzxkbX4DJQwH/4eRIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA+Zz2pHZ6ZB86WLG51PiJstSsyTp0kNq5r8HtT4qvCjjdUmr4iDUAiAAVx0jzsT2+ymUPNFFMs6It2Wx+UZs2TQH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoQEIawJHMEQCIFJjbTMG6mUY+99PJDmnuOrVQyst58e0J+FqbDmrOT3rAiA/+VTkDcD/LxUk9UQbCYDv01OpM2siWQGbJAZRVeIoEgEhAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFG+gFlAKPGpzfrsmDi3cp4upI0VYAQhsAkgwRQIhALKZtvO/51mWXmT5vAvy3CUsr4kQz0pekGmXXxQTGM83AiA5dY+nqoO0FQ6Ytp7ZxtRCdhPj/QoRYX6s5fzKJPTiOQEhA+7tIFppAi/tSmKgJFfzaZsZwGv3S/gBrMbZroS8FqnhAQ4gldiA0vDN690NElE/qXPtd6u76Fv1oVvNwYvINfhx6N8BDwQAAAAAARAE/v///wABAwgw5gIAAAAAAAEEIlEgQR/Q1fcGFdKAXOVfN/x5gNJki6BFaTzD5fcxsppcDGkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "transaction_id": "1ef33a458c1a8408009884a292e696c00f21e380f6aa6cf548011f53d158e6de" } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAmcOzf/PYeb50isRkiio5eVa07QCBzxkbX4DJQwH/4eRIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA+Zz2pHZ6ZB86WLG51PiJstSsyTp0kNq5r8HtT4qvCjjdUmr4iDUAiAAVx0jzsT2+ymUPNFFMs6It2Wx+UZs2TQH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoQEIawJHMEQCIFJjbTMG6mUY+99PJDmnuOrVQyst58e0J+FqbDmrOT3rAiA/+VTkDcD/LxUk9UQbCYDv01OpM2siWQGbJAZRVeIoEgEhAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFG+gFlAKPGpzfrsmDi3cp4upI0VYAQhsAkgwRQIhALKZtvO/51mWXmT5vAvy3CUsr4kQz0pekGmXXxQTGM83AiA5dY+nqoO0FQ6Ytp7ZxtRCdhPj/QoRYX6s5fzKJPTiOQEhA+7tIFppAi/tSmKgJFfzaZsZwGv3S/gBrMbZroS8FqnhAQ4gldiA0vDN690NElE/qXPtd6u76Fv1oVvNwYvINfhx6N8BDwQAAAAAARAE/v///wABAwgw5gIAAAAAAAEEIlEgQR/Q1fcGFdKAXOVfN/x5gNJki6BFaTzD5fcxsppcDGkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "description": "Two-input P2WPKH to silent payment workflow (global-share): Extractor produces the raw transaction", + "supplementary": { + "task": "extract" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAIgcCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GghAmcOzf/PYeb50isRkiio5eVa07QCBzxkbX4DJQwH/4eRIggCekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GhA+Zz2pHZ6ZB86WLG51PiJstSsyTp0kNq5r8HtT4qvCjjdUmr4iDUAiAAVx0jzsT2+ymUPNFFMs6It2Wx+UZs2TQH7BAIAAAAAAQEfoIYBAAAAAAAWABTQxKPvCemXtumeOX5Rj+PkGhGMoQEIawJHMEQCIFJjbTMG6mUY+99PJDmnuOrVQyst58e0J+FqbDmrOT3rAiA/+VTkDcD/LxUk9UQbCYDv01OpM2siWQGbJAZRVeIoEgEhAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFG+gFlAKPGpzfrsmDi3cp4upI0VYAQhsAkgwRQIhALKZtvO/51mWXmT5vAvy3CUsr4kQz0pekGmXXxQTGM83AiA5dY+nqoO0FQ6Ytp7ZxtRCdhPj/QoRYX6s5fzKJPTiOQEhA+7tIFppAi/tSmKgJFfzaZsZwGv3S/gBrMbZroS8FqnhAQ4gldiA0vDN690NElE/qXPtd6u76Fv1oVvNwYvINfhx6N8BDwQAAAAAARAE/v///wABAwgw5gIAAAAAAAEEIlEgQR/Q1fcGFdKAXOVfN/x5gNJki6BFaTzD5fcxsppcDGkBCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "transaction_id": "1ef33a458c1a8408009884a292e696c00f21e380f6aa6cf548011f53d158e6de", + "tx": "02000000000102c0f931d700c0dc2ff07d7de1a32277e405dbaa8622dcbd9827770f841b427a610000000000feffffff95d880d2f0cdebdd0d12513fa973ed77abbbe85bf5a15bcdc18bc835f871e8df0000000000feffffff0130e6020000000000225120411fd0d5f70615d2805ce55f37fc7980d2648ba045693cc3e5f731b29a5c0c6902473044022052636d3306ea6518fbdf4f2439a7b8ead5432b2de7c7b427e16a6c39ab393deb02203ff954e40dc0ff2f1524f5441b0980efd353a9336b2259019b24065155e22812012102e7ab2537b5d49e970309aae06e9e49f36ce1c9febbd44ec8e0d1cca0b4f9c31902483045022100b299b6f3bfe759965e64f9bc0bf2dc252caf8910cf4a5e9069975f141318cf37022039758fa7aa83b4150e98b69ed9c6d4427613e3fd0a11617eace5fcca24f4e239012103eeed205a69022fed4a62a02457f3699b19c06bf74bf801acc6d9ae84bc16a9e100000000" + } + }, + { + "psbt": "", + "description": "Two-input P2WPKH to silent payment workflow (per-input-share): Creator adds inputs and SP outputs", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "prevout_txid": "617a421b840f772798bddc2286aadb05e47722a3e17d7df02fdcc000d731f9c0", + "prevout_index": 0, + "sequence": 4294967294 + }, + { + "input_index": 1, + "prevout_txid": "a3a559fea487db8799313ef1fe733747291cd1f49a5452669c9afe5603c79939", + "prevout_index": 0, + "sequence": 4294967294 + } + ], + "outputs": [ + { + "output_index": 0, + "amount": 190000, + "sp_v0_info": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe0680361e1b1e9de5e42cb2007f7ca54b9e0d57ed13938fad56d3f19e57513a8fce039" + } + ], + "task": "create" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABDiDA+THXAMDcL/B9feGjInfkBduqhiLcvZgndw+EG0J6YQEPBAAAAAABEAT+////AAEOIDmZxwNW/pqcZlJUmvTRHClHN3P+8T4xmYfbh6T+WaWjAQ8EAAAAAAEQBP7///8AAQMIMOYCAAAAAAABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABDiDA+THXAMDcL/B9feGjInfkBduqhiLcvZgndw+EG0J6YQEPBAAAAAABEAT+////AAEOIDmZxwNW/pqcZlJUmvTRHClHN3P+8T4xmYfbh6T+WaWjAQ8EAAAAAAEQBP7///8AAQMIMOYCAAAAAAABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "description": "Two-input P2WPKH to silent payment workflow (per-input-share): Updater adds UTXO and BIP32 derivation data", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "public_key": "02e7ab2537b5d49e970309aae06e9e49f36ce1c9febbd44ec8e0d1cca0b4f9c319", + "witness_utxo": "a086010000000000160014d0c4a3ef09e997b6e99e397e518fe3e41a118ca1", + "non_witness_utxo": "020000000118a717663b0bab14b12a1a771323ff1e4079dd532e5dd13e28ea1081c700984a0000000000ffffffff01a086010000000000160014d0c4a3ef09e997b6e99e397e518fe3e41a118ca100000000", + "master_fingerprint": "73c5da0a", + "derivation_path": [ + 2147483732, + 2147483649, + 2147483648, + 0, + 0 + ] + }, + { + "input_index": 1, + "public_key": "03bd84f121f3325b3c49feccc20cf274a7d4e173b3e31622dc1c4cf1aba685d81a", + "witness_utxo": "a0860100000000001600149907150486bac5680f9b46fde6300e69e8e4f623", + "non_witness_utxo": "0200000001be9d65c83915fb09248abbdfca8ca3eee6ce350c554f65e8d526e5df527ab5220000000000ffffffff01a0860100000000001600149907150486bac5680f9b46fde6300e69e8e4f62300000000", + "master_fingerprint": "3f635a63", + "derivation_path": [ + 2147483732, + 2147483649, + 2147483648, + 0, + 1 + ] + } + ], + "task": "update" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFJkHFQSGusVoD5tG/eYwDmno5PYjIgYDvYTxIfMyWzxJ/szCDPJ0p9Thc7PjFiLcHEzxq6aF2BoYP2NaY1QAAIABAACAAAAAgAAAAAABAAAAAQ4gOZnHA1b+mpxmUlSa9NEcKUc3c/7xPjGZh9uHpP5ZpaMBDwQAAAAAARAE/v///wABAwgw5gIAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "transaction_id": "fc2bcbe9f62764f759f1537d0150a3b6d45f77fd747d32a9312f0301777554ae" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///wABAR+ghgEAAAAAABYAFJkHFQSGusVoD5tG/eYwDmno5PYjIgYDvYTxIfMyWzxJ/szCDPJ0p9Thc7PjFiLcHEzxq6aF2BoYP2NaY1QAAIABAACAAAAAgAAAAAABAAAAAQ4gOZnHA1b+mpxmUlSa9NEcKUc3c/7xPjGZh9uHpP5ZpaMBDwQAAAAAARAE/v///wABAwgw5gIAAAAAAAEJQgJ6SH/Bn7dph3uHQtbqGBGPPE5yseqMbeYCp61KQdvgaANh4bHp3l5CyyAH98pUueDVftE5OPrVbT8Z5XUTqPzgOQA=", + "description": "Two-input P2WPKH to silent payment workflow (per-input-share): Signer adds its ECDH share and DLEQ proof, wait for every eligible input to have a share before signing (signer 1 of 2)", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "a9c4134b73560f43fc5c081e5c1daa7ce068adc806d80e1f37cb658e0fea4c8d" + }, + { + "input_index": 1, + "private_key": "" + } + ], + "task": "sign", + "dleq_aux_rand": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "input_index": 0, + "aux_rand": "0743566c1dd13716c8a86c195e99878415713a65114a3ab3d8fcb070b13e55e2" + } + ] + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQMpUsqPKOoN+2261J443xqTQ3obpB63Ox+sZJMHJDdhBiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGGiAVGSbQR38xm4aFBMmZzPcsuqfTFQShTMBldITF+cw/yFy33U0jrHORBp7oA6kQ88mWoEanDuTaDKiKsRUZoAAQEfoIYBAAAAAAAWABSZBxUEhrrFaA+bRv3mMA5p6OT2IyIGA72E8SHzMls8Sf7MwgzydKfU4XOz4xYi3BxM8aumhdgaGD9jWmNUAACAAQAAgAAAAIAAAAAAAQAAAAEOIDmZxwNW/pqcZlJUmvTRHClHN3P+8T4xmYfbh6T+WaWjAQ8EAAAAAAEQBP7///8AAQMIMOYCAAAAAAABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "transaction_id": "fc2bcbe9f62764f759f1537d0150a3b6d45f77fd747d32a9312f0301777554ae" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEDAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQMpUsqPKOoN+2261J443xqTQ3obpB63Ox+sZJMHJDdhBiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGGiAVGSbQR38xm4aFBMmZzPcsuqfTFQShTMBldITF+cw/yFy33U0jrHORBp7oA6kQ88mWoEanDuTaDKiKsRUZoAAQEfoIYBAAAAAAAWABSZBxUEhrrFaA+bRv3mMA5p6OT2IyIGA72E8SHzMls8Sf7MwgzydKfU4XOz4xYi3BxM8aumhdgaGD9jWmNUAACAAQAAgAAAAIAAAAAAAQAAAAEOIDmZxwNW/pqcZlJUmvTRHClHN3P+8T4xmYfbh6T+WaWjAQ8EAAAAAAEQBP7///8AAQMIMOYCAAAAAAABCUICekh/wZ+3aYd7h0LW6hgRjzxOcrHqjG3mAqetSkHb4GgDYeGx6d5eQssgB/fKVLng1X7ROTj61W0/GeV1E6j84DkA", + "description": "Two-input P2WPKH to silent payment workflow (per-input-share): Signer adds its ECDH share and DLEQ proof, verifies other DLEQ proofs, computes the silent payment output scripts, signs its input (signer 2 of 2)", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "" + }, + { + "input_index": 1, + "private_key": "a9984cbbfc28d1da23785b948392fdb028f32205875ed5a45cac5ea6aab1bd2b" + } + ], + "task": "sign", + "dleq_aux_rand": [ + { + "scan_key": "027a487fc19fb769877b8742d6ea18118f3c4e72b1ea8c6de602a7ad4a41dbe068", + "input_index": 1, + "aux_rand": "b1f38574d9302aecd1a6600c15e22fdb02a1998777dd5ac63cc219a0f4a1f317" + } + ] + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQMpUsqPKOoN+2261J443xqTQ3obpB63Ox+sZJMHJDdhBiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGGiAVGSbQR38xm4aFBMmZzPcsuqfTFQShTMBldITF+cw/yFy33U0jrHORBp7oA6kQ88mWoEanDuTaDKiKsRUZoAAQEfoIYBAAAAAAAWABSZBxUEhrrFaA+bRv3mMA5p6OT2IyICA72E8SHzMls8Sf7MwgzydKfU4XOz4xYi3BxM8aumhdgaRzBEAiB+Lec7AFjGAeUli0HpTF+tvC27rXQL5eaoOy7ybWHqfAIge1C+CIFjGwaiU4am40x9ZS/WFXClOCYviQZjPnTtJsIBIgYDvYTxIfMyWzxJ/szCDPJ0p9Thc7PjFiLcHEzxq6aF2BoYP2NaY1QAAIABAACAAAAAgAAAAAABAAAAAQ4gOZnHA1b+mpxmUlSa9NEcKUc3c/7xPjGZh9uHpP5ZpaMBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQOcaPHGSUYGtOPHPZSSAn3hpVsiwZhpTY17fY0chlNk6CIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC8TWaS3k4MLbUs0UPHs7Q2JTYgagUi5LO+jkRi0leOHFT/dqx3+W7cL84o7+5TYOla03NqWvldaPdk5R7TDKhMAAQMIMOYCAAAAAAABBCJRIHXYX6pjg8Ed6cviuJjsDHngmtZQb7Pd+rYwYT4skRjFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "transaction_id": "fc2bcbe9f62764f759f1537d0150a3b6d45f77fd747d32a9312f0301777554ae" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQMpUsqPKOoN+2261J443xqTQ3obpB63Ox+sZJMHJDdhBiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGGiAVGSbQR38xm4aFBMmZzPcsuqfTFQShTMBldITF+cw/yFy33U0jrHORBp7oA6kQ88mWoEanDuTaDKiKsRUZoAAQEfoIYBAAAAAAAWABSZBxUEhrrFaA+bRv3mMA5p6OT2IyICA72E8SHzMls8Sf7MwgzydKfU4XOz4xYi3BxM8aumhdgaRzBEAiB+Lec7AFjGAeUli0HpTF+tvC27rXQL5eaoOy7ybWHqfAIge1C+CIFjGwaiU4am40x9ZS/WFXClOCYviQZjPnTtJsIBIgYDvYTxIfMyWzxJ/szCDPJ0p9Thc7PjFiLcHEzxq6aF2BoYP2NaY1QAAIABAACAAAAAgAAAAAABAAAAAQ4gOZnHA1b+mpxmUlSa9NEcKUc3c/7xPjGZh9uHpP5ZpaMBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQOcaPHGSUYGtOPHPZSSAn3hpVsiwZhpTY17fY0chlNk6CIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC8TWaS3k4MLbUs0UPHs7Q2JTYgagUi5LO+jkRi0leOHFT/dqx3+W7cL84o7+5TYOla03NqWvldaPdk5R7TDKhMAAQMIMOYCAAAAAAABBCJRIHXYX6pjg8Ed6cviuJjsDHngmtZQb7Pd+rYwYT4skRjFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "description": "Two-input P2WPKH to silent payment workflow (per-input-share): Signer verifies the DLEQ proofs and the output scripts, signs its input (signer 1 of 2)", + "supplementary": { + "inputs": [ + { + "input_index": 0, + "private_key": "a9c4134b73560f43fc5c081e5c1daa7ce068adc806d80e1f37cb658e0fea4c8d" + }, + { + "input_index": 1, + "private_key": "" + } + ], + "task": "sign" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgIC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxlIMEUCIQC5sZc/GTSQLYb1baCPH0/G2jhGUbDDkbQXoWsgkxHbagIgVrTFjiV6zvvJBMFJxVWOHhDMsrT64jYOin4sVv5sja8BIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQMpUsqPKOoN+2261J443xqTQ3obpB63Ox+sZJMHJDdhBiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGGiAVGSbQR38xm4aFBMmZzPcsuqfTFQShTMBldITF+cw/yFy33U0jrHORBp7oA6kQ88mWoEanDuTaDKiKsRUZoAAQEfoIYBAAAAAAAWABSZBxUEhrrFaA+bRv3mMA5p6OT2IyICA72E8SHzMls8Sf7MwgzydKfU4XOz4xYi3BxM8aumhdgaRzBEAiB+Lec7AFjGAeUli0HpTF+tvC27rXQL5eaoOy7ybWHqfAIge1C+CIFjGwaiU4am40x9ZS/WFXClOCYviQZjPnTtJsIBIgYDvYTxIfMyWzxJ/szCDPJ0p9Thc7PjFiLcHEzxq6aF2BoYP2NaY1QAAIABAACAAAAAgAAAAAABAAAAAQ4gOZnHA1b+mpxmUlSa9NEcKUc3c/7xPjGZh9uHpP5ZpaMBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQOcaPHGSUYGtOPHPZSSAn3hpVsiwZhpTY17fY0chlNk6CIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC8TWaS3k4MLbUs0UPHs7Q2JTYgagUi5LO+jkRi0leOHFT/dqx3+W7cL84o7+5TYOla03NqWvldaPdk5R7TDKhMAAQMIMOYCAAAAAAABBCJRIHXYX6pjg8Ed6cviuJjsDHngmtZQb7Pd+rYwYT4skRjFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "transaction_id": "fc2bcbe9f62764f759f1537d0150a3b6d45f77fd747d32a9312f0301777554ae" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhIgIC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxlIMEUCIQC5sZc/GTSQLYb1baCPH0/G2jhGUbDDkbQXoWsgkxHbagIgVrTFjiV6zvvJBMFJxVWOHhDMsrT64jYOin4sVv5sja8BIgYC56slN7XUnpcDCargbp5J82zhyf671E7I4NHMoLT5wxkYc8XaClQAAIABAACAAAAAgAAAAAAAAAAAAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQMpUsqPKOoN+2261J443xqTQ3obpB63Ox+sZJMHJDdhBiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGGiAVGSbQR38xm4aFBMmZzPcsuqfTFQShTMBldITF+cw/yFy33U0jrHORBp7oA6kQ88mWoEanDuTaDKiKsRUZoAAQEfoIYBAAAAAAAWABSZBxUEhrrFaA+bRv3mMA5p6OT2IyICA72E8SHzMls8Sf7MwgzydKfU4XOz4xYi3BxM8aumhdgaRzBEAiB+Lec7AFjGAeUli0HpTF+tvC27rXQL5eaoOy7ybWHqfAIge1C+CIFjGwaiU4am40x9ZS/WFXClOCYviQZjPnTtJsIBIgYDvYTxIfMyWzxJ/szCDPJ0p9Thc7PjFiLcHEzxq6aF2BoYP2NaY1QAAIABAACAAAAAgAAAAAABAAAAAQ4gOZnHA1b+mpxmUlSa9NEcKUc3c/7xPjGZh9uHpP5ZpaMBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQOcaPHGSUYGtOPHPZSSAn3hpVsiwZhpTY17fY0chlNk6CIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC8TWaS3k4MLbUs0UPHs7Q2JTYgagUi5LO+jkRi0leOHFT/dqx3+W7cL84o7+5TYOla03NqWvldaPdk5R7TDKhMAAQMIMOYCAAAAAAABBCJRIHXYX6pjg8Ed6cviuJjsDHngmtZQb7Pd+rYwYT4skRjFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "description": "Two-input P2WPKH to silent payment workflow (per-input-share): Input Finalizer builds the final scriptwitness", + "supplementary": { + "task": "finalize" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhAQhsAkgwRQIhALmxlz8ZNJAthvVtoI8fT8baOEZRsMORtBehayCTEdtqAiBWtMWOJXrO+8kEwUnFVY4eEMyytPriNg6KfixW/myNrwEhAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQMpUsqPKOoN+2261J443xqTQ3obpB63Ox+sZJMHJDdhBiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGGiAVGSbQR38xm4aFBMmZzPcsuqfTFQShTMBldITF+cw/yFy33U0jrHORBp7oA6kQ88mWoEanDuTaDKiKsRUZoAAQEfoIYBAAAAAAAWABSZBxUEhrrFaA+bRv3mMA5p6OT2IwEIawJHMEQCIH4t5zsAWMYB5SWLQelMX628LbutdAvl5qg7LvJtYep8AiB7UL4IgWMbBqJThqbjTH1lL9YVcKU4Ji+JBmM+dO0mwgEhA72E8SHzMls8Sf7MwgzydKfU4XOz4xYi3BxM8aumhdgaAQ4gOZnHA1b+mpxmUlSa9NEcKUc3c/7xPjGZh9uHpP5ZpaMBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQOcaPHGSUYGtOPHPZSSAn3hpVsiwZhpTY17fY0chlNk6CIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC8TWaS3k4MLbUs0UPHs7Q2JTYgagUi5LO+jkRi0leOHFT/dqx3+W7cL84o7+5TYOla03NqWvldaPdk5R7TDKhMAAQMIMOYCAAAAAAABBCJRIHXYX6pjg8Ed6cviuJjsDHngmtZQb7Pd+rYwYT4skRjFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "transaction_id": "fc2bcbe9f62764f759f1537d0150a3b6d45f77fd747d32a9312f0301777554ae" + } + }, + { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhAQhsAkgwRQIhALmxlz8ZNJAthvVtoI8fT8baOEZRsMORtBehayCTEdtqAiBWtMWOJXrO+8kEwUnFVY4eEMyytPriNg6KfixW/myNrwEhAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQMpUsqPKOoN+2261J443xqTQ3obpB63Ox+sZJMHJDdhBiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGGiAVGSbQR38xm4aFBMmZzPcsuqfTFQShTMBldITF+cw/yFy33U0jrHORBp7oA6kQ88mWoEanDuTaDKiKsRUZoAAQEfoIYBAAAAAAAWABSZBxUEhrrFaA+bRv3mMA5p6OT2IwEIawJHMEQCIH4t5zsAWMYB5SWLQelMX628LbutdAvl5qg7LvJtYep8AiB7UL4IgWMbBqJThqbjTH1lL9YVcKU4Ji+JBmM+dO0mwgEhA72E8SHzMls8Sf7MwgzydKfU4XOz4xYi3BxM8aumhdgaAQ4gOZnHA1b+mpxmUlSa9NEcKUc3c/7xPjGZh9uHpP5ZpaMBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQOcaPHGSUYGtOPHPZSSAn3hpVsiwZhpTY17fY0chlNk6CIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC8TWaS3k4MLbUs0UPHs7Q2JTYgagUi5LO+jkRi0leOHFT/dqx3+W7cL84o7+5TYOla03NqWvldaPdk5R7TDKhMAAQMIMOYCAAAAAAABBCJRIHXYX6pjg8Ed6cviuJjsDHngmtZQb7Pd+rYwYT4skRjFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "description": "Two-input P2WPKH to silent payment workflow (per-input-share): Extractor produces the raw transaction", + "supplementary": { + "task": "extract" + }, + "expected": { + "psbt": "cHNidP8BAgQCAAAAAQQBAgEFAQEBBgEAAfsEAgAAAAABAR+ghgEAAAAAABYAFNDEo+8J6Ze26Z45flGP4+QaEYyhAQhsAkgwRQIhALmxlz8ZNJAthvVtoI8fT8baOEZRsMORtBehayCTEdtqAiBWtMWOJXrO+8kEwUnFVY4eEMyytPriNg6KfixW/myNrwEhAuerJTe11J6XAwmq4G6eSfNs4cn+u9ROyODRzKC0+cMZAQ4gwPkx1wDA3C/wfX3hoyJ35AXbqoYi3L2YJ3cPhBtCemEBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQMpUsqPKOoN+2261J443xqTQ3obpB63Ox+sZJMHJDdhBiIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQGGiAVGSbQR38xm4aFBMmZzPcsuqfTFQShTMBldITF+cw/yFy33U0jrHORBp7oA6kQ88mWoEanDuTaDKiKsRUZoAAQEfoIYBAAAAAAAWABSZBxUEhrrFaA+bRv3mMA5p6OT2IwEIawJHMEQCIH4t5zsAWMYB5SWLQelMX628LbutdAvl5qg7LvJtYep8AiB7UL4IgWMbBqJThqbjTH1lL9YVcKU4Ji+JBmM+dO0mwgEhA72E8SHzMls8Sf7MwgzydKfU4XOz4xYi3BxM8aumhdgaAQ4gOZnHA1b+mpxmUlSa9NEcKUc3c/7xPjGZh9uHpP5ZpaMBDwQAAAAAARAE/v///yIdAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoIQOcaPHGSUYGtOPHPZSSAn3hpVsiwZhpTY17fY0chlNk6CIeAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoQC8TWaS3k4MLbUs0UPHs7Q2JTYgagUi5LO+jkRi0leOHFT/dqx3+W7cL84o7+5TYOla03NqWvldaPdk5R7TDKhMAAQMIMOYCAAAAAAABBCJRIHXYX6pjg8Ed6cviuJjsDHngmtZQb7Pd+rYwYT4skRjFAQlCAnpIf8Gft2mHe4dC1uoYEY88TnKx6oxt5gKnrUpB2+BoA2HhseneXkLLIAf3ylS54NV+0Tk4+tVtPxnldROo/OA5AA==", + "transaction_id": "fc2bcbe9f62764f759f1537d0150a3b6d45f77fd747d32a9312f0301777554ae", + "tx": "02000000000102c0f931d700c0dc2ff07d7de1a32277e405dbaa8622dcbd9827770f841b427a610000000000feffffff3999c70356fe9a9c6652549af4d11c29473773fef13e319987db87a4fe59a5a30000000000feffffff0130e602000000000022512075d85faa6383c11de9cbe2b898ec0c79e09ad6506fb3ddfab630613e2c9118c502483045022100b9b1973f1934902d86f56da08f1f4fc6da384651b0c391b417a16b209311db6a022056b4c58e257acefbc904c149c5558e1e10ccb2b4fae2360e8a7e2c56fe6c8daf012102e7ab2537b5d49e970309aae06e9e49f36ce1c9febbd44ec8e0d1cca0b4f9c3190247304402207e2de73b0058c601e5258b41e94c5fadbc2dbbad740be5e6a83b2ef26d61ea7c02207b50be0881631b06a25386a6e34c7d652fd61570a538262f8906633e74ed26c2012103bd84f121f3325b3c49feccc20cf274a7d4e173b3e31622dc1c4cf1aba685d81a00000000" + } + } + ], + "wallets": [ + { + "fingerprint": "73c5da0a", + "mnemonic": "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" + }, + { + "fingerprint": "3f635a63", + "mnemonic": "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong" } ] } \ No newline at end of file diff --git a/testing/test_bip375_vectors.py b/testing/test_bip375_vectors.py index e53b4fcad..eece9b41f 100644 --- a/testing/test_bip375_vectors.py +++ b/testing/test_bip375_vectors.py @@ -84,7 +84,12 @@ def _get(self, substr): ("input 1 missing ECDH share for scan key", "missing ECDH share"), ("segwit version greater than 1", "Segwit v"), ("non-SIGHASH_ALL signature", "SIGHASH_ALL"), - ("NUMS internal key", "Missing ECDH share for output"), + ("NUMS internal key cannot derive sp output", "Missing ECDH share for output"), + ("NUMS internal key claim not matching prevout", "missing ECDH share"), + ("derivation: P2WPKH BIP32_DERIVATION pubkey does not match prevout script", "does not match prevout script"), + ("P2PKH BIP32_DERIVATION pubkey does not match prevout script", "does not match prevout script"), + ("P2SH-P2WPKH BIP32_DERIVATION pubkey does not match prevout script", "does not match prevout script"), + ("global ECDH share computed from decoy pubkey", "does not match prevout script"), ("PSBT_OUT_SCRIPT does not match derived sp output", "output script mismatch"), ("not sorted lexicographically by spend key", "output script mismatch"), ("k values assigned to wrong output indices", "output script mismatch"), @@ -124,6 +129,8 @@ def test_valid_ecdh_computation(self, sim_exec, sim_execfile): expected_ecdh = unhexlify(expected["ecdh_share"]) if "input_index" in expected: ik = next(k for k in vec["supplementary"]["inputs"] if k["input_index"] == expected["input_index"]) + if not ik["private_key"]: + continue privkey = unhexlify(ik["private_key"]) actual = _sim_compute_ecdh_share(sim_exec, sim_execfile, privkey, scan_key) else: From b2f9a7fe084975370975e443fa482ea5af579727 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 30 Sep 2026 14:19:14 -0400 Subject: [PATCH 28/41] test (SP): drive BIP-375 workflow Signer steps through the sign flow Run the Signer steps of the draft BIP-375 workflow vectors through start_sign and end_sign. Select the acting seeded wallet from the input BIP32 derivation fingerprint for each step. Compare ECDH shares, output scripts, signed inputs, and the BIP-370 unique id. Verify DLEQ proofs and ECDSA signatures instead of comparing randomized proofs or signatures whose low-R grinding differs. Bypass the end_sign signature-length check because a cosigner signature already in the PSBT may exceed its limit. The workflow vectors remain a draft and may change. --- testing/test_bip375_workflows.py | 129 +++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 testing/test_bip375_workflows.py diff --git a/testing/test_bip375_workflows.py b/testing/test_bip375_workflows.py new file mode 100644 index 000000000..6d100a7dc --- /dev/null +++ b/testing/test_bip375_workflows.py @@ -0,0 +1,129 @@ +# (c) Copyright 2024 by Coinkite Inc. This file is covered by license found in COPYING-CC. +# +# test_bip375_workflows.py - Drive BIP-375 workflow vectors through the simulator's signing flow +# +# Each `workflows` entry is one role transition: `psbt` is the role's input and `expected.psbt` its +# output. The Coldcard is a Signer, so only sign steps run here; the other roles belong to the +# coordinator. +# +# The vector keys come from seeded wallets listed under `wallets`. A sign step discloses the private +# keys of the inputs its party holds, and the PSBT's BIP32 derivation for such an input names the +# wallet by fingerprint. The test loads that wallet's seed into the simulator and signs through the +# normal start_sign/end_sign flow, so the same steps cover every party (signer 1 and signer 2). +# +# Compared: ECDH shares, output scripts, which inputs are signed and the BIP-370 unique id. +# Verified, not compared: DLEQ proofs (fresh randomness) and ECDSA signatures (the firmware grinds +# for low R, the reference does not, so the bytes legitimately differ). +# +import json +import time +import pytest +from base64 import b64decode +from binascii import unhexlify +from helpers import hash160 +from bip322 import ecdsa_verify_sig +from sighash import segwit_v0_sighash +from ctransaction import CTransaction, CTxIn, CTxOut, COutPoint, uint256_from_str +from psbt import BasicPSBT +from sp_helpers import _sim_get_ecdh_and_pubkey, _sim_pubkey_from_input, _sim_verify_dleq + +SIMULATOR_DELAY = 0.5 + +with open("bip375_test_vectors.json") as f: + VECTORS = json.load(f) + +WORKFLOWS = VECTORS["workflows"] +MNEMONICS = {w["fingerprint"]: w["mnemonic"] for w in VECTORS["wallets"]} + + +def _acting_mnemonic(entry): + """Seed words of the wallet whose keys this sign step discloses.""" + held = [row["input_index"] for row in entry["supplementary"]["inputs"] if row.get("private_key")] + psbt = BasicPSBT().parse(entry["psbt"].encode()) + # the wallet is named by the origin fingerprint in the PSBT; all held inputs share one wallet + fingerprints = {next(iter(psbt.inputs[i].bip32_paths.values()))[:4].hex() for i in held} + assert len(fingerprints) == 1, "one step should act for a single wallet" + return MNEMONICS[fingerprints.pop()] + + +def _id(entry): + return entry["description"].replace("Two-input P2WPKH to silent payment workflow ", "")[:90] + + +def _params(): + for entry in WORKFLOWS: + marks = [] + if entry["supplementary"]["task"] != "sign": + marks.append(pytest.mark.skip(reason="not a Signer step")) + yield pytest.param(entry, marks=marks, id=_id(entry)) + + +def _unique_id(psbt): + """BIP-370 unique id, with PSBT_OUT_SP_V0_INFO standing in for unset SP output scripts (BIP-375).""" + tx = CTransaction() + tx.nVersion = psbt.txn_version + tx.nLockTime = 0 + for inp in psbt.inputs: + tx.vin.append(CTxIn(COutPoint(uint256_from_str(inp.previous_txid), inp.prevout_idx), b"", 0)) + for out in psbt.outputs: + script = b"\x00" + out.sp_v0_info if out.sp_v0_info else out.script + tx.vout.append(CTxOut(out.amount, script)) + tx.calc_sha256() + return tx.sha256.to_bytes(32, "big").hex() + + +def _sp_fields(psbt): + return { + "global_ecdh": dict(psbt.sp_global_ecdh_shares or {}), + "input_ecdh": [dict(i.sp_ecdh_shares or {}) for i in psbt.inputs], + "output_scripts": [o.script for o in psbt.outputs], + "signed_by": [sorted(i.part_sigs or {}) for i in psbt.inputs], + } + + +def _verify_p2wpkh_sigs(psbt): + """Check every partial signature against the BIP-143 sighash of the PSBT's transaction.""" + tx = CTransaction() + tx.nVersion = psbt.txn_version + tx.nLockTime = psbt.fallback_locktime or 0 + for inp in psbt.inputs: + tx.vin.append(CTxIn(COutPoint(uint256_from_str(inp.previous_txid), inp.prevout_idx), b"", inp.sequence)) + for out in psbt.outputs: + tx.vout.append(CTxOut(out.amount, out.script)) + for idx, inp in enumerate(psbt.inputs): + for pubkey, sig in (inp.part_sigs or {}).items(): + amount = int.from_bytes(inp.witness_utxo[:8], "little") + script_code = b"\x76\xa9\x14" + hash160(pubkey) + b"\x88\xac" + assert ecdsa_verify_sig(pubkey, sig, segwit_v0_sighash(tx, idx, script_code, amount)), ( + "bad signature on input %d" % idx + ) + + +def _verify_dleq_proofs(sim_exec, sim_execfile, psbt): + for scan_key, proof in (psbt.sp_global_dleq_proofs or {}).items(): + _, summed_pubkey = _sim_get_ecdh_and_pubkey(sim_exec, sim_execfile, psbt, scan_key) + _sim_verify_dleq(sim_exec, sim_execfile, summed_pubkey, scan_key, psbt.sp_global_ecdh_shares[scan_key], proof) + for idx, inp in enumerate(psbt.inputs): + for scan_key, proof in (inp.sp_dleq_proofs or {}).items(): + pubkey = _sim_pubkey_from_input(sim_exec, sim_execfile, psbt, idx) + _sim_verify_dleq(sim_exec, sim_execfile, pubkey, scan_key, inp.sp_ecdh_shares[scan_key], proof) + + +@pytest.mark.parametrize("entry", _params()) +def test_workflow_sign_step(set_seed_words, start_sign, end_sign, press_cancel, sim_exec, sim_execfile, entry): + set_seed_words(_acting_mnemonic(entry)) + start_sign(b64decode(entry["psbt"])) + time.sleep(SIMULATOR_DELAY) + # expect_txn=False: end_sign's own check rejects signatures over 71 bytes, but a cosigner's + # signature already in the PSBT was not ground for low R + signed = BasicPSBT().parse(end_sign(accept=True, finalize=False, expect_txn=False)) + press_cancel() + expected = BasicPSBT().parse(entry["expected"]["psbt"].encode()) + + got, want = _sp_fields(signed), _sp_fields(expected) + for field in want: + assert got[field] == want[field], "%s differs from expected.psbt" % field + + assert _unique_id(signed) == entry["expected"]["transaction_id"] + _verify_dleq_proofs(sim_exec, sim_execfile, signed) + _verify_p2wpkh_sigs(signed) From 733fe43bfd9d49f3b41ac0ab79063d403c9c02b2 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 7 Oct 2026 22:10:55 -0400 Subject: [PATCH 29/41] fix (SP): treat a completely signed SP PSBT as a no-op A redundant signing round in a multi-party BIP-375 flow hands the signer a PSBT whose inputs are all signed. Coldcard refused it with "Transaction looks completely signed already?" before any Silent Payments checks ran. For PSBTs with SP outputs, skip that refusal: the normal flow still verifies ECDH shares, DLEQ proofs and output scripts, signs nothing, and returns the PSBT byte-for-byte. Non-SP PSBTs keep the existing refusal. --- shared/psbt.py | 4 ++- testing/test_silentpayments.py | 46 +++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/shared/psbt.py b/shared/psbt.py index 98ae9b591..8db1f7559 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -2507,7 +2507,9 @@ def consider_inputs(self, cosign_xfp=None): "%d input(s) provided unverified witness UTXO." % unverified_witness_utxo)) - if presigned_inputs == self.num_inputs: + if presigned_inputs == self.num_inputs and not self.has_silent_payment_outputs(): + # Silent Payments: a completely signed PSBT is a no-op (a redundant signing + # round in a multi-party flow); SP fields are still verified before export. # Maybe wrong f cases? Maybe they want to add their # own signature, even tho N of M is satisfied?! raise FatalPSBTIssue('Transaction looks completely signed already?') diff --git a/testing/test_silentpayments.py b/testing/test_silentpayments.py index 552c8dd78..1d0a1582c 100644 --- a/testing/test_silentpayments.py +++ b/testing/test_silentpayments.py @@ -620,10 +620,9 @@ def test_sp_single_signer_resign_idempotent(dev, fake_txn, start_sign, end_sign) DLEQ proof either. Note: a real single-key, single-input PSBT is fully signed after the first - pass, and firmware refuses to re-sign a completely-signed transaction - (unrelated pre-existing guard in psbt.py, "Transaction looks completely - signed already?"). To exercise the second signing pass at all, we clear the - signature before feeding the PSBT back. This leaves the already-computed + pass, and firmware treats a completely-signed SP transaction as a no-op + (see test_sp_fully_signed_returned_unchanged). To exercise the second + signing pass at all, we clear the signature before feeding the PSBT back. This leaves the already-computed SP fields in place (as a second signer merging back a partially-signed PSBT would see them) while making the input signable again. """ @@ -651,6 +650,45 @@ def sp_hacker(psbt): assert rp.sp_global_dleq_proofs[SCAN_KEY] == orig_proof +def _sign_single_signer_sp(fake_txn, start_sign, end_sign, xp): + def sp_hacker(psbt): + _add_sp_outputs(psbt, [(0, SCAN_KEY, SPEND_KEY_B)]) + + psbt_bytes = fake_txn(1, 1, xp, addr_fmt="p2wpkh", psbt_v2=True, psbt_hacker=sp_hacker) + start_sign(psbt_bytes) + time.sleep(SIMULATOR_DELAY) + return end_sign(accept=True, finalize=False) + + +def test_sp_fully_signed_returned_unchanged(dev, fake_txn, start_sign, end_sign): + """A completely signed SP PSBT is a no-op: SP fields are re-verified, nothing is + signed, and the PSBT comes back unchanged (as a redundant signing round expects).""" + signed = _sign_single_signer_sp(fake_txn, start_sign, end_sign, dev.master_xpub) + + start_sign(signed) + time.sleep(SIMULATOR_DELAY) + resigned = end_sign(accept=True, finalize=False) + + assert resigned == signed + + +def test_sp_fully_signed_tampered_script_rejected(dev, fake_txn, start_sign, end_sign): + """The no-op path still verifies the SP output script against the shares.""" + signed = _sign_single_signer_sp(fake_txn, start_sign, end_sign, dev.master_xpub) + + tp = BasicPSBT().parse(signed) + sp_out = [o for o in tp.outputs if o.sp_v0_info][0] + script = bytearray(sp_out.script) + script[-1] ^= 0x01 + sp_out.script = bytes(script) + + start_sign(tp.as_bytes()) + time.sleep(SIMULATOR_DELAY) + with pytest.raises(CCProtoError) as ee: + end_sign(accept=True, finalize=False) + assert 'output script mismatch' in ee.value.args[0] + + # --------------------------------------------------------------------------- # BIP-376 Silent Payments spend sp output test # --------------------------------------------------------------------------- From f4af227abbb92f74760fdda0b99d049f3f35b4b2 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 2 Sep 2026 21:33:58 -0400 Subject: [PATCH 30/41] WIP: Use new secp256k1 --- shared/dleq.py | 12 ++++-------- shared/silentpayments.py | 14 ++++++-------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/shared/dleq.py b/shared/dleq.py index b3f8c6f8c..cdf6efebc 100644 --- a/shared/dleq.py +++ b/shared/dleq.py @@ -135,19 +135,15 @@ def verify_dleq_proof(A_sum_bytes, B_scan_bytes, ecdh_share_bytes, proof, m=None sG = ngu.secp256k1.ec_pubkey_tweak_mul(G, s_bytes) eA = ngu.secp256k1.ec_pubkey_tweak_mul(A_sum_bytes, e_bytes) - # Negate eA by flipping the y-coordinate (change 02<->03 prefix) - eA_neg = bytearray(eA) - eA_neg[0] = 0x03 if eA[0] == 0x02 else 0x02 - R1_bytes = ngu.secp256k1.ec_pubkey_combine([sG, bytes(eA_neg)]) + eA_neg = ngu.secp256k1.ec_pubkey_negate(eA) + R1_bytes = ngu.secp256k1.ec_pubkey_combine([sG, eA_neg]) # Reconstruct R2 = s*B - e*C sB = ngu.secp256k1.ec_pubkey_tweak_mul(B_scan_bytes, s_bytes) eC = ngu.secp256k1.ec_pubkey_tweak_mul(ecdh_share_bytes, e_bytes) - # Negate eC - eC_neg = bytearray(eC) - eC_neg[0] = 0x03 if eC[0] == 0x02 else 0x02 - R2_bytes = ngu.secp256k1.ec_pubkey_combine([sB, bytes(eC_neg)]) + eC_neg = ngu.secp256k1.ec_pubkey_negate(eC) + R2_bytes = ngu.secp256k1.ec_pubkey_combine([sB, eC_neg]) # Recompute challenge e' e_check = dleq_challenge(A_sum_bytes, B_scan_bytes, ecdh_share_bytes, R1_bytes, R2_bytes, m, _G=G) diff --git a/shared/silentpayments.py b/shared/silentpayments.py index 75d340185..4099ec8b6 100644 --- a/shared/silentpayments.py +++ b/shared/silentpayments.py @@ -195,15 +195,13 @@ def compute_silent_payment_spending_privkey(b_spend_bytes, sp_tweak_bytes): ValueError: If sp_tweak or spending_privkey is invalid """ sp_tweak_int = int.from_bytes(sp_tweak_bytes, "big") - b_spend_int = int.from_bytes(b_spend_bytes, "big") - if not (0 < b_spend_int < SECP256K1_ORDER): - raise ValueError("Invalid spend private key: not in valid scalar range") if not (0 < sp_tweak_int < SECP256K1_ORDER): raise ValueError("Invalid tweak: not in valid scalar range") - spending_sk = (b_spend_int + sp_tweak_int) % SECP256K1_ORDER - if spending_sk == 0: - raise ValueError("Invalid computed spend key: result is zero") - return _negate_if_odd_y(spending_sk.to_bytes(32, "big")) + try: + spending_sk = ngu.secp256k1.ec_seckey_tweak_add(b_spend_bytes, sp_tweak_bytes) + except ValueError: + raise ValueError("Invalid computed spend key") + return _negate_if_odd_y(spending_sk) def _compute_silent_payment_spending_xonly(B_spend_bytes, sp_tweak_bytes): @@ -233,7 +231,7 @@ def _negate_if_odd_y(privkey): """ pubkey = ngu.secp256k1.ec_pubkey_tweak_mul(G, privkey) if pubkey[0] == 0x03: - privkey = (SECP256K1_ORDER - int.from_bytes(privkey, "big")).to_bytes(32, "big") + privkey = ngu.secp256k1.ec_seckey_negate(privkey) return privkey From 6dfe0c87d3059c2a835c02cd6f5a40b8d9bc7008 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Thu, 16 Jul 2026 20:02:03 -0400 Subject: [PATCH 31/41] bump ckcc submodule sp partial fields --- external/ckcc-protocol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/ckcc-protocol b/external/ckcc-protocol index dec724e2a..9a1ac4ce9 160000 --- a/external/ckcc-protocol +++ b/external/ckcc-protocol @@ -1 +1 @@ -Subproject commit dec724e2a645cecbfad0d8c7d68a03fdda0722ff +Subproject commit 9a1ac4ce9c8a7d87e5e65e62978f6fbbe899daa6 From ab14ddd98180e4f7330be142f74da78e6c2a65c0 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:32:54 -0400 Subject: [PATCH 32/41] feat (MuSig2 + SP): partial field parse & serialize plumbing Adds provisional SP_PARTIAL_* fields. --- shared/psbt.py | 32 ++++++++++++++++--- testing/data/desc-musig-sp-demo.txt | 1 + testing/data/musig2-sp-cosigner-contrib.psbt | Bin 0 -> 3884 bytes testing/devtest/unit_silentpayments.py | 25 ++++++++++++--- testing/psbt.py | 26 +++++++++++++++ 5 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 testing/data/desc-musig-sp-demo.txt create mode 100644 testing/data/musig2-sp-cosigner-contrib.psbt diff --git a/shared/psbt.py b/shared/psbt.py index 8db1f7559..6590b79a1 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -46,6 +46,7 @@ PSBT_IN_SP_DLEQ, PSBT_IN_SP_ECDH_SHARE, PSBT_GLOBAL_SP_DLEQ, PSBT_GLOBAL_SP_ECDH_SHARE, PSBT_IN_SP_TWEAK, PSBT_IN_SP_SPEND_BIP32_DERIVATION, + PSBT_IN_SP_PARTIAL_ECDH_SHARE, PSBT_IN_SP_PARTIAL_DLEQ, AF_P2WSH, AF_P2WSH_P2SH, AF_P2SH, AF_P2TR, AF_P2WPKH, AF_CLASSIC, AF_P2WPKH_P2SH, AFC_SEGWIT, AF_BARE_PK ) @@ -713,7 +714,8 @@ class psbtInputProxy(psbtProxy): # just need to store a simple number for these # Silent Payments (shares/dleq): bytes (not proxied) so scan-pub can be used as dict key # and dict can be mutated in place - short_values = { PSBT_IN_SIGHASH_TYPE, PSBT_IN_SP_ECDH_SHARE, PSBT_IN_SP_DLEQ } + short_values = { PSBT_IN_SIGHASH_TYPE, PSBT_IN_SP_ECDH_SHARE, PSBT_IN_SP_DLEQ, + PSBT_IN_SP_PARTIAL_ECDH_SHARE, PSBT_IN_SP_PARTIAL_DLEQ } # only part-sigs have a key to be stored. no_keys = {PSBT_IN_NON_WITNESS_UTXO, PSBT_IN_WITNESS_UTXO, PSBT_IN_SIGHASH_TYPE, @@ -731,8 +733,10 @@ class psbtInputProxy(psbtProxy): 'taproot_merkle_root', 'taproot_script_sigs', 'taproot_scripts', 'taproot_subpaths', 'taproot_internal_key', 'taproot_key_sig', 'tr_added_sigs', 'ik_idx', 'musig_pubkeys', 'musig_pubnonces', 'musig_part_sigs', 'musig_agg_idx', - 'musig_added_pubnonces', 'musig_added_sigs', 'wif_key', 'wif_redeem_script', - 'sp_ecdh_shares', 'sp_dleq_proofs', 'sp_tweak', 'sp_spend_bip32_derivation', + 'musig_added_pubnonces', 'musig_added_sigs', + 'wif_key', 'wif_redeem_script', 'sp_ecdh_shares', 'sp_dleq_proofs', + 'sp_partial_ecdh_shares', 'sp_partial_dleq_proofs', + 'sp_tweak', 'sp_spend_bip32_derivation', ) def __init__(self, fd, idx): @@ -781,10 +785,14 @@ def __init__(self, fd, idx): #self.musig_part_sigs = None # === silent payments === - #self.sp_ecdh_shares = None # dict[scan-pub] = ecdh_share - #self.sp_dleq_proofs = None # dict[scan-pub] = dleq_proof + #self.sp_ecdh_shares = None # dict[scan-key] = ecdh_share + #self.sp_dleq_proofs = None # dict[scan-key] = dleq_proof #self.sp_tweak = None #self.sp_spend_bip32_derivation = None # (spend-pub, xfp || path) + # key = scan_key_33 || participant_pk_33 + #self.sp_partial_ecdh_shares = None # dict[scan-key||part-pk] = ecdh_share + # key = scan_key_33 || participant_pk_33 + #self.sp_partial_dleq_proofs = None # dict[scan-key||part-pk] = dleq_proof self.parse(fd) @@ -1328,6 +1336,12 @@ def store(self, kt, key, val): self.sp_tweak = self.get(val) elif kt == PSBT_IN_SP_SPEND_BIP32_DERIVATION: self.sp_spend_bip32_derivation = (key, val) + elif kt == PSBT_IN_SP_PARTIAL_ECDH_SHARE: + self.sp_partial_ecdh_shares = self.sp_partial_ecdh_shares or {} + self.sp_partial_ecdh_shares[(key[:33], key[33:66])] = val + elif kt == PSBT_IN_SP_PARTIAL_DLEQ: + self.sp_partial_dleq_proofs = self.sp_partial_dleq_proofs or {} + self.sp_partial_dleq_proofs[(key[:33], key[33:66])] = val else: # including: PSBT_IN_FINAL_SCRIPTSIG, PSBT_IN_FINAL_SCRIPTWITNESS self.unknown = self.unknown or [] @@ -1440,6 +1454,14 @@ def serialize(self, out_fd, is_v2): k, v = self.sp_spend_bip32_derivation wr(PSBT_IN_SP_SPEND_BIP32_DERIVATION, v, k) + if self.sp_partial_ecdh_shares: + for (scan_key, participant_pk), share in self.sp_partial_ecdh_shares.items(): + wr(PSBT_IN_SP_PARTIAL_ECDH_SHARE, share, scan_key + participant_pk) + + if self.sp_partial_dleq_proofs: + for (scan_key, participant_pk), proof in self.sp_partial_dleq_proofs.items(): + wr(PSBT_IN_SP_PARTIAL_DLEQ, proof, scan_key + participant_pk) + if self.unknown: for k, v in self.unknown: wr(None, v, k) diff --git a/testing/data/desc-musig-sp-demo.txt b/testing/data/desc-musig-sp-demo.txt new file mode 100644 index 000000000..6ab47f538 --- /dev/null +++ b/testing/data/desc-musig-sp-demo.txt @@ -0,0 +1 @@ +tr(musig([0f056943/48h/1h/0h/3h]tpubDF2rnouQaaYrY6CUWTapYkeFEs3h3qrzL4M52ZGoPeU9dkarJMtrw6VF1zJRGuGuAFxYS3kXtavfAwQPTQkU5dyNYpbgxcpftrR8H3U85Ez,[6ba6cfd0/48h/1h/0h/3h]tpubDFcrvj5n7gyazzxdg9k6uvzQsoQWow1xbksr7EvKPRBgUbwCdqu2qxyTJjYFNJ7MQLfdXSJV4n8xPZGtrvwQtEbktinC4EP3k8JN2hcBtz4,[747b698e/48h/1h/0h/3h]tpubDExj5FnaUnPAnoAge8edwn7qr8VdquTossNwPPPZVdGH3AZ3et8vVNnJXagqq18d4QWYoja9GeHfpVGZQjQAHozrSHK1HZtnF4XCE1RwE24)/0/*) \ No newline at end of file diff --git a/testing/data/musig2-sp-cosigner-contrib.psbt b/testing/data/musig2-sp-cosigner-contrib.psbt new file mode 100644 index 0000000000000000000000000000000000000000..717fe933d8f999e2a2240cb9526f19e53bbbb268 GIT binary patch literal 3884 zcmd56`M})?xAjB8?>-vK$koL~+LLx%ZEI@44?hPygKKeSXjT{`38Qmf!FFKEF?3uv^Fucnbyr zfk0r$w-*cy2E)Nz><0=0??tknR8Ib{1r~&{i$P$pQs4k`_X~tRgIu)GF>xH_O5-wK z^Lt0NewW?Kk3;o^&RCg?w$d$Nzn~C2)Xc6DL%Xk}oXJa#2@+3>?rQpe7GOQDRfrAm zIoowj03^8h%5k?Hl)X?0)jVkG(N~xc$EgAO(H2)J&B#6&(vp8h@j@P4$-%--4CGf# zXQ+WdH^A)0F1f+3yMaRJEpo~AhA)fKydODf@g3u#svP9vE&U*w7-1l`euFCvar7Q-Pjbyfy%o?3r)#6N#+BnA?M`{4e)4lIrY5{BLn zjf@DaoU2G_Qp#0Vw$#~5nlw$&Hz>y5{&Z=bOjnxabB6$-LxJpo0_ny{0rr3Z?Vw~A-D7RIM-We4TTH5r0jP$A#A{)DuZnp~!Eo7-L){7+5 zYqybM=-(N6RSL7)Y#KmJIiSHbm9NbBN|5q0@T=3<=h`{eb}U~0dBrI06fev5koE?| z&FSjd?1y7pzO8fOBGKvRhbu28K%U5lmZ!f*2RmFdz@Z@illt_PGVR@Vr z6d*THkaKO#x-l2#MGE!^6u}f;rM)}4S?q+WNbck-(CHAiX0lN(=R_Sp?a!5|Zd>JZ zupOrL7K0n@lNxwYQ<(cvdfxQ~uoh@uRXw**by)7$>YTXVYREEN8va>7FdT36_PxZY z8a09w6ksif#W07vz6w=jsc!4%tn4%9MpLe5E+{Bv?I%%w>8?bwQEH9s>V4XIBXnMU ztx;ILT=$dSgF(u|2cMiJb+XGB8EX!-$g7?z@ws4>29_6$;2+K^x_sp`S|oM8?{iCy~93x|T97@1O&Q?h&w zrcP>^A9!6@gTE54vk>9ga|Io*-md2ctOas}YE*?-c#$uhATeLBb&1@wRab+Wi1qXw z$d(Jl!8JHR0oF2|p6Dfgp_SU7+?eeA8iq+ZRqI1gA^L0HJVe^C>^EkktO^@FJN$rW zB*UcTjIeYO*7WK@T`5F2LdfRYf$bUtIcxh*@Ni6V_WpA2q}I)#R5;-pvKT_i8V@yzdy$Nrh#d;DiLA z6DwL4DfD(8^ey~M?4dV)8t%i|L!pS&^4ry;&YFG0Drx~X zCri+5HF$h#@uSF*LmTnW!Gn9v|jNB}x9iuC14>MU+&4n&u_2Hk7(x-rKr)OWhlzNE|5oh4?Tj;n;63{OP0u_G*m2cLIThU zSGA$cG(3xqjmv zyMMce7JYwZPtnI385LcwsXa@)giey zLK{62&QoD(O}h<|E&pl=c;X<-;>XMj@u=(L{qZ^aT&^Zmrwz? Date: Wed, 20 May 2026 19:18:58 -0400 Subject: [PATCH 33/41] feat (MuSig2 + SP): calculate stable nonce_msg using sp_v0_info Generate nonce message for SP outputs - required since scriptPubKey is not defined on musig round 1. taproot sighash computation remains unaffected for musig round 2. --- shared/psbt.py | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/shared/psbt.py b/shared/psbt.py index 6590b79a1..7c61cf51e 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -2147,7 +2147,13 @@ def consider_outputs(self, len_pths, hard_p, prefix_pths, idx_max, cosign_xfp=No if self.session: if idx == 0: self.session.update(ser_compact_size(self.num_outputs)) - self.session.update(txo.serialize()) + sp_out = self.outputs[idx] + if sp_out.sp_v0_info: + # Use the stable value||sp_v0_info bytes so the session cache is identical + # in both rounds. See "MuSig2 Silent Payments: stable nonce_msg" for more details. + self.session.update(pack(' Date: Fri, 26 Jun 2026 13:09:41 -0400 Subject: [PATCH 34/41] feat (MuSig2 + SP): build musig reusable helpers --- shared/psbt.py | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/shared/psbt.py b/shared/psbt.py index 7c61cf51e..b9e4cbf9d 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -2834,6 +2834,27 @@ def musig_derive_keyagg_cache(to_derive, agg_key, keyagg_cache): return agg + @staticmethod + def musig_build_cache(agg_k, participant_pks): + # Aggregate the participant keys and verify the result matches the enrolled + # aggregate key. Raises FatalPSBTIssue on mismatch + keyagg_cache = ngu.secp256k1.MusigKeyAggCache() + ngu.secp256k1.musig_pubkey_agg( + [ngu.secp256k1.pubkey(pk) for pk in participant_pks], keyagg_cache) + if keyagg_cache.agg_pubkey().to_bytes() != agg_k: + raise FatalPSBTIssue("musig keyagg mismatch") + return keyagg_cache + + def musig_taproot_tweak(self, inp, keyagg_cache, der_xonly): + # BIP-341 keyspend tweak applied to the keyagg cache. Caller decides whether a + # tweak applies (keyspend only, not tapscript leaf). Returns (output_key_33, tweak_32). + tweak_data = der_xonly + if inp.taproot_merkle_root: + tweak_data += self.get(inp.taproot_merkle_root) + tap_tweak = ngu.hash.sha256t(TAP_TWEAK_H, tweak_data, True) + output_key = ngu.secp256k1.musig_pubkey_xonly_tweak_add(keyagg_cache, tap_tweak) + return output_key.to_bytes(), tap_tweak + def musig_process_input(self, session, inp_idx, inp, keypair, agg_k, der_agg_k, digest, leaf_hash=b""): @@ -2849,15 +2870,7 @@ def musig_process_input(self, session, inp_idx, inp, keypair, agg_k, der_agg_k, musig_partial_sigs = inp.get_musig_part_sigs() musig_pubnonces = inp.get_musig_pubnonces() - keyagg_cache = ngu.secp256k1.MusigKeyAggCache() - - # below will sort, but should be already sorted in PSBT - ngu.secp256k1.musig_pubkey_agg( - [ngu.secp256k1.pubkey(pk) for pk in cosigners], - keyagg_cache - ) - # verify aggregate key is correct - assert keyagg_cache.agg_pubkey().to_bytes() == agg_k + keyagg_cache = self.musig_build_cache(agg_k, cosigners) # get derivation we need to use for musig sp = inp.get_tr_der_coords_by_key(der_agg_k) @@ -2867,17 +2880,14 @@ def musig_process_input(self, session, inp_idx, inp, keypair, agg_k, der_agg_k, # is derived aggregate key xonly ? dak_xo = int(len(der_agg_k) == 32) # key is derived inside the key_agg cache - assert self.musig_derive_keyagg_cache(to_derive, agg_k, keyagg_cache)[dak_xo:] == der_agg_k + derived_k = self.musig_derive_keyagg_cache(to_derive, agg_k, keyagg_cache) + assert derived_k[dak_xo:] == der_agg_k if not leaf_hash: # now finally get the output key - only for musig in taproot internal key - tweak_data = der_agg_k - if inp.taproot_merkle_root: - tweak_data += self.get(inp.taproot_merkle_root) - tweak32 = ngu.hash.sha256t(TAP_TWEAK_H, tweak_data, True) - output_key = ngu.secp256k1.musig_pubkey_xonly_tweak_add(keyagg_cache, tweak32) + output_key, _ = self.musig_taproot_tweak(inp, keyagg_cache, derived_k[1:]) # tweaked derived aggregate key - der_agg_k = output_key.to_bytes() + der_agg_k = output_key my_musig_pubnonces_key = (my_participant_key, der_agg_k, leaf_hash) From 1877b4d57cde6012f104c3fa953336057775c348 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Fri, 26 Jun 2026 13:02:42 -0400 Subject: [PATCH 35/41] feat (MuSig2 + SP): compute sum(IL) with musig_derive_keyagg_cache --- shared/psbt.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/psbt.py b/shared/psbt.py index b9e4cbf9d..f6aab9953 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -2824,15 +2824,20 @@ def ecdsa_grind_sign(sk, digest, sighash): @staticmethod def musig_derive_keyagg_cache(to_derive, agg_key, keyagg_cache): + # Returns (agg_pubkey_33, sum_IL_32) where sum_IL is used to reconstruct the + # BIP-327 tweak accumulator for MuSig2+SP partial ECDH share combining. ck = MUSIG_CHAIN_CODE agg = agg_key + sum_IL = 0 + SECP256K1_ORDER = ngu.secp256k1.curve_order_int() for idx in to_derive: I = ngu.hmac.hmac_sha512(ck, agg + pack(">I", idx)) IL, ck = I[:32], I[32:] ngu.secp256k1.musig_pubkey_ec_tweak_add(keyagg_cache, IL) agg = keyagg_cache.agg_pubkey().to_bytes() + sum_IL = (sum_IL + int.from_bytes(IL, 'big')) % SECP256K1_ORDER - return agg + return agg, sum_IL.to_bytes(32, 'big') @staticmethod def musig_build_cache(agg_k, participant_pks): @@ -2880,7 +2885,7 @@ def musig_process_input(self, session, inp_idx, inp, keypair, agg_k, der_agg_k, # is derived aggregate key xonly ? dak_xo = int(len(der_agg_k) == 32) # key is derived inside the key_agg cache - derived_k = self.musig_derive_keyagg_cache(to_derive, agg_k, keyagg_cache) + derived_k, _ = self.musig_derive_keyagg_cache(to_derive, agg_k, keyagg_cache) assert derived_k[dak_xo:] == der_agg_k if not leaf_hash: From 3c83e3b5a8f4c683ed69cddf42199e3e515b0ea6 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Tue, 30 Jun 2026 17:08:03 -0400 Subject: [PATCH 36/41] fix (psbt): handle unpacking taproot_subpaths with cached coordinates Gracefully handle the 3-element value parse_taproot_subpaths caches when the same input is parsed more than once (MuSig2 + SP). --- shared/psbt.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shared/psbt.py b/shared/psbt.py index f6aab9953..22495ac00 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -382,7 +382,11 @@ def parse_taproot_subpaths(self, my_xfp, parent, cosign_xfp=None): key, val = self.taproot_subpaths[i] assert key[1] == 32 # "PSBT_IN_TAP_BIP32_DERIVATION xonly-pubkey length != 32" xonly_pk = self.get(key) - pos, length = val + # 3rd element is cached coordinates written by earlier parse, drop and it will be re-computed below + if len(val) == 2: + pos, length = val + else: + pos, length, _ = val end_pos = pos + length self.fd.seek(pos) leaf_hash_len = deser_compact_size(self.fd) From 121b11fba17506ff88223f7bff3f561929bf14a4 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 20 May 2026 19:19:07 -0400 Subject: [PATCH 37/41] feat (MuSig2 + SP): partial ECDH share contribution and signing UX auth: - Signing UX: prompt the user to contribute shares, run round 1 nonce generation. psbt: - Add musig_keyagg_context: assemble the keyagg cache and derive the BIP-327 combine factors (MusigEcdhFactors). - Allow musig sp inputs round 1 sign_it despite incomplete SP coverage. serializations: - determine_my_change - get_address returns (None, None) when scriptPubKey is None, no longer errors on musig sp inputs before output scripts are computed. silentpayments: - Contribute partial shares and DLEQ proof bound to the account-level participant key (_contribute_musig_ecdh_shares). - Aggregate shares via KeyAgg coefficients and the input's combine factors (_musig_aggregate_shares, _musig_keyagg_coefficient, _musig_sp_ecdh_factors, _musig_input_ecdh_share). Add bip327 tagged hashes Add musig2 silent payments round 1 test and fixtures. --- shared/auth.py | 24 +- shared/precomp_tag_hash.py | 6 + shared/psbt.py | 50 +++- shared/serializations.py | 5 + shared/silentpayments.py | 333 ++++++++++++++++++++++++-- testing/data/musig2-sp-round1-in.psbt | Bin 0 -> 1264 bytes testing/test_musig2_silentpayments.py | 136 +++++++++++ 7 files changed, 518 insertions(+), 36 deletions(-) create mode 100644 testing/data/musig2-sp-round1-in.psbt create mode 100644 testing/test_musig2_silentpayments.py diff --git a/shared/auth.py b/shared/auth.py index 63feb6045..686edbcb5 100644 --- a/shared/auth.py +++ b/shared/auth.py @@ -430,7 +430,6 @@ async def interact(self): if not self.psbt.process_silent_payment_outputs(sv): # Coverage incomplete: shares computed but waiting on other signers # Skip normal approval flow — prompt user to contribute shares, then save - del args ch = await ux_show_story( "Silent payment ECDH shares will be added to this transaction.\n\n" "Other signers must contribute their shares before signing can proceed.\n\n" @@ -440,16 +439,23 @@ async def interact(self): if ch != 'y': self.refused = True await ux_dramatic_pause("Refused.", 1) - del self.psbt + del args, self.psbt self.done() return - try: - await done_signing(self.psbt, self, self.input_method, - self.filename, self.output_encoder, - finalize=False) - self.done() - except BaseException as exc: - return await self.failure("PSBT output failed", exc) + + # Handle nonce generation for MuSig2 + SP inputs + if self.psbt.has_musig_sp_inputs(): + self.psbt.consider_outputs(*args, cosign_xfp=ccc_c_xfp) + del args + if self.psbt.session: + self.psbt.session.update(pack('b\xd4\x13\xba\x8c\xcdQ\x98\x91\x90\x17\xa1\xe9\x9c\xbei\x1fZ4\xa9\x93w\xe0\x95' +# BIP-327 MuSig2 KeyAgg tag hashes +# SHA256(KeyAgg list) +KEYAGG_LIST_TAG_H = b'H\x1c\x97\x1c<\x0bF\xd7\xf0\xb2u\xaeY\x8dN,~\xd71\x9cYJ\\n\xc7\x9e\xa0\xd4\x99\x02\x94\xf0' +# SHA256(KeyAgg coefficient) +KEYAGG_COEFF_TAG_H = b'\xbf\xc9\x04\x03M\x1c\x88\xe8\xc8\x0e"\xe5=$Vmd\x82N\xd6Br\x81\xc0\x91\x00\xf9M\xcdR\xc9\x81' + # BIP-374 DLEQ proof tag hashes # SHA256(BIP0374/aux) DLEQ_TAG_AUX_H = b'\xfc\xe2u partial-ECDH-share path""" + return inp.is_musig and self._is_input_eligible(inp) + + def _is_regular_sp_input(self, inp): + """SP-eligible non-MuSig2 input -> per-input ECDH-share path""" + return self._is_input_eligible(inp) and not inp.is_musig + + def _contribute_musig_ecdh_shares(self, sv, input): + """ + Contribute partial ECDH share + DLEQ proof for our participant key in a MuSig2 SP input, + store contributions in PSBT input fields + + Returns: + bool: True if we contributed at least one share + False if we are not a participant + """ + # Select participants from the spending aggregate + participants = self._musig_spending_participants(input) + if not participants: + return False + key = self.active_miniscript.to_descriptor().key + + # Locate our participant in the enrolled descriptor and derive it via its + # origin path as specified in the descriptor + my_participant_sk = None + my_participant_pk = None + for k in key.keys: + if k.origin.cc_fp != self.my_xfp: + continue + node = sv.derive_path(k.origin.str_derivation(), register=False) + my_participant_sk = node.privkey() + my_participant_pk = k.node.pubkey() + del node + break + + if my_participant_sk is None: + return False + + # Confirm our account-level key is a participant in this input's musig aggregate + my_xonly = my_participant_pk[1:] + is_participant = any((p[1:] if len(p) == 33 else p) == my_xonly for p in participants) + if not is_participant: + stash.blank_object(my_participant_sk) + return False + + contributed = False + scan_keys = self._get_silent_payment_scan_keys() + for scan_key in scan_keys: + if input.sp_partial_ecdh_shares and (scan_key, my_participant_pk) in input.sp_partial_ecdh_shares: + contributed = True + continue + + my_share = _compute_ecdh_share(my_participant_sk, scan_key) + my_proof = generate_dleq_proof(my_participant_sk, scan_key) + + input.sp_partial_ecdh_shares = input.sp_partial_ecdh_shares or {} + input.sp_partial_dleq_proofs = input.sp_partial_dleq_proofs or {} + input.sp_partial_ecdh_shares[(scan_key, my_participant_pk)] = my_share + input.sp_partial_dleq_proofs[(scan_key, my_participant_pk)] = my_proof + contributed = True + + stash.blank_object(my_participant_sk) + return contributed + + def _musig_input_ecdh_share(self, input, scan_key): + """ + Combine this input's MuSig2 partial ECDH shares for scan_key into the aggregate + share a_Q * B_scan + + Note: + This is the MuSig2 equivalent of inp.sp_ecdh_shares[scan_key] for a non-musig input. + + Returns: + bytes: aggregate share, or None if no shares are present for scan_key or no + enrolled MuSig2 descriptor is available + """ + if not input.sp_partial_ecdh_shares: + return None + + participant_pks, factors = self._musig_sp_ecdh_factors(input) + if participant_pks is None or factors is None: + return None + + # Only combine shares from the spending aggregate's participants + participant_set = set(participant_pks) + partial_shares = [ + (participant_pk, share) + for (entry_scan_key, participant_pk), share in input.sp_partial_ecdh_shares.items() + if entry_scan_key == scan_key and participant_pk in participant_set + ] + if not partial_shares: + return None + + return _musig_aggregate_shares(participant_pks, partial_shares, factors, scan_key) + + def _musig_sp_ecdh_factors(self, input): + """ + Derive BIP-327 factors to combine partial ECDH shares into a_Q * B_scan for a + tr(musig(...)) keyspend SP input + + Rebuilds the KeyAgg cache from the participant set, applies the descriptor's + BIP-328 synthetic derivation and the BIP-341 taproot tweak, then reads the parity + accumulators (gacc before taproot, g_v after) and the accumulated tweak (tacc). + + Returns: + tuple: (participant_pks, MusigEcdhFactors) + (None, None) if there is no enrolled MuSig2 descriptor for this input + """ + participant_pks = self._musig_spending_participants(input) + if not participant_pks: + return None, None + agg_k = self.active_miniscript.to_descriptor().key.node.pubkey() + + # BIP-328 synthetic derivation indices (e.g. /0/*) from the enrolled descriptor + parsed = input.parse_subpaths(self.my_xfp, self) + xfp_paths = [v[1:] for v in parsed.values()] + branch, idx = self.active_miniscript.subderivation_indexes(xfp_paths) + to_derive = [branch, idx] + + # aggregate + verify, BIP-328 synthetic derivation, BIP-341 keyspend taproot tweak + _, _, output_key, factors = self.musig_keyagg_context( + input, agg_k, participant_pks, to_derive, compute_factors=True + ) + + # derived output key must match the input's actual scriptPubKey + if output_key[1:] != input.utxo_spk[2:34]: + raise FatalPSBTIssue("MuSig2+Silent Payments output key mismatch") + + return participant_pks, factors + + def _musig_spending_participants(self, input): + """ + Participant pubkeys of the aggregate that actually spends this input, per the + enrolled descriptor; None if unavailable. + """ + if self.active_miniscript is None: + return None + key = self.active_miniscript.to_descriptor().key + if not isinstance(key, MusigKey): + return None + return input.get_musig_pubkeys().get(key.node.pubkey()) diff --git a/testing/data/musig2-sp-round1-in.psbt b/testing/data/musig2-sp-round1-in.psbt new file mode 100644 index 0000000000000000000000000000000000000000..b6449adb3a3565e4cd5169b84a78dbc315819c2c GIT binary patch literal 1264 zcmXRYPAd7&_?v}^fq{XM2|}?jGBUCA810$cp`+aNg;lqslEI`c+jEvd^=M+FJ z2BkoSSH4yr5!cwJu(^NA{;(+E!<+-$&Wfi?ANu=<960aGGFefKW6_Lb%UwhMw$8nm zv#U$u(9&sUSwDH-Z{DiWQgt%wST!#L|EoI@Amf;USW!%WKJ!GKJBD8@7v(uN`Iar% zt8kh{!H@f)X54&M?J(aEQHJbg=PwvAFf=d%F;GhbP+xDGb zb;5b=$6U!wgluOf6dcTi{LR3~%%QL!6z{;e<8)%SzIxw4MceNY9OYm3}`NQm{X7ct4_OloGq^=4E8R)`D32Yd2n=6arAkddsr zc@gXN{?-T2sxnqN{Pqg^VOYJlKnY}E!ecSGfm_`|c4Qvrth2iFcZn|>N z`6YAiYvT#=f8+z0ZaCo%*Bps5g7_?` + + +import json +import os +import pytest +import time +from psbt import BasicPSBT + +DATA_DIR = os.path.join(os.path.dirname(__file__), 'data') +ROUND1_PSBT = os.path.join(DATA_DIR, 'musig2-sp-round1-in.psbt') +# The tr(musig(A,B,C)) treasury descriptor matching the fixtures. Alice (xfp 0f056943) is the +# simulator's default seed; the device enrolls this wallet before signing. +TREASURY_DESC = os.path.join(DATA_DIR, 'desc-musig-sp-demo.txt') + +NUM_RECIPIENTS = 5 + +SIMULATOR_DELAY = .1 # seconds to wait for the simulator to process the PSBT and update the story + + +def _load_psbt(path): + with open(path, 'rb') as f: + return f.read() + +def _get_scan_keys(tp): + return {bytes(out.sp_v0_info[:33]) for out in tp.outputs if out.sp_v0_info} + +def _enroll_treasury(clear_miniscript, offer_minsc_import, press_select): + """Register the tr(musig(A,B,C)) treasury so signing runs the enrolled path.""" + clear_miniscript() + with open(TREASURY_DESC) as f: + desc = f.read().strip() + _, story = offer_minsc_import(json.dumps(dict(name='sp_treasury', desc=desc))) + assert 'Create new miniscript wallet?' in story + press_select() + +def _our_participant_key(tp): + """ + Return the participant pubkey (33 bytes) that the simulator contributed shares for. + We identify it by finding any entry in sp_partial_ecdh_shares on input[0]. + Raises if none found (round 1 contribution not present). + """ + inp = tp.inputs[0] + if not inp.sp_partial_ecdh_shares: + raise AssertionError("No MuSig2 partial ECDH shares found on input[0] after round 1") + # Composite key is (scan_key, participant_pk); the simulator only contributes its own + # participant key, so all entries share the same participant_pk in the second slot. + _, participant_key = next(iter(inp.sp_partial_ecdh_shares)) + return participant_key + +# --------------------------------------------------------------------------- +# Round 1 test +# --------------------------------------------------------------------------- + +def test_musig2_sp_round1(dev, start_sign, end_sign, cap_story, + clear_miniscript, offer_minsc_import, press_select): + """ + Round 1: load the pre-contribution PSBT, approve the 'CONTRIBUTE SHARES?' story, + and confirm the simulator contributes ECDH shares (0x21), DLEQ proofs (0x22), and a + MuSig2 pubnonce (0x1b) for every SP scan key — without adding a signature. + """ + if not os.path.exists(ROUND1_PSBT): + pytest.skip(f"Fixture not found: {ROUND1_PSBT}") + + _enroll_treasury(clear_miniscript, offer_minsc_import, press_select) + + start_sign(_load_psbt(ROUND1_PSBT)) + + time.sleep(SIMULATOR_DELAY) + title, story = cap_story() + if title != 'CONTRIBUTE SHARES?': + print("\nSTORY BODY:\n", story) + assert title == 'CONTRIBUTE SHARES?', f"Unexpected story title: {title!r}" + assert 'Silent payment ECDH shares will be added to this transaction' in story, "SP addresses should appear in round 1 story" + + signed = end_sign(accept=True, finalize=False, accept_ms_import=True) + tp = BasicPSBT().parse(signed) + + scan_keys = _get_scan_keys(tp) + assert len(scan_keys) == NUM_RECIPIENTS, \ + f"Expected {NUM_RECIPIENTS} SP recipients, got {len(scan_keys)}" + + _assert_round1_output(tp, scan_keys) + +def _assert_round1_output(tp, scan_keys): + """ + After Round 1 the PSBT must have, on input[0]: + - One sp_partial_ecdh_shares entry per scan key, keyed by (scan_key, our_pk) + - One sp_partial_dleq_proofs entry per scan key, keyed by (scan_key, our_pk) + - One musig_pubnonces entry (our 0x1b contribution) + - No taproot_key_sig (coordinator hasn't aggregated yet) + """ + inp = tp.inputs[0] + + assert inp.sp_partial_ecdh_shares, "Round 1: 0x21 ECDH shares missing on input[0]" + assert inp.sp_partial_dleq_proofs, "Round 1: 0x22 DLEQ proofs missing on input[0]" + assert inp.musig_pubnonces, "Round 1: 0x1b pubnonce missing on input[0]" + assert not inp.taproot_key_sig, "Round 1: tap_key_sig must not be present" + + participant_key = _our_participant_key(tp) + + # One entry per scan key in the ECDH share map + contributed_scan_keys_ecdh = {sk for (sk, pk) in inp.sp_partial_ecdh_shares if pk == participant_key} + assert contributed_scan_keys_ecdh == scan_keys, ( + f"Round 1 ECDH share scan keys mismatch: " + f"got {len(contributed_scan_keys_ecdh)}, expected {len(scan_keys)}" + ) + + # One entry per scan key in the DLEQ proof map + contributed_scan_keys_dleq = {sk for (sk, pk) in inp.sp_partial_dleq_proofs if pk == participant_key} + assert contributed_scan_keys_dleq == scan_keys, ( + f"Round 1 DLEQ proof scan keys mismatch: " + f"got {len(contributed_scan_keys_dleq)}, expected {len(scan_keys)}" + ) + + # ECDH share format: compressed point + for (sk, pk), share in inp.sp_partial_ecdh_shares.items(): + assert len(share) == 33 and share[0] in (0x02, 0x03), \ + f"Invalid ECDH share format for scan_key={sk.hex()}: {share.hex()}" + + # DLEQ proof format: 64 bytes + for (sk, pk), proof in inp.sp_partial_dleq_proofs.items(): + assert len(proof) == 64, \ + f"DLEQ proof must be 64 bytes for scan_key={sk.hex()}, got {len(proof)}" + + # Exactly one pubnonce from our participant key + our_pubnonces = [(pk, ak, lh) for (pk, ak, lh) in inp.musig_pubnonces if pk == participant_key] + assert len(our_pubnonces) == 1, \ + f"Expected 1 pubnonce from our participant key, got {len(our_pubnonces)}" + pubnonce = inp.musig_pubnonces[our_pubnonces[0]] + assert len(pubnonce) == 66, f"Pubnonce must be 66 bytes, got {len(pubnonce)}" From 811d4204c6624236038065fde72782cd78d51340 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Wed, 20 May 2026 19:20:13 -0400 Subject: [PATCH 38/41] test (MuSig2 + SP): two round integration tests and fixtures Add cosigner contrib test fixture for simulating round 2 partial signature - 1 simulator/signer in test_musig2_sp_full_flow, the other 2 participants in 3 of 3 provide contributions from coordinator. --- testing/data/musig2-sp-cosigner-contrib.psbt | Bin 3884 -> 3884 bytes testing/data/musig2-sp-round1-in.psbt | Bin 1264 -> 1264 bytes testing/test_musig2_silentpayments.py | 212 ++++++++++++++++++- 3 files changed, 209 insertions(+), 3 deletions(-) diff --git a/testing/data/musig2-sp-cosigner-contrib.psbt b/testing/data/musig2-sp-cosigner-contrib.psbt index 717fe933d8f999e2a2240cb9526f19e53bbbb268..17b74e0c2599db472da804890aa394b6d19254b4 100644 GIT binary patch delta 28 kcmZ1@w?=M*70={*e14P7c|s=l@&#_z0`UT-z|Bs~35=8fF$PXv#Nr14<~I!Y delta 32 ocmeys`GIr8KgP*{EP<2%F$PXvz!W&ypDA$jN2UbE$%|P00O;8b2LJ#7 diff --git a/testing/test_musig2_silentpayments.py b/testing/test_musig2_silentpayments.py index c48402a58..ddf4e324a 100644 --- a/testing/test_musig2_silentpayments.py +++ b/testing/test_musig2_silentpayments.py @@ -1,15 +1,19 @@ # (c) Copyright 2026 by Coinkite Inc. This file is covered by license found in COPYING-CC. # -# test_musig2_silentpayments.py - Coldcard simulator tests for MuSig2 + Silent Payments (BIP-327 + BIP-352). +# test_musig2_silentpayments.py - Coldcard simulator tests for MuSig2 + Silent Payments (BIP-327 + BIP-352) # # Fixture PSBTs are generated by the Rust binary in bip375-examples: # cargo run -p musig2-signer --bin payroll +# +# Use CC_SP_OUT env var to capture debug artifacts (PSBTs, final transaction) from the test run. +# ex. export CC_SP_OUT=/tmp/cc-sp-out && pytest test_musig2_silentpayments.py import json import os import pytest import time + from psbt import BasicPSBT DATA_DIR = os.path.join(os.path.dirname(__file__), 'data') @@ -17,6 +21,9 @@ # The tr(musig(A,B,C)) treasury descriptor matching the fixtures. Alice (xfp 0f056943) is the # simulator's default seed; the device enrolls this wallet before signing. TREASURY_DESC = os.path.join(DATA_DIR, 'desc-musig-sp-demo.txt') +# Bob's + Charlie's static Round-1 contributions (pubnonce 0x1b, ECDH shares 0x21, DLEQ 0x22 +# on input[0]). Generated once by the Rust tool from the same keys as ROUND1_PSBT. +COSIGNER_CONTRIB_PSBT = os.path.join(DATA_DIR, 'musig2-sp-cosigner-contrib.psbt') NUM_RECIPIENTS = 5 @@ -76,9 +83,10 @@ def test_musig2_sp_round1(dev, start_sign, end_sign, cap_story, if title != 'CONTRIBUTE SHARES?': print("\nSTORY BODY:\n", story) assert title == 'CONTRIBUTE SHARES?', f"Unexpected story title: {title!r}" - assert 'Silent payment ECDH shares will be added to this transaction' in story, "SP addresses should appear in round 1 story" + assert 'ECDH shares' in story + assert 'Other signers' in story - signed = end_sign(accept=True, finalize=False, accept_ms_import=True) + signed = end_sign(accept=True, finalize=False, accept_ms_import=False) tp = BasicPSBT().parse(signed) scan_keys = _get_scan_keys(tp) @@ -134,3 +142,201 @@ def _assert_round1_output(tp, scan_keys): f"Expected 1 pubnonce from our participant key, got {len(our_pubnonces)}" pubnonce = inp.musig_pubnonces[our_pubnonces[0]] assert len(pubnonce) == 66, f"Pubnonce must be 66 bytes, got {len(pubnonce)}" + +# --------------------------------------------------------------------------- +# Round 1 and partial Round 2 test +# --------------------------------------------------------------------------- + +def test_musig2_sp_full_flow(dev, start_sign, end_sign, cap_story, sim_exec, + clear_miniscript, offer_minsc_import, press_select): + """ + Full two-round flow with the simulator as Alice: + + Round 1 (live) -> device emits Alice's pubnonce (0x1b), ECDH share (0x21), DLEQ (0x22) + Merge -> add Bob's + Charlie's static Round-1 contributions + Round 2 (live) -> device verifies the cosigners' DLEQ proofs, sums all three ECDH shares, + derives the SP output scripts, aggregates all three nonces, and emits + Alice's partial sig (0x1c) + + Only Alice signs, so the device produces one partial sig and does NOT finalize (it cannot + aggregate until all three partials are present). + """ + merged, alice_pk, scan_keys = _alice_round1_and_merge( + start_sign, end_sign, cap_story, sim_exec, + clear_miniscript, offer_minsc_import, press_select) + + # ---- After the merge, all three participants' Round-1 material must be present ---- + inp = merged.inputs[0] + assert len(inp.musig_pubnonces) == 3, \ + f"Expected 3 pubnonces after merge, got {len(inp.musig_pubnonces)}" + assert len(inp.sp_partial_ecdh_shares) == 3 * NUM_RECIPIENTS, ( + f"Expected {3 * NUM_RECIPIENTS} ECDH share entries " + f"(3 participants × {NUM_RECIPIENTS} scan keys), got {len(inp.sp_partial_ecdh_shares)}" + ) + assert len(inp.sp_partial_dleq_proofs) == 3 * NUM_RECIPIENTS, ( + f"Expected {3 * NUM_RECIPIENTS} DLEQ proof entries, got {len(inp.sp_partial_dleq_proofs)}" + ) + for sk in scan_keys: + ecdh_pks = {pk for (s, pk) in inp.sp_partial_ecdh_shares if s == sk} + dleq_pks = {pk for (s, pk) in inp.sp_partial_dleq_proofs if s == sk} + assert len(ecdh_pks) == 3, \ + f"scan_key {sk.hex()}: expected 3 ECDH participants, got {len(ecdh_pks)}" + assert ecdh_pks == dleq_pks, \ + f"scan_key {sk.hex()}: ECDH and DLEQ participant sets differ" + + # ---- Round 2: device signs the merged PSBT ---- + start_sign(merged.as_bytes()) + time.sleep(SIMULATOR_DELAY) + title, story = cap_story() + assert title == 'OK TO SEND?', f"R2 unexpected story title: {title!r}" + assert 'sp1' in story, "SP addresses should appear in round 2 confirmation story" + + signed = end_sign(accept=True, finalize=False, accept_ms_import=False) + tp = BasicPSBT().parse(signed) + + scan_keys = _get_scan_keys(tp) + assert len(scan_keys) == NUM_RECIPIENTS, \ + f"Expected {NUM_RECIPIENTS} SP recipients, got {len(scan_keys)}" + + _assert_round2_output(tp, scan_keys, alice_pk) + + # Hand off Alice's R2-signed PSBT to the Rust coordinator for finalization. + _maybe_write_artifact(signed, "r2-alice.psbt") + +def test_musig2_sp_round2_tampered_recipient(dev, start_sign, end_sign, cap_story, sim_exec, + clear_miniscript, offer_minsc_import, press_select, press_cancel): + """ + Negative test: a coordinator writes a PSBT_OUT_SCRIPT for an SP output that differs from the + one derivable from the contributed ECDH shares (swapped recipient). The device must re-derive + the script, detect the mismatch, refuse to sign, and emit no partial sig. + + We build the same merged Round-2 PSBT as the happy path, then overwrite one SP output's + script with a well-formed but wrong P2TR before submitting for signing. A wrong (not empty) + script is required: an empty script is silently filled by the device, so only a present-and- + wrong script reaches the mismatch branch in silentpayments.py. + """ + merged, _alice_pk, _scan_keys = _alice_round1_and_merge( + start_sign, end_sign, cap_story, sim_exec, + clear_miniscript, offer_minsc_import, press_select) + + # Tamper: overwrite one SP output's script with a well-formed but wrong P2TR (OP_1 <32 bytes>). + tampered = False + for out in merged.outputs: + if out.sp_v0_info: + out.script = b'\x51\x20' + (b'\xab' * 32) + tampered = True + break + assert tampered, "No SP output found to tamper" + + # Round 2: device must detect the script mismatch and refuse to produce a partial sig. + start_sign(merged.as_bytes()) + time.sleep(SIMULATOR_DELAY) + title, story = cap_story() + + if title == 'OK TO SEND?': + # Approval shown: the mismatch should fire during signing, so end_sign must raise. + with pytest.raises(Exception): + end_sign(accept=True, finalize=False, accept_ms_import=False) + else: + # Mismatch detected during PSBT validation; an error story is shown. + assert 'recipient' in story.lower() or 'mismatch' in story.lower() or \ + 'invalid' in story.lower() or 'fail' in story.lower(), \ + f"Expected tamper-detection error, got title={title!r} story={story!r}" + + press_cancel() + +def _alice_round1_and_merge(start_sign, end_sign, cap_story, sim_exec, + clear_miniscript, offer_minsc_import, press_select): + """ + Run Alice's live Round 1 against ROUND1_PSBT, then merge Bob's + Charlie's static Round-1 + contributions. Returns (merged_psbt, alice_pk, scan_keys). + """ + if not (os.path.exists(ROUND1_PSBT) and os.path.exists(COSIGNER_CONTRIB_PSBT)): + pytest.skip(f"Test PSBT fixtures not found at {DATA_DIR}") + + # Clears MUSIG_SESSION_CACHE first: the session-scoped simulator + module-global cache would + # otherwise let a prior test would interfere with Alice's R1->R2 nonce regeneration. + sim_exec("from psbt import MUSIG_SESSION_CACHE; MUSIG_SESSION_CACHE.clear()") + + _enroll_treasury(clear_miniscript, offer_minsc_import, press_select) + + # ---- Round 1: Alice (the simulator) contributes nonce + ECDH share + DLEQ ---- + start_sign(_load_psbt(ROUND1_PSBT)) + time.sleep(SIMULATOR_DELAY) + title, _ = cap_story() + assert title == 'CONTRIBUTE SHARES?', f"R1 unexpected story title: {title!r}" + r1_out = BasicPSBT().parse(end_sign(accept=True, finalize=False, accept_ms_import=False)) + + alice_pk = _our_participant_key(r1_out) + + # ---- Merge Bob's + Charlie's static Round-1 contributions ---- + contrib = BasicPSBT().parse(_load_psbt(COSIGNER_CONTRIB_PSBT)) + _merge_cosigner_contrib(r1_out, contrib) + + scan_keys = _get_scan_keys(r1_out) + assert len(scan_keys) == NUM_RECIPIENTS, \ + f"Expected {NUM_RECIPIENTS} SP recipients, got {len(scan_keys)}" + + return r1_out, alice_pk, scan_keys + +def _assert_round2_output(tp, scan_keys, participant_key): + """ + After Round 2 the PSBT must have, on input[0]: + - Exactly one musig_part_sigs entry, from our participant key (0x1c). Only Alice signs here; + the device cannot finalize until all three partials are present (done later in Rust). + - No tap_key_sig yet. + + And every SP output must have a derived P2TR script. + """ + inp = tp.inputs[0] + + assert inp.musig_part_sigs, "Round 2: 0x1c partial sig missing on input[0]" + + our_part_sigs = [(pk, ak, lh) for (pk, ak, lh) in inp.musig_part_sigs if pk == participant_key] + assert len(our_part_sigs) == 1, \ + f"Round 2: expected exactly 1 partial sig from our participant, got {len(our_part_sigs)}" + assert len(inp.musig_part_sigs) == 1, \ + f"Round 2: only Alice should have signed, got {len(inp.musig_part_sigs)} partial sigs" + + part_sig = inp.musig_part_sigs[our_part_sigs[0]] + assert len(part_sig) == 32, \ + f"MuSig2 partial sig must be 32 bytes, got {len(part_sig)}" + + # Every SP output must have a finalized P2TR script + sp_scripts = [] + for out in tp.outputs: + if out.sp_v0_info: + assert out.script is not None, "SP output script not set after round 2" + assert len(out.script) == 34, \ + f"SP P2TR script must be 34 bytes (OP_1 <32-byte xonly>), got {len(out.script)}" + assert out.script[0] == 0x51, \ + f"SP output must start with OP_1 (0x51), got 0x{out.script[0]:02x}" + sp_scripts.append(bytes(out.script)) + + assert len(sp_scripts) == NUM_RECIPIENTS, \ + f"Expected {NUM_RECIPIENTS} SP output scripts, got {len(sp_scripts)}" + + return sp_scripts + +def _maybe_write_artifact(data, filename): + """If CC_SP_OUT is set, write a demo artifact into that directory.""" + out_dir = os.environ.get('CC_SP_OUT') + if not out_dir: + return + os.makedirs(out_dir, exist_ok=True) + path = os.path.join(out_dir, filename) + with open(path, 'wb') as f: + f.write(data) + print(f"Wrote {filename} to {path}") + +def _merge_cosigner_contrib(target_tp, contrib_tp): + """ + Merge Bob's + Charlie's static Round-1 contributions into input[0] of a PSBT that already + holds Alice's live Round-1 output. Copies the pubnonce (0x1b), partial ECDH share (0x21), and + DLEQ proof (0x22) maps. + """ + src = contrib_tp.inputs[0] + dst = target_tp.inputs[0] + dst.musig_pubnonces.update(src.musig_pubnonces) + dst.sp_partial_ecdh_shares.update(src.sp_partial_ecdh_shares) + dst.sp_partial_dleq_proofs.update(src.sp_partial_dleq_proofs) From e87dd6f39cd1eec2b2e57d7735084a5ba4bcb2c2 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:13:36 -0400 Subject: [PATCH 39/41] test (MuSig2 + SP): full two round - three simulators/signers test_musig2_sp_three_hardware_signers coordinates three separate simulator processes to compute silent payments outputs and sign a psbt paying multiple recipients through two rounds. --- testing/test_musig2_sp_signers.py | 469 ++++++++++++++++++++++++++++++ 1 file changed, 469 insertions(+) create mode 100644 testing/test_musig2_sp_signers.py diff --git a/testing/test_musig2_sp_signers.py b/testing/test_musig2_sp_signers.py new file mode 100644 index 000000000..762221d71 --- /dev/null +++ b/testing/test_musig2_sp_signers.py @@ -0,0 +1,469 @@ +# (c) Copyright 2026 by Coinkite Inc. This file is covered by license found in COPYING-CC. +# +# test_musig2_sp_signers.py - Coldcard simulator tests for MuSig2 + Silent Payments. +# +# Test keeps three simulator processes alive so Alice, Bob, Charlie each perform both +# rounds and the last signer finalizes the transaction. +# +# Expected musig2-sp-final-tx.hex is generated by the Rust binary in bip375-examples: +# cargo run -p musig2-signer --bin finalize +# +# Use CC_SP_OUT env var to capture debug artifacts (PSBTs, final transaction) from the test run. +# ex. export CC_SP_OUT=/tmp/cc-sp-out && pytest test_musig2_sp_signers.py + + +import io +import json +import os +import pytest +import shutil +import sys +import time +from binascii import b2a_hex +from ckcc_protocol.client import ColdcardDevice +from ckcc_protocol.protocol import CCProtocolPacker +from core_fixtures import _cap_story, _dev_hw_label, _need_keypress, _press_cancel, _press_select +from ctransaction import CTransaction, CTxOut +from helpers import xfp2str +from psbt import BasicPSBT +from run_sim_tests import ColdcardSimulator +from test_musig2_silentpayments import ( + NUM_RECIPIENTS, + ROUND1_PSBT, + TREASURY_DESC, + _load_psbt, + _get_scan_keys, + _maybe_write_artifact, +) + +DATA_DIR = os.path.join(os.path.dirname(__file__), "data") + +SIGNER_XFPS = { + "Alice": "0F056943", + "Bob": "6BA6CFD0", + "Charlie": "747B698E", +} +SIM_START_TIMEOUT = 15 +SIM_START_POLL_INTERVAL = 0.5 + + +def _exec_sim_file(device, path): + full_path = os.path.abspath(path) + hook = "execfile(%r)" % full_path + rv = device.send_recv(b"EXEC" + hook.encode("utf-8"), timeout=60000, encrypt=False) + rv = rv.decode("utf-8") + assert "Traceback" not in rv, rv + return rv + + +def _clear_sim_cache(device): + cmd = "from psbt import MUSIG_SESSION_CACHE; MUSIG_SESSION_CACHE.clear()" + rv = device.send_recv(b"EXEC" + cmd.encode("utf-8"), timeout=60000, encrypt=False) + assert b"Traceback" not in rv, rv + + +def _activate_bip39_passphrase(device, is_q1, passphrase): + """Activate a simulator BIP39 passphrase and refresh the encrypted USB session.""" + device.send_recv(CCProtocolPacker.bip39_passphrase(passphrase), timeout=None) + time.sleep(0.1) + + _, story = _cap_story(device) + assert "to master seed" in story + _press_select(device, is_q1) + + time.sleep(0.3) + _, story = _cap_story(device) + if "Press (1) to store temporary seed into Seed Vault" in story: + _press_select(device, is_q1) + time.sleep(0.2) + _, story = _cap_story(device) + + assert "Above is the master key fingerprint" in story + _press_select(device, is_q1) + + done = None + while done is None: + time.sleep(0.05) + done = device.send_recv(CCProtocolPacker.get_passphrase_done(), timeout=None) + assert done[1:4] == "pub" + + device.start_encryption() + device.check_mitm() + + +class HardwareSigner: + """Device-bound operations needed by the two-round signing test.""" + + def __init__(self, name, device, is_q1): + self.name = name + self.device = device + self.is_q1 = is_q1 + + def assert_fingerprint(self): + got = xfp2str(self.device.master_fingerprint) + assert got == SIGNER_XFPS[self.name], f"{self.name}: expected XFP {SIGNER_XFPS[self.name]}, got {got}" + + def clear_session_cache(self): + _clear_sim_cache(self.device) + + def enroll_treasury(self): + _exec_sim_file(self.device, "devtest/wipe_miniscript.py") + with open(TREASURY_DESC) as f: + desc = f.read().strip() + config = json.dumps(dict(name="sp_treasury", desc=desc)).encode("ascii") + file_len, sha = self.device.upload_file(config) + self.device.send_recv(CCProtocolPacker.miniscript_enroll(file_len, sha)) + + time.sleep(0.2) + _, story = _cap_story(self.device) + assert "Create new miniscript wallet?" in story + _press_select(self.device, self.is_q1) + time.sleep(0.1) + + def sign(self, psbt_bytes, expected_title, finalize=False): + file_len, sha = self.device.upload_file(psbt_bytes) + self.device.send_recv(CCProtocolPacker.sign_transaction(file_len, sha, finalize)) + + title, story = _cap_story(self.device) + assert title == expected_title, f"{self.name}: expected story {expected_title!r}, got {title!r}: {story}" + + _need_keypress(self.device, "y", timeout=None) + done = None + while done is None: + done = self.device.send_recv(CCProtocolPacker.get_signed_txn(), timeout=None) + result_len, checksum = done + result = self.device.download_file(result_len, checksum) + _press_cancel(self.device, self.is_q1) + + if finalize: + assert not result.startswith(b"psbt\xff") + else: + assert result.startswith(b"psbt\xff") + return result, story + + +def _start_child_simulator(simulator): + """ColdcardSimulator uses bare `python`; make it resolve to pytest's interpreter.""" + old_path = os.environ.get("PATH", "") + os.environ["PATH"] = os.path.dirname(sys.executable) + os.pathsep + old_path + try: + simulator.start(start_wait=SIM_START_POLL_INTERVAL) + finally: + os.environ["PATH"] = old_path + + try: + deadline = time.monotonic() + SIM_START_TIMEOUT + last_error = None + while time.monotonic() < deadline: + exit_code = simulator.proc.poll() + if exit_code is not None: + raise RuntimeError(f"Simulator exited before socket was ready: {simulator.socket} (exit={exit_code})") + + device = None + try: + device = ColdcardDevice(sn=simulator.socket, is_simulator=True) + return + except Exception as exc: + last_error = exc + time.sleep(SIM_START_POLL_INTERVAL) + finally: + if device is not None: + device.close() + + exit_code = simulator.proc.poll() + status = "still running" if exit_code is None else f"exited with {exit_code}" + raise RuntimeError(f"Simulator socket was not ready after {SIM_START_TIMEOUT}s: {simulator.socket} ({status})") from last_error + except Exception: + socket_path = simulator.socket + work_path = f"/tmp/cc-simulators/{simulator.proc.pid}" + simulator.stop() + if os.path.exists(socket_path): + os.unlink(socket_path) + shutil.rmtree(work_path, ignore_errors=True) + raise + + +@pytest.fixture +def three_musig_signers(request, is_headless): + """ + Alice, Bob and Charlie each run in their own segregated simulator process so the test + starts every simulator it needs (no pre-running simulator required) and each signer + retains an independent MUSIG_SESSION_CACHE between Round 1 and Round 2. + + The hardware build matches the simulator run_sim_tests pre-starts (read via --sim-socket); + a bare pytest run with no simulator defaults to Q1. Alice uses the fixed simulator seed + (no passphrase); Bob and Charlie layer BIP39 passphrases to get distinct fingerprints. + """ + sim_socket = request.config.getoption("--sim-socket") + if sim_socket: + probe = ColdcardDevice(sn=sim_socket, is_simulator=True) + try: + hw_label = _dev_hw_label(probe) + finally: + probe.close() + else: + hw_label = "q1" if request.config.getoption("--Q") else "mk%d" % int(request.config.getoption("--mk")) + + if hw_label == "q1": + args = ["--q1"] + elif hw_label == "mk4": + args = ["--mk4"] + elif hw_label == "mk5": + args = [] + else: + pytest.skip(f"Three-simulator MuSig2 test does not support {hw_label}") + is_q1 = hw_label == "q1" + + signers = [] + simulators = [] + + try: + for name, passphrase in [("Alice", None), ("Bob", "Me"), ("Charlie", "Myself")]: + simulator = ColdcardSimulator( + args=list(args), + headless=is_headless, + segregate=True, + ) + _start_child_simulator(simulator) + simulators.append(simulator) + device = ColdcardDevice(sn=simulator.socket, is_simulator=True) + signer = HardwareSigner(name, device, is_q1) + signers.append(signer) + if passphrase is not None: + _activate_bip39_passphrase(device, is_q1, passphrase) + + for signer in signers: + assert _dev_hw_label(signer.device) == hw_label + signer.assert_fingerprint() + signer.clear_session_cache() + signer.enroll_treasury() + + yield signers + finally: + for signer in reversed(signers): + signer.device.close() + for simulator in reversed(simulators): + socket_path = simulator.socket + work_path = f"/tmp/cc-simulators/{simulator.proc.pid}" + simulator.stop() + if os.path.exists(socket_path): + os.unlink(socket_path) + shutil.rmtree(work_path, ignore_errors=True) + + +def _assert_round1_contribution(before, after, signer_name, scan_keys): + """Assert and return the participant key added by one hardware signer.""" + before_inp = before.inputs[0] + after_inp = after.inputs[0] + + new_pubnonces = set(after_inp.musig_pubnonces) - set(before_inp.musig_pubnonces) + new_ecdh = set(after_inp.sp_partial_ecdh_shares) - set(before_inp.sp_partial_ecdh_shares) + new_dleq = set(after_inp.sp_partial_dleq_proofs) - set(before_inp.sp_partial_dleq_proofs) + + assert len(new_pubnonces) == 1, f"{signer_name}: expected one new pubnonce, got {len(new_pubnonces)}" + participant_keys = {pk for _, pk in new_ecdh} + assert len(participant_keys) == 1, f"{signer_name}: expected one ECDH participant key, got {len(participant_keys)}" + (participant_key,) = participant_keys + + (nonce_key,) = new_pubnonces + assert nonce_key[0] == participant_key + assert {sk for sk, pk in new_ecdh if pk == participant_key} == scan_keys + assert {sk for sk, pk in new_dleq if pk == participant_key} == scan_keys + assert len(new_ecdh) == len(scan_keys) + assert len(new_dleq) == len(scan_keys) + + assert len(after_inp.musig_pubnonces[nonce_key]) == 66 + for key in new_ecdh: + share = after_inp.sp_partial_ecdh_shares[key] + assert len(share) == 33 and share[0] in (0x02, 0x03) + for key in new_dleq: + assert len(after_inp.sp_partial_dleq_proofs[key]) == 64 + + assert not after_inp.musig_part_sigs + assert not after_inp.taproot_key_sig + return participant_key + + +def _sp_scripts(tp): + return [bytes(out.script) for out in tp.outputs if out.sp_v0_info] + + +def _assert_partial_sigs(tp, participant_keys, expected_names): + inp = tp.inputs[0] + assert len(inp.musig_part_sigs) == len(expected_names) + expected_keys = {participant_keys[name] for name in expected_names} + actual_keys = {pk for pk, _ak, _lh in inp.musig_part_sigs} + assert actual_keys == expected_keys + assert all(len(sig) == 32 for sig in inp.musig_part_sigs.values()) + assert not inp.taproot_key_sig + + +def _assert_complete_psbt(tp, participant_keys): + """The final signer's PSBT: all three partial sigs plus the aggregated taproot key sig.""" + inp = tp.inputs[0] + assert len(inp.musig_part_sigs) == len(participant_keys) + actual_keys = {pk for pk, _ak, _lh in inp.musig_part_sigs} + assert actual_keys == set(participant_keys.values()) + assert all(len(sig) == 32 for sig in inp.musig_part_sigs.values()) + + assert inp.taproot_key_sig, "final signer must aggregate the taproot key sig" + # 64-byte Schnorr sig, or 65 bytes when a sighash flag is appended + assert len(inp.taproot_key_sig) in (64, 65) + + +def _parse_transaction(raw): + tx = CTransaction() + tx.deserialize(io.BytesIO(raw)) + return tx + + +def _parse_txout(raw): + txout = CTxOut() + txout.deserialize(io.BytesIO(raw)) + return txout + + +def _assert_final_transaction(raw_tx, expected_psbt): + actual = _parse_transaction(raw_tx) + + expected_version = 2 if expected_psbt.txn_version is None else expected_psbt.txn_version + expected_locktime = 0 if expected_psbt.fallback_locktime is None else expected_psbt.fallback_locktime + assert actual.nVersion == expected_version + assert actual.nLockTime == expected_locktime + assert len(actual.vin) == 1 + assert len(actual.vout) == len(expected_psbt.outputs) + + expected_input = expected_psbt.inputs[0] + actual_input = actual.vin[0] + assert actual_input.prevout.hash == int.from_bytes(expected_input.previous_txid, "little") + assert actual_input.prevout.n == expected_input.prevout_idx + assert actual_input.scriptSig == b"" + expected_sequence = 0xffffffff if expected_input.sequence is None else expected_input.sequence + assert actual_input.nSequence == expected_sequence + + expected_outputs = [(out.amount, out.script) for out in expected_psbt.outputs] + actual_outputs = [(out.nValue, out.scriptPubKey) for out in actual.vout] + assert actual_outputs == expected_outputs + + witness_utxo = _parse_txout(expected_input.witness_utxo) + assert sum(out.nValue for out in actual.vout) < witness_utxo.nValue + + sp_outputs = [out for out in expected_psbt.outputs if out.sp_v0_info] + change_outputs = [out for out in expected_psbt.outputs if not out.sp_v0_info] + assert len(sp_outputs) == NUM_RECIPIENTS + assert len(change_outputs) == 1 + assert all(out.script and len(out.script) == 34 and out.script[0] == 0x51 for out in sp_outputs) + + assert len(actual.wit.vtxinwit) == 1 + witness = actual.wit.vtxinwit[0].scriptWitness.stack + assert len(witness) == 1 + assert len(witness[0]) == 64 + + +# --------------------------------------------------------------------------- +# Test +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize("finalize_on_device", [True, False], ids=["final-txn", "signed-psbt"]) +def test_musig2_sp_three_hardware_signers(three_musig_signers, finalize_on_device): + """ + End-to-end hardware workflow: + + Round 1: Alice -> Bob -> Charlie each add a pubnonce and SP ECDH/DLEQ shares. + Round 2: Alice -> Bob add partial signatures; Charlie adds the third partial and + aggregates the MuSig2 signature. + + Charlie's last step runs as one of two cases (CC finalizes only as part of the final + signature, and his nonce is one-shot, so each output needs its own fresh run): + - finalize_on_device=True : Charlie signs with finalize=True -> broadcast-ready txn. + - finalize_on_device=False: Charlie signs with finalize=False -> fully-signed PSBT. + """ + if not all(os.path.exists(path) for path in (ROUND1_PSBT, TREASURY_DESC)): + pytest.skip(f"Three-signer fixtures not found at {DATA_DIR}") + + signers = three_musig_signers + current = BasicPSBT().parse(_load_psbt(ROUND1_PSBT)) + scan_keys = _get_scan_keys(current) + assert len(scan_keys) == NUM_RECIPIENTS + + participant_keys = {} + + # Round 1: pass the growing PSBT through three independent hardware devices. + for expected_count, signer in enumerate(signers, start=1): + before = current + expected_title = "OK TO SEND?" if expected_count == len(signers) else "CONTRIBUTE SHARES?" + signed, story = signer.sign( + before.as_bytes(), + expected_title=expected_title, + finalize=False, + ) + if expected_title == "CONTRIBUTE SHARES?": + assert "ECDH shares" in story + assert "Other signers" in story + else: + # Charlie's shares complete ECDH coverage during preview, but his empty device + # session cache still makes this approval cryptographic Round 1. + assert "sp1" in story + + current = BasicPSBT().parse(signed) + _maybe_write_artifact(signed, f"r1-{signer.name.lower()}.psbt") + participant_keys[signer.name] = _assert_round1_contribution(before, current, signer.name, scan_keys) + assert len(current.inputs[0].musig_pubnonces) == expected_count + assert len(current.inputs[0].sp_partial_ecdh_shares) == expected_count * NUM_RECIPIENTS + assert len(current.inputs[0].sp_partial_dleq_proofs) == expected_count * NUM_RECIPIENTS + + assert len(set(participant_keys.values())) == 3 + assert len(current.inputs[0].musig_pubnonces) == 3 + assert len(current.inputs[0].sp_partial_ecdh_shares) == 3 * NUM_RECIPIENTS + assert len(current.inputs[0].sp_partial_dleq_proofs) == 3 * NUM_RECIPIENTS + + # Round 2: Alice derives the SP scripts and signs; Bob verifies and signs the same PSBT. + round2_psbt = current + expected_scripts = None + for expected_count, signer in enumerate(signers[:2], start=1): + signed, story = signer.sign( + round2_psbt.as_bytes(), + expected_title="OK TO SEND?", + finalize=False, + ) + assert "sp1" in story + + round2_psbt = BasicPSBT().parse(signed) + _maybe_write_artifact(signed, f"r2-{signer.name.lower()}.psbt") + _assert_partial_sigs( + round2_psbt, + participant_keys, + [s.name for s in signers[:expected_count]], + ) + + scripts = _sp_scripts(round2_psbt) + assert len(scripts) == NUM_RECIPIENTS + assert all(len(script) == 34 and script[0] == 0x51 for script in scripts) + if expected_scripts is None: + expected_scripts = scripts + else: + assert scripts == expected_scripts + + # Charlie consumes the last secret nonce, adds the final partial, and aggregates the + # MuSig2 signature. + charlie = signers[2] + result, story = charlie.sign( + round2_psbt.as_bytes(), + expected_title="OK TO SEND?", + finalize=finalize_on_device, + ) + assert "sp1" in story + + if finalize_on_device: + # Charlie finalizes in the same pass: broadcast-ready transaction. + _maybe_write_artifact(b2a_hex(result) + b"\n", "musig2-sp-final.hex") + _assert_final_transaction(result, round2_psbt) + else: + # Charlie exports the fully-signed PSBT (all three partials + aggregated key sig). + complete_psbt = BasicPSBT().parse(result) + _maybe_write_artifact(result, "musig2-sp-final.psbt") + _assert_complete_psbt(complete_psbt, participant_keys) + scripts = _sp_scripts(complete_psbt) + assert len(scripts) == NUM_RECIPIENTS + assert scripts == expected_scripts From 7d7414a80fb83cd10c96e2f636efc3fc82462967 Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Tue, 26 May 2026 15:14:18 -0400 Subject: [PATCH 40/41] docs (MuSig2 + SP): Add MuSig2 to SP documentation From 421341042e88f96a68aa15d47eab70e1ccbc5bff Mon Sep 17 00:00:00 2001 From: macgyver13 <4712150+macgyver13@users.noreply.github.com> Date: Thu, 13 Aug 2026 14:51:29 -0400 Subject: [PATCH 41/41] fix: (MuSig2 + SP): treat empty output as valid --- shared/psbt.py | 4 +++- testing/data/desc-musig-sp-demo.txt | 2 +- testing/data/musig2-sp-cosigner-contrib.psbt | Bin 3884 -> 3884 bytes testing/data/musig2-sp-round1-in.psbt | Bin 1264 -> 1264 bytes 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/shared/psbt.py b/shared/psbt.py index 44168998d..45e54ad84 100644 --- a/shared/psbt.py +++ b/shared/psbt.py @@ -2964,7 +2964,7 @@ def musig_process_input(self, session, inp_idx, inp, keypair, agg_k, der_agg_k, # round 2). Bind to session_digest instead: it commits to all inputs and outputs, # substituting value||sp_v0_info for SP-output scripts, so it is byte-identical in both rounds. if self.has_silent_payment_outputs(): - nonce_msg = ngu.hash.sha256s(session_digest + der_agg_k + leaf_hash) + nonce_msg = ngu.hash.sha256s(self.session.digest() + der_agg_k + leaf_hash) else: nonce_msg = digest @@ -3082,6 +3082,8 @@ def sign_it(self, alternate_secret=None, my_xfp=None): stash.blank_object(session_rand) def _sign_it(self, alternate_secret, my_xfp, musig_session): + musig_round1 = musig_session[1] if musig_session else False + # txn is approved. sign all inputs we can sign. add signatures # - hash the txn first # - sign all inputs we have the key for diff --git a/testing/data/desc-musig-sp-demo.txt b/testing/data/desc-musig-sp-demo.txt index 6ab47f538..96309077b 100644 --- a/testing/data/desc-musig-sp-demo.txt +++ b/testing/data/desc-musig-sp-demo.txt @@ -1 +1 @@ -tr(musig([0f056943/48h/1h/0h/3h]tpubDF2rnouQaaYrY6CUWTapYkeFEs3h3qrzL4M52ZGoPeU9dkarJMtrw6VF1zJRGuGuAFxYS3kXtavfAwQPTQkU5dyNYpbgxcpftrR8H3U85Ez,[6ba6cfd0/48h/1h/0h/3h]tpubDFcrvj5n7gyazzxdg9k6uvzQsoQWow1xbksr7EvKPRBgUbwCdqu2qxyTJjYFNJ7MQLfdXSJV4n8xPZGtrvwQtEbktinC4EP3k8JN2hcBtz4,[747b698e/48h/1h/0h/3h]tpubDExj5FnaUnPAnoAge8edwn7qr8VdquTossNwPPPZVdGH3AZ3et8vVNnJXagqq18d4QWYoja9GeHfpVGZQjQAHozrSHK1HZtnF4XCE1RwE24)/0/*) \ No newline at end of file +tr(musig([0f056943/48h/1h/0h/3h]tpubDF2rnouQaaYrY6CUWTapYkeFEs3h3qrzL4M52ZGoPeU9dkarJMtrw6VF1zJRGuGuAFxYS3kXtavfAwQPTQkU5dyNYpbgxcpftrR8H3U85Ez,[6ba6cfd0/48h/1h/0h/3h]tpubDFcrvj5n7gyazzxdg9k6uvzQsoQWow1xbksr7EvKPRBgUbwCdqu2qxyTJjYFNJ7MQLfdXSJV4n8xPZGtrvwQtEbktinC4EP3k8JN2hcBtz4,[747b698e/48h/1h/0h/3h]tpubDExj5FnaUnPAnoAge8edwn7qr8VdquTossNwPPPZVdGH3AZ3et8vVNnJXagqq18d4QWYoja9GeHfpVGZQjQAHozrSHK1HZtnF4XCE1RwE24)/<0;1>/*) \ No newline at end of file diff --git a/testing/data/musig2-sp-cosigner-contrib.psbt b/testing/data/musig2-sp-cosigner-contrib.psbt index 17b74e0c2599db472da804890aa394b6d19254b4..1b1ef9e945bbcecdc6fbbf061e3b90a9638b7c89 100644 GIT binary patch delta 32 mcmZ1@w?=M*70+f}-UP*$Rkz`TPLHA`6oM delta 32 ncmZ1@w?=M*70={ezQD;gK>V6FaI+Op0^{U+e14Os^9BL{#cT`1 diff --git a/testing/data/musig2-sp-round1-in.psbt b/testing/data/musig2-sp-round1-in.psbt index 80152374e6e8e5fa3be467a89cdb290408e33131..5da0a3f24b3cf8f98d74c9b60f47103cc0814043 100644 GIT binary patch delta 32 ocmeys`GIr8KgP`;nGzT$FJkeVJeMhCvOiPc