forked from LBRYCommunity/lbry-sdk
faster wallet sync with get_transaction_and_merkle
This commit is contained in:
parent
b0aee3d335
commit
ec20d9a2a8
4 changed files with 34 additions and 16 deletions
|
@ -587,19 +587,23 @@ class Ledger(metaclass=LedgerRegistry):
|
|||
# check local db
|
||||
tx = cache_item.tx = await self.db.get_transaction(txid=txid)
|
||||
|
||||
merkle = None
|
||||
if tx is None:
|
||||
# fetch from network
|
||||
_raw = await self.network.retriable_call(self.network.get_transaction, txid, remote_height)
|
||||
tx = Transaction(unhexlify(_raw))
|
||||
_raw, merkle = await self.network.retriable_call(
|
||||
self.network.get_transaction_and_merkle, txid, remote_height
|
||||
)
|
||||
tx = Transaction(unhexlify(_raw), height=merkle.get('block_height'))
|
||||
cache_item.tx = tx # make sure it's saved before caching it
|
||||
|
||||
await self.maybe_verify_transaction(tx, remote_height)
|
||||
await self.maybe_verify_transaction(tx, remote_height, merkle)
|
||||
return tx
|
||||
|
||||
async def maybe_verify_transaction(self, tx, remote_height):
|
||||
async def maybe_verify_transaction(self, tx, remote_height, merkle=None):
|
||||
tx.height = remote_height
|
||||
if 0 < remote_height < len(self.headers):
|
||||
merkle = await self.network.retriable_call(self.network.get_merkle, tx.id, remote_height)
|
||||
if not merkle:
|
||||
merkle = await self.network.retriable_call(self.network.get_merkle, tx.id, remote_height)
|
||||
merkle_root = self.get_root_of_merkle_tree(merkle['merkle'], merkle['pos'], tx.hash)
|
||||
header = await self.headers.get(remote_height)
|
||||
tx.position = merkle['pos']
|
||||
|
|
|
@ -256,18 +256,20 @@ class WalletManager:
|
|||
def get_unused_address(self):
|
||||
return self.default_account.receiving.get_or_create_usable_address()
|
||||
|
||||
async def get_transaction(self, txid):
|
||||
async def get_transaction(self, txid: str):
|
||||
tx = await self.db.get_transaction(txid=txid)
|
||||
if not tx:
|
||||
try:
|
||||
raw = await self.ledger.network.get_transaction(txid)
|
||||
height = await self.ledger.network.get_transaction_height(txid)
|
||||
except CodeMessageError as e:
|
||||
if 'No such mempool or blockchain transaction.' in e.message:
|
||||
return {'success': False, 'code': 404, 'message': 'transaction not found'}
|
||||
return {'success': False, 'code': e.code, 'message': e.message}
|
||||
tx = Transaction(unhexlify(raw))
|
||||
await self.ledger.maybe_verify_transaction(tx, height)
|
||||
if tx:
|
||||
return tx
|
||||
try:
|
||||
raw, merkle = await self.ledger.network.get_transaction_and_merkle(txid)
|
||||
except CodeMessageError as e:
|
||||
if 'No such mempool or blockchain transaction.' in e.message:
|
||||
return {'success': False, 'code': 404, 'message': 'transaction not found'}
|
||||
return {'success': False, 'code': e.code, 'message': e.message}
|
||||
height = merkle.get('block_height')
|
||||
tx = Transaction(unhexlify(raw), height=height)
|
||||
if height and height > 0:
|
||||
await self.ledger.maybe_verify_transaction(tx, height, merkle)
|
||||
return tx
|
||||
|
||||
async def create_purchase_transaction(
|
||||
|
|
|
@ -256,6 +256,11 @@ class Network:
|
|||
restricted = known_height in (None, -1, 0) or 0 > known_height > self.remote_height - 10
|
||||
return self.rpc('blockchain.transaction.get', [tx_hash], restricted)
|
||||
|
||||
def get_transaction_and_merkle(self, tx_hash, known_height=None):
|
||||
# use any server if its old, otherwise restrict to who gave us the history
|
||||
restricted = known_height in (None, -1, 0) or 0 > known_height > self.remote_height - 10
|
||||
return self.rpc('blockchain.transaction.info', [tx_hash], restricted)
|
||||
|
||||
def get_transaction_height(self, tx_hash, known_height=None):
|
||||
restricted = not known_height or 0 > known_height > self.remote_height - 10
|
||||
return self.rpc('blockchain.transaction.get_height', [tx_hash], restricted)
|
||||
|
|
|
@ -33,6 +33,13 @@ class MockNetwork:
|
|||
self.get_transaction_called.append(tx_hash)
|
||||
return self.transaction[tx_hash]
|
||||
|
||||
async def get_transaction_and_merkle(self, tx_hash, known_height=None):
|
||||
tx = await self.get_transaction(tx_hash)
|
||||
merkle = {}
|
||||
if known_height:
|
||||
merkle = await self.get_merkle(tx_hash, known_height)
|
||||
return tx, merkle
|
||||
|
||||
|
||||
class LedgerTestCase(AsyncioTestCase):
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue