def recursive_check(aclass: type) -> None: assert issubclass(aclass, CCoinAddress) if extra_addr_testfunc(aclass, pub): pass else: a = None if getattr(aclass, 'from_pubkey', None): a = aclass.from_pubkey(pub) elif getattr(aclass, 'from_redeemScript', None): a = aclass.from_redeemScript( CScript(b'\xa9' + Hash160(pub) + b'\x87')) else: assert len(dispatcher_mapped_list(aclass)) > 0,\ ("dispatcher mapped list for {} " "must not be empty".format(aclass)) if a is not None: spk = a.to_scriptPubKey() test.assertEqual(a, aclass.from_scriptPubKey(spk)) a2 = aclass.from_bytes(a) test.assertEqual(bytes(a), bytes(a2)) test.assertEqual(str(a), str(a2)) a3 = aclass(str(a)) test.assertEqual(bytes(a), bytes(a3)) test.assertEqual(str(a), str(a3)) for next_aclass in dispatcher_mapped_list(aclass): recursive_check(next_aclass)
def test_scriptpubkey_type(self) -> None: for l1_cls in dispatcher_mapped_list(CCoinAddress): for l2_cls in dispatcher_mapped_list(l1_cls): for l3_cls in dispatcher_mapped_list(l2_cls): spk_type = l3_cls.get_scriptPubKey_type() matched_cls = CCoinAddress.match_scriptPubKey_type(spk_type) self.assertTrue(l3_cls is matched_cls)
def from_unconfidential( cls: Type[T_CCoinConfidentialAddress], unconfidential_adr: CCoinAddress, blinding_pubkey: Union[CPubKey, bytes, bytearray] ) -> T_CCoinConfidentialAddress: """Convert unconfidential address to confidential Raises CConfidentialAddressError if blinding_pubkey is invalid (CConfidentialAddressError is a subclass of CCoinAddressError) unconfidential_adr can be string or CBase58CoinAddress instance. blinding_pubkey must be a bytes instance """ ensure_isinstance(blinding_pubkey, (CPubKey, bytes, bytearray), 'blinding_pubkey') if not isinstance(blinding_pubkey, CPubKey): blinding_pubkey = CPubKey(blinding_pubkey) if not blinding_pubkey.is_fullyvalid(): raise ValueError('invalid blinding pubkey') # without #noqa linter gives warning that we should use isinstance. # but here we want exact match, isinstance is not applicable if type(cls) is not type(unconfidential_adr.__class__): #noqa raise TypeError( 'cannot create {} from {}: this address class might belong ' 'to different chain'.format( cls.__name__, unconfidential_adr.__class__.__name__)) clsmap = { P2PKHCoinAddress: P2PKHCoinConfidentialAddress, P2WPKHCoinAddress: P2WPKHCoinConfidentialAddress, P2SHCoinAddress: P2SHCoinConfidentialAddress, P2WSHCoinAddress: P2WSHCoinConfidentialAddress, } for unconf_cls, conf_cls in clsmap.items(): mapped_cls_list = dispatcher_mapped_list(conf_cls) if mapped_cls_list: if len(mapped_cls_list) != 1: raise TypeError( f"{conf_cls.__name__} must be final dispatch class") chain_specific_conf_cls = mapped_cls_list[0] else: chain_specific_conf_cls = conf_cls if isinstance(unconfidential_adr, unconf_cls) and\ (issubclass(cls, (conf_cls, chain_specific_conf_cls)) or issubclass(chain_specific_conf_cls, cls)): conf_adr = conf_cls.from_bytes(blinding_pubkey + unconfidential_adr) return cast(T_CCoinConfidentialAddress, conf_adr) if issubclass(cls, (conf_cls, chain_specific_conf_cls)): raise TypeError( 'cannot create {} from {}: only subclasses of {} are accepted' .format(cls.__name__, unconfidential_adr.__class__.__name__, unconf_cls.__name__)) raise CConfidentialAddressError( 'cannot create {} from {}: no matching confidential address class'. format(cls.__name__, unconfidential_adr.__class__.__name__))
def from_bytes(cls, witprog, witver=None): if cls._witness_version is None: assert witver is not None, \ ("witver must be specified for {}.from_bytes()" .format(cls.__name__)) for candidate in dispatcher_mapped_list(cls): if len(witprog) == candidate._data_length and \ witver == candidate._witness_version: break else: raise CBech32AddressError( 'witness program does not match any known Bech32 ' 'address length or version') else: candidate = cls if len(witprog) != candidate._data_length or \ (witver is not None and witver != candidate._witness_version): raise CBech32AddressError('witness program does not match {}' ' expected length or version'.format( cls.__name__)) self = super(CBech32CoinAddress, cls).from_bytes(bytes(witprog), witver=candidate._witness_version) self.__class__ = candidate return self
def base58_get_match_candidates(cls): candidates = dispatcher_mapped_list(cls) if not candidates: if not cls.base58_prefix: raise TypeError( "if class has no dispatched descendants, it must have " "base58_prefix set") candidates = [cls] return candidates
def base58_get_match_candidates( cls: Type[T_CBase58DataDispatched] ) -> List[Type[T_CBase58DataDispatched]]: assert isinstance(cls, ClassMappingDispatcher) candidates = dispatcher_mapped_list(cls) if P2SHLitecoinAddress in candidates\ and get_current_chain_params().allow_legacy_p2sh: return [P2SHLitecoinLegacyAddress] + candidates return super(CBase58LitecoinAddress, cls).base58_get_match_candidates()
def from_scriptPubKey(cls, scriptPubKey): """Convert a scriptPubKey to a subclass of CCoinAddress""" for candidate in dispatcher_mapped_list(cls): try: return candidate.from_scriptPubKey(scriptPubKey) except CCoinAddressError: pass raise CCoinAddressError( 'scriptPubKey is not in a recognized address format')
def bech32_get_match_candidates(cls: Type[T_CBech32DataDispatched] ) -> List[Type[T_CBech32DataDispatched]]: assert isinstance(cls, ClassMappingDispatcher) candidates = dispatcher_mapped_list(cls) if not candidates: if cls.bech32_witness_version < 0: raise TypeError( "if class has no dispatched descendants, it must have " "bech32_witness_version set to non-negative value") candidates = [cls] return candidates
def base58_get_match_candidates(cls: Type[T_CBase58DataDispatched] ) -> List[Type[T_CBase58DataDispatched]]: assert isinstance(cls, ClassMappingDispatcher) candidates = dispatcher_mapped_list(cls) if not candidates: if not cls.base58_prefix: raise TypeError( "if class has no dispatched descendants, it must have " "base58_prefix set") candidates = [cls] return candidates
def match_scriptPubKey_type(cls, spk_type_string: str): """match the concrete address class by scriptPubKey type. For example, given the string 'scripthash', it will return P2SHCoinAddress. If no matching scriptPubKey type is found, will return None.""" for target_cls in dispatcher_mapped_list(cls): spk_type = getattr(target_cls, '_scriptpubkey_type', None) if not spk_type: matched = target_cls.match_scriptPubKey_type(spk_type_string) if matched is not None: return matched elif spk_type_string == spk_type: return target_cls return None
def __new__(cls, s): recognized_encoding = [] target_cls_set = dispatcher_mapped_list(cls) for target_cls in target_cls_set: try: return target_cls(s) except CCoinAddressError: recognized_encoding.append(target_cls.__name__) except bitcointx.core.AddressDataEncodingError: pass if recognized_encoding: raise CCoinAddressError( 'Correct encoding for any of {}, but not correct format'. format(recognized_encoding)) raise CCoinAddressError('Unrecognized encoding for any of {}'.format( [tcls.__name__ for tcls in target_cls_set]))
def __new__(cls: Type[T_CCoinAddress], s: str) -> T_CCoinAddress: ensure_isinstance(s, str, 'address string') recognized_encoding = [] target_cls_set = dispatcher_mapped_list(cls) for target_cls in target_cls_set: try: return target_cls(s) except CCoinAddressError: recognized_encoding.append(target_cls.__name__) except bitcointx.core.AddressDataEncodingError: pass if recognized_encoding: raise CCoinAddressError( 'Correct encoding for any of {}, but not correct format' .format(recognized_encoding)) raise CCoinAddressError( 'Unrecognized encoding for any of {}' .format([tcls.__name__ for tcls in target_cls_set]))
def _xpub_class(self): return dispatcher_mapped_list(CCoinExtPubKey)[0]
def _key_class(self) -> Type[CCoinKey]: return cast(Type[CCoinKey], dispatcher_mapped_list(CCoinKey)[0])
def _xpub_class(self) -> Type[CCoinExtPubKey]: return cast(Type[CCoinExtPubKey], dispatcher_mapped_list(CCoinExtPubKey)[0])
def _key_class(self): return dispatcher_mapped_list(CCoinKey)[0]
def test_from_to_unconfidential(self): #noqa pub1 = CPubKey( x('02546c76587482cd2468b76768da70c0166ecb2aa2eb1038624f4fedc138b042bc' )) pub2 = CPubKey( x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71' )) params_list = get_params_list() for pl_index, chainparam in enumerate(params_list): next_chainparam = (params_list[0] if pl_index + 1 == len(params_list) else params_list[pl_index + 1]) with ChainParams(chainparam): mapped_cls_list = dispatcher_mapped_list( CCoinConfidentialAddress) assert len(mapped_cls_list) == 1 chain_specific_cls = mapped_cls_list[0] with ChainParams(next_chainparam): mapped_cls_list = dispatcher_mapped_list( CCoinConfidentialAddress) assert len(mapped_cls_list) == 1 next_chain_specific_cls = mapped_cls_list[0] assert next_chain_specific_cls is not chain_specific_cls smpl = get_unconfidential_address_samples(pub1, pub2) for uct in unconf_types: for ct in conf_types: unconf = getattr(smpl, uct) conf = getattr(smpl, ct) with self.assertRaises(TypeError): next_chain_specific_cls.from_unconfidential( unconf, pub2) if ct.endswith(uct): self.assertEqual(str(conf.to_unconfidential()), str(unconf)) self.assertEqual( str(conf.from_unconfidential(unconf, pub2)), str(conf)) self.assertNotEqual( str(conf.from_unconfidential(unconf, pub1)), str(conf)) self.assertEqual( str( CCoinConfidentialAddress. from_unconfidential(unconf, pub2)), str(conf)) self.assertEqual( str( chain_specific_cls.from_unconfidential( unconf, pub2)), str(conf)) if ct.endswith('p2pkh'): self.assertEqual( str( CBase58CoinConfidentialAddress. from_unconfidential(unconf, pub2)), str(conf)) self.assertEqual( str( P2PKHCoinConfidentialAddress. from_unconfidential(unconf, pub2)), str(conf)) elif ct.endswith('p2sh'): self.assertEqual( str( CBase58CoinConfidentialAddress. from_unconfidential(unconf, pub2)), str(conf)) self.assertEqual( str( P2SHCoinConfidentialAddress. from_unconfidential(unconf, pub2)), str(conf)) elif ct.endswith('p2wpkh'): self.assertEqual( str( CBlech32CoinConfidentialAddress. from_unconfidential(unconf, pub2)), str(conf)) self.assertEqual( str( P2WPKHCoinConfidentialAddress. from_unconfidential(unconf, pub2)), str(conf)) elif ct.endswith('p2wsh'): self.assertEqual( str( CBlech32CoinConfidentialAddress. from_unconfidential(unconf, pub2)), str(conf)) self.assertEqual( str( P2WSHCoinConfidentialAddress. from_unconfidential(unconf, pub2)), str(conf)) else: assert 0, "unexpected addr type" if issubclass(conf.__class__, CBlech32CoinConfidentialAddress): with self.assertRaises( CConfidentialAddressError): CBase58CoinConfidentialAddress.from_unconfidential( unconf, pub2) elif issubclass(conf.__class__, CBase58CoinConfidentialAddress): with self.assertRaises( CConfidentialAddressError): CBlech32CoinConfidentialAddress.from_unconfidential( unconf, pub2) else: assert 0, "unexpected conf.__class__" for ct2 in conf_types: if ct != ct2: conf_cls = getattr(smpl, ct2).__class__ with self.assertRaises(TypeError): conf_cls.from_unconfidential( unconf, pub2) else: self.assertNotEqual(str(conf.to_unconfidential()), str(unconf)) with self.assertRaises(TypeError): conf.from_unconfidential(unconf, pub2)
def base58_get_match_candidates(cls): candidates = dispatcher_mapped_list(cls) if P2SHLitecoinAddress in candidates\ and get_current_chain_params().allow_legacy_p2sh: return [P2SHLitecoinLegacyAddress] + candidates return super(CBase58LitecoinAddress, cls).base58_get_match_candidates()