def multisig_script(cls, m, pubkeys): '''Returns the script for a pay-to-multisig transaction.''' n = len(pubkeys) if not 1 <= m <= n <= 15: raise ScriptError( '{:d} of {:d} multisig script not possible'.format(m, n)) for pubkey in pubkeys: PublicKey.from_bytes(pubkey) # Can be compressed or not # See https://bitcoin.org/en/developer-guide # 2 of 3 is: OP_2 pubkey1 pubkey2 pubkey3 OP_3 OP_CHECKMULTISIG return (bytes([Ops.OP_1 + m - 1]) + b''.join(cls.push_data(pubkey) for pubkey in pubkeys) + bytes([Ops.OP_1 + n - 1, Ops.OP_CHECKMULTISIG]))
def get_master_public_key(self, bip32_path): self.checkDevice() # bip32_path is of the form 44'/0'/1' # S-L-O-W - we don't handle the fingerprint directly, so compute # it manually from the previous node # This only happens once so it's bearable #self.get_client() # prompt for the PIN before displaying the dialog if necessary #self.handler.show_message("Computing master public key") splitPath = bip32_path.split('/') if splitPath[0] == 'm': splitPath = splitPath[1:] bip32_path = bip32_path[2:] fingerprint = 0 if len(splitPath) > 1: prevPath = "/".join(splitPath[0:len(splitPath) - 1]) nodeData = self.dongleObject.getWalletPublicKey(prevPath) publicKey = compress_public_key(nodeData['publicKey']) h = hashlib.new('ripemd160') h.update(hashlib.sha256(publicKey).digest()) fingerprint = unpack(">I", h.digest()[0:4])[0] nodeData = self.dongleObject.getWalletPublicKey(bip32_path) publicKey = bytes(compress_public_key(nodeData['publicKey'])) depth = len(splitPath) lastChild = splitPath[len(splitPath) - 1].split('\'') childnum = int(lastChild[0]) if len( lastChild) == 1 else 0x80000000 | int(lastChild[0]) derivation = BIP32Derivation( chain_code=nodeData['chainCode'], depth=depth, parent_fingerprint=pack_be_uint32(fingerprint), n=childnum) return BIP32PublicKey(PublicKey.from_bytes(publicKey), derivation, Net.COIN)
def do_send(self, window: 'ElectrumWindow', account: AbstractAccount, tx: Transaction) -> None: def on_done(window, future): try: future.result() except Exception as exc: window.on_exception(exc) else: window.show_message('\n'.join(( _("Your transaction was sent to the cosigning pool."), _("Open your cosigner wallet to retrieve it."), ))) def send_message(): server.put(item.keyhash_hex, message) account_id = account.get_id() for item in self._items: if self._is_theirs(window, account_id, item, tx): raw_tx_bytes = json.dumps(tx.to_dict()).encode() public_key = PublicKey.from_bytes(item.pubkey_bytes) message = public_key.encrypt_message_to_base64(raw_tx_bytes) WaitingDialog(item.window, _('Sending transaction to cosigning pool...'), send_message, on_done=partial(on_done, item.window))
def from_pubkey(cls, pubkey): '''Returns a P2PKH address from a public key. The public key can be bytes or a hex string.''' if isinstance(pubkey, str): pubkey = PublicKey.from_hex(pubkey) else: pubkey = PublicKey.from_bytes(pubkey) return cls(hash_160(pubkey.to_bytes()), cls.ADDR_P2PKH)
def to_public_key(self) -> Union[BIP32PublicKey, PublicKey]: '''Returns a PublicKey instance or an Address instance.''' kind = self.kind() if self._pubkey_bytes is not None: return PublicKey.from_bytes(self._pubkey_bytes) elif self._bip32_xpub is not None: assert self._derivation_path is not None result = bip32_key_from_string(self._bip32_xpub) for n in self._derivation_path: result = result.child(n) return result elif self._old_mpk is not None: assert self._derivation_path is not None path = self._derivation_path pubkey = PublicKey.from_bytes(pack_byte(4) + self._old_mpk) # pylint: disable=unsubscriptable-object delta = double_sha256(f'{path[1]}:{path[0]}:'.encode() + self._old_mpk) return pubkey.add(delta) raise ValueError("invalid key data")
def test_signatures(filename): tx, values, pk_scripts = read_json_tx(filename) for input_index, (value, pk_script, txin) in enumerate(zip(values, pk_scripts, tx.inputs)): signature, pubkey = txin.script_sig.ops() pubkey = PublicKey.from_bytes(pubkey) signature_hash = tx.signature_hash(input_index, value, pk_script, SigHash(signature[-1])) assert pubkey.verify_der_signature(signature[:-1], signature_hash, None)
def get_master_public_key(self, bip32_path, creating=False): address_n = bip32_decompose_chain_string(bip32_path) with self.run_flow(creating_wallet=creating): node = trezorlib.btc.get_public_node(self.client, address_n).node self.used() derivation = BIP32Derivation(chain_code=node.chain_code, depth=node.depth, parent_fingerprint=pack_be_uint32( node.fingerprint), n=node.child_num) return BIP32PublicKey(PublicKey.from_bytes(node.public_key), derivation, Net.COIN)
def get_master_public_key(self, bip32_path): address_n = bip32_decompose_chain_string(bip32_path) creating = False node = self.get_public_node(address_n, creating).node self.used() derivation = BIP32Derivation(chain_code=node.chain_code, depth=node.depth, parent_fingerprint=pack_be_uint32( node.fingerprint), n=node.child_num) return BIP32PublicKey(PublicKey.from_bytes(node.public_key), derivation, Net.COIN)
def to_public_key(self): '''Returns a PublicKey instance or an Address instance.''' kind = self.kind() if kind in {0x02, 0x03, 0x04}: return PublicKey.from_bytes(self.raw) if kind == 0xff: return self._bip32_public_key() if kind == 0xfe: return self._old_keystore_public_key() assert kind == 0xfd result = classify_output_script(Script(self.raw[1:]), Net.COIN) assert isinstance(result, Address) return result
def get_master_public_key(self, bip32_path: str, creating: bool = False) -> BIP32PublicKey: address_n = bip32_decompose_chain_string(bip32_path) # This will be cleared by the wrapper around `get_public_node`. self.creating_wallet = creating node = self.get_public_node(address_n).node self.used() derivation = BIP32Derivation(chain_code=node.chain_code, depth=node.depth, parent_fingerprint=pack_be_uint32( node.fingerprint), n=node.child_num) return BIP32PublicKey(PublicKey.from_bytes(node.public_key), derivation, Net.COIN)
def do_send(self, wallet, tx): def on_done(window, future): try: future.result() except Exception as exc: window.on_exception(exc) else: window.show_message('\n'.join(( _("Your transaction was sent to the cosigning pool."), _("Open your cosigner wallet to retrieve it."), ))) def send_message(): server.put(item.hash, message) for item in self.items: if self.is_theirs(wallet, item, tx): raw_tx_bytes = bfh(str(tx)) public_key = PublicKey.from_bytes(item.K) message = public_key.encrypt_message_to_base64(raw_tx_bytes) WaitingDialog(item.window, _('Sending transaction to cosigning pool...'), send_message, on_done=partial(on_done, item.window))
def get_address_from_output_script(_bytes): decoded = [x for x in _script_GetOp(_bytes)] # The Genesis Block, self-payments, and pay-by-IP-address payments look like: # 65 BYTES:... CHECKSIG match = [Ops.OP_PUSHDATA4, Ops.OP_CHECKSIG] if _match_decoded(decoded, match): return TYPE_PUBKEY, PublicKey.from_bytes(bytes(decoded[0][1])) # Pay-by-Bitcoin-address TxOuts look like: # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG match = [ Ops.OP_DUP, Ops.OP_HASH160, Ops.OP_PUSHDATA4, Ops.OP_EQUALVERIFY, Ops.OP_CHECKSIG ] if _match_decoded(decoded, match): return TYPE_ADDRESS, Address.from_P2PKH_hash(decoded[2][1]) # p2sh match = [Ops.OP_HASH160, Ops.OP_PUSHDATA4, Ops.OP_EQUAL] if _match_decoded(decoded, match): return TYPE_ADDRESS, Address.from_P2SH_hash(decoded[1][1]) return TYPE_SCRIPT, ScriptOutput(bytes(_bytes))
read_le_uint32, read_le_int32, read_le_int64, read_list, read_varbytes, unpack_le_uint16, ) from .bitcoin import ScriptTemplate from .constants import ScriptType from .logs import logs from .networks import Net from .script import AccumulatorMultiSigOutput NO_SIGNATURE = b'\xff' dummy_public_key = PublicKey.from_bytes(bytes(range(3, 36))) dummy_signature = bytes(72) logger = logs.get_logger("transaction") def classify_tx_output(tx_output: TxOutput) -> ScriptTemplate: # This returns a P2PKH_Address, P2SH_Address, P2PK_Output, OP_RETURN_Output, # P2MultiSig_Output or Unknown_Output return classify_output_script(tx_output.script_pubkey, Net.COIN) def tx_output_to_display_text(tx_output: TxOutput): kind = classify_tx_output(tx_output) if isinstance(kind, Address): text = kind.to_string()
def _old_keystore_public_key(self): mpk, path = self.old_keystore_mpk_and_path() mpk = PublicKey.from_bytes(pack_byte(4) + mpk) delta = double_sha256(f'{path[1]}:{path[0]}:'.encode() + self.raw[1:65]) return mpk.add(delta)