Browse Source

Remove wallet.get_transactions()

Because references are returned, it's not threadsafe as ThomasV
pointed out.
master
Neil Booth 11 years ago
parent
commit
37c3cce329
  1. 32
      lib/verifier.py
  2. 62
      lib/wallet.py

32
lib/verifier.py

@ -36,19 +36,14 @@ class SPV(util.DaemonThread):
self.queue = Queue.Queue() self.queue = Queue.Queue()
def run(self): def run(self):
requested_merkle = [] requested_merkle = set()
while self.is_running(): while self.is_running():
verified_tx, unverified_tx = self.wallet.get_transactions() unverified = self.wallet.get_unverified_txs()
# request missing tx for (tx_hash, tx_height) in unverified:
for tx_hash, tx_height in unverified_tx.items(): if self.merkle_roots.get(tx_hash) is None and tx_hash not in requested_merkle:
if tx_hash not in verified_tx: if self.network.send([ ('blockchain.transaction.get_merkle',[tx_hash, tx_height]) ], self.queue.put):
# do not request merkle branch before headers are available self.print_error('requesting merkle', tx_hash)
if tx_height > self.network.get_local_height(): requested_merkle.add(tx_hash)
continue
if self.merkle_roots.get(tx_hash) is None and tx_hash not in requested_merkle:
if self.network.send([ ('blockchain.transaction.get_merkle',[tx_hash, tx_height]) ], self.queue.put):
self.print_error('requesting merkle', tx_hash)
requested_merkle.append(tx_hash)
try: try:
r = self.queue.get(timeout=0.1) r = self.queue.get(timeout=0.1)
except Queue.Empty: except Queue.Empty:
@ -97,12 +92,7 @@ class SPV(util.DaemonThread):
def undo_verifications(self, height): def undo_verifications(self, height):
verified_tx, unverified_tx = self.wallet.get_transactions() tx_hashes = selt.wallet.undo_verifications(height)
txs = [] for tx_hash in tx_hashes:
for tx_hash, item in verified_tx: self.print_error("redoing", tx_hash)
tx_height, timestamp, pos = item self.merkle_roots.pop(tx_hash, None)
if tx_height >= height:
self.print_error("redoing", tx_hash)
txs.append(tx_hash)
self.merkle_roots.pop(tx_hash, None)
self.wallet.unverify_txs(txs)

62
lib/wallet.py

@ -403,38 +403,48 @@ class Abstract_Wallet(object):
self.storage.put('verified_tx3', self.verified_tx, True) self.storage.put('verified_tx3', self.verified_tx, True)
self.network.trigger_callback('updated') self.network.trigger_callback('updated')
def unverify_txs(self, txs): def get_unverified_txs(self):
'''Used by the verifier when a reorg has happened''' '''Returns a list of tuples (tx_hash, height) that are unverified and not beyond local height'''
txs = []
with self.lock: with self.lock:
for tx_hash in txs: for tx_hash, tx_height in self.unverified_tx.items():
self.verified_tx.pop(tx_hash, None) # do not request merkle branch before headers are available
if tx_hash not in self.verified_tx and tx_height <= self.network.get_local_height():
txs.append((tx_hash, tx_height))
return txs
def get_transactions(self): def undo_verifications(self, height):
'''Return the verified and unverified tx dicts''' '''Used by the verifier when a reorg has happened'''
txs = []
with self.lock: with self.lock:
return self.verified_tx, self.unverified_tx for tx_hash, item in self.verified_tx:
tx_height, timestamp, pos = item
if tx_height >= height:
self.verified_tx.pop(tx_hash, None)
txs.append(tx_hash)
return txs
def get_confirmations(self, tx): def get_confirmations(self, tx):
""" return the number of confirmations of a monitored transaction. """ """ return the number of confirmations of a monitored transaction. """
verified_tx, unverified_tx = self.get_transactions() with self.lock:
if tx in verified_tx: if tx in self.verified_tx:
height, timestamp, pos = verified_tx[tx] height, timestamp, pos = self.verified_tx[tx]
conf = (self.network.get_local_height() - height + 1) conf = (self.network.get_local_height() - height + 1)
if conf <= 0: timestamp = None if conf <= 0: timestamp = None
elif tx in unverified_tx: elif tx in self.unverified_tx:
conf = -1 conf = -1
timestamp = None timestamp = None
else: else:
conf = 0 conf = 0
timestamp = None timestamp = None
return conf, timestamp return conf, timestamp
def get_txpos(self, tx_hash): def get_txpos(self, tx_hash):
"return position, even if the tx is unverified" "return position, even if the tx is unverified"
verified_tx, unverified_tx = self.get_transactions() with self.lock:
x = verified_tx.get(tx_hash) x = self.verified_tx.get(tx_hash)
y = unverified_tx.get(tx_hash) y = self.unverified_tx.get(tx_hash)
if x: if x:
height, timestamp, pos = x height, timestamp, pos = x
return height, pos return height, pos
@ -1021,8 +1031,8 @@ class Abstract_Wallet(object):
self.add_unverified_tx (tx_hash, tx_height) self.add_unverified_tx (tx_hash, tx_height)
# if we are on a pruning server, remove unverified transactions # if we are on a pruning server, remove unverified transactions
verified_tx, unverified_tx = self.get_transactions() with self.lock:
vr = verified_tx.keys() + unverified_tx.keys() vr = self.verified_tx.keys() + self.unverified_tx.keys()
for tx_hash in self.transactions.keys(): for tx_hash in self.transactions.keys():
if tx_hash not in vr: if tx_hash not in vr:
print_error("removing transaction", tx_hash) print_error("removing transaction", tx_hash)
@ -1038,7 +1048,6 @@ class Abstract_Wallet(object):
return False return False
# check that we are not "orphaning" a transaction # check that we are not "orphaning" a transaction
verified_tx, unverified_tx = self.get_transactions()
old_hist = self.history.get(addr,[]) old_hist = self.history.get(addr,[])
for tx_hash, height in old_hist: for tx_hash, height in old_hist:
if tx_hash in map(lambda x:x[0], hist): if tx_hash in map(lambda x:x[0], hist):
@ -1058,8 +1067,9 @@ class Abstract_Wallet(object):
if not tx: continue if not tx: continue
# already verified? # already verified?
if tx_hash in verified_tx: with self.lock:
continue if tx_hash in self.verified_tx:
continue
# unconfirmed tx # unconfirmed tx
print_error("new history is orphaning transaction:", tx_hash) print_error("new history is orphaning transaction:", tx_hash)
# check that all outputs are not mine, request histories # check that all outputs are not mine, request histories

Loading…
Cancel
Save