electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 2fcdd458b3af68b46fd9e7b2f42921c924b9ba9a
parent e6560b8d7f9977bd1b97fdfbd505890faaa20932
Author: ThomasV <thomasv@electrum.org>
Date:   Mon, 27 Mar 2017 12:48:10 +0200

add checkpoint dialog to the kivy gui

Diffstat:
Agui/kivy/uix/dialogs/checkpoint_dialog.py | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mgui/kivy/uix/dialogs/settings.py | 22++++++++++++++++++++++
Mgui/qt/network_dialog.py | 6++----
Mlib/blockchain.py | 16++++++++++++++--
4 files changed, 124 insertions(+), 6 deletions(-)

diff --git a/gui/kivy/uix/dialogs/checkpoint_dialog.py b/gui/kivy/uix/dialogs/checkpoint_dialog.py @@ -0,0 +1,86 @@ +from kivy.app import App +from kivy.factory import Factory +from kivy.properties import ObjectProperty +from kivy.lang import Builder + + + +Builder.load_string(''' +#:import _ electrum_gui.kivy.i18n._ + +<CheckpointDialog@Popup> + id: popup + cp_height: 0 + cp_value: '' + title: _('Checkpoint') + size_hint: 0.8, 0.8 + pos_hint: {'top':0.9} + BoxLayout: + orientation: 'vertical' + Label: + id: description + text: 'In the event of a blockchain fork, a checkpoint can be used to ensure that you are on the correct blockchain.' + halign: 'left' + text_size: self.width, None + size: self.texture_size + BoxLayout: + orientation: 'horizontal' + size_hint: 1, 0.2 + Label: + text: _('Height') + height: '48dp' + TextInput: + id: height_input + text: '%d'%root.cp_height + on_focus: root.on_height_str() + TopLabel: + text: _('Block hash') + ':' + TxHashLabel: + data: root.cp_value + Label: + text: 'Edit the height to fetch a checkpoint from your main server, and check its value from independent sources.' + halign: 'left' + text_size: self.width, None + size: self.texture_size + Widget: + size_hint: 1, 0.3 + BoxLayout: + orientation: 'horizontal' + size_hint: 1, 0.2 + Button: + text: _('Cancel') + size_hint: 0.5, None + height: '48dp' + on_release: popup.dismiss() + Button: + text: _('OK') + size_hint: 0.5, None + height: '48dp' + on_release: + root.callback(root.cp_height, root.cp_value) + popup.dismiss() +''') + +class CheckpointDialog(Factory.Popup): + def __init__(self, network, callback): + Factory.Popup.__init__(self) + self.network = network + self.cp_height, self.cp_value = self.network.blockchain.get_checkpoint() + self.callback = callback + + def on_height_str(self): + try: + new_height = int(self.ids.height_input.text) + except: + new_height = 0 + if new_height == self.cp_height: + return + try: + header = self.network.synchronous_get(('blockchain.block.get_header', [new_height]), 5) + new_value = self.network.blockchain.hash_header(header) + except BaseException as e: + self.network.print_error(str(e)) + new_value = '' + if new_value: + self.cp_height = new_height + self.cp_value = new_value diff --git a/gui/kivy/uix/dialogs/settings.py b/gui/kivy/uix/dialogs/settings.py @@ -113,6 +113,12 @@ Builder.load_string(''' title: _('Coin selection') + ': ' + self.status description: "Coin selection method" action: partial(root.coinselect_dialog, self) + CardSeparator + SettingsItem: + status: root.checkpoint_status() + title: _('Checkpoint') + ': ' + self.status + description: _("Configure blockchain checkpoint") + action: partial(root.checkpoint_dialog, self) ''') @@ -134,6 +140,7 @@ class SettingsDialog(Factory.Popup): self._language_dialog = None self._unit_dialog = None self._coinselect_dialog = None + self._checkpoint_dialog = None def update(self): self.wallet = self.app.wallet @@ -177,6 +184,21 @@ class SettingsDialog(Factory.Popup): self._coinselect_dialog = ChoiceDialog(_('Coin selection'), choosers, chooser_name, cb) self._coinselect_dialog.open() + def checkpoint_status(self): + height, value = self.app.network.blockchain.get_checkpoint() + return "Block %d"% height if height else _("Genesis block") + + def checkpoint_dialog(self, item, dt): + from checkpoint_dialog import CheckpointDialog + if self._checkpoint_dialog is None: + def callback(height, value): + if value: + self.app.network.blockchain.set_checkpoint(height, value) + item.status = self.checkpoint_status() + + self._checkpoint_dialog = CheckpointDialog(self.app.network, callback) + self._checkpoint_dialog.open() + def network_dialog(self, item, dt): if self._network_dialog is None: server, port, protocol, proxy, auto_connect = self.app.network.get_parameters() diff --git a/gui/qt/network_dialog.py b/gui/qt/network_dialog.py @@ -192,8 +192,7 @@ class NetworkChoiceLayout(object): n = len(network.get_interfaces()) status = _("Connected to %d nodes.")%n if n else _("Not connected") height_str = "%d "%(network.get_local_height()) + _("blocks") - self.checkpoint_height = self.config.get('checkpoint_height', 0) - self.checkpoint_value = self.config.get('checkpoint_value', bitcoin.GENESIS) + self.checkpoint_height, self.checkpoint_value = network.blockchain.get_checkpoint() self.cph_label = QLabel(_('Height')) self.cph = QLineEdit("%d"%self.checkpoint_height) self.cph.setFixedWidth(80) @@ -337,8 +336,7 @@ class NetworkChoiceLayout(object): auto_connect = self.autoconnect_cb.isChecked() self.network.set_parameters(host, port, protocol, proxy, auto_connect) - self.config.set_key('checkpoint_height', self.checkpoint_height) - self.config.set_key('checkpoint_value', self.checkpoint_value) + self.network.blockchain.set_checkpoint(self.checkpoint_height, self.checkpoint_value) def suggest_proxy(self, found_proxy): self.tor_proxy = found_proxy diff --git a/lib/blockchain.py b/lib/blockchain.py @@ -37,8 +37,7 @@ class Blockchain(util.PrintError): def __init__(self, config, network): self.config = config self.network = network - self.checkpoint_height = self.config.get('checkpoint_height', 0) - self.checkpoint_hash = self.config.get('checkpoint_value', bitcoin.GENESIS) + self.checkpoint_height, self.checkpoint_hash = self.get_checkpoint() self.check_truncate_headers() self.set_local_height() @@ -189,6 +188,7 @@ class Blockchain(util.PrintError): return if self.hash_header(checkpoint) == self.checkpoint_hash: return + self.print_error('checkpoint mismatch:', self.hash_header(checkpoint), self.checkpoint_hash) self.print_error('Truncating headers file at height %d'%self.checkpoint_height) name = self.path() f = open(name, 'rb+') @@ -274,3 +274,15 @@ class Blockchain(util.PrintError): except BaseException as e: self.print_error('verify_chunk failed', str(e)) return idx - 1 + + def get_checkpoint(self): + height = self.config.get('checkpoint_height', 0) + value = self.config.get('checkpoint_value', bitcoin.GENESIS) + return (height, value) + + def set_checkpoint(self, height, value): + self.checkpoint_height = height + self.checkpoint_hash = value + self.config.set_key('checkpoint_height', height) + self.config.set_key('checkpoint_value', value) + self.check_truncate_headers()