예제 #1
0
            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)
예제 #2
0
 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)
예제 #3
0
    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__))
예제 #4
0
    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
예제 #5
0
 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
예제 #6
0
 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()
예제 #7
0
    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')
예제 #8
0
 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
예제 #9
0
 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
예제 #10
0
 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
예제 #11
0
    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]))
예제 #12
0
    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]))
예제 #13
0
 def _xpub_class(self):
     return dispatcher_mapped_list(CCoinExtPubKey)[0]
예제 #14
0
 def _key_class(self) -> Type[CCoinKey]:
     return cast(Type[CCoinKey],
                 dispatcher_mapped_list(CCoinKey)[0])
예제 #15
0
 def _xpub_class(self) -> Type[CCoinExtPubKey]:
     return cast(Type[CCoinExtPubKey],
                 dispatcher_mapped_list(CCoinExtPubKey)[0])
예제 #16
0
 def _key_class(self):
     return dispatcher_mapped_list(CCoinKey)[0]
예제 #17
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)
예제 #18
0
 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()