def process_permissions(): # todo: check if we have new perms / votes client = get_active_rpc_client() try: perms = client.listpermissions("*", "*", True) except Exception as e: log.debug(e) return with data_session_scope() as session: session.query(Permission).delete() session.query(PendingVote).delete() with data_session_scope() as session: for perm in perms: perm_type = perm['type'] perm_start = perm['startblock'] perm_end = perm['endblock'] address = perm['address'] Address.create_if_not_exists(session, address) if perm_type not in [ enums.ISSUE, enums.CREATE, enums.MINE, enums.ADMIN ]: continue perm_obj = Permission(address=address, perm_type=perm_type, start_block=perm_start, end_block=perm_end) session.add(perm_obj) for vote in perm['pending']: start_block = vote['startblock'] end_block = vote['endblock'] # If candidate has already the permission continue. if start_block == perm['startblock'] and end_block == perm[ 'endblock']: continue for admin in vote['admins']: Address.create_if_not_exists(session, admin) vote_obj = PendingVote(address_from=admin, address_to=address, perm_type=perm_type, start_block=start_block, end_block=end_block) session.add(vote_obj) signals.votes_changed.emit() with profile_session_scope() as profile_db: profile = Profile.get_active(profile_db) with data_session_scope() as data_db: is_admin, is_miner = Permission.get_permissions_for_address( data_db, profile.address) if is_admin != profile.is_admin: profile.is_admin = is_admin signals.is_admin_changed.emit(is_admin) if is_miner != profile.is_miner: profile.is_miner = is_miner signals.is_miner_changed.emit(is_miner) signals.permissions_changed.emit()
def process_blocks(): """ Find last valid Block, delete every Block above in DB and get all Blocks above from Node. Process through new Blocks: Add them to DB. Process through all transactions in block. """ client = get_active_rpc_client() ### get last valid block in DB ### last_valid_height = -1 last_block_is_valid = False with data_session_scope() as session: while not last_block_is_valid: latest_block = session.query(Block).order_by( Block.height.desc()).first() if not latest_block: break try: block_from_chain = client.getblock('{}'.format( latest_block.height)) except Exception as e: log.debug(e) return if latest_block.hash == unhexlify(block_from_chain['hash']): last_block_is_valid = True last_valid_height = latest_block.height else: session.delete(latest_block) blockchain_params = client.getblockchainparams() pubkeyhash_version = blockchain_params['address-pubkeyhash-version'] checksum_value = blockchain_params['address-checksum-value'] block_count_node = client.getblockcount() with data_session_scope() as session: # height is 0 indexed, for batch in batchwise(range(last_valid_height + 1, block_count_node), 100): try: with data_session_scope() as session: signals.batch_gui_updates_allowed.emit(False) new_blocks = client.listblocks(batch) first = True for block in new_blocks: # Allow emitting certain GUI update signals for the first block in the batch # or if we're close to the current node block count if first or block_count_node - block['height'] < 16: signals.batch_gui_updates_allowed.emit(True) block_obj = Block( hash=unhexlify(block['hash']), height=block['height'], mining_time=datetime.fromtimestamp(block['time']), ) session.add(block_obj) session.add( MiningReward(block=unhexlify(block['hash']), address=block['miner'])) Address.create_if_not_exists(session, block['miner']) if block['txcount'] > 1: process_transactions(session, block['height'], pubkeyhash_version, checksum_value, client) signals.database_blocks_updated.emit( block['height'], block_count_node) signals.blockschanged.emit( session.query(Block).count()) # Skip certain GUI update signals for the remainder of the batch if first: signals.batch_gui_updates_allowed.emit(False) first = False except Exception as e: signals.batch_gui_updates_allowed.emit(True) log.debug('Exception in process_blocks:') log.debug(e) return signals.batch_gui_updates_allowed.emit(True) if last_valid_height != block_count_node: # permissions and votes tables are completely refreshed after each new block process_permissions()
def process_inputs_and_outputs(data_db, raw_transaction, pubkeyhash_version, checksum_value) -> bool: # todo: better name relevant = False txid = raw_transaction["txid"] signers = [] # todo: SIGHASH_ALL for n, vin in enumerate(raw_transaction["vin"]): if 'scriptSig' in vin: public_key = vin['scriptSig']['asm'].split(' ')[1] signers.append( public_key_to_address(public_key, pubkeyhash_version, checksum_value)) for i, vout in enumerate(raw_transaction["vout"]): for item in vout.get("items", []): # stream item if item["type"] == "stream": publishers = item["publishers"] for publisher in publishers: Address.create_if_not_exists(data_db, publisher) if item["name"] == app.STREAM_TIMESTAMP: relevant = True comment = '' if item['data']: data = ubjson.loadb(unhexlify(item['data'])) if 'comment' in data: comment += data.get('comment', '') data_db.add( Timestamp(txid=txid, pos_in_tx=i, hash=item["keys"][0], comment=comment, address=publishers[0])) # flush for the primary key data_db.flush() elif item['name'] == app.STREAM_ALIAS: alias = item["keys"][0] # Sanity checks if item["data"] or not is_valid_username( alias) or len(publishers) != 1: continue relevant = True data_db.add( Alias(txid=txid, pos_in_tx=i, address=publishers[0], alias=alias)) # flush for the primary key data_db.flush() elif item['name'] == app.STREAM_ISCC: iscc = item["keys"] if len(iscc) != 4: continue meta_id, content_id, data_id, instance_id = iscc if ISCC.already_exists(data_db, meta_id, content_id, data_id, instance_id): continue data = item['data'] if 'json' not in data or 'title' not in data['json']: continue relevant = True data_db.add( ISCC(txid=txid, address=publishers[0], meta_id=meta_id, content_id=content_id, data_id=data_id, instance_id=instance_id, title=data['json']['title'])) # flush for the primary key data_db.flush() # vote for perm in vout.get('permissions', []): relevant = True for perm_type, changed in perm.items(): if changed and perm_type in permission_candidates: for address in vout['scriptPubKey']['addresses']: Address.create_if_not_exists(data_db, address) Address.create_if_not_exists(data_db, signers[vout['n']]) data_db.add( Vote(txid=txid, pos_in_tx=i, from_address=signers[vout['n']], to_address=address, start_block=perm['startblock'], end_block=perm['endblock'], perm_type=perm_type)) # flush for the primary key data_db.flush() return relevant