예제 #1
0
 def update(self, window):
     wallet = window.wallet
     self.window = window
     if type(wallet) != Multisig_Wallet:
         return
     if self.listener is None:
         self.print_error("starting listener")
         self.listener = Listener(self)
         self.listener.start()
     elif self.listener:
         self.print_error("shutting down listener")
         self.listener.stop()
         self.listener = None
     self.keys = []
     self.cosigner_list = []
     for key, keystore in wallet.keystores.items():
         xpub = keystore.get_master_public_key()
         K = bip32.deserialize_xpub(xpub)[-1]
         _hash = bh2u(crypto.sha256d(K))
         if not keystore.is_watching_only():
             self.keys.append((key, _hash, window))
         else:
             self.cosigner_list.append((window, xpub, K, _hash))
     if self.listener:
         self.listener.set_keyhashes([t[1] for t in self.keys])
예제 #2
0
 def _make_node_path(self, xpub, address_n):
     _, depth, fingerprint, child_num, chain_code, key = deserialize_xpub(xpub)
     node = self.types.HDNodeType(
         depth=depth,
         fingerprint=int.from_bytes(fingerprint, 'big'),
         child_num=int.from_bytes(child_num, 'big'),
         chain_code=chain_code,
         public_key=key,
     )
     return self.types.HDNodePathType(node=node, address_n=address_n)
예제 #3
0
def make_billing_address(wallet, num, addr_type):
    long_id, short_id = wallet.get_user_id()
    xpub = make_xpub(get_billing_xpub(), long_id)
    version, _, _, _, c, cK = deserialize_xpub(xpub)
    cK, c = CKD_pub(cK, c, num)
    if addr_type == 'legacy':
        return bitcoin.public_key_to_p2pkh(cK)
    elif addr_type == 'segwit':
        return bitcoin.public_key_to_p2wpkh(cK)
    else:
        raise ValueError(f'unexpected billing type: {addr_type}')
예제 #4
0
def get_signing_xpub(xtype):
    if not constants.net.TESTNET:
        xpub = "xpub661MyMwAqRbcGnMkaTx2594P9EDuiEqMq25PM2aeG6UmwzaohgA6uDmNsvSUV8ubqwA3Wpste1hg69XHgjUuCD5HLcEp2QPzyV1HMrPppsL"
    else:
        xpub = "tpubD6NzVbkrYhZ4XdmyJQcCPjQfg6RXVUzGFhPjZ7uvRC8JLcS7Hw1i7UTpyhp9grHpak4TyK2hzBJrujDVLXQ6qB5tNpVx9rC6ixijUXadnmY"
    if xtype not in ('standard', 'p2wsh'):
        raise NotImplementedError('xtype: {}'.format(xtype))
    if xtype == 'standard':
        return xpub
    _, depth, fingerprint, child_number, c, cK = bip32.deserialize_xpub(xpub)
    xpub = bip32.serialize_xpub(xtype, c, cK, depth, fingerprint, child_number)
    return xpub
예제 #5
0
 def get_xpub(self, bip32_path, xtype):
     assert xtype in self.plugin.SUPPORTED_XTYPES
     reply = self._get_xpub(bip32_path)
     if reply:
         xpub = reply['xpub']
         # Change type of xpub to the requested type. The firmware
         # only ever returns the mainnet standard type, but it is agnostic
         # to the type when signing.
         if xtype != 'standard' or constants.net.TESTNET:
             _, depth, fingerprint, child_number, c, cK = deserialize_xpub(xpub, net=constants.BitcoinMainnet)
             xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number)
         return xpub
     else:
         raise Exception('no reply')
예제 #6
0
        def mitm_verify(self, sig, expect_xpub):
            # verify a signature (65 bytes) over the session key, using the master bip32 node
            # - customized to use specific EC library of Electrum.
            from electrum_exos.ecc import ECPubkey

            xtype, depth, parent_fingerprint, child_number, chain_code, K_or_k \
                = deserialize_xpub(expect_xpub)

            pubkey = ECPubkey(K_or_k)
            try:
                pubkey.verify_message_hash(sig[1:65], self.session_key)
                return True
            except:
                return False
예제 #7
0
 def get_xpub(self, bip32_path, xtype):
     assert xtype in ColdcardPlugin.SUPPORTED_XTYPES
     print_error('[coldcard]', 'Derive xtype = %r' % xtype)
     xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000)
     # TODO handle timeout?
     # change type of xpub to the requested type
     try:
         __, depth, fingerprint, child_number, c, cK = deserialize_xpub(xpub)
     except InvalidMasterKeyVersionBytes:
         raise UserFacingException(_('Invalid xpub magic. Make sure your {} device is set to the correct chain.')
                                   .format(self.device)) from None
     if xtype != 'standard':
         xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number)
     return xpub
예제 #8
0
    def __init__(self, tx, parent, desc, prompt_if_unsaved):
        '''Transactions in the wallet will show their description.
        Pass desc to give a description for txs not yet in the wallet.
        '''
        # We want to be a top-level window
        QDialog.__init__(self, parent=None)
        # Take a copy; it might get updated in the main window by
        # e.g. the FX plugin.  If this happens during or after a long
        # sign operation the signatures are lost.
        self.tx = tx = copy.deepcopy(tx)  # type: Transaction

        try:
            self.tx.deserialize()
        except BaseException as e:
            raise SerializationError(e)
        self.main_window = parent
        self.wallet = parent.wallet
        self.prompt_if_unsaved = prompt_if_unsaved
        self.saved = False
        self.desc = desc

        # store the keyhash and cosigners for current wallet
        self.keyhashes = set()
        self.cosigner_list = set()
        if type(self.wallet) == Multisig_Wallet:
            for key, keystore in self.wallet.keystores.items():
                xpub = keystore.get_master_public_key()
                K = bip32.deserialize_xpub(xpub)[-1]
                _hash = bh2u(crypto.sha256d(K))
                if not keystore.is_watching_only():
                    self.keyhashes.add(_hash)
                else:
                    self.cosigner_list.add(_hash)

        # if the wallet can populate the inputs with more info, do it now.
        # as a result, e.g. we might learn an imported address tx is segwit,
        # in which case it's ok to display txid
        tx.add_inputs_info(self.wallet)

        self.setMinimumWidth(950)
        self.setWindowTitle(_("Transaction"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        vbox.addWidget(QLabel(_("Transaction ID:")))
        self.tx_hash_e = ButtonsLineEdit()
        qr_show = lambda: parent.show_qrcode(
            str(self.tx_hash_e.text()), 'Transaction ID', parent=self)
        qr_icon = "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png"
        self.tx_hash_e.addButton(qr_icon, qr_show, _("Show as QR code"))
        self.tx_hash_e.setReadOnly(True)
        vbox.addWidget(self.tx_hash_e)
        self.tx_desc = QLabel()
        vbox.addWidget(self.tx_desc)
        self.status_label = QLabel()
        vbox.addWidget(self.status_label)
        self.date_label = QLabel()
        vbox.addWidget(self.date_label)
        self.amount_label = QLabel()
        vbox.addWidget(self.amount_label)
        self.size_label = QLabel()
        vbox.addWidget(self.size_label)
        self.fee_label = QLabel()
        vbox.addWidget(self.fee_label)

        self.add_io(vbox)

        self.sign_button = b = QPushButton(_("Sign"))
        b.clicked.connect(self.sign)

        self.broadcast_button = b = QPushButton(_("Broadcast"))
        b.clicked.connect(self.do_broadcast)

        self.save_button = b = QPushButton(_("Save"))
        save_button_disabled = not tx.is_complete()
        b.setDisabled(save_button_disabled)
        if save_button_disabled:
            b.setToolTip(SAVE_BUTTON_DISABLED_TOOLTIP)
        else:
            b.setToolTip(SAVE_BUTTON_ENABLED_TOOLTIP)
        b.clicked.connect(self.save)

        self.export_button = b = QPushButton(_("Export"))
        b.clicked.connect(self.export)

        self.cancel_button = b = QPushButton(_("Close"))
        b.clicked.connect(self.close)
        b.setDefault(True)

        self.qr_button = b = QPushButton()
        b.setIcon(read_QIcon(qr_icon))
        b.clicked.connect(self.show_qr)

        self.copy_button = CopyButton(lambda: str(self.tx), parent.app)

        # Action buttons
        self.buttons = [
            self.sign_button, self.broadcast_button, self.cancel_button
        ]
        # Transaction sharing buttons
        self.sharing_buttons = [
            self.copy_button, self.qr_button, self.export_button,
            self.save_button
        ]

        run_hook('transaction_dialog', self)

        hbox = QHBoxLayout()
        hbox.addLayout(Buttons(*self.sharing_buttons))
        hbox.addStretch(1)
        hbox.addLayout(Buttons(*self.buttons))
        vbox.addLayout(hbox)
        self.update()
예제 #9
0
def make_xpub(xpub, s):
    version, _, _, _, c, cK = deserialize_xpub(xpub)
    cK2, c2 = bip32._CKD_pub(cK, c, s)
    return serialize_xpub(version, c2, cK2)
    def __init__(self, tx, parent, desc, prompt_if_unsaved):
        '''Transactions in the wallet will show their description.
        Pass desc to give a description for txs not yet in the wallet.
        '''
        # We want to be a top-level window
        QDialog.__init__(self, parent=None)

        self.tx = tx = copy.deepcopy(tx)  # type: Transaction
        try:
            self.tx.deserialize()
        except BaseException as e:
            raise SerializationError(e)
        self.main_window = parent
        self.wallet = parent.wallet
        self.prompt_if_unsaved = prompt_if_unsaved
        self.saved = False
        self.desc = desc
        self.locks = {}
        self.currently_signing = None

        # Set timeout flag
        self.timed_out = False

        self.main_window = parent
        self.wallet = parent.wallet

        # store the keyhash and cosigners for current wallet
        self.keyhashes = set()
        self.cosigner_list = set()
        if type(self.wallet) == Multisig_Wallet:
            for key, keystore in self.wallet.keystores.items():
                xpub = keystore.get_master_public_key()
                K = bip32.deserialize_xpub(xpub)[-1]
                _hash = bh2u(crypto.sha256d(K))
                if not keystore.is_watching_only():
                    self.keyhashes.add(_hash)
                else:
                    self.cosigner_list.add(_hash)
                    self.locks[_hash] = server.get(_hash + '_lock')
                    if self.locks[_hash]:
                        name = server.get(_hash + '_name')
                        if name:
                            self.currently_signing = name

        self.setMinimumWidth(200)
        self.setWindowTitle(_("Information"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)
        self.warning = QLabel()
        vbox.addWidget(self.warning)
        warning_text = (_(
            'A transaction with the following information is currently being signed'
        ) + '\n' + _(
            'by a cosigner. A notification will appear within 30 seconds of either signing'
        ) + '\n' + _('or the transaction window expiring.'))
        self.warning.setText(warning_text)
        self.tx_desc = QLabel()
        vbox.addWidget(self.tx_desc)
        self.status_label = QLabel()
        vbox.addWidget(self.status_label)
        self.date_label = QLabel()
        vbox.addWidget(self.date_label)
        self.amount_label = QLabel()
        vbox.addWidget(self.amount_label)
        self.size_label = QLabel()
        vbox.addWidget(self.size_label)
        self.fee_label = QLabel()
        vbox.addWidget(self.fee_label)

        self.cancel_button = b = QPushButton(_("Close"))
        b.clicked.connect(self.close)
        b.setDefault(True)

        # Action buttons
        self.buttons = [self.cancel_button]

        # Add label for countdown timer
        self.time_out_label = QLabel()
        vbox.addWidget(self.time_out_label)

        run_hook('transaction_dialog', self)

        hbox = QHBoxLayout()
        hbox.addLayout(Buttons(*self.buttons))
        vbox.addLayout(hbox)

        for _hash, expire in self.locks.items():
            if expire:
                # Set time left to desired duration
                self.time_left_int = int(DURATION_INT -
                                         (int(server.get_current_time()) -
                                          int(expire)))

        self.timer_start()
        self.update()