예제 #1
0
def pubkeys_to_multisig_p2sh(pubkeys: Sequence[str], m: int) -> str:
    """

    :param pubkeys: List of publics keys, as hexadecimal strings.
        The keys will be sorted.
    :param m: Minimal number of signatures to unlock the multisig script
        (it is the M in M-of-N)
    :return: p2sh CashAddr
    """
    pubkeys_bytes = [bytes.fromhex(pubkey) for pubkey in pubkeys]
    redeem_script = Script.multisig_script(m, sorted(pubkeys_bytes))
    fmt = Address.FMT_CASHADDR_BCH
    return Address.from_multisig_script(redeem_script).to_full_string(fmt)
예제 #2
0
def validate_op_return_output_and_get_data(
    output: tuple,  # tuple(typ, 'address', amount)
    max_size: int = 220,  # in bytes
    max_pushes:
    int = 1  # number of pushes supported after the OP_RETURN, most HW wallets support only 1 push, some more than 1.  Specify None to omit the number-of-pushes check.
) -> bytes:  # will return address.script[2:] (everyting after the first OP_RETURN & PUSH bytes)
    _type, address, _amount = output

    if max_pushes is None:
        # Caller says "no limit", so just to keep the below code simple, we
        # do this and effectively sets the limit on pushes to "unlimited",
        # since there can never be more pushes than bytes in the payload!
        max_pushes = max_size

    assert max_pushes >= 1

    if _type != TYPE_SCRIPT:
        raise Exception("Unexpected output type: {}".format(_type))

    ops = Script.get_ops(address.script)

    num_pushes = len(ops) - 1

    if len(ops) < 1 or ops[0][0] != OpCodes.OP_RETURN:
        raise RuntimeError(_("Only OP_RETURN scripts are supported."))

    if num_pushes < 1 or num_pushes > max_pushes or any(
            ops[i + 1][1] is None for i in range(num_pushes)):
        raise RuntimeError(
            ngettext("OP_RETURN is limited to {max_pushes} data push.",
                     "OP_RETURN is limited to {max_pushes} data pushes.",
                     max_pushes).format(max_pushes=max_pushes))

    data = address.script[
        2:]  # caller expects everything after the OP_RETURN and PUSHDATA op

    if len(data) > max_size:
        raise RuntimeError(
            _("OP_RETURN data size exceeds the maximum of {} bytes.".format(
                max_size)))

    if _amount != 0:
        raise RuntimeError(_("Amount for OP_RETURN output must be zero."))

    return data
예제 #3
0
 def __init__(self, contract_tuple_list, keypairs, public_keys, wallet):
     self.contract_tuple_list = contract_tuple_list
     self.contract_index = 0
     self.chosen_utxo = 0
     self.tx = contract_tuple_list[self.contract_index][UTXO][
         self.chosen_utxo]
     self.contract = contract_tuple_list[self.contract_index][CONTRACT]
     self.mode = contract_tuple_list[self.contract_index][MODE][0]
     self.keypair = keypairs
     self.pubkeys = public_keys
     self.wallet = wallet
     self.dummy_scriptsig = '00' * (110 + len(self.contract.redeemscript))
     self.version = self.contract.version
     self.script_pub_key = Script.P2SH_script(
         self.contract.address.hash160).hex()
     self.sequence = 0
     self.value = int(self.tx.get('value'))
     self.txin = dict()
예제 #4
0
def validate_op_return_output_and_get_data(output, max_size=220) -> bytes:
    _type, address, _amount = output

    if _type != TYPE_SCRIPT:
        raise Exception("Unexpected output type: {}".format(_type))

    ops = Script.get_ops(address.script)

    if len(ops) < 1 or ops[0][0] != OpCodes.OP_RETURN:
        raise RuntimeError(_("Only OP_RETURN scripts are supported."))

    if len(ops) != 2 or ops[1][1] is None:
        raise RuntimeError(_("OP_RETURN is limited to a single data push."))

    if len(ops[1][1]) > max_size:
        raise RuntimeError(
            _("OP_RETURN data size exceeds the maximum of {} bytes.".format(
                max_size)))

    if _amount != 0:
        raise RuntimeError(_("Amount for OP_RETURN output must be zero."))

    return ops[1][1]