Exemplo n.º 1
0
    def solve_finalize_commit(self, **kwargs):
        hash160_lookup = kwargs.get("hash160_lookup")
        sign_value = kwargs.get("sign_value")
        signature_type = kwargs.get("signature_type")
        existing_script = kwargs.get("existing_script")

        # FIXME validate on receiving the commit
        # validate payer sig
        opcode, data, pc = tools.get_opcode(existing_script, 0)  # OP_0
        opcode, payer_sig, pc = tools.get_opcode(existing_script, pc)
        sig_pair, actual_signature_type = parse_signature_blob(payer_sig)
        try:
            public_pair = encoding.sec_to_public_pair(self.payer_sec)
            sig_pair, signature_type = parse_signature_blob(payer_sig)
            valid = ecdsa.verify(ecdsa.generator_secp256k1, public_pair,
                                 sign_value, sig_pair)
            if not valid:
                raise Exception("Invalid payer public_pair!")
        except (encoding.EncodingError, UnexpectedDER):
            raise Exception("Invalid payer public_pair!")

        # sign
        private_key = hash160_lookup.get(encoding.hash160(self.payee_sec))
        secret_exponent, public_pair, compressed = private_key
        payee_sig = self._create_script_signature(
            secret_exponent, sign_value, signature_type
        )

        script_text = "OP_0 {payer_sig} {payee_sig} OP_1".format(
            payer_sig=b2h(payer_sig), payee_sig=b2h(payee_sig)
        )
        return tools.compile(script_text)
Exemplo n.º 2
0
def dump_signatures(tx, tx_in, tx_out, idx, netcode, address_prefix,
                    traceback_f, disassembly_level):
    signatures = []
    for opcode in opcode_list(tx_in.script):
        if not opcode.startswith("OP_"):
            try:
                signatures.append(parse_signature_blob(h2b(opcode[1:-1])))
            except UnexpectedDER:
                pass
    if signatures:
        sig_types_identical = (tuple(zip(*signatures))[1].count(
            signatures[0][1]) == len(signatures))
        i = 1 if len(signatures) > 1 else ''
        for sig_pair, sig_type in signatures:
            print("      r{0}: {1:#x}\n      s{0}: {2:#x}".format(
                i, *sig_pair))
            if not sig_types_identical and tx_out:
                print("      z{}: {:#x} {}".format(
                    i, tx.signature_hash(tx_out.script, idx, sig_type),
                    sighash_type_to_string(sig_type)))
            if i:
                i += 1
        if sig_types_identical and tx_out:
            print("      z:{} {:#x} {}".format(
                ' ' if i else '',
                tx.signature_hash(tx_out.script, idx, sig_type),
                sighash_type_to_string(sig_type)))
Exemplo n.º 3
0
    def __eq__(a, b):
        if a.sighash != b.sighash:
            if a.sighash is not None and b.sighash is not None:
                return False

        rv =  a.utxo == b.utxo and \
                a.witness_utxo == b.witness_utxo and \
                a.redeem_script == b.redeem_script and \
                a.witness_script == b.witness_script and \
                a.my_index == b.my_index and \
                a.bip32_paths == b.bip32_paths and \
                sorted(a.part_sigs.keys()) == sorted(b.part_sigs.keys())
        if rv:
            # NOTE: equality test on signatures requires parsing DER stupidness
            #       and some maybe understanding of R/S values on curve that I don't have.
            assert all(
                parse_signature_blob(a.part_sigs[k]) == parse_signature_blob(
                    b.part_sigs[k]) for k in a.part_sigs)
        return rv
Exemplo n.º 4
0
def add_signature_annotations(annotations, signature_blob, signature_for_hash_type_f, output_script):
    sig_pair, sig_type = parse_signature_blob(signature_blob)
    annotations.append("r: {0:#066x}".format(sig_pair[0]))
    annotations.append("s: {0:#066x}".format(sig_pair[1]))
    sig_hash = signature_for_hash_type_f(sig_type, output_script)
    annotations.append("z: {0:#066x}".format(sig_hash))
    annotations.append("signature type %s" % sighash_type_to_string(sig_type))
    addresses = []
    pairs = possible_public_pairs_for_signature(generator_secp256k1, sig_hash, sig_pair)
    for pair in pairs:
        for comp in (True, False):
            address = public_pair_to_bitcoin_address(pair, compressed=comp, address_prefix=b'\0')
            addresses.append(address)
    annotations.append(" sig for %s" % " ".join(addresses))
Exemplo n.º 5
0
def who_signed_tx(tx, tx_in_idx, netcode='BTC'):
    """
    Given a transaction (tx) an input index (tx_in_idx), attempt to figure
    out which addresses where used in signing (so far). This method
    depends on tx.unspents being properly configured. This should work on
    partially-signed MULTISIG transactions (it will return as many
    addresses as there are good signatures).
    Returns a list of ( address, sig_type ) pairs.
    Raises NoAddressesForScriptTypeError if addresses cannot be determined
    for the input's script.
    TODO: This does not yet support P2SH.
    """
    tx_in = tx.txs_in[tx_in_idx]
    parent_tx_out_idx = tx_in.previous_index
    parent_tx_out_script = tx.unspents[tx_in_idx].script
    script_obj = script_obj_from_script(parent_tx_out_script)
    signed_by = []

    if type(script_obj) not in (ScriptPayToAddress, ScriptPayToPublicKey,
                                ScriptMultisig):
        raise NoAddressesForScriptTypeError(
            'unable to determine signing addresses for script type of parent tx {}[{}]'
            .format(b2h_rev(tx_in.previous_hash), parent_tx_out_idx))

    script = tx_in.script
    pc = 0
    while pc < len(script):
        opcode, data, pc = get_opcode(script, pc)
        if data is None:
            continue
        try:
            sig_pair, sig_type = parse_signature_blob(data)
        except (ValueError, TypeError, binascii.Error, UnexpectedDER):
            continue

        sig_hash = tx.signature_hash(parent_tx_out_script, parent_tx_out_idx,
                                     sig_type)

        for sec_key in script_obj.sec_keys:
            public_pair = sec_to_public_pair(sec_key)

            if ecdsa_verify(generator_secp256k1, public_pair, sig_hash,
                            sig_pair):
                addr_pfx = address_prefix_for_netcode(netcode)
                addr = public_pair_to_bitcoin_address(public_pair,
                                                      address_prefix=addr_pfx)
                signed_by.append((addr, sig_type))
    return signed_by
Exemplo n.º 6
0
def who_signed_tx(tx, tx_in_idx, netcode='BTC'):
    """
    Given a transaction (tx) an input index (tx_in_idx), attempt to figure
    out which addresses where used in signing (so far). This method
    depends on tx.unspents being properly configured. This should work on
    partially-signed MULTISIG transactions (it will return as many
    addresses as there are good signatures).
    Returns a list of ( address, sig_type ) pairs.
    Raises NoAddressesForScriptTypeError if addresses cannot be determined
    for the input's script.
    TODO: This does not yet support P2SH.
    """
    tx_in = tx.txs_in[tx_in_idx]
    parent_tx_out_idx = tx_in.previous_index
    parent_tx_out_script = tx.unspents[tx_in_idx].script
    script_obj = script_obj_from_script(parent_tx_out_script)
    signed_by = []

    if type(script_obj) not in (ScriptPayToAddress, ScriptPayToPublicKey, ScriptMultisig):
        raise NoAddressesForScriptTypeError(
            'unable to determine signing addresses for script type of parent tx {}[{}]'
            .format(b2h_rev(tx_in.previous_hash), parent_tx_out_idx))

    script = tx_in.script
    pc = 0
    while pc < len(script):
        opcode, data, pc = get_opcode(script, pc)
        if data is None:
            continue
        try:
            sig_pair, sig_type = parse_signature_blob(data)
        except (ValueError, TypeError, binascii.Error, UnexpectedDER):
            continue

        sig_hash = tx.signature_hash(parent_tx_out_script, parent_tx_out_idx, sig_type)

        for sec_key in script_obj.sec_keys:
            public_pair = sec_to_public_pair(sec_key)

            if ecdsa_verify(generator_secp256k1, public_pair, sig_hash, sig_pair):
                addr_pfx = address_prefix_for_netcode(netcode)
                addr = public_pair_to_bitcoin_address(public_pair, address_prefix=addr_pfx)
                signed_by.append((addr, sig_type))
    return signed_by
Exemplo n.º 7
0
    def solve_finalize_commit(self, **kwargs):
        hash160_lookup = kwargs.get("hash160_lookup")
        signature_type = kwargs.get("signature_type")
        existing_script = kwargs.get("existing_script")

        # validate existing script
        reference_script_hex = _compile_commit_scriptsig(
            "deadbeef", "deadbeef", b2h(self.script))
        _validate(reference_script_hex, b2h(existing_script))

        # check provided payer signature
        try:
            opcode, data, pc = tools.get_opcode(existing_script, 0)  # OP_0
            opcode, payer_sig, pc = tools.get_opcode(existing_script, pc)

            # verify signature type
            sig_r_s, actual_signature_type = parse_signature_blob(payer_sig)
            assert (signature_type == actual_signature_type)

            # verify payer signature
            public_pair = encoding.sec_to_public_pair(self.payer_sec)
            sign_value = kwargs.get("sign_value")

            public_pair = encoding.sec_to_public_pair(self.payer_sec)
            sign_value = kwargs["signature_for_hash_type_f"](
                signature_type, kwargs["script_to_hash"])

            if not ecdsa.verify(ecdsa.generator_secp256k1, public_pair,
                                sign_value, sig_r_s):
                raise InvalidPayerSignature("invalid r s values")
        except UnexpectedDER:
            raise InvalidPayerSignature("not in DER format")

        # sign
        private_key = hash160_lookup.get(encoding.hash160(self.payee_sec))
        secret_exponent, public_pair, compressed = private_key
        payee_sig = self._create_sig(secret_exponent, **kwargs)

        script_asm = COMMIT_SCRIPTSIG.format(payer_sig=b2h(payer_sig),
                                             payee_sig=b2h(payee_sig))
        return tools.compile(script_asm)
Exemplo n.º 8
0
def dump_signatures(tx, tx_in, tx_out, idx, netcode, address_prefix, traceback_f, disassembly_level):
    signatures = []
    for opcode in opcode_list(tx_in.script):
        if not opcode.startswith("OP_"):
            try:
                signatures.append(parse_signature_blob(h2b(opcode[1:-1])))
            except UnexpectedDER:
                pass
    if signatures:
        sig_types_identical = (
            tuple(zip(*signatures))[1].count(signatures[0][1]) == len(signatures))
        i = 1 if len(signatures) > 1 else ''
        for sig_pair, sig_type in signatures:
            print("      r{0}: {1:#x}\n      s{0}: {2:#x}".format(i, *sig_pair))
            if not sig_types_identical and tx_out:
                print("      z{}: {:#x} {}".format(i, tx.signature_hash(tx_out.script, idx, sig_type),
                                                   sighash_type_to_string(sig_type)))
            if i:
                i += 1
        if sig_types_identical and tx_out:
            print("      z:{} {:#x} {}".format(' ' if i else '', tx.signature_hash(
                tx_out.script, idx, sig_type), sighash_type_to_string(sig_type)))
Exemplo n.º 9
0
def dump_tx(tx, netcode, verbose_signature, disassembly_level, do_trace):
    address_prefix = address_prefix_for_netcode(netcode)
    tx_bin = stream_to_bytes(tx.stream)
    print("Version: %2d  tx hash %s  %d bytes   " % (tx.version, tx.id(), len(tx_bin)))
    print("TxIn count: %d; TxOut count: %d" % (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
    missing_unspents = tx.missing_unspents()
    traceback_f = trace_script if do_trace else None
    for idx, tx_in in enumerate(tx.txs_in):
        if disassembly_level > 0:
            signature_for_hash_type_f = lambda hash_type, script: tx.signature_hash(
                                        script, idx, hash_type)
        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" % (idx, satoshi_to_mbtc(tx.total_in())))
        else:
            suffix = ""
            if tx.missing_unspent(idx):
                tx_out = None
                address = tx_in.bitcoin_address(address_prefix=address_prefix)
            else:
                tx_out = tx.unspents[idx]
                sig_result = " sig ok" if tx.is_signature_ok(idx, traceback_f=traceback_f) else " BAD SIG"
                suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(tx_out.coin_value), sig_result)
                address = tx_out.bitcoin_address(netcode=netcode)
            t = "%4d: %34s from %s:%-4d%s" % (idx, address, b2h_rev(tx_in.previous_hash),
                                              tx_in.previous_index, suffix)
            print(t.rstrip())
            if disassembly_level > 0:
                out_script = b''
                if tx_out:
                    out_script = tx_out.script
                for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                        disassemble_scripts(tx_in.script, out_script, signature_for_hash_type_f):
                    for l in pre_annotations:
                        print("           %s" % l)
                    print(    "    %4x: %02x  %s" % (pc, opcode, instruction))
                    for l in post_annotations:
                        print("           %s" % l)

            if verbose_signature:
                signatures = []
                for opcode in opcode_list(tx_in.script):
                    if not opcode.startswith("OP_"):
                        try:
                            signatures.append(parse_signature_blob(h2b(opcode)))
                        except UnexpectedDER:
                            pass
                if signatures:
                    sig_types_identical = (zip(*signatures)[1]).count(signatures[0][1]) == len(signatures)
                    i = 1 if len(signatures) > 1 else ''
                    for sig_pair, sig_type in signatures:
                        print("      r{0}: {1:#x}\n      s{0}: {2:#x}".format(i, *sig_pair))
                        if not sig_types_identical and tx_out:
                            print("      z{}: {:#x} {}".format(i, tx.signature_hash(tx_out.script, idx, sig_type),
                                                               sighash_type_to_string(sig_type)))
                        if i: i += 1
                    if sig_types_identical and tx_out:
                        print("      z:{} {:#x} {}".format(' ' if i else '', tx.signature_hash(tx_out.script, idx, sig_type),
                                                           sighash_type_to_string(sig_type)))

    print("Output%s:" % ('s' if len(tx.txs_out) != 1 else ''))
    for idx, tx_out in enumerate(tx.txs_out):
        amount_mbtc = satoshi_to_mbtc(tx_out.coin_value)
        address = tx_out.bitcoin_address(netcode=netcode) or "(unknown)"
        print("%4d: %34s receives %12.5f mBTC" % (idx, address, amount_mbtc))
        if disassembly_level > 0:
            for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                    disassemble_scripts(b'', tx_out.script, signature_for_hash_type_f):
                for l in pre_annotations:
                    print("           %s" % l)
                print(    "    %4x: %02x  %s" % (pc, opcode, instruction))
                for l in post_annotations:
                    print("           %s" % l)

    if not missing_unspents:
        print("Total input  %12.5f mBTC" % satoshi_to_mbtc(tx.total_in()))
    print(    "Total output %12.5f mBTC" % satoshi_to_mbtc(tx.total_out()))
    if not missing_unspents:
        print("Total fees   %12.5f mBTC" % satoshi_to_mbtc(tx.fee()))
Exemplo n.º 10
0
def dump_tx(tx, netcode, verbose_signature, disassembly_level, do_trace,
            use_pdb):
    address_prefix = address_prefix_for_netcode(netcode)
    tx_bin = stream_to_bytes(tx.stream)
    #     print("Tx_type:%2d" % tx.tx_type)
    if TransactionUtils.isCFTransation(tx):
        print("original_hash : %s" % tx.cf_header.original_hash)
        print("target_amount : %s" % tx.cf_header.target_amount)
        print("pubkey : %s" % tx.cf_header.pubkey)
        print("end_time : %s" % tx.cf_header.end_time)
        print("pre_hash : %s" % tx.cf_header.pre_hash)
        print("lack_amount : %s" % tx.cf_header.lack_amount)
    print("Version: %2d  tx hash %s  %d bytes   " %
          (tx.version, tx.id(), len(tx_bin)))
    print("TransactionIn count: %d; TransactionOut count: %d" %
          (len(tx.txs_in), len(tx.txs_out)))
    if tx.lock_time == 0:
        meaning = "valid anytime"
    elif tx.lock_time < LOCKTIME_THRESHOLD:
        meaning = "valid after block index %d" % tx.lock_time
    else:
        when = datetime.datetime.utcfromtimestamp(tx.lock_time)
        meaning = "valid on or after %s utc" % when.isoformat()
    print("Lock time: %d (%s)" % (tx.lock_time, meaning))
    print("Input%s:" % ('s' if len(tx.txs_in) != 1 else ''))
    missing_unspents = tx.missing_unspents()

    def trace_script(old_pc, opcode, data, stack, altstack, if_condition_stack,
                     is_signature):
        from pycoin.tx.script.tools import disassemble_for_opcode_data
        print("%3d : %02x  %s" %
              (old_pc, opcode, disassemble_for_opcode_data(opcode, data)))
        if use_pdb:
            import pdb
            from pycoin.serialize import b2h
            print("stack: [%s]" % ', '.join(b2h(s) for s in stack))
            if len(altstack) > 0:
                print("altstack: %s" % altstack)
            if len(if_condition_stack) > 0:
                print("condition stack: %s" %
                      ', '.join(int(s) for s in if_condition_stack))
            pdb.set_trace()

    traceback_f = trace_script if do_trace or use_pdb else None
    for idx, tx_in in enumerate(tx.txs_in):
        if disassembly_level > 0:

            def signature_for_hash_type_f(hash_type, script):
                return tx.signature_hash(script, idx, hash_type)

        if tx.is_coinbase():
            print("%4d: COINBASE  %12.5f mBTC" %
                  (idx, satoshi_to_mbtc(tx.total_in())))
        else:
            suffix = ""
            if tx.missing_unspent(idx):
                tx_out = None
                address = tx_in.bitcoin_address(address_prefix=address_prefix)
            else:
                tx_out = tx.unspents[idx]
                sig_result = " sig ok" if tx.is_signature_ok(
                    idx, traceback_f=traceback_f) else " BAD SIG"
                suffix = " %12.5f mBTC %s" % (satoshi_to_mbtc(
                    tx_out.coin_value), sig_result)
                address = tx_out.bitcoin_address(netcode=netcode)
            t = "%4d: %34s from %s:%-4d%s" % (idx, address,
                                              b2h_rev(tx_in.previous_hash),
                                              tx_in.previous_index, suffix)
            print(t.rstrip())
            if disassembly_level > 0:
                out_script = b''
                if tx_out:
                    out_script = tx_out.script
                for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                        disassemble_scripts(
                            tx_in.script, out_script, tx.lock_time, signature_for_hash_type_f):
                    for l in pre_annotations:
                        print("           %s" % l)
                    print("    %4x: %02x  %s" % (pc, opcode, instruction))
                    for l in post_annotations:
                        print("           %s" % l)

            if verbose_signature:
                signatures = []
                for opcode in opcode_list(tx_in.script):
                    if not opcode.startswith("OP_"):
                        try:
                            signatures.append(parse_signature_blob(
                                h2b(opcode)))
                        except UnexpectedDER:
                            pass
                if signatures:
                    sig_types_identical = (zip(*signatures)[1]).count(
                        signatures[0][1]) == len(signatures)
                    i = 1 if len(signatures) > 1 else ''
                    for sig_pair, sig_type in signatures:
                        print("      r{0}: {1:#x}\n      s{0}: {2:#x}".format(
                            i, *sig_pair))
                        if not sig_types_identical and tx_out:
                            print("      z{}: {:#x} {}".format(
                                i,
                                tx.signature_hash(tx_out.script, idx,
                                                  sig_type),
                                sighash_type_to_string(sig_type)))
                        if i:
                            i += 1
                    if sig_types_identical and tx_out:
                        print("      z:{} {:#x} {}".format(
                            ' ' if i else '',
                            tx.signature_hash(tx_out.script, idx, sig_type),
                            sighash_type_to_string(sig_type)))

    print("Output%s:" % ('s' if len(tx.txs_out) != 1 else ''))
    for idx, tx_out in enumerate(tx.txs_out):
        amount_mbtc = satoshi_to_mbtc(tx_out.coin_value)
        address = tx_out.bitcoin_address(netcode=netcode) or "(unknown)"
        print("%4d: %34s receives %12.5f mBTC" % (idx, address, amount_mbtc))
        if disassembly_level > 0:
            for (pre_annotations, pc, opcode, instruction, post_annotations) in \
                    disassemble_scripts(b'', tx_out.script, tx.lock_time, signature_for_hash_type_f):
                for l in pre_annotations:
                    print("           %s" % l)
                print("    %4x: %02x  %s" % (pc, opcode, instruction))
                for l in post_annotations:
                    print("           %s" % l)

    if not missing_unspents:
        print("Total input  %12.5f mBTC" % satoshi_to_mbtc(tx.total_in()))
    print("Total output %12.5f mBTC" % satoshi_to_mbtc(tx.total_out()))
    if not missing_unspents:
        print("Total fees   %12.5f mBTC" % satoshi_to_mbtc(tx.fee()))
Exemplo n.º 11
0
def solve(self, **kwargs):
    """
    The kwargs required depend upon the script type.
    hash160_lookup:
        dict-like structure that returns a secret exponent for a hash160
    existing_script:
        existing solution to improve upon (optional)
    sign_value:
        the integer value to sign (derived from the transaction hash)
    signature_type:
        usually SIGHASH_ALL (1)
    """
    # we need a hash160 => secret_exponent lookup
    db = kwargs.get("hash160_lookup")
    if db is None:
        raise SolvingError("missing hash160_lookup parameter")

    sign_value = kwargs.get("sign_value")
    signature_type = kwargs.get("signature_type")

    secs_solved = set()
    existing_signatures = []
    existing_script = kwargs.get("existing_script")
    if existing_script:
        pc = 0
        opcode, data, pc = tools.get_opcode(existing_script, pc)
        # ignore the first opcode
        while pc < len(existing_script):
            opcode, data, pc = tools.get_opcode(existing_script, pc)
            sig_pair, actual_signature_type = parse_signature_blob(data)
            for sec_key in self.sec_keys:
                try:
                    public_pair = encoding.sec_to_public_pair(sec_key)
                    sig_pair, signature_type = parse_signature_blob(data)
                    v = ecdsa.verify(ecdsa.generator_secp256k1, public_pair, sign_value, sig_pair)
                    if v:
                        existing_signatures.append(data)
                        secs_solved.add(sec_key)
                        break
                except encoding.EncodingError:
                    # if public_pair is invalid, we just ignore it
                    pass

    for sec_key in self.sec_keys:
        if sec_key in secs_solved:
            continue
        if len(existing_signatures) >= self.n:
            break
        hash160 = encoding.hash160(sec_key)
        result = db.get(hash160)
        if result is None:
            continue
        secret_exponent, public_pair, compressed = result
        binary_signature = self._create_script_signature(secret_exponent, sign_value, signature_type)
        existing_signatures.append(b2h(binary_signature))
    DUMMY_SIGNATURE = "OP_0"
    while len(existing_signatures) < self.n:
        existing_signatures.append(DUMMY_SIGNATURE)

    script = "OP_0 %s" % " ".join(s for s in existing_signatures)
    solution = tools.compile(script)
    return solution
Exemplo n.º 12
0
def solve(self, **kwargs):
    """
    The kwargs required depend upon the script type.
    hash160_lookup:
        dict-like structure that returns a secret exponent for a hash160
    existing_script:
        existing solution to improve upon (optional)
    sign_value:
        the integer value to sign (derived from the transaction hash)
    signature_type:
        usually SIGHASH_ALL (1)
    """
    # we need a hash160 => secret_exponent lookup
    db = kwargs.get("hash160_lookup")
    if db is None:
        raise SolvingError("missing hash160_lookup parameter")

    sign_value = kwargs.get("sign_value")
    signature_type = kwargs.get("signature_type")

    secs_solved = set()
    existing_signatures = []
    existing_script = kwargs.get("existing_script")
    if existing_script:
        pc = 0
        opcode, data, pc = tools.get_opcode(existing_script, pc)
        # ignore the first opcode
        while pc < len(existing_script):
            opcode, data, pc = tools.get_opcode(existing_script, pc)
            sig_pair, actual_signature_type = parse_signature_blob(data)
            for sec_key in self.sec_keys:
                try:
                    public_pair = encoding.sec_to_public_pair(sec_key)
                    sig_pair, signature_type = parse_signature_blob(data)
                    v = ecdsa.verify(ecdsa.generator_secp256k1, public_pair, sign_value, sig_pair)
                    if v:
                        existing_signatures.append(data)
                        secs_solved.add(sec_key)
                        break
                except encoding.EncodingError:
                    # if public_pair is invalid, we just ignore it
                    pass

    for sec_key in self.sec_keys:
        if sec_key in secs_solved:
            continue
        if len(existing_signatures) >= self.n:
            break
        hash160 = encoding.hash160(sec_key)
        result = db.get(hash160)
        if result is None:
            continue
        secret_exponent, public_pair, compressed = result
        binary_signature = self._create_script_signature(secret_exponent, sign_value, signature_type)
        existing_signatures.append(b2h(binary_signature))
    DUMMY_SIGNATURE = "OP_0"
    while len(existing_signatures) < self.n:
        existing_signatures.append(DUMMY_SIGNATURE)

    script = "OP_0 %s" % " ".join(s for s in existing_signatures)
    solution = tools.compile(script)
    return solution