def test_multisig_sig():
    sig_script = Script('OP_0 0x30440220762ce7bca626942975bfd5b130ed3470b9f538eb2ac120c2043b445709369628022051d73c80328b543f744aa64b7e9ebefa7ade3e5c716eab4a09b408d2c307ccd701 0x3045022100abf740b58d79cab000f8b0d328c2fff7eb88933971d1b63f8b99e89ca3f2dae602203354770db3cc2623349c87dea7a50cee1f78753141a5052b2d58aeb592bcf50f01 0x524104a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd41046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187410411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e8353ae')  # nopep8

    assert sig_script.is_multisig_sig()

    r = sig_script.extract_multisig_sig_info()
    redeem_info = r['redeem_script'].extract_multisig_redeem_info()
    assert len(r['signatures']) == 2
    assert r['redeem_script']
    assert isinstance(r['redeem_script'], Script)

    s = Script.build_multisig_sig(r['signatures'], r['redeem_script'])
    assert bytes(s) == bytes(sig_script)

    # This is a test case where there is no OP_PUSHDATA
    raw_scr = "00483045022100fa1225f8828fd6fe52665c3c4258169a84af52b41525f2e288082f174c032f47022022758d5519db3ab2cec4a330e96568b9289fb77c5653bce49397df01a3fcff5101475221038b5fa60aee4c4e9ab3a66e6bb32211a54da6b054c6143dd221c122ce936315d921023180e1b49b7f3fd1254a19c7aa8016ad995089b99c9dac89752cd17e40d9072d52ae"  # nopep8
    s, _ = Script.from_bytes(pack_var_str(bytes.fromhex(raw_scr)))

    assert sig_script.is_multisig_sig()

    r = s.extract_multisig_sig_info()
    assert len(r['signatures']) == 1
    assert r['redeem_script']
    assert isinstance(r['redeem_script'], Script)

    sig_addresses = sig_script.get_addresses()
    assert len(sig_addresses) == redeem_info['n'] + 1
    assert sig_addresses == ['1JzVFZSN1kxGLTHG41EVvY5gHxLAX7q1Rh',
                             '14JfSvgEq8A8S7qcvxeaSCxhn1u1L71vo4',
                             '1Kyy7pxzSKG75L9HhahRZgYoer9FePZL4R',
                             '347N1Thc213QqfYCz3PZkjoJpNv5b14kBd']
Exemple #2
0
    def _do_multisig_script(self, sigs, message, current_script_sig,
                            redeem_script, hash_type):
        # If the current script is empty or None, create it
        sig_script = None
        if current_script_sig is None or not str(current_script_sig):
            sig_bytes = [s['signature'].to_der() + pack_compact_int(hash_type)
                         for s in sigs]

            sig_script = Script.build_multisig_sig(sigs=sig_bytes,
                                                   redeem_script=redeem_script)
        else:
            # Need to extract all the sigs already present
            multisig_params = redeem_script.extract_multisig_redeem_info()
            sig_info = current_script_sig.extract_multisig_sig_info()

            # Do a few quick sanity checks
            if str(sig_info['redeem_script']) != str(redeem_script):
                raise ValueError(
                    "Redeem script in signature script does not match redeem_script!")

            if len(sig_info['signatures']) == multisig_params['n']:
                # Already max number of signatures
                return current_script_sig

            # Go through the signatures and match them up to the public keys
            # in the redeem script
            pub_keys = []
            for pk in multisig_params['public_keys']:
                pub_keys.append(crypto.PublicKey.from_bytes(pk))

            existing_sigs = []
            for s in sig_info['signatures']:
                s1, h = s[:-1], s[-1]  # Last byte is hash_type
                existing_sigs.append(crypto.Signature.from_der(s1))
                if h != hash_type:
                    raise ValueError("hash_type does not match that of the existing signatures.")

            # Match them up
            existing_sig_indices = self._match_sigs_to_pub_keys(existing_sigs,
                                                                pub_keys,
                                                                message)
            sig_indices = {s['index']: s['signature'] for s in sigs}

            # Make sure there are no dups
            all_indices = set(list(existing_sig_indices.keys()) +
                              list(sig_indices.keys()))
            if len(all_indices) < len(existing_sig_indices) + len(sig_indices):
                raise ValueError("At least one signature matches an existing signature.")

            if len(all_indices) > multisig_params['n']:
                raise ValueError("There are too many signatures.")

            all_sigs = []
            for i in sorted(all_indices):
                if i in existing_sig_indices:
                    all_sigs.append(existing_sig_indices[i])
                elif i in sig_indices:
                    all_sigs.append(sig_indices[i])

            all_sigs_bytes = [s.to_der() + pack_compact_int(hash_type)
                              for s in all_sigs]
            sig_script = Script.build_multisig_sig(all_sigs_bytes,
                                                   redeem_script)

        return sig_script
Exemple #3
0
    def _do_multisig_script(self, sigs, message, current_script_sig,
                            redeem_script, hash_type):
        # If the current script is empty or None, create it
        sig_script = None
        if current_script_sig is None or not str(current_script_sig):
            sig_bytes = [s['signature'].to_der() + pack_compact_int(hash_type)
                         for s in sigs]

            sig_script = Script.build_multisig_sig(sigs=sig_bytes,
                                                   redeem_script=redeem_script)
        else:
            # Need to extract all the sigs already present
            multisig_params = redeem_script.extract_multisig_redeem_info()
            sig_info = current_script_sig.extract_multisig_sig_info()

            # Do a few quick sanity checks
            if str(sig_info['redeem_script']) != str(redeem_script):
                raise ValueError(
                    "Redeem script in signature script does not match redeem_script!")

            if len(sig_info['signatures']) == multisig_params['n']:
                # Already max number of signatures
                return current_script_sig

            # Go through the signatures and match them up to the public keys
            # in the redeem script
            pub_keys = []
            for pk in multisig_params['public_keys']:
                pub_keys.append(crypto.PublicKey.from_bytes(pk))

            existing_sigs = []
            for s in sig_info['signatures']:
                s1, h = s[:-1], s[-1]  # Last byte is hash_type
                existing_sigs.append(crypto.Signature.from_der(s1))
                if h != hash_type:
                    raise ValueError("hash_type does not match that of the existing signatures.")

            # Match them up
            existing_sig_indices = self._match_sigs_to_pub_keys(existing_sigs,
                                                                pub_keys,
                                                                message)
            sig_indices = {s['index']: s['signature'] for s in sigs}

            # Make sure there are no dups
            all_indices = set(list(existing_sig_indices.keys()) +
                              list(sig_indices.keys()))
            if len(all_indices) < len(existing_sig_indices) + len(sig_indices):
                raise ValueError("At least one signature matches an existing signature.")

            if len(all_indices) > multisig_params['n']:
                raise ValueError("There are too many signatures.")

            all_sigs = []
            for i in sorted(all_indices):
                if i in existing_sig_indices:
                    all_sigs.append(existing_sig_indices[i])
                elif i in sig_indices:
                    all_sigs.append(sig_indices[i])

            all_sigs_bytes = [s.to_der() + pack_compact_int(hash_type)
                              for s in all_sigs]
            sig_script = Script.build_multisig_sig(all_sigs_bytes,
                                                   redeem_script)

        return sig_script