Skip to content

Commit

Permalink
electrum plugin: Automatically enable --skipmerklecheck and --electru…
Browse files Browse the repository at this point in the history
…m-skip-merkle

For better out-of-the-box pruning support, and to save some resources.

This also changes the way the server/oneserver/skipmerklecheck settings
are set, to reduce the risk of accidentally connecting to public servers
with inappropriate settings:

- The configurations are no longer persisted to the config file and will
  get lost on restart, unless the plugin explicitly re-enables them.

- The GUI for changing servers is disabled while the plugin is active,
  preventing the user from switching servers with the settings still on.
  • Loading branch information
shesek committed Jun 14, 2020
1 parent f868aca commit e6a3399
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 16 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

## Unreleased

- Electrum: Implement `--electrum-skip-merkle` to avoid generating SPV proofs entirely, even when it's possible. (#34)
- Electrum server: Implement `--electrum-skip-merkle` to save some resources by not generating SPV proofs entirely, even when it's possible. (#34)

- Electrum plugin: Automatically enable `--skipmerklecheck` and `--electrum-skip-merkle`, for better out-of-the-box pruning support and to save some resources. (#34)

- Indexer: Use `listsinceblock` instead of `listtransactions`. This makes syncing more bandwidth-efficient and simplifies the implementation. (#33)

- Electrum server: Optimize dispatching notifications to subscribers.

## 0.1.3 - 2020-06-02

- Electrum: Use dummy SPV proofs to support pruning with the `--skipmerklecheck` option.
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,9 @@ You can use bwt with pruning, but:

2. Electrum needs to be run with `--skipmerklecheck` to tolerate missing SPV proofs for transactions in pruned blocks.

If you're running Electrum with `--skipmerklecheck`, you may also configure bwt with `--electrum-skip-merkle` to save some resource by not generating SPV proofs even when it's possible.
> If you're running Electrum with `--skipmerklecheck`, you may also configure bwt with `--electrum-skip-merkle` to save some resources by not generating SPV proofs even when it's possible.
>
> Both of these settings are automatically enabled when using the Electrum plugin.
### Real-time indexing

Expand Down
58 changes: 44 additions & 14 deletions contrib/electrum-plugin/bwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
bwt_bin = '%s.exe' % bwt_bin

class BwtPlugin(BasePlugin):
wallets = set()
proc = None
prev_settings = None

def __init__(self, parent, config, name):
BasePlugin.__init__(self, parent, config, name)
self.proc = None
self.wallets = set()

self.enabled = config.get('bwt_enabled')
self.bitcoind_url = config.get('bwt_bitcoind_url', default_bitcoind_url())
Expand All @@ -36,22 +37,24 @@ def __init__(self, parent, config, name):
self.socket_path = config.get('bwt_socket_path', default_socket_path())
self.verbose = config.get('bwt_verbose', 0)

if config.get('bwt_was_oneserver') is None:
config.set_key('bwt_was_oneserver', config.get('oneserver'))

self.start()
if self.enabled:
self.set_config()
self.start()

def start(self):
if not self.enabled or not self.wallets:
return

self.stop()

self.rpc_port = free_port()

args = [
'--network', get_network_name(),
'--bitcoind-url', self.bitcoind_url,
'--bitcoind-dir', self.bitcoind_dir,
'--electrum-rpc-addr', '127.0.0.1:%d' % self.rpc_port,
'--electrum-skip-merkle',
]

if self.bitcoind_cred:
Expand All @@ -74,8 +77,9 @@ def start(self):
# XXX this doesn't support arguments with spaces. thankfully bwt doesn't currently have any.
args.extend(self.custom_opt.split(' '))

self.stop()
_logger.info('Starting bwt daemon')
self.set_config()

_logger.info('Starting the bwt daemon')
_logger.debug('bwt options: %s' % ' '.join(args))

if platform.system() == 'Windows':
Expand All @@ -91,12 +95,34 @@ def start(self):

def stop(self):
if self.proc:
_logger.info('Stopping bwt daemon')
_logger.info('Stopping the bwt daemon')
self.proc.terminate()
self.proc = None
self.thread = None

# enable oneserver/skipmerklecheck and disable manual server selection
def set_config(self):
if self.prev_settings: return # run once

self.prev_settings = { setting: self.config.cmdline_options.get(setting)
for setting in [ 'oneserver', 'skipmerklecheck', 'server' ] }

# setting `oneserver`/`skipmerklecheck` directly on `cmdline_options` keeps the settings in-memory only without
# persisting them to the config file, reducing the chance of accidentally leaving them on with public servers.
self.config.cmdline_options['oneserver'] = True

# for `skipmerklecheck`, this is also the only way to set it an runtime prior to v4 (see https://github.com/spesmilo/electrum/commit/61ccc1ccd3a437d98084089f1d4014ba46c96e3b)
self.config.cmdline_options['skipmerklecheck'] = True

# set a dummy server so electrum won't attempt connecting to other servers on startup. setting this
# in `cmdline_options` also prevents the user from switching servers using the gui, which further reduces
# the chance of accidentally connecting to public servers with inappropriate settings.
self.config.cmdline_options['server'] = '127.0.0.1:1:t'

def set_server(self):
# first, remove the `server` config to allow `set_parameters()` below to update it and trigger the connection mechanism
del self.config.cmdline_options['server']

network = Network.get_instance()
net_params = network.get_parameters()._replace(
host='127.0.0.1',
Expand All @@ -106,6 +132,9 @@ def set_server(self):
)
network.run_from_another_thread(network.set_parameters(net_params))

# now set the server in `cmdline_options` to lock it in
self.config.cmdline_options['server'] = '127.0.0.1:%s:t' % self.rpc_port

@hook
def load_wallet(self, wallet, main_window):
if wallet.get_master_public_keys():
Expand All @@ -126,11 +155,12 @@ def close(self):
BasePlugin.close(self)
self.stop()

# restore the user's previous oneserver setting when the plugin is disabled
was_oneserver = self.config.get('bwt_was_oneserver')
if was_oneserver is not None:
self.config.set_key('oneserver', was_oneserver)
self.config.set_key('bwt_was_oneserver', None)
# restore the user's previous settings when the plugin is disabled
if self.prev_settings:
for setting, prev_value in self.prev_settings.items():
if prev_value is None: self.config.cmdline_options.pop(setting, None)
else: self.config.cmdline_options[setting] = prev_value
self.prev_settings = None

def handle_log(self, level, pkg, msg):
if msg.startswith('Electrum RPC server running'):
Expand Down

0 comments on commit e6a3399

Please sign in to comment.