Merge branch 'develop'
This commit is contained in:
commit
ef9ce91027
42
query.py
Normal file
42
query.py
Normal file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# See the file "LICENSE" for information about the copyright
|
||||
# and warranty status of this software.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from server.env import Env
|
||||
from server.db import DB
|
||||
|
||||
|
||||
def main():
|
||||
env = Env()
|
||||
os.chdir(env.db_dir)
|
||||
db = DB(env)
|
||||
coin = db.coin
|
||||
argc = 1
|
||||
try:
|
||||
limit = int(sys.argv[argc])
|
||||
argc += 1
|
||||
except:
|
||||
limit = 10
|
||||
for addr in sys.argv[argc:]:
|
||||
print('Address: ', addr)
|
||||
hash160 = coin.address_to_hash160(addr)
|
||||
n = None
|
||||
for n, (tx_hash, height) in enumerate(db.get_history(hash160, limit)):
|
||||
print('History #{:d}: hash: {} height: {:d}'
|
||||
.format(n + 1, bytes(reversed(tx_hash)).hex(), height))
|
||||
if n is None:
|
||||
print('No history')
|
||||
n = None
|
||||
for n, utxo in enumerate(db.get_utxos(hash160, limit)):
|
||||
print('UTXOs #{:d}: hash: {} pos: {:d} height: {:d} value: {:d}'
|
||||
.format(n, bytes(reversed(utxo.tx_hash)).hex(),
|
||||
utxo.tx_pos, utxo.height, utxo.value))
|
||||
if n is None:
|
||||
print('No UTXOs')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
59
server/db.py
59
server/db.py
@ -433,27 +433,41 @@ class DB(object):
|
||||
|
||||
return tx_hash, height
|
||||
|
||||
@staticmethod
|
||||
def resolve_limit(limit):
|
||||
if limit is None:
|
||||
return -1
|
||||
assert isinstance(limit, int) and limit >= 0
|
||||
return limit
|
||||
|
||||
def get_history(self, hash160, limit=1000):
|
||||
'''Generator that returns an unpruned, sorted list of (tx_hash,
|
||||
height) tuples of transactions that touched the address,
|
||||
earliest in the blockchain first. Includes both spending and
|
||||
receiving transactions. By default yields at most 1000 entries.
|
||||
Set limit to None to get them all.
|
||||
'''
|
||||
limit = self.resolve_limit(limit)
|
||||
prefix = b'H' + hash160
|
||||
for key, hist in self.db.iterator(prefix=prefix):
|
||||
a = array.array('I')
|
||||
a.frombytes(hist)
|
||||
for tx_num in a:
|
||||
if limit == 0:
|
||||
return
|
||||
yield self.get_tx_hash(tx_num)
|
||||
limit -= 1
|
||||
|
||||
def get_balance(self, hash160):
|
||||
'''Returns the confirmed balance of an address.'''
|
||||
utxos = self.get_utxos(hash_160)
|
||||
return sum(utxo.value for utxo in utxos)
|
||||
return sum(utxo.value for utxo in self.get_utxos(hash_160, limit=None))
|
||||
|
||||
def get_history(self, hash160):
|
||||
'''Returns an unpruned, sorted list of (tx_hash, height) tuples of
|
||||
transactions that touched the address, earliest in the
|
||||
blockchain first. Includes both spending and receiving
|
||||
transactions.
|
||||
'''
|
||||
prefix = b'H' + hash160
|
||||
a = array.array('I')
|
||||
for key, hist in self.db.iterator(prefix=prefix):
|
||||
a.frombytes(hist)
|
||||
return [self.get_tx_hash(tx_num) for tx_num in a]
|
||||
|
||||
def get_utxos(self, hash160):
|
||||
'''Returns all UTXOs for an address sorted such that the earliest
|
||||
in the blockchain comes first.
|
||||
def get_utxos(self, hash160, 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 = self.resolve_limit(limit)
|
||||
unpack = struct.unpack
|
||||
prefix = b'u' + hash160
|
||||
utxos = []
|
||||
@ -461,10 +475,15 @@ class DB(object):
|
||||
(tx_pos, ) = unpack('<H', k[-2:])
|
||||
|
||||
for n in range(0, len(v), 12):
|
||||
if limit == 0:
|
||||
return
|
||||
(tx_num, ) = unpack('<I', v[n:n+4])
|
||||
(value, ) = unpack('<Q', v[n+4:n+12])
|
||||
tx_hash, height = self.get_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)
|
||||
limit -= 1
|
||||
|
||||
# Sorted by height and block position.
|
||||
return sorted(utxos)
|
||||
def get_utxos_sorted(self, hash160):
|
||||
'''Returns all the UTXOs for an address sorted by height and
|
||||
position in the block.'''
|
||||
return sorted(self.get_utxos(hash160, limit=None))
|
||||
|
||||
@ -15,11 +15,11 @@ from server.db import DB
|
||||
|
||||
class Server(object):
|
||||
|
||||
def __init__(self, env, loop):
|
||||
def __init__(self, env):
|
||||
self.env = env
|
||||
self.db = DB(env)
|
||||
self.rpc = RPC(env)
|
||||
self.block_cache = BlockCache(env, self.db, self.rpc, loop)
|
||||
self.block_cache = BlockCache(env, self.db, self.rpc)
|
||||
|
||||
def async_tasks(self):
|
||||
return [
|
||||
@ -32,7 +32,7 @@ class BlockCache(object):
|
||||
'''Requests blocks ahead of time from the daemon. Serves them
|
||||
to the blockchain processor.'''
|
||||
|
||||
def __init__(self, env, db, rpc, loop):
|
||||
def __init__(self, env, db, rpc):
|
||||
self.logger = logging.getLogger('BlockCache')
|
||||
self.logger.setLevel(logging.INFO)
|
||||
|
||||
@ -47,6 +47,8 @@ class BlockCache(object):
|
||||
self.blocks = []
|
||||
self.recent_sizes = []
|
||||
self.ave_size = 0
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
for signame in ('SIGINT', 'SIGTERM'):
|
||||
loop.add_signal_handler(getattr(signal, signame),
|
||||
partial(self.on_signal, signame))
|
||||
@ -201,32 +203,3 @@ class RPC(object):
|
||||
|
||||
self.logger.info('sleeping 1 second and trying again...')
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# for addr in [
|
||||
# # '1dice8EMZmqKvrGE4Qc9bUFf9PX3xaYDp',
|
||||
# # '1HYBcza9tVquCCvCN1hUZkYT9RcM6GfLot',
|
||||
# # '1BNwxHGaFbeUBitpjy2AsKpJ29Ybxntqvb',
|
||||
# # '1ARanTkswPiVM6tUEYvbskyqDsZpweiciu',
|
||||
# # '1VayNert3x1KzbpzMGt2qdqrAThiRovi8',
|
||||
# # '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
|
||||
# # '1XPTgDRhN8RFnzniWCddobD9iKZatrvH4',
|
||||
# # '153h6eE6xRhXuN3pE53gWVfXacAtfyBF8g',
|
||||
# ]:
|
||||
# print('Address: ', addr)
|
||||
# hash160 = coin.address_to_hash160(addr)
|
||||
# utxos = self.db.get_utxos(hash160)
|
||||
# for n, utxo in enumerate(utxos):
|
||||
# print('UTXOs #{:d}: hash: {} pos: {:d} height: {:d} value: {:d}'
|
||||
# .format(n, bytes(reversed(utxo.tx_hash)).hex(),
|
||||
# utxo.tx_pos, utxo.height, utxo.value))
|
||||
|
||||
# for addr in [
|
||||
# '19k8nToWwMGuF4HkNpzgoVAYk4viBnEs5D',
|
||||
# '1HaHTfmvoUW6i6nhJf8jJs6tU4cHNmBQHQ',
|
||||
# '1XPTgDRhN8RFnzniWCddobD9iKZatrvH4',
|
||||
# ]:
|
||||
# print('Address: ', addr)
|
||||
# hash160 = coin.address_to_hash160(addr)
|
||||
# for n, (tx_hash, height) in enumerate(self.db.get_history(hash160)):
|
||||
# print('History #{:d}: hash: {} height: {:d}'
|
||||
# .format(n + 1, bytes(reversed(tx_hash)).hex(), height))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user