def _generate_and_finalize(self, unknown_inputs, psbt): if not unknown_inputs: # Just do the normal signing process to test "all inputs" case sign_res = self.do_command(self.dev_args + ['signtx', psbt['psbt']]) finalize_res = self.wrpc.finalizepsbt(sign_res['psbt']) self.assertTrue(sign_res["signed"]) self.assertTrue(finalize_res["complete"]) else: # Sign only input one on first pass # then rest on second pass to test ability to successfully # ignore inputs that are not its own. Then combine both # signing passes to ensure they are actually properly being # partially signed at each step. first_psbt = PSBT() first_psbt.deserialize(psbt['psbt']) second_psbt = PSBT() second_psbt.deserialize(psbt['psbt']) # Blank master fingerprint to make hww fail to sign # Single input PSBTs will be fully signed by first signer for psbt_input in first_psbt.inputs[1:]: for pubkey, path in psbt_input.hd_keypaths.items(): psbt_input.hd_keypaths[pubkey] = KeyOriginInfo(b"\x00\x00\x00\x01", path.path) for pubkey, (leaves, origin) in psbt_input.tap_bip32_paths.items(): psbt_input.tap_bip32_paths[pubkey] = (leaves, KeyOriginInfo(b"\x00\x00\x00\x01", origin.path)) for pubkey, path in second_psbt.inputs[0].hd_keypaths.items(): second_psbt.inputs[0].hd_keypaths[pubkey] = KeyOriginInfo(b"\x00\x00\x00\x01", path.path) for pubkey, (leaves, origin) in second_psbt.inputs[0].tap_bip32_paths.items(): second_psbt.inputs[0].tap_bip32_paths[pubkey] = (leaves, KeyOriginInfo(b"\x00\x00\x00\x01", origin.path)) single_input = len(first_psbt.inputs) == 1 # Process the psbts first_psbt = first_psbt.serialize() second_psbt = second_psbt.serialize() # First will always have something to sign first_sign_res = self.do_command(self.dev_args + ['signtx', first_psbt]) self.assertTrue(first_sign_res["signed"]) self.assertTrue(single_input == self.wrpc.finalizepsbt(first_sign_res['psbt'])['complete']) # Second may have nothing to sign (1 input case) # and also may throw an error(e.g., ColdCard) second_sign_res = self.do_command(self.dev_args + ['signtx', second_psbt]) if 'psbt' in second_sign_res: if single_input: self.assertFalse(second_sign_res["signed"]) else: self.assertTrue(second_sign_res["signed"]) self.assertTrue(not self.wrpc.finalizepsbt(second_sign_res['psbt'])['complete']) combined_psbt = self.wrpc.combinepsbt([first_sign_res['psbt'], second_sign_res['psbt']]) else: self.assertTrue('error' in second_sign_res) combined_psbt = first_sign_res['psbt'] finalize_res = self.wrpc.finalizepsbt(combined_psbt) self.assertTrue(finalize_res['complete']) self.assertTrue(self.wrpc.testmempoolaccept([finalize_res['hex']])[0]["allowed"]) return finalize_res['hex']
def _make_multisig(self, addrtype): if addrtype == "legacy": coin_type = 0 desc_prefix = "sh(" desc_suffix = ")" elif addrtype == "p2sh-segwit": coin_type = 1 if self.emulator.strict_bip48 else 0 desc_prefix = "sh(wsh(" desc_suffix = "))" elif addrtype == "bech32": coin_type = 2 if self.emulator.strict_bip48 else 0 desc_prefix = "wsh(" desc_suffix = ")" else: self.fail(f"Unknown address type {addrtype}") desc_pubkeys = [] xpubs: Dict[bytes, KeyOriginInfo] = {} for account in range(0, 3 if self.emulator.supports_device_multiple_multisig else 1): path = f"/48h/1h/{account}h/{coin_type}h" origin = '{}{}'.format(self.emulator.fingerprint, path) xpub = self.do_command(self.dev_args + ["getxpub", "m{}".format(path)]) desc_pubkeys.append("[{}]{}/0/0".format(origin, xpub["xpub"])) if self.emulator.include_xpubs: extkey = ExtendedKey.deserialize(xpub["xpub"]) xpubs[extkey.serialize()] = KeyOriginInfo.from_string(origin) if not self.emulator.supports_device_multiple_multisig: # If the device does not support itself in the multisig more than once, # we need to fetch a key from Core, and use another key that will not be signed with counter_descs = self.wpk_rpc.listdescriptors()["descriptors"] desc = parse_descriptor(counter_descs[0]["desc"]) pubkey_prov = None while pubkey_prov is None: if len(desc.pubkeys) > 0: pubkey_prov = desc.pubkeys[0] else: desc = desc.subdescriptors[0] assert pubkey_prov.extkey is not None assert pubkey_prov.origin is not None pubkey_prov.deriv_path = "/0/0" desc_pubkeys.append(pubkey_prov.to_string()) if self.emulator.include_xpubs: xpubs[pubkey_prov.extkey.serialize()] = pubkey_prov.origin # A fixed key fixed_extkey = ExtendedKey.deserialize("tpubDCBWBScQPGv4Xk3JSbhw6wYYpayMjb2eAYyArpbSqQTbLDpphHGAetB6VQgVeftLML8vDSUEWcC2xDi3qJJ3YCDChJDvqVzpgoYSuT52MhJ") fixed_origin = KeyOriginInfo(b"\xde\xad\xbe\xef", [0x80000000]) desc_pubkeys.append(PubkeyProvider(fixed_origin, fixed_extkey.to_string(), "/0/0").to_string()) if self.emulator.include_xpubs: xpubs[fixed_extkey.serialize()] = fixed_origin desc = AddChecksum(f"{desc_prefix}sortedmulti(2,{desc_pubkeys[0]},{desc_pubkeys[1]},{desc_pubkeys[2]}){desc_suffix}") return desc, self.rpc.deriveaddresses(desc)[0], xpubs