Remove wallet.get_transactions()
Because references are returned, it's not threadsafe as ThomasV pointed out.
This commit is contained in:
@@ -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)
|
|
||||||
|
|||||||
@@ -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):
|
||||||
|
'''Returns a list of tuples (tx_hash, height) that are unverified and not beyond local height'''
|
||||||
|
txs = []
|
||||||
|
with self.lock:
|
||||||
|
for tx_hash, tx_height in self.unverified_tx.items():
|
||||||
|
# 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 undo_verifications(self, height):
|
||||||
'''Used by the verifier when a reorg has happened'''
|
'''Used by the verifier when a reorg has happened'''
|
||||||
|
txs = []
|
||||||
with self.lock:
|
with self.lock:
|
||||||
for tx_hash in txs:
|
for tx_hash, item in self.verified_tx:
|
||||||
self.verified_tx.pop(tx_hash, None)
|
tx_height, timestamp, pos = item
|
||||||
|
if tx_height >= height:
|
||||||
def get_transactions(self):
|
self.verified_tx.pop(tx_hash, None)
|
||||||
'''Return the verified and unverified tx dicts'''
|
txs.append(tx_hash)
|
||||||
with self.lock:
|
return txs
|
||||||
return self.verified_tx, self.unverified_tx
|
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
Reference in New Issue
Block a user