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)
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
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()
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]