Exemple #1
0
def liststreamitems_alias():
    """
    Sample stream item (none verbose):
    {
        'blocktime': 1505905511,
        'confirmations': 28948,
        'data': '4d696e65722031',
        'key': 'Miner_1',
        'publishers': ['1899xJpqZN3kMQdpvTxESWqykxgFJwRddCE4Tr'],
        'txid': 'caa1155e719803b9f39096860519a5e08e78214245ae9822beeea2b37a656178'
    }
    """

    client = get_active_rpc_client()

    # TODO read and process only fresh stream data by storing a state cursor between runs
    # TODO read stream items 100 at a time
    stream_items = client.liststreamitems(Stream.alias.name, count=100000)
    if not stream_items['result']:
        log.debug('got no items from stream alias')
        return 0

    by_addr = {}  # address -> alias
    reseved = set()  # reserved aliases

    # aggregate the final state of address to alias mappings from stream
    for item in stream_items['result']:
        confirmations = item['confirmations']
        alias = item['key']
        address = item['publishers'][0]
        data = item['data']
        num_publishers = len(item['publishers'])

        # Sanity checks
        if confirmations < 1:
            log.debug('ignore alias - 0 confirmations for %s -> %s' %
                      (address, alias))
            continue
        if data:
            log.debug('ignore alias - alias item "%s" with data "%s..."' %
                      (alias, data[:8]))
            continue
        if not is_valid_username(alias):
            log.debug('ignore alias - alias does not match our regex: %s' %
                      alias)
            continue
        if num_publishers != 1:
            log.debug('ignore alias - alias has multiple publishers: %s' %
                      alias)
            continue
        if alias in reseved:
            log.debug('ignore alias - alias "%s" already reserved by "%s"' %
                      (alias, address))
            continue

        is_new_address = address not in by_addr

        if is_new_address:
            by_addr[address] = alias
            reseved.add(alias)
            continue

        is_alias_change = by_addr[address] != alias

        if is_alias_change:
            log.debug('change alias of %s from %s to %s' %
                      (address, by_addr[address], alias))
            # reserve new name
            reseved.add(alias)
            # release old name
            reseved.remove(by_addr[address])
            # set new name
            by_addr[address] = alias
            continue

    # update database
    profile = Profile.get_active()
    new_main_alias = by_addr.get(profile.address)
    if new_main_alias and profile.alias != new_main_alias:
        log.debug('sync found new alias. profile.alias from %s to %s' %
                  (profile.alias, new_main_alias))
        profile.alias = new_main_alias
        profile.save()

    with data_db.atomic():
        old_addrs = set(
            Address.select(Address.address, Address.alias).tuples())
        new_addrs = set(by_addr.items())
        # set of elements that are only in new_addr but not in old_addr
        changed_addrs = new_addrs - old_addrs
        new_rows = [dict(address=i[0], alias=i[1]) for i in changed_addrs]
        if new_rows:
            log.debug('adding new aliases %s' % changed_addrs)
            # insert rows 100 at a time.
            for idx in range(0, len(new_rows), 100):
                Address.insert_many(new_rows[idx:idx +
                                             100]).upsert(True).execute()

    return len(changed_addrs)