Rename get_utxos to all_utxos.
- no longer takes a limit - runs in a thread to avoid blocking
This commit is contained in:
parent
0c8d5ddf63
commit
a036a2eb3f
@ -80,13 +80,16 @@ async def query(args):
|
|||||||
if n is None:
|
if n is None:
|
||||||
print('No history found')
|
print('No history found')
|
||||||
n = None
|
n = None
|
||||||
for n, utxo in enumerate(db.get_utxos(hashX, limit), start=1):
|
utxos = await db.all_utxos(hashX)
|
||||||
|
for n, utxo in enumerate(utxos, start=1):
|
||||||
print(f'UTXO #{n:,d}: tx_hash {hash_to_hex_str(utxo.tx_hash)} '
|
print(f'UTXO #{n:,d}: tx_hash {hash_to_hex_str(utxo.tx_hash)} '
|
||||||
f'tx_pos {utxo.tx_pos:,d} height {utxo.height:,d} '
|
f'tx_pos {utxo.tx_pos:,d} height {utxo.height:,d} '
|
||||||
f'value {utxo.value:,d}')
|
f'value {utxo.value:,d}')
|
||||||
|
if n == limit:
|
||||||
|
break
|
||||||
if n is None:
|
if n is None:
|
||||||
print('No UTXOs found')
|
print('No UTXOs found')
|
||||||
balance = db.get_balance(hashX)
|
balance = sum(utxo.value for utxo in utxos)
|
||||||
print(f'Balance: {coin.decimal_value(balance):,f} {coin.SHORTNAME}')
|
print(f'Balance: {coin.decimal_value(balance):,f} {coin.SHORTNAME}')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ class ChainState(object):
|
|||||||
self.force_chain_reorg = self._bp.force_chain_reorg
|
self.force_chain_reorg = self._bp.force_chain_reorg
|
||||||
self.tx_branch_and_root = self._bp.merkle.branch_and_root
|
self.tx_branch_and_root = self._bp.merkle.branch_and_root
|
||||||
self.read_headers = self._bp.read_headers
|
self.read_headers = self._bp.read_headers
|
||||||
|
self.all_utxos = self._bp.all_utxos
|
||||||
|
|
||||||
async def broadcast_transaction(self, raw_tx):
|
async def broadcast_transaction(self, raw_tx):
|
||||||
return await self._daemon.sendrawtransaction([raw_tx])
|
return await self._daemon.sendrawtransaction([raw_tx])
|
||||||
@ -57,13 +58,6 @@ class ChainState(object):
|
|||||||
|
|
||||||
return await run_in_thread(job)
|
return await run_in_thread(job)
|
||||||
|
|
||||||
async def get_utxos(self, hashX):
|
|
||||||
'''Get UTXOs asynchronously to reduce latency.'''
|
|
||||||
def job():
|
|
||||||
return list(self._bp.get_utxos(hashX, limit=None))
|
|
||||||
|
|
||||||
return await run_in_thread(job)
|
|
||||||
|
|
||||||
def header_branch_and_root(self, length, height):
|
def header_branch_and_root(self, length, height):
|
||||||
return self._bp.header_mc.branch_and_root(length, height)
|
return self._bp.header_mc.branch_and_root(length, height)
|
||||||
|
|
||||||
@ -115,15 +109,18 @@ class ChainState(object):
|
|||||||
if n is None:
|
if n is None:
|
||||||
lines.append('No history found')
|
lines.append('No history found')
|
||||||
n = None
|
n = None
|
||||||
for n, utxo in enumerate(db.get_utxos(hashX, limit), start=1):
|
utxos = await db.all_utxos(hashX)
|
||||||
|
for n, utxo in enumerate(utxos, start=1):
|
||||||
lines.append(f'UTXO #{n:,d}: tx_hash '
|
lines.append(f'UTXO #{n:,d}: tx_hash '
|
||||||
f'{hash_to_hex_str(utxo.tx_hash)} '
|
f'{hash_to_hex_str(utxo.tx_hash)} '
|
||||||
f'tx_pos {utxo.tx_pos:,d} height '
|
f'tx_pos {utxo.tx_pos:,d} height '
|
||||||
f'{utxo.height:,d} value {utxo.value:,d}')
|
f'{utxo.height:,d} value {utxo.value:,d}')
|
||||||
|
if n == limit:
|
||||||
|
break
|
||||||
if n is None:
|
if n is None:
|
||||||
lines.append('No UTXOs found')
|
lines.append('No UTXOs found')
|
||||||
|
|
||||||
balance = db.get_balance(hashX)
|
balance = sum(utxo.value for utxo in utxos)
|
||||||
lines.append(f'Balance: {coin.decimal_value(balance):,f} '
|
lines.append(f'Balance: {coin.decimal_value(balance):,f} '
|
||||||
f'{coin.SHORTNAME}')
|
f'{coin.SHORTNAME}')
|
||||||
|
|
||||||
|
|||||||
@ -375,28 +375,25 @@ class DB(object):
|
|||||||
with self.utxo_db.write_batch() as batch:
|
with self.utxo_db.write_batch() as batch:
|
||||||
self.write_utxo_state(batch)
|
self.write_utxo_state(batch)
|
||||||
|
|
||||||
def get_balance(self, hashX):
|
async def all_utxos(self, hashX):
|
||||||
'''Returns the confirmed balance of an address.'''
|
'''Return all UTXOs for an address sorted in no particular order. By
|
||||||
return sum(utxo.value for utxo in self.get_utxos(hashX, limit=None))
|
default yields at most 1000 entries.
|
||||||
|
|
||||||
def get_utxos(self, hashX, limit=1000):
|
|
||||||
'''Generator that yields all UTXOs for an address sorted in no
|
|
||||||
particular order. By default yields at most 1000 entries.
|
|
||||||
Set limit to None to get them all.
|
|
||||||
'''
|
'''
|
||||||
limit = util.resolve_limit(limit)
|
def read_utxos():
|
||||||
s_unpack = unpack
|
utxos = []
|
||||||
# Key: b'u' + address_hashX + tx_idx + tx_num
|
utxos_append = utxos.append
|
||||||
# Value: the UTXO value as a 64-bit unsigned integer
|
s_unpack = unpack
|
||||||
prefix = b'u' + hashX
|
# Key: b'u' + address_hashX + tx_idx + tx_num
|
||||||
for db_key, db_value in self.utxo_db.iterator(prefix=prefix):
|
# Value: the UTXO value as a 64-bit unsigned integer
|
||||||
if limit == 0:
|
prefix = b'u' + hashX
|
||||||
return
|
for db_key, db_value in self.utxo_db.iterator(prefix=prefix):
|
||||||
limit -= 1
|
tx_pos, tx_num = s_unpack('<HI', db_key[-6:])
|
||||||
tx_pos, tx_num = s_unpack('<HI', db_key[-6:])
|
value, = unpack('<Q', db_value)
|
||||||
value, = unpack('<Q', db_value)
|
tx_hash, height = self.fs_tx_hash(tx_num)
|
||||||
tx_hash, height = self.fs_tx_hash(tx_num)
|
utxos_append(UTXO(tx_num, tx_pos, tx_hash, height, value))
|
||||||
yield UTXO(tx_num, tx_pos, tx_hash, height, value)
|
return utxos
|
||||||
|
|
||||||
|
return await run_in_thread(read_utxos)
|
||||||
|
|
||||||
async def lookup_utxos(self, prevouts):
|
async def lookup_utxos(self, prevouts):
|
||||||
'''For each prevout, lookup it up in the DB and return a (hashX,
|
'''For each prevout, lookup it up in the DB and return a (hashX,
|
||||||
|
|||||||
@ -17,7 +17,7 @@ from collections import defaultdict, Counter
|
|||||||
from aiorpcx import (ClientSession, SOCKSProxy,
|
from aiorpcx import (ClientSession, SOCKSProxy,
|
||||||
Notification, handler_invocation,
|
Notification, handler_invocation,
|
||||||
SOCKSError, RPCError, TaskTimeout,
|
SOCKSError, RPCError, TaskTimeout,
|
||||||
TaskGroup, run_in_thread, ignore_after, timeout_after)
|
TaskGroup, ignore_after, timeout_after)
|
||||||
|
|
||||||
from electrumx.lib.peer import Peer
|
from electrumx.lib.peer import Peer
|
||||||
from electrumx.lib.util import class_logger, protocol_tuple
|
from electrumx.lib.util import class_logger, protocol_tuple
|
||||||
|
|||||||
@ -796,7 +796,7 @@ class ElectrumX(SessionBase):
|
|||||||
async def hashX_listunspent(self, hashX):
|
async def hashX_listunspent(self, hashX):
|
||||||
'''Return the list of UTXOs of a script hash, including mempool
|
'''Return the list of UTXOs of a script hash, including mempool
|
||||||
effects.'''
|
effects.'''
|
||||||
utxos = await self.chain_state.get_utxos(hashX)
|
utxos = await self.chain_state.all_utxos(hashX)
|
||||||
utxos = sorted(utxos)
|
utxos = sorted(utxos)
|
||||||
utxos.extend(await self.mempool.unordered_UTXOs(hashX))
|
utxos.extend(await self.mempool.unordered_UTXOs(hashX))
|
||||||
spends = await self.mempool.potential_spends(hashX)
|
spends = await self.mempool.potential_spends(hashX)
|
||||||
@ -853,7 +853,7 @@ class ElectrumX(SessionBase):
|
|||||||
return await self.hashX_subscribe(hashX, address)
|
return await self.hashX_subscribe(hashX, address)
|
||||||
|
|
||||||
async def get_balance(self, hashX):
|
async def get_balance(self, hashX):
|
||||||
utxos = await self.chain_state.get_utxos(hashX)
|
utxos = await self.chain_state.all_utxos(hashX)
|
||||||
confirmed = sum(utxo.value for utxo in utxos)
|
confirmed = sum(utxo.value for utxo in utxos)
|
||||||
unconfirmed = await self.mempool.balance_delta(hashX)
|
unconfirmed = await self.mempool.balance_delta(hashX)
|
||||||
return {'confirmed': confirmed, 'unconfirmed': unconfirmed}
|
return {'confirmed': confirmed, 'unconfirmed': unconfirmed}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user