fix spend_utxo

This commit is contained in:
Jack Robison 2021-07-25 21:45:42 -04:00 committed by Victor Shyba
parent a48fe84971
commit 68596be1b9
2 changed files with 19 additions and 19 deletions

View file

@ -29,7 +29,7 @@ from lbry.wallet.server.db.claimtrie import StagedClaimtrieItem, StagedClaimtrie
from lbry.wallet.server.db.claimtrie import get_takeover_name_ops, StagedActivation, get_add_effective_amount_ops from lbry.wallet.server.db.claimtrie import get_takeover_name_ops, StagedActivation, get_add_effective_amount_ops
from lbry.wallet.server.db.claimtrie import get_remove_name_ops, get_remove_effective_amount_ops from lbry.wallet.server.db.claimtrie import get_remove_name_ops, get_remove_effective_amount_ops
from lbry.wallet.server.db.prefixes import ACTIVATED_SUPPORT_TXO_TYPE, ACTIVATED_CLAIM_TXO_TYPE from lbry.wallet.server.db.prefixes import ACTIVATED_SUPPORT_TXO_TYPE, ACTIVATED_CLAIM_TXO_TYPE
from lbry.wallet.server.db.prefixes import PendingActivationKey, PendingActivationValue, Prefixes from lbry.wallet.server.db.prefixes import PendingActivationKey, PendingActivationValue, Prefixes, ClaimToTXOValue
from lbry.wallet.server.udp import StatusServer from lbry.wallet.server.udp import StatusServer
from lbry.wallet.server.db.revertable import RevertableOp, RevertablePut, RevertableDelete, RevertableOpStack from lbry.wallet.server.db.revertable import RevertableOp, RevertablePut, RevertableDelete, RevertableOpStack
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
@ -204,7 +204,7 @@ class BlockProcessor:
self.touched_hashXs: Set[bytes] = set() self.touched_hashXs: Set[bytes] = set()
# UTXO cache # UTXO cache
self.utxo_cache: Dict[Tuple[bytes, int], bytes] = {} self.utxo_cache: Dict[Tuple[bytes, int], Tuple[bytes, int]] = {}
# Claimtrie cache # Claimtrie cache
self.db_op_stack: Optional[RevertableOpStack] = None self.db_op_stack: Optional[RevertableOpStack] = None
@ -1159,7 +1159,6 @@ class BlockProcessor:
for txin in tx.inputs: for txin in tx.inputs:
if txin.is_generation(): if txin.is_generation():
continue continue
txin_num = self.db.transaction_num_mapping[txin.prev_hash]
# spend utxo for address histories # spend utxo for address histories
hashX = spend_utxo(txin.prev_hash, txin.prev_idx) hashX = spend_utxo(txin.prev_hash, txin.prev_idx)
if hashX: if hashX:
@ -1305,7 +1304,7 @@ class BlockProcessor:
hashX = self.coin.hashX_from_script(txout.pk_script) hashX = self.coin.hashX_from_script(txout.pk_script)
if hashX: if hashX:
self.touched_hashXs.add(hashX) self.touched_hashXs.add(hashX)
self.utxo_cache[(tx_hash, nout)] = hashX self.utxo_cache[(tx_hash, nout)] = (hashX, txout.value)
self.db_op_stack.extend_ops([ self.db_op_stack.extend_ops([
RevertablePut( RevertablePut(
*Prefixes.utxo.pack_item(hashX, tx_num, nout, txout.value) *Prefixes.utxo.pack_item(hashX, tx_num, nout, txout.value)
@ -1317,15 +1316,13 @@ class BlockProcessor:
return hashX return hashX
def spend_utxo(self, tx_hash: bytes, nout: int): def spend_utxo(self, tx_hash: bytes, nout: int):
# Fast track is it being in the cache hashX, amount = self.utxo_cache.pop((tx_hash, nout), (None, None))
cache_value = self.utxo_cache.pop((tx_hash, nout), None)
if cache_value:
return cache_value
txin_num = self.db.transaction_num_mapping[tx_hash] txin_num = self.db.transaction_num_mapping[tx_hash]
hdb_key = Prefixes.hashX_utxo.pack_key(tx_hash[:4], txin_num, nout) hdb_key = Prefixes.hashX_utxo.pack_key(tx_hash[:4], txin_num, nout)
if not hashX:
hashX = self.db.db.get(hdb_key) hashX = self.db.db.get(hdb_key)
if hashX: if not hashX:
return
udb_key = Prefixes.utxo.pack_key(hashX, txin_num, nout) udb_key = Prefixes.utxo.pack_key(hashX, txin_num, nout)
utxo_value_packed = self.db.db.get(udb_key) utxo_value_packed = self.db.db.get(udb_key)
if utxo_value_packed is None: if utxo_value_packed is None:
@ -1335,17 +1332,20 @@ class BlockProcessor:
raise ChainError( raise ChainError(
f"{hash_to_hex_str(tx_hash)}:{nout} is not found in UTXO db for {hash_to_hex_str(hashX)}" f"{hash_to_hex_str(tx_hash)}:{nout} is not found in UTXO db for {hash_to_hex_str(hashX)}"
) )
# Remove both entries for this UTXO
self.touched_hashXs.add(hashX) self.touched_hashXs.add(hashX)
self.db_op_stack.extend_ops([ self.db_op_stack.extend_ops([
RevertableDelete(hdb_key, hashX), RevertableDelete(hdb_key, hashX),
RevertableDelete(udb_key, utxo_value_packed) RevertableDelete(udb_key, utxo_value_packed)
]) ])
return hashX return hashX
elif amount is not None:
self.logger.error('UTXO {hash_to_hex_str(tx_hash)} / {tx_idx} not found in "h" table') udb_key = Prefixes.utxo.pack_key(hashX, txin_num, nout)
raise ChainError('UTXO {} / {:,d} not found in "h" table' self.touched_hashXs.add(hashX)
.format(hash_to_hex_str(tx_hash), nout)) self.db_op_stack.extend_ops([
RevertableDelete(hdb_key, hashX),
RevertableDelete(udb_key, Prefixes.utxo.pack_value(amount))
])
return hashX
async def _process_prefetched_blocks(self): async def _process_prefetched_blocks(self):
"""Loop forever processing blocks as they arrive.""" """Loop forever processing blocks as they arrive."""

View file

@ -658,9 +658,9 @@ class LevelDB:
start_prefix = Prefixes.pending_activation.pack_partial_key(height + 1) start_prefix = Prefixes.pending_activation.pack_partial_key(height + 1)
stop_prefix = Prefixes.pending_activation.pack_partial_key(height + 1 + self.coin.maxTakeoverDelay) stop_prefix = Prefixes.pending_activation.pack_partial_key(height + 1 + self.coin.maxTakeoverDelay)
for _k, _v in self.db.iterator(start=start_prefix, stop=stop_prefix, reverse=True): for _k, _v in self.db.iterator(start=start_prefix, stop=stop_prefix, reverse=True):
if _v not in yielded:
yielded.add(_v)
v = Prefixes.pending_activation.unpack_value(_v) v = Prefixes.pending_activation.unpack_value(_v)
if v not in yielded:
yielded.add(v)
k = Prefixes.pending_activation.unpack_key(_k) k = Prefixes.pending_activation.unpack_key(_k)
yield v, k yield v, k