From 79de458101d81afa7d5eb7a6e0d23bd2b99204d4 Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Thu, 7 May 2015 08:52:34 +0900 Subject: [PATCH] Preparation for moving the set of verified and unverified txs to the wallet. The verifier will retain responsibility for verification, but will no longer hold the transaction sets itself. Change requires_fee to take a wallet. Add new function add_unverified_tx() Move get_confirmations() to the wallet from the verifier. --- gui/gtk.py | 4 +-- gui/qt/main_window.py | 2 +- gui/qt/transaction_dialog.py | 2 +- lib/transaction.py | 4 +-- lib/verifier.py | 33 +-------------------- lib/wallet.py | 57 ++++++++++++++++++++++++++++-------- scripts/merchant/merchant.py | 2 +- 7 files changed, 52 insertions(+), 52 deletions(-) diff --git a/gui/gtk.py b/gui/gtk.py index e18ff717..8688ffe1 100644 --- a/gui/gtk.py +++ b/gui/gtk.py @@ -813,7 +813,7 @@ class ElectrumWindow: self.show_message(str(e)) return - if tx.requires_fee(self.wallet.verifier) and fee < MIN_RELAY_TX_FEE: + if tx.requires_fee(self.wallet) and fee < MIN_RELAY_TX_FEE: self.show_message( "This transaction requires a higher fee, or it will not be propagated by the network." ) return @@ -1200,7 +1200,7 @@ class ElectrumWindow: tx = self.wallet.transactions.get(tx_hash) tx.deserialize() is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx) - conf, timestamp = self.wallet.verifier.get_confirmations(tx_hash) + conf, timestamp = self.wallet.get_confirmations(tx_hash) if timestamp: time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3] diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py index 096d098d..85e2e291 100644 --- a/gui/qt/main_window.py +++ b/gui/qt/main_window.py @@ -1121,7 +1121,7 @@ class ElectrumWindow(QMainWindow): self.show_message(str(e)) return - if tx.get_fee() < MIN_RELAY_TX_FEE and tx.requires_fee(self.wallet.verifier): + if tx.get_fee() < MIN_RELAY_TX_FEE and tx.requires_fee(self.wallet): QMessageBox.warning(self, _('Error'), _("This transaction requires a higher fee, or it will not be propagated by the network."), _('OK')) return diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py index 3026e510..9a219ca9 100644 --- a/gui/qt/transaction_dialog.py +++ b/gui/qt/transaction_dialog.py @@ -149,7 +149,7 @@ class TxDialog(QDialog): status = _("Signed") if tx_hash in self.wallet.transactions.keys(): - conf, timestamp = self.wallet.verifier.get_confirmations(tx_hash) + conf, timestamp = self.wallet.get_confirmations(tx_hash) if timestamp: time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3] else: diff --git a/lib/transaction.py b/lib/transaction.py index badaf283..0c4d0d5c 100644 --- a/lib/transaction.py +++ b/lib/transaction.py @@ -769,7 +769,7 @@ class Transaction: return out - def requires_fee(self, verifier): + def requires_fee(self, wallet): # see https://en.bitcoin.it/wiki/Transaction_fees # # size must be smaller than 1 kbyte for free tx @@ -784,7 +784,7 @@ class Transaction: threshold = 57600000 weight = 0 for txin in self.inputs: - age = verifier.get_confirmations(txin["prevout_hash"])[0] + age = wallet.get_confirmations(txin["prevout_hash"])[0] weight += txin["value"] * age priority = weight / size print_error(priority, threshold) diff --git a/lib/verifier.py b/lib/verifier.py index 13dfb014..87141e71 100644 --- a/lib/verifier.py +++ b/lib/verifier.py @@ -36,41 +36,10 @@ class SPV(util.DaemonThread): self.network = network self.transactions = {} # requested verifications (with height sent by the requestor) self.verified_tx = storage.get('verified_tx3',{}) # height, timestamp of verified transactions - self.merkle_roots = storage.get('merkle_roots',{}) # hashed by me + self.merkle_roots = {} # hashed by me self.lock = threading.Lock() self.queue = Queue.Queue() - def get_confirmations(self, tx): - """ return the number of confirmations of a monitored transaction. """ - with self.lock: - if tx in self.verified_tx: - height, timestamp, pos = self.verified_tx[tx] - conf = (self.network.get_local_height() - height + 1) - if conf <= 0: timestamp = None - elif tx in self.transactions: - conf = -1 - timestamp = None - else: - conf = 0 - timestamp = None - - return conf, timestamp - - - def get_txpos(self, tx_hash): - "return position, even if the tx is unverified" - with self.lock: - x = self.verified_tx.get(tx_hash) - y = self.transactions.get(tx_hash) - if x: - height, timestamp, pos = x - return height, pos - elif y: - return y, 0 - else: - return 1e12, 0 - - def get_height(self, tx_hash): with self.lock: v = self.verified_tx.get(tx_hash) diff --git a/lib/wallet.py b/lib/wallet.py index 199206e8..6d684b77 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -387,6 +387,41 @@ class Abstract_Wallet(object): decrypted = ec.decrypt_message(message) return decrypted + def add_unverified_tx(self, tx_hash, tx_height): + if self.verifier and tx_height > 0: + self.verifier.add(tx_hash, tx_height) + + def get_confirmations(self, tx): + """ return the number of confirmations of a monitored transaction. """ + if not self.verifier: + return (None, None) + with self.verifier.lock: + if tx in self.verifier.verified_tx: + height, timestamp, pos = self.verifier.verified_tx[tx] + conf = (self.network.get_local_height() - height + 1) + if conf <= 0: timestamp = None + elif tx in self.verifier.transactions: + conf = -1 + timestamp = None + else: + conf = 0 + timestamp = None + + return conf, timestamp + + def get_txpos(self, tx_hash): + "return position, even if the tx is unverified" + with self.verifier.lock: + x = self.verifier.verified_tx.get(tx_hash) + y = self.verifier.transactions.get(tx_hash) + if x: + height, timestamp, pos = x + return height, pos + elif y: + return y, 0 + else: + return 1e12, 0 + def is_found(self): return self.history.values() != [[]] * len(self.history) @@ -685,8 +720,7 @@ class Abstract_Wallet(object): def receive_tx_callback(self, tx_hash, tx, tx_height): self.add_transaction(tx_hash, tx, tx_height) #self.network.pending_transactions_for_notifications.append(tx) - if self.verifier and tx_height>0: - self.verifier.add(tx_hash, tx_height) + self.add_unverified_tx(tx_hash, tx_height) def receive_history_callback(self, addr, hist): @@ -701,10 +735,8 @@ class Abstract_Wallet(object): self.storage.put('addr_history', self.history, True) for tx_hash, tx_height in hist: - if tx_height>0: - # add it in case it was previously unconfirmed - if self.verifier: - self.verifier.add(tx_hash, tx_height) + # add it in case it was previously unconfirmed + self.add_unverified_tx (tx_hash, tx_height) # if addr is new, we have to recompute txi and txo tx = self.transactions.get(tx_hash) @@ -734,9 +766,9 @@ class Abstract_Wallet(object): # 2. create sorted history history = [] for tx_hash, delta in tx_deltas.items(): - conf, timestamp = self.verifier.get_confirmations(tx_hash) if self.verifier else (None, None) + conf, timestamp = self.get_confirmations(tx_hash) history.append((tx_hash, conf, delta, timestamp)) - history.sort(key = lambda x: self.verifier.get_txpos(x[0])) + history.sort(key = lambda x: self.get_txpos(x[0])) history.reverse() # 3. add balance @@ -784,7 +816,7 @@ class Abstract_Wallet(object): def estimated_fee(self, tx): estimated_size = len(tx.serialize(-1))/2 fee = int(self.fee_per_kb*estimated_size/1000.) - if fee < MIN_RELAY_TX_FEE: # and tx.requires_fee(self.verifier): + if fee < MIN_RELAY_TX_FEE: # and tx.requires_fee(self): fee = MIN_RELAY_TX_FEE return fee @@ -963,9 +995,8 @@ class Abstract_Wallet(object): # review transactions that are in the history for addr, hist in self.history.items(): for tx_hash, tx_height in hist: - if tx_height>0: - # add it in case it was previously unconfirmed - self.verifier.add(tx_hash, tx_height) + # add it in case it was previously unconfirmed + self.add_unverified_tx (tx_hash, tx_height) # if we are on a pruning server, remove unverified transactions vr = self.verifier.transactions.keys() + self.verifier.verified_tx.keys() @@ -1022,7 +1053,7 @@ class Abstract_Wallet(object): height = item.get('height') if height: print_error("found height for", tx_hash, height) - self.verifier.add(tx_hash, height) + self.add_unverified_tx(tx_hash, height) else: print_error("removing orphaned tx from history", tx_hash) self.transactions.pop(tx_hash) diff --git a/scripts/merchant/merchant.py b/scripts/merchant/merchant.py index b0a77056..4334cbe4 100644 --- a/scripts/merchant/merchant.py +++ b/scripts/merchant/merchant.py @@ -87,7 +87,7 @@ def on_wallet_update(): for tx_hash, tx_height in h: tx = wallet.transactions.get(tx_hash) if not tx: continue - if wallet.verifier.get_confirmations(tx_hash) < requested_confs: continue + if wallet.get_confirmations(tx_hash)[0] < requested_confs: continue for o in tx.outputs: o_type, o_address, o_value = o if o_address == addr: