Exemple #1
0
 def mock_fork(self, bad_header):
     forkpoint = bad_header['block_height']
     b = blockchain.Blockchain(config=self.config,
                               forkpoint=forkpoint,
                               parent=None,
                               forkpoint_hash=bh2u(sha256(str(forkpoint))),
                               prev_hash=bh2u(sha256(str(forkpoint - 1))))
     return b
Exemple #2
0
 def test_mnemonic_to_seed(self):
     for test_name, test in SEED_TEST_CASES.items():
         if test.words_hex is not None:
             self.assertEqual(test.words_hex, bh2u(test.words.encode('utf8')), msg=test_name)
         self.assertTrue(is_new_seed(test.words, prefix=test.seed_version), msg=test_name)
         m = mnemonic.Mnemonic(lang=test.lang)
         if test.entropy is not None:
             self.assertEqual(test.entropy, m.mnemonic_decode(test.words), msg=test_name)
         if test.passphrase_hex is not None:
             self.assertEqual(test.passphrase_hex, bh2u(test.passphrase.encode('utf8')), msg=test_name)
         seed = mnemonic.Mnemonic.mnemonic_to_seed(mnemonic=test.words, passphrase=test.passphrase)
         self.assertEqual(test.bip32_seed, bh2u(seed), msg=test_name)
Exemple #3
0
 def gen_random_versioned_seed(cls):
     version = cls.LATEST_VERSION
     hex_seed = bh2u(os.urandom(16))
     checksum = cls.code_hashid(version + hex_seed)
     return VersionedSeed(version=version.upper(),
                          seed=hex_seed.upper(),
                          checksum=checksum.upper())
Exemple #4
0
 def update(self, window: 'ElectrumSysWindow'):
     wallet = window.wallet
     if type(wallet) != Multisig_Wallet:
         return
     assert isinstance(wallet, Multisig_Wallet)  # only here for type-hints in IDE
     if self.listener is None:
         self.logger.info("starting listener")
         self.listener = Listener(self)
         self.listener.start()
     elif self.listener:
         self.logger.info("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()  # type: str
         pubkey = BIP32Node.from_xkey(xpub).eckey.get_public_key_bytes(compressed=True)
         _hash = bh2u(crypto.sha256d(pubkey))
         if not keystore.is_watching_only():
             self.keys.append((key, _hash, window))
         else:
             self.cosigner_list.append((window, xpub, pubkey, _hash))
     if self.listener:
         self.listener.set_keyhashes([t[1] for t in self.keys])
Exemple #5
0
        def update(features):
            self.features = features
            set_label_enabled()
            bl_hash = bh2u(features.bootloader_hash)
            bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]])
            noyes = [_("No"), _("Yes")]
            endis = [_("Enable Passphrases"), _("Disable Passphrases")]
            disen = [_("Disabled"), _("Enabled")]
            setchange = [_("Set a PIN"), _("Change PIN")]

            version = "%d.%d.%d" % (features.major_version,
                                    features.minor_version,
                                    features.patch_version)
            coins = ", ".join(coin.coin_name for coin in features.coins)

            device_label.setText(features.label)
            pin_set_label.setText(noyes[features.pin_protection])
            passphrases_label.setText(disen[features.passphrase_protection])
            bl_hash_label.setText(bl_hash)
            label_edit.setText(features.label)
            device_id_label.setText(features.device_id)
            initialized_label.setText(noyes[features.initialized])
            version_label.setText(version)
            coins_label.setText(coins)
            clear_pin_button.setVisible(features.pin_protection)
            clear_pin_warning.setVisible(features.pin_protection)
            pin_button.setText(setchange[features.pin_protection])
            pin_msg.setVisible(not features.pin_protection)
            passphrase_button.setText(endis[features.passphrase_protection])
            language_label.setText(features.language)
Exemple #6
0
 def on_suggest():
     self.parent.wallet.network.start_gossip()
     nodeid = bh2u(lnworker.suggest_peer() or b'')
     if not nodeid:
         remote_nodeid.setText("")
         remote_nodeid.setPlaceholderText(
             "Please wait until the graph is synchronized to 30%, and then try again.")
     else:
         remote_nodeid.setText(nodeid)
     remote_nodeid.repaint()  # macOS hack for #6269
Exemple #7
0
 def open(self, *args, **kwargs):
     super(LightningOpenChannelDialog, self).open(*args, **kwargs)
     if self.lnaddr:
         fee = self.app.electrumsys_config.fee_per_kb()
         if not fee:
             fee = config.FEERATE_FALLBACK_STATIC_FEE
         self.amount = self.app.format_amount_and_units(self.lnaddr.amount * COIN + fee * 2)  # FIXME magic number?!
         self.pubkey = bh2u(self.lnaddr.pubkey.serialize())
     if self.msg:
         self.app.show_info(self.msg)
Exemple #8
0
 def sign_transaction(self, keystore, tx: PartialTransaction, prev_tx):
     self.prev_tx = prev_tx
     client = self.get_client(keystore)
     inputs = self.tx_inputs(tx, for_sig=True, keystore=keystore)
     outputs = self.tx_outputs(tx, keystore=keystore)
     signatures = client.sign_tx(self.get_coin_name(),
                                 inputs,
                                 outputs,
                                 lock_time=tx.locktime,
                                 version=tx.version)[0]
     signatures = [(bh2u(x) + '01') for x in signatures]
     tx.update_signatures(signatures)
 def make_htlc_item(self, i: UpdateAddHtlc,
                    direction: Direction) -> HTLCItem:
     it = HTLCItem(
         _('Sent HTLC with ID {}' if Direction.SENT ==
           direction else 'Received HTLC with ID {}').format(i.htlc_id))
     it.appendRow(
         [HTLCItem(_('Amount')),
          HTLCItem(self.format_msat(i.amount_msat))])
     it.appendRow(
         [HTLCItem(_('CLTV expiry')),
          HTLCItem(str(i.cltv_expiry))])
     it.appendRow(
         [HTLCItem(_('Payment hash')),
          HTLCItem(bh2u(i.payment_hash))])
     return it
Exemple #10
0
 def __init__(self, chan: Channel, app: 'ElectrumSysWindow', **kwargs):
     Popup.__init__(self, **kwargs)
     Logger.__init__(self)
     self.is_closed = chan.is_closed()
     self.can_be_deleted = chan.can_be_deleted()
     self.app = app
     self.chan = chan
     self.title = _('Channel details')
     self.node_id = bh2u(chan.node_id)
     self.channel_id = bh2u(chan.channel_id)
     self.funding_txid = chan.funding_outpoint.txid
     self.short_id = format_short_channel_id(chan.short_channel_id)
     self.capacity = self.app.format_amount_and_units(chan.get_capacity())
     self.state = chan.get_state_for_GUI()
     self.local_ctn = chan.get_latest_ctn(LOCAL)
     self.remote_ctn = chan.get_latest_ctn(REMOTE)
     self.local_csv = chan.config[LOCAL].to_self_delay
     self.remote_csv = chan.config[REMOTE].to_self_delay
     self.initiator = 'Local' if chan.constraints.is_initiator else 'Remote'
     feerate_kw = chan.get_latest_feerate(LOCAL)
     self.feerate = str(
         quantize_feerate(Transaction.satperbyte_from_satperkw(feerate_kw)))
     self.can_send = self.app.format_amount_and_units(
         chan.available_to_spend(LOCAL) // 1000)
     self.can_receive = self.app.format_amount_and_units(
         chan.available_to_spend(REMOTE) // 1000)
     self.is_open = chan.is_open()
     closed = chan.get_closing_height()
     if closed:
         self.closing_txid, closing_height, closing_timestamp = closed
     msg = messages.MSG_NON_TRAMPOLINE_CHANNEL_FROZEN_WITHOUT_GOSSIP
     self.warning = '' if self.app.wallet.lnworker.channel_db or self.app.wallet.lnworker.is_trampoline_peer(
         chan.node_id) else _('Warning') + ': ' + msg
     self.is_frozen_for_sending = chan.is_frozen_for_sending()
     self.is_frozen_for_receiving = chan.is_frozen_for_receiving()
     self.update_action_dropdown()
Exemple #11
0
 def sign_transaction(self, keystore, tx: PartialTransaction, prev_tx):
     prev_tx = {
         bfh(txhash): self.electrumsys_tx_to_txtype(tx)
         for txhash, tx in prev_tx.items()
     }
     client = self.get_client(keystore)
     inputs = self.tx_inputs(tx, for_sig=True, keystore=keystore)
     outputs = self.tx_outputs(tx, keystore=keystore)
     signatures, _ = client.sign_tx(
         self.get_coin_name(),
         inputs,
         outputs,
         lock_time=tx.locktime,
         version=tx.version,
         amount_unit=self.get_trezor_amount_unit(),
         prev_txes=prev_tx)
     signatures = [(bh2u(x) + '01') for x in signatures]
     tx.update_signatures(signatures)
Exemple #12
0
    def sign_transaction(
        self,
        keystore: Hardware_KeyStore,
        tx: PartialTransaction,
        wallet: Deterministic_Wallet,
    ):
        if tx.is_complete():
            return

        if self.bitbox02_device is None:
            raise Exception(
                "Need to setup communication first before attempting any BitBox02 calls"
            )

        coin = self._get_coin()
        tx_script_type = None

        # Build BTCInputType list
        inputs = []
        for txin in tx.inputs():
            my_pubkey, full_path = keystore.find_my_pubkey_in_txinout(txin)

            if full_path is None:
                raise Exception(
                    "A wallet owned pubkey was not found in the transaction input to be signed"
                )

            prev_tx = txin.utxo
            if prev_tx is None:
                raise UserFacingException(_('Missing previous tx.'))

            prev_inputs: List[bitbox02.BTCPrevTxInputType] = []
            prev_outputs: List[bitbox02.BTCPrevTxOutputType] = []
            for prev_txin in prev_tx.inputs():
                prev_inputs.append({
                    "prev_out_hash":
                    prev_txin.prevout.txid[::-1],
                    "prev_out_index":
                    prev_txin.prevout.out_idx,
                    "signature_script":
                    prev_txin.script_sig,
                    "sequence":
                    prev_txin.nsequence,
                })
            for prev_txout in prev_tx.outputs():
                prev_outputs.append({
                    "value": prev_txout.value,
                    "pubkey_script": prev_txout.scriptpubkey,
                })

            inputs.append({
                "prev_out_hash": txin.prevout.txid[::-1],
                "prev_out_index": txin.prevout.out_idx,
                "prev_out_value": txin.value_sats(),
                "sequence": txin.nsequence,
                "keypath": full_path,
                "script_config_index": 0,
                "prev_tx": {
                    "version": prev_tx.version,
                    "locktime": prev_tx.locktime,
                    "inputs": prev_inputs,
                    "outputs": prev_outputs,
                },
            })

            if tx_script_type == None:
                tx_script_type = txin.script_type
            elif tx_script_type != txin.script_type:
                raise Exception("Cannot mix different input script types")

        if tx_script_type == "p2wpkh":
            tx_script_type = bitbox02.btc.BTCScriptConfig(
                simple_type=bitbox02.btc.BTCScriptConfig.P2WPKH)
        elif tx_script_type == "p2wpkh-p2sh":
            tx_script_type = bitbox02.btc.BTCScriptConfig(
                simple_type=bitbox02.btc.BTCScriptConfig.P2WPKH_P2SH)
        elif tx_script_type in ("p2wsh-p2sh", "p2wsh"):
            if type(wallet) is Multisig_Wallet:
                tx_script_type = self.btc_multisig_config(
                    coin, full_path, wallet, tx_script_type)
            else:
                raise Exception(
                    "Can only use p2wsh-p2sh or p2wsh with multisig wallets")
        else:
            raise UserFacingException(
                "invalid input script type: {} is not supported by the BitBox02"
                .format(tx_script_type))

        # Build BTCOutputType list
        outputs = []
        for txout in tx.outputs():
            assert txout.address
            # check for change
            if txout.is_change:
                my_pubkey, change_pubkey_path = keystore.find_my_pubkey_in_txinout(
                    txout)
                outputs.append(
                    bitbox02.BTCOutputInternal(
                        keypath=change_pubkey_path,
                        value=txout.value,
                        script_config_index=0,
                    ))
            else:
                addrtype, pubkey_hash = syscoin.address_to_hash(txout.address)
                if addrtype == OnchainOutputType.P2PKH:
                    output_type = bitbox02.btc.P2PKH
                elif addrtype == OnchainOutputType.P2SH:
                    output_type = bitbox02.btc.P2SH
                elif addrtype == OnchainOutputType.WITVER0_P2WPKH:
                    output_type = bitbox02.btc.P2WPKH
                elif addrtype == OnchainOutputType.WITVER0_P2WSH:
                    output_type = bitbox02.btc.P2WSH
                else:
                    raise UserFacingException(
                        "Received unsupported output type during transaction signing: {} is not supported by the BitBox02"
                        .format(addrtype))
                outputs.append(
                    bitbox02.BTCOutputExternal(
                        output_type=output_type,
                        output_hash=pubkey_hash,
                        value=txout.value,
                    ))

        keypath_account = full_path[:-2]
        sigs = self.bitbox02_device.btc_sign(
            coin,
            [
                bitbox02.btc.BTCScriptConfigWithKeypath(
                    script_config=tx_script_type,
                    keypath=keypath_account,
                )
            ],
            inputs=inputs,
            outputs=outputs,
            locktime=tx.locktime,
            version=tx.version,
        )

        # Fill signatures
        if len(sigs) != len(tx.inputs()):
            raise Exception(
                "Incorrect number of inputs signed.")  # Should never occur
        signatures = [
            bh2u(ecc.der_sig_from_sig_string(x[1])) + "01" for x in sigs
        ]
        tx.update_signatures(signatures)
Exemple #13
0
 def test_mnemonic_to_seed_basic(self):
     # note: not a valid electrumsys seed
     seed = mnemonic.Mnemonic.mnemonic_to_seed(mnemonic='foobar', passphrase='none')
     self.assertEqual('741b72fd15effece6bfe5a26a52184f66811bd2be363190e07a42cca442b1a5bb22b3ad0eb338197287e6d314866c7fba863ac65d3f156087a5052ebc7157fce',
                      bh2u(seed))
    def __init__(self, window: 'ElectrumSysWindow', chan_id: bytes):
        super().__init__(window)

        # initialize instance fields
        self.window = window
        self.wallet = window.wallet
        chan = self.chan = window.wallet.lnworker.channels[chan_id]
        self.format_msat = lambda msat: window.format_amount_and_units(msat /
                                                                       1000)

        # connect signals with slots
        self.htlc_fulfilled.connect(self.on_htlc_fulfilled)
        self.htlc_failed.connect(self.on_htlc_failed)
        self.state_changed.connect(self.do_state_changed)
        self.htlc_added.connect(self.on_htlc_added)

        # register callbacks for updating
        util.register_callback(self.htlc_fulfilled.emit, ['htlc_fulfilled'])
        util.register_callback(self.htlc_failed.emit, ['htlc_failed'])
        util.register_callback(self.htlc_added.emit, ['htlc_added'])
        util.register_callback(self.state_changed.emit, ['channel'])

        # set attributes of QDialog
        self.setWindowTitle(_('Channel Details'))
        self.setMinimumSize(800, 400)

        # add layouts
        vbox = QtWidgets.QVBoxLayout(self)
        vbox.addWidget(QLabel(_('Remote Node ID:')))
        remote_id_e = ButtonsLineEdit(bh2u(chan.node_id))
        remote_id_e.addCopyButton(self.window.app)
        remote_id_e.setReadOnly(True)
        vbox.addWidget(remote_id_e)
        funding_label_text = f'<a href=click_destination>{chan.funding_outpoint.txid}</a>:{chan.funding_outpoint.output_index}'
        vbox.addWidget(QLabel(_('Funding Outpoint:')))
        vbox.addWidget(LinkedLabel(funding_label_text, self.show_tx))

        form_layout = QtWidgets.QFormLayout(None)
        # add form content
        form_layout.addRow(
            _('Channel ID:'),
            SelectableLabel(
                f"{chan.channel_id.hex()} (Short: {chan.short_channel_id})"))
        form_layout.addRow(_('State:'),
                           SelectableLabel(chan.get_state_for_GUI()))
        self.initiator = 'Local' if chan.constraints.is_initiator else 'Remote'
        form_layout.addRow(_('Initiator:'), SelectableLabel(self.initiator))
        self.capacity = self.window.format_amount_and_units(
            chan.get_capacity())
        form_layout.addRow(_('Capacity:'), SelectableLabel(self.capacity))
        self.can_send_label = SelectableLabel()
        self.can_receive_label = SelectableLabel()
        form_layout.addRow(_('Can send:'), self.can_send_label)
        form_layout.addRow(_('Can receive:'), self.can_receive_label)
        self.received_label = SelectableLabel()
        form_layout.addRow(_('Received:'), self.received_label)
        self.sent_label = SelectableLabel()
        form_layout.addRow(_('Sent:'), self.sent_label)
        #self.htlc_minimum_msat = SelectableLabel(str(chan.config[REMOTE].htlc_minimum_msat))
        #form_layout.addRow(_('Minimum HTLC value accepted by peer (mSAT):'), self.htlc_minimum_msat)
        #self.max_htlcs = SelectableLabel(str(chan.config[REMOTE].max_accepted_htlcs))
        #form_layout.addRow(_('Maximum number of concurrent HTLCs accepted by peer:'), self.max_htlcs)
        #self.max_htlc_value = SelectableLabel(self.window.format_amount_and_units(chan.config[REMOTE].max_htlc_value_in_flight_msat / 1000))
        #form_layout.addRow(_('Maximum value of in-flight HTLCs accepted by peer:'), self.max_htlc_value)
        self.dust_limit = SelectableLabel(
            self.window.format_amount_and_units(
                chan.config[REMOTE].dust_limit_sat))
        form_layout.addRow(_('Remote dust limit:'), self.dust_limit)
        self.remote_reserve = self.window.format_amount_and_units(
            chan.config[REMOTE].reserve_sat)
        form_layout.addRow(_('Remote reserve:'),
                           SelectableLabel(self.remote_reserve))
        vbox.addLayout(form_layout)

        # add htlc tree view to vbox (wouldn't scale correctly in QFormLayout)
        vbox.addWidget(QLabel(_('Payments (HTLCs):')))
        w = QtWidgets.QTreeView(self)
        htlc_dict = chan.get_payments()
        htlc_list = []
        for rhash, plist in htlc_dict.items():
            for htlc_with_status in plist:
                htlc_list.append(htlc_with_status)
        w.setModel(self.make_model(htlc_list))
        w.header().setSectionResizeMode(0,
                                        QtWidgets.QHeaderView.ResizeToContents)
        vbox.addWidget(w)
        vbox.addLayout(Buttons(CloseButton(self)))
        # initialize sent/received fields
        self.update()