def read_status(q=None): if q == 'getInfo': latest_block = Block.select().order_by(Block.height.desc()).get() mempool_txs = Transaction.select().where(Transaction.block == None).count() return { 'blocks': latest_block.height, 'lastblockhash': latest_block.hash, 'difficulty': latest_block.difficulty, 'mempool_txs': mempool_txs, } elif q == 'getBestBlockHash': latest_block = Block.select(Block.hash).where(Block.orphaned == False).order_by(Block.height.desc()).get() return { 'bestblockhash': latest_block.hash } elif q == 'getDifficulty': latest_block = Block.select(Block.difficulty).where(Block.orphaned == False).order_by(Block.height.desc()).get() return { 'difficulty': latest_block.difficulty } elif q == 'getLastBlockHash': latest_block = Block.select(Block.hash).where(Block.orphaned == False).order_by(Block.height.desc()).get() return { 'syncTipHash': latest_block.hash, 'lastblockhash': latest_block.hash, }
def read_blocks(beforeBlock=None, limit : int = 100): q = Block.select() if beforeBlock: q = q.where(Block.height < beforeBlock) if limit > 100: limit = 100 blocks = q.order_by(Block.timestamp.desc()).limit(limit) res = [] for b in blocks: pool = None cb = bytes(b.coinbase) for key, value in POOLS.items(): if cb.find(key.encode()) != -1: pool = value res.append({ 'height': b.height, 'hash': b.hash, 'timestamp': int(b.timestamp.timestamp()), 'merkle_root': b.merkle_root, 'tx': b.tx, 'difficulty': b.difficulty, 'size': b.size, 'version_hex': bytes(b.version).hex(), 'version': struct.unpack('i', bytes(b.version))[0], 'bits': bytes(b.bits).hex(), 'nonce': b.nonce, 'pool': pool }) return res
def read_status(q=None): if q == 'getInfo': latest_block = Block.select().order_by(Block.height.desc()).get() mempool_txs = Transaction.select().where(Transaction.block == None).count() return { 'blocks': latest_block.height, 'lastblockhash': latest_block.hash, 'difficulty': latest_block.difficulty, 'mempool_txs': mempool_txs, }
def __init__(self, log, mempool, params): self.log = log self.mempool = mempool self.params = params self.utxo_changes = 0 self.cache = Cache() self.cache.clear() ## level DB # pg_block: block data to insert into PG database # pg_tx: transaction data to insert into PG database # tx:* transaction outputs # misc:* state # height:* list of blocks at height h # blkmeta:* block metadata # blocks:* block seek point in stream datadir = '/data/explorer/blocks/' self.db = self.cache.db self.blk_write = io.BufferedWriter(io.FileIO(datadir + '/blocks.dat','ab')) self.blk_read = io.BufferedReader(io.FileIO(datadir + '/blocks.dat','rb')) if self.db.get(b'misc:height') is None: self.log.info('INITIALIZING EMPTY BLOCKCHAIN DATABASE') with self.db.write_batch(transaction=True) as batch: batch.put(b'misc:height', struct.pack('i', -1)) batch.put(b'misc:msg_start', self.params.NETMAGIC) batch.put(b'misc:tophash', ser_uint256(0)) batch.put(b'misc:total_work', b'0x0') start = self.db.get(b'misc:msg_start') if start != self.params.NETMAGIC: self.log.error("Database magic number mismatch. Data corruption or incorrect network?") raise RuntimeError self.block_lock = BoundedSemaphore() self.address_changes = {} self.address_change_count = 0 self.transaction_change_count = 0 self.utxo_cache = {} self.tx_lock = False self.initial_sync = True self.wallet_group = WalletGrouper('/data/explorer/wallets') self.checktransactions(True) self.checkaddresses(True) self.checkblocks(0, True) self.checkutxos(True) self.orphans = {} self.orphan_deps = {} if Block.select().count(None) == 0: self.log.info('Initialising genesis block') self.putblock(self.params.GENESIS_BLOCK)
def get_latest_block(): return Block.select().order_by(Block.height.desc()).limit(1)[0]