def cosigner_can_sign(self, tx, cosigner_xpub): from electrum_sum.keystore import is_xpubkey, parse_xpubkey xpub_set = set([]) for txin in tx.inputs(): for x_pubkey in txin['x_pubkeys']: if is_xpubkey(x_pubkey): xpub, s = parse_xpubkey(x_pubkey) xpub_set.add(xpub) return cosigner_xpub in xpub_set
def tx_inputs(self, tx, xpub_path, for_sig=False): inputs = [] for txin in tx.inputs(): txinputtype = TxInputType() if txin['type'] == 'coinbase': prev_hash = b"\x00" * 32 prev_index = 0xffffffff # signed int -1 else: if for_sig: x_pubkeys = txin['x_pubkeys'] xpubs = [parse_xpubkey(x) for x in x_pubkeys] multisig = self._make_multisig(txin.get('num_sig'), xpubs, txin.get('signatures')) script_type = self.get_trezor_input_script_type( txin['type']) txinputtype = TxInputType(script_type=script_type, multisig=multisig) # find which key is mine for xpub, deriv in xpubs: if xpub in xpub_path: xpub_n = parse_path(xpub_path[xpub]) txinputtype.address_n = xpub_n + deriv break prev_hash = bfh(txin['prevout_hash']) prev_index = txin['prevout_n'] if 'value' in txin: txinputtype.amount = txin['value'] txinputtype.prev_hash = prev_hash txinputtype.prev_index = prev_index if txin.get('scriptSig') is not None: script_sig = bfh(txin['scriptSig']) txinputtype.script_sig = script_sig txinputtype.sequence = txin.get('sequence', 0xffffffff - 1) inputs.append(txinputtype) return inputs
def sign_transaction(self, tx, password): if tx.is_complete(): return # previous transactions used as inputs prev_tx = {} # path of the xpubs that are involved xpub_path = {} for txin in tx.inputs(): pubkeys, x_pubkeys = tx.get_sorted_pubkeys(txin) tx_hash = txin['prevout_hash'] if txin.get('prev_tx') is None and not Transaction.is_segwit_input( txin): raise UserFacingException( _('Offline signing with {} is not supported for legacy inputs.' ).format(self.device)) prev_tx[tx_hash] = txin['prev_tx'] for x_pubkey in x_pubkeys: if not is_xpubkey(x_pubkey): continue xpub, s = parse_xpubkey(x_pubkey) if xpub == self.get_master_public_key(): xpub_path[xpub] = self.get_derivation() self.plugin.sign_transaction(self, tx, prev_tx, xpub_path)
def f(x_pubkey): xpub, s = parse_xpubkey(x_pubkey) return self._make_node_path(xpub, s)
def tx_inputs(self, tx, for_sig=False): inputs = [] for txin in tx.inputs(): txinputtype = self.types.TxInputType() if txin['type'] == 'coinbase': prev_hash = b"\x00" * 32 prev_index = 0xffffffff # signed int -1 else: if for_sig: x_pubkeys = txin['x_pubkeys'] if len(x_pubkeys) == 1: x_pubkey = x_pubkeys[0] xpub, s = parse_xpubkey(x_pubkey) xpub_n = self.client_class.expand_path( self.xpub_path[xpub]) txinputtype.address_n.extend(xpub_n + s) txinputtype.script_type = self.get_keepkey_input_script_type( txin['type']) else: def f(x_pubkey): xpub, s = parse_xpubkey(x_pubkey) return self._make_node_path(xpub, s) pubkeys = list(map(f, x_pubkeys)) multisig = self.types.MultisigRedeemScriptType( pubkeys=pubkeys, signatures=map(lambda x: bfh(x)[:-1] if x else b'', txin.get('signatures')), m=txin.get('num_sig'), ) script_type = self.get_keepkey_input_script_type( txin['type']) txinputtype = self.types.TxInputType( script_type=script_type, multisig=multisig) # find which key is mine for x_pubkey in x_pubkeys: if is_xpubkey(x_pubkey): xpub, s = parse_xpubkey(x_pubkey) if xpub in self.xpub_path: xpub_n = self.client_class.expand_path( self.xpub_path[xpub]) txinputtype.address_n.extend(xpub_n + s) break prev_hash = unhexlify(txin['prevout_hash']) prev_index = txin['prevout_n'] if 'value' in txin: txinputtype.amount = txin['value'] txinputtype.prev_hash = prev_hash txinputtype.prev_index = prev_index if txin.get('scriptSig') is not None: script_sig = bfh(txin['scriptSig']) txinputtype.script_sig = script_sig txinputtype.sequence = txin.get('sequence', 0xffffffff - 1) inputs.append(txinputtype) return inputs