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 e18ff717c..8688ffe10 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 096d098d6..85e2e291d 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 3026e510c..9a219ca93 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 badaf283c..0c4d0d5c5 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 13dfb0140..87141e71a 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 199206e84..6d684b775 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 b0a770561..4334cbe48 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: