electrum

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

commit 36ddb6838413caeca041c0c2f7073a9cc770f258
parent 9365b0f924a41284b471ba6a0521003dd76151ac
Author: SomberNight <somber.night@protonmail.com>
Date:   Thu, 14 Jun 2018 23:31:19 +0200

synchronizer.py: fix bug where synchronizer would get stuck in case of weird server behaviour

there was some kind of re-org but our reorged transactions did not get into the server's mempool for some reason (and they were not mined either). the synchronizer detected the change in address status and asked for the new address histories but in `on_address_history` it thought it did not ask for the histories.

from log:
[Synchronizer] receiving history (unsolicited) 2N6DydVfmheVM9F94G46pcUi5piyffgNBQ9 0
[Synchronizer] receiving history (unsolicited) 2Mw6LDQUzmmxCX3wouDXo2Pj4wbonJATays 0
[SPV] received an error: {'jsonrpc': '2.0', 'error': {'code': 1, 'message': 'tx hash f7c89eec3454b627dcb8cfc822202a0d1f8b38f2a53db182b607a2f61e6946d1 not in block 000000007ac4e95633a16232bea35bc17edf855e3964dff0ebb108b5887647ff at height 1,325,443'}, 'id': 120, 'method': 'blockchain.transaction.get_merkle', 'params': ['f7c89eec3454b627dcb8cfc822202a0d1f8b38f2a53db182b607a2f61e6946d1', 1325443]}

Diffstat:
Mlib/synchronizer.py | 12+++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/lib/synchronizer.py b/lib/synchronizer.py @@ -94,7 +94,10 @@ class Synchronizer(ThreadJob): addr = params[0] history = self.wallet.history.get(addr, []) if self.get_status(history) != result: - if self.requested_histories.get(addr) is None: + # note that at this point 'result' can be None; + # if we had a history for addr but now the server is telling us + # there is no history + if addr not in self.requested_histories: self.requested_histories[addr] = result self.network.request_address_history(addr, self.on_address_history) # remove addr from list only after it is added to requested_histories @@ -108,8 +111,11 @@ class Synchronizer(ThreadJob): if not params: return addr = params[0] - server_status = self.requested_histories.get(addr) - if server_status is None: + try: + server_status = self.requested_histories[addr] + except KeyError: + # note: server_status can be None even if we asked for the history, + # so it is not sufficient to test that self.print_error("receiving history (unsolicited)", addr, len(result)) return self.print_error("receiving history", addr, len(result))