listunspent methods consider mempool receipts
- Update docs. Height is 0 for mempool receipts - Implement mempool.get_utxos() and use it - Rename mempool.spends to mempool.potential_spends Closes #365
This commit is contained in:
parent
3e6ced6039
commit
76f4969a98
@ -272,14 +272,17 @@ Return an ordered list of UTXOs sent to a bitcoin address.
|
||||
**Response**
|
||||
|
||||
A list of unspent outputs in blockchain order. Each transaction
|
||||
is a dictionary with keys *height* , *tx_pos*, *tx_height* and
|
||||
is a dictionary with keys *height* , *tx_pos*, *tx_hash* and
|
||||
*value* keys. *height* is the integer height of the block the
|
||||
transaction was confirmed in; if unconfirmed then *height* is 0 if
|
||||
all inputs are confirmed, and -1 otherwise. *tx_hash* the
|
||||
transaction hash in hexadecimal, *tx_pos* the zero-based index of
|
||||
the output in the transaction's list of outputs, and *value* its
|
||||
integer value in minimum coin units (satoshis in the case of
|
||||
Bitcoin).
|
||||
transaction was confirmed in, *tx_hash* the transaction hash in
|
||||
hexadecimal, *tx_pos* the zero-based index of the output in the
|
||||
transaction's list of outputs, and *value* its integer value in
|
||||
minimum coin units (satoshis in the case of Bitcoin).
|
||||
|
||||
This function takes the mempool into account. Mempool
|
||||
transactions paying to the address are included at the end of the
|
||||
list in an undefined order, each with *tx_height* of zero. Any
|
||||
output that is spent in the mempool does not appear.
|
||||
|
||||
**Response Example**
|
||||
|
||||
|
||||
@ -788,15 +788,16 @@ class Controller(ServerBase):
|
||||
return await self.unconfirmed_history(hashX)
|
||||
|
||||
async def hashX_listunspent(self, hashX):
|
||||
'''Return the list of UTXOs of a script hash.
|
||||
|
||||
We should remove mempool spends from the in-DB UTXOs.'''
|
||||
'''Return the list of UTXOs of a script hash, including mempool
|
||||
effects.'''
|
||||
utxos = await self.get_utxos(hashX)
|
||||
spends = await self.mempool.spends(hashX)
|
||||
utxos = sorted(utxos)
|
||||
utxos.extend(self.mempool.get_utxos(hashX))
|
||||
spends = await self.mempool.potential_spends(hashX)
|
||||
|
||||
return [{'tx_hash': hash_to_str(utxo.tx_hash), 'tx_pos': utxo.tx_pos,
|
||||
'height': utxo.height, 'value': utxo.value}
|
||||
for utxo in sorted(utxos)
|
||||
for utxo in utxos
|
||||
if (utxo.tx_hash, utxo.tx_pos) not in spends]
|
||||
|
||||
async def address_listunspent(self, address):
|
||||
|
||||
@ -305,14 +305,33 @@ class MemPool(util.LoggedClass):
|
||||
item = self.txs.get(hex_hash)
|
||||
if not item or not raw_tx:
|
||||
continue
|
||||
txin_pairs, txout_pairs, tx_fee, tx_size = item
|
||||
tx_fee = item[2]
|
||||
tx = deserializer(raw_tx).read_tx()
|
||||
unconfirmed = any(hash_to_str(txin.prev_hash) in self.txs
|
||||
for txin in tx.inputs)
|
||||
result.append((hex_hash, tx_fee, unconfirmed))
|
||||
return result
|
||||
|
||||
async def spends(self, hashX):
|
||||
def get_utxos(self, hashX):
|
||||
'''Return an unordered list of UTXO named tuples from mempool
|
||||
transactions that pay to hashX.
|
||||
|
||||
This does not consider if any other mempool transactions spend
|
||||
the outputs.
|
||||
'''
|
||||
utxos = []
|
||||
# hashXs is a defaultdict, so use get() to query
|
||||
for hex_hash in self.hashXs.get(hashX, []):
|
||||
item = self.txs.get(hex_hash)
|
||||
if not item:
|
||||
continue
|
||||
txout_pairs = item[1]
|
||||
for pos, (hX, value) in enumerate(txout_pairs):
|
||||
if hX == hashX:
|
||||
utxos.append(UTXO(-1, pos, hex_hash, 0, value))
|
||||
return utxos
|
||||
|
||||
async def potential_spends(self, hashX):
|
||||
'''Return a set of (prev_hash, prev_idx) pairs from mempool
|
||||
transactions that touch hashX.
|
||||
|
||||
@ -320,14 +339,14 @@ class MemPool(util.LoggedClass):
|
||||
'''
|
||||
deserializer = self.coin.DESERIALIZER
|
||||
pairs = await self.raw_transactions(hashX)
|
||||
spends = set()
|
||||
result = set()
|
||||
for hex_hash, raw_tx in pairs:
|
||||
if not raw_tx:
|
||||
continue
|
||||
tx = deserializer(raw_tx).read_tx()
|
||||
for txin in tx.inputs:
|
||||
spends.add((txin.prev_hash, txin.prev_idx))
|
||||
return spends
|
||||
result.add((txin.prev_hash, txin.prev_idx))
|
||||
return result
|
||||
|
||||
def value(self, hashX):
|
||||
'''Return the unconfirmed amount in the mempool for hashX.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user