def _check_duplicate_keys(cls, keys): """raise a SpecterError when a xpub in the passed KeyList is listed twice. Should prevent MultisigWallets where xpubs are used twice. """ # normalizing xpubs in order to ignore slip132 differences xpubs = [Key.parse_xpub(key.original).xpub for key in keys] for xpub in xpubs: if xpubs.count(xpub) > 1: raise SpecterError(_(f"xpub {xpub} seem to be used at least twice!"))
def parse_signers(self, devices, cosigners_types): keys = [] cosigners = [] unknown_cosigners = [] unknown_cosigners_types = [] if self.multisig_N == None: self.multisig_N = 1 self.multisig_M = 1 self.origin_fingerprint = [self.origin_fingerprint] self.origin_path = [self.origin_path] self.base_key = [self.base_key] for i in range(self.multisig_N): cosigner_found = False for device in devices: cosigner = devices[device] if self.origin_fingerprint[i] is None: self.origin_fingerprint[i] = "" if self.origin_path[i] is None: self.origin_path[i] = self.origin_fingerprint[i] for key in cosigner.keys: if key.fingerprint + key.derivation.replace( "m", "" ) == self.origin_fingerprint[i] + self.origin_path[i].replace( "'", "h" ): keys.append(key) cosigners.append(cosigner) cosigner_found = True break if cosigner_found: break if not cosigner_found: desc_key = Key.parse_xpub( "[{}{}]{}".format( self.origin_fingerprint[i], self.origin_path[i], self.base_key[i], ) ) if len(cosigners_types) > i: unknown_cosigners.append((desc_key, cosigners_types[i]["label"])) else: unknown_cosigners.append((desc_key, None)) if len(unknown_cosigners) > len(cosigners_types): unknown_cosigners_types.append("other") else: unknown_cosigners_types.append(cosigners_types[i]["type"]) return (keys, cosigners, unknown_cosigners, unknown_cosigners_types)
def parse_signers(self, devices, cosigners_types): keys = [] cosigners = [] unknown_cosigners = [] unknown_cosigners_types = [] for i, descriptor_key in enumerate(self.descriptor.keys): # remove derivation from the key for comparison account_key = DescriptorKey.from_string(str(descriptor_key)) account_key.allowed_derivation = None # Specter Key class desc_key = Key.parse_xpub(str(account_key)) cosigner_found = False for cosigner in devices.values(): for key in cosigner.keys: # check key matches if key.to_string(slip132=False) == desc_key.to_string( slip132=False ): keys.append(key) cosigners.append(cosigner) cosigner_found = True break if cosigner_found: break if not cosigner_found: if len(cosigners_types) > i: unknown_cosigners.append((desc_key, cosigners_types[i]["label"])) else: unknown_cosigners.append((desc_key, None)) if len(unknown_cosigners) > len(cosigners_types): unknown_cosigners_types.append("other") else: unknown_cosigners_types.append(cosigners_types[i]["type"]) return (keys, cosigners, unknown_cosigners, unknown_cosigners_types)
def test_fingerprint(ghost_machine_xpub_44): key = Key.parse_xpub(ghost_machine_xpub_44) assert key.fingerprint == "81f802e3"
def test_derivation(ghost_machine_zpub): key = Key.parse_xpub(f"[81f802e3/84'/0'/3]{ghost_machine_zpub}") assert key.derivation == "m/84h/0h/3"
def test_xpub(ghost_machine_ypub, ghost_machine_xpub_49): key = Key.parse_xpub(ghost_machine_ypub) assert key.xpub == ghost_machine_xpub_49
def test_purpose(ghost_machine_ypub): key = Key.parse_xpub(ghost_machine_ypub) assert key.purpose == "Single (Nested)"
def test_key_type(ghost_machine_ypub): key = Key.parse_xpub(ghost_machine_ypub) assert key.key_type == "sh-wpkh"