Exemple #1
0
def listblocks() -> int:
    """Synch block data from node

    :return int: number of new blocks synched to database
    """

    # TODO: Handle blockchain forks gracefully

    client = get_active_rpc_client()

    height_node = client.getblockcount()['result']
    latest_block_obj = Block.select().order_by(Block.height.desc()).first()
    if latest_block_obj is None:
        height_db = 0
    else:
        height_db = latest_block_obj.height

    if height_db == height_node:
        return 0

    synced = 0

    for batch in batchwise(range(height_db, height_node), 100):

        new_blocks = client.listblocks(batch)

        with data_db.atomic():
            for block in new_blocks['result']:

                addr_obj, adr_created = Address.get_or_create(
                    address=block['miner'])
                block_obj, blk_created = Block.get_or_create(
                    hash=unhexlify(block['hash']),
                    defaults=dict(
                        time=datetime.fromtimestamp(block['time']),
                        miner=addr_obj,
                        txcount=block['txcount'],
                        height=block['height'],
                    ))
                if blk_created:
                    synced += 1

                log.debug('Synced block {}'.format(block_obj.height))
                signals.database_blocks_updated.emit(block_obj.height,
                                                     height_node)
    log.debug('Synced {} blocks total.'.format(synced))
    return synced
Exemple #2
0
def getblock():
    """Process detailed data from individual blocks to find last votes from guardians"""

    # TODO cleanup this deeply nested mess :)

    client = get_active_rpc_client()
    global getblock_proccessed_height
    blockchain_params = client.getblockchainparams()['result']
    pubkeyhash_version = blockchain_params['address-pubkeyhash-version']
    checksum_value = blockchain_params['address-checksum-value']

    block_objs = Block.multi_tx_blocks().where(
        Block.height > getblock_proccessed_height)

    votes_changed = False

    with data_db.atomic():
        for block_obj in block_objs:
            height = block_obj.height
            block_info = client.getblock("{}".format(height))['result']
            for txid in block_info['tx']:
                transaction = client.getrawtransaction(txid, 4)
                if transaction['error'] is None:
                    if 'vout' in transaction['result']:
                        vout = transaction['result']['vout']
                        permissions = []
                        start_block = None
                        end_block = None
                        for vout_key, entry in enumerate(vout):
                            if len(entry['permissions']) > 0:
                                for key, perm in entry['permissions'][0].items(
                                ):
                                    if perm and key in permission_candidates:
                                        permissions.append(key)
                                    if key == 'startblock':
                                        start_block = perm
                                    if key == 'endblock':
                                        end_block = perm
                                in_entry = transaction['result']['vin'][
                                    vout_key]
                                public_key = in_entry['scriptSig'][
                                    'asm'].split(' ')[1]
                                from_pubkey = public_key_to_address(
                                    public_key, pubkeyhash_version,
                                    checksum_value)
                                given_to = entry['scriptPubKey']['addresses']
                                for addr in given_to:
                                    log.debug(
                                        'Grant or Revoke {} given by {} to {} at time {}'
                                        .format(permissions, from_pubkey, addr,
                                                block_obj.time))
                                    addr_from_obj, _ = Address.get_or_create(
                                        address=from_pubkey)
                                    addr_to_obj, _ = Address.get_or_create(
                                        address=addr)
                                    vote_obj, created = Vote.get_or_create(
                                        txid=txid,
                                        defaults=dict(
                                            from_address=addr_from_obj,
                                            to_address_id=addr_to_obj,
                                            time=block_obj.time))
                                    if created:
                                        votes_changed = True

            getblock_proccessed_height = height

    if votes_changed:
        signals.votes_changed.emit()
Exemple #3
0
def listpermissions():
    client = get_active_rpc_client()
    node_height = client.getblockcount()['result']

    perms = client.listpermissions()
    if not perms:
        log.warning('no permissions from api')
        return
    new_perms, new_votes = False, False

    Permission.delete().execute()
    CurrentVote.delete().execute()

    admin_addresses = set()
    miner_addresses = set()

    with data_db.atomic():
        profile = Profile.get_active()

        for perm in perms['result']:
            perm_type = perm['type']
            perm_start = perm['startblock']
            perm_end = perm['endblock']

            if perm_type not in Permission.PERM_TYPES:
                continue

            if perm_type == Permission.ADMIN and perm_start < node_height < perm_end:
                admin_addresses.add(perm['address'])

            if perm_type == Permission.MINE and perm_start < node_height < perm_end:
                miner_addresses.add(perm['address'])

            addr_obj, created = Address.get_or_create(address=perm['address'])

            for vote in perm['pending']:
                # If candidate has already the permission continue.
                if vote['startblock'] == perm['startblock'] and vote[
                        'endblock'] == perm['endblock']:
                    continue
                start_block = vote['startblock']
                end_block = vote['endblock']
                # new stuff start
                for admin in vote['admins']:
                    admin_obj, created = Address.get_or_create(address=admin)
                    vote_obj, created = CurrentVote.get_or_create(
                        address=addr_obj,
                        perm_type=perm_type,
                        start_block=start_block,
                        end_block=end_block,
                        given_from=admin_obj)
                    vote_obj.set_vote_type()
                # new stuff end
                approbations = len(vote['admins'])
                # TODO: Fix: current time of syncing is not the time of first_vote!

            start_block = perm['startblock']
            end_block = perm['endblock']
            # TODO Why get_or_create ... we just deleted all Permission objects
            perm_obj, created = Permission.get_or_create(
                address=addr_obj,
                perm_type=perm_type,
                defaults=dict(start_block=start_block, end_block=end_block))
            if created:
                new_perms = True
            else:
                perm_obj.save()

    new_is_admin = profile.address in admin_addresses
    if profile.is_admin != new_is_admin:
        profile.is_admin = new_is_admin

    new_is_miner = profile.address in miner_addresses
    if profile.is_miner != new_is_miner:
        profile.is_miner = new_is_miner

    if profile.dirty_fields:
        profile.save()

    # Todo: maybe only trigger table updates on actual change?
    signals.listpermissions.emit()  # triggers community tab updates
    signals.votes_changed.emit()  # triggers community tab updates
    return {'new_perms': new_perms, 'new_votes': new_votes}