Small optimization for large wallets
Previously the verifier job would scan all transactions in unverified_tx each time it ran. Nothing was ever removed from this map; it would essentially be the full set of transactions. As the job runs about 10 times a second, for a wallet with 500 txs this would be 5,000 useless loops a second. This patch makes unverified_tx be simply the set of confirmed transactions that haven't yet been verified. txs are added once confirmed, and removed once verified. Hence it will almost always be empty.
This commit is contained in:
parent
478bde8afa
commit
351272f0b6
|
@ -33,9 +33,11 @@ class SPV(ThreadJob):
|
||||||
self.merkle_roots = {}
|
self.merkle_roots = {}
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
lh = self.wallet.get_local_height()
|
||||||
unverified = self.wallet.get_unverified_txs()
|
unverified = self.wallet.get_unverified_txs()
|
||||||
for (tx_hash, tx_height) in unverified:
|
for tx_hash, tx_height in unverified.items():
|
||||||
if tx_hash not in self.merkle_roots:
|
# do not request merkle branch before headers are available
|
||||||
|
if tx_hash not in self.merkle_roots and tx_height <= lh:
|
||||||
request = ('blockchain.transaction.get_merkle',
|
request = ('blockchain.transaction.get_merkle',
|
||||||
[tx_hash, tx_height])
|
[tx_hash, tx_height])
|
||||||
if self.network.send([request], self.merkle_response):
|
if self.network.send([request], self.merkle_response):
|
||||||
|
@ -64,6 +66,8 @@ class SPV(ThreadJob):
|
||||||
merkle_root = self.hash_merkle_root(merkle['merkle'], tx_hash, pos)
|
merkle_root = self.hash_merkle_root(merkle['merkle'], tx_hash, pos)
|
||||||
header = header.get('result')
|
header = header.get('result')
|
||||||
if not header or header.get('merkle_root') != merkle_root:
|
if not header or header.get('merkle_root') != merkle_root:
|
||||||
|
# FIXME: we should make a fresh connection to a server to
|
||||||
|
# recover from this, as this TX will now never verify
|
||||||
self.print_error("merkle verification failed for", tx_hash)
|
self.print_error("merkle verification failed for", tx_hash)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -417,10 +417,13 @@ class Abstract_Wallet(object):
|
||||||
return decrypted
|
return decrypted
|
||||||
|
|
||||||
def add_unverified_tx(self, tx_hash, tx_height):
|
def add_unverified_tx(self, tx_hash, tx_height):
|
||||||
if tx_height > 0:
|
# Only add if confirmed and not verified
|
||||||
|
if tx_height > 0 and tx_hash not in self.verified_tx:
|
||||||
self.unverified_tx[tx_hash] = tx_height
|
self.unverified_tx[tx_hash] = tx_height
|
||||||
|
|
||||||
def add_verified_tx(self, tx_hash, info):
|
def add_verified_tx(self, tx_hash, info):
|
||||||
|
# Remove from the unverified map and add to the verified map and
|
||||||
|
self.unverified_tx.pop(tx_hash, None)
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.verified_tx[tx_hash] = info # (tx_height, timestamp, pos)
|
self.verified_tx[tx_hash] = info # (tx_height, timestamp, pos)
|
||||||
self.storage.put('verified_tx3', self.verified_tx, True)
|
self.storage.put('verified_tx3', self.verified_tx, True)
|
||||||
|
@ -429,14 +432,8 @@ class Abstract_Wallet(object):
|
||||||
self.network.trigger_callback('verified', (tx_hash, conf, timestamp))
|
self.network.trigger_callback('verified', (tx_hash, conf, timestamp))
|
||||||
|
|
||||||
def get_unverified_txs(self):
|
def get_unverified_txs(self):
|
||||||
'''Returns a list of tuples (tx_hash, height) that are unverified
|
'''Returns a map from tx hash to transaction height'''
|
||||||
and not beyond local height'''
|
return self.unverified_tx
|
||||||
txs = []
|
|
||||||
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.get_local_height():
|
|
||||||
txs.append((tx_hash, tx_height))
|
|
||||||
return txs
|
|
||||||
|
|
||||||
def undo_verifications(self, height):
|
def undo_verifications(self, height):
|
||||||
'''Used by the verifier when a reorg has happened'''
|
'''Used by the verifier when a reorg has happened'''
|
||||||
|
|
Loading…
Reference in New Issue