def scenario( wallets, **kw ):

    global preorder_info, register_info, update_info, balance_before, balance_after, names_owned_before, names_owned_after, whois, blockchain_record, deposit_info, price_info
    global blockchain_history, zonefile_info, all_names_info, namespace_names_info, wallet_info, lookup_info, update_history, zonefile_history, names_info

    testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey )
    testlib.next_block( **kw )

    testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey )
    testlib.next_block( **kw )

    testlib.blockstack_namespace_ready( "test", wallets[1].privkey )
    testlib.next_block( **kw )
    
    wallet = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[2].privkey, wallets[3].privkey, wallets[4].privkey )

    balance_before = testlib.blockstack_cli_balance()
    deposit_info = testlib.blockstack_cli_deposit()
    price_info = testlib.blockstack_cli_price( "foo.test", password="******" )
    wallet_info = testlib.blockstack_cli_wallet( "0123456789abcdef" ) 

    resp = testlib.blockstack_cli_register( "foo.test", "0123456789abcdef" )
    if 'error' in resp:
        print >> sys.stderr, json.dumps(resp, indent=4, sort_keys=True)
        return False
   
    # wait for the preorder to get confirmed
    for i in xrange(0, 5):
        testlib.next_block( **kw )

    # queued?
    preorder_info = testlib.blockstack_cli_info()
    names_owned_before = testlib.blockstack_cli_get_names_owned_by_address( wallets[3].addr )

    for i in xrange(0, 7):
        testlib.next_block( **kw )

    # wait for the poller to pick it up
    print >> sys.stderr, "Waiting 10 seconds for the backend to submit the register"
    time.sleep(10)

    # wait for the register to get confirmed 
    for i in xrange(0, 5):
        testlib.next_block( **kw )

    # registered?
    register_info = testlib.blockstack_cli_info()
    names_info = testlib.blockstack_cli_names()

    for i in xrange(0, 7):
        testlib.next_block( **kw )

    print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge registration"
    time.sleep(10)

    # wait for update to get confirmed 
    for i in xrange(0, 5):
        testlib.next_block( **kw )

    update_info = testlib.blockstack_cli_info()
    names_owned_after = testlib.blockstack_cli_get_names_owned_by_address( wallets[3].addr )
    whois = testlib.blockstack_cli_whois( "foo.test" )

    for i in xrange(0, 7):
        testlib.next_block( **kw )

    print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge update"
    time.sleep(10)

    # put some immutable data 
    put_immutable_info = testlib.blockstack_cli_put_immutable( "foo.test", "hello_world", '{"hello": "world"}' )    
    if 'error' in put_immutable_info:
        print "put_immutable failed"
        print json.dumps(put_immutable_info, indent=4, sort_keys=True)
        return False

    # wait for update to be confirmed 
    for i in xrange(0, 12):
        testlib.next_block( **kw )

    print >> sys.stderr, "Waiting 10 seconds for backend to acknowledge put-immutable update"
    time.sleep(10)

    balance_after = testlib.blockstack_cli_balance()
    blockchain_history = testlib.blockstack_cli_get_name_blockchain_history( "foo.test" )
    zonefile_info = testlib.blockstack_cli_get_name_zonefile( "foo.test", json=False )
    all_names_info = testlib.blockstack_cli_get_all_names(0)
    namespace_names_info = testlib.blockstack_cli_get_names_in_namespace("test", 0)
    lookup_info = testlib.blockstack_cli_lookup( "foo.test" )
    update_history = testlib.blockstack_cli_list_update_history( "foo.test" )
    zonefile_history = testlib.blockstack_cli_list_zonefile_history( "foo.test" )
    blockchain_record = testlib.blockstack_cli_get_name_blockchain_record( "foo.test" )
def scenario(wallets, **kw):

    testlib.blockstack_namespace_preorder("test", wallets[1].addr,
                                          wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.next_block(**kw)

    working_dir = testlib.get_working_dir(**kw)

    sub_zf_template = '$ORIGIN {}\n$TTL 3600\n_http._tcp URI 10 1 "http://www.foo.com"\n{}'
    zf_template = '$ORIGIN {}\n$TTL 3600\n_http._tcp URI 10 1 "http://www.foo.com"\n_resolver URI 10 1 "http://resolver.foo"\n{}'
    zf_default_url = '_file URI 10 1 "file://' + working_dir + '/{}"'
    zf_default_url_2 = '_file URI 20 1 "file://' + working_dir + '/{}"'

    subdomain_zonefiles = {
        'bar.foo1.test':
        sub_zf_template.format('bar.foo1.test',
                               zf_default_url.format('bar.foo1.test')),
        'bar.foo2.test':
        sub_zf_template.format('bar.foo2.test',
                               zf_default_url.format('bar.foo2.test')),
        'bar.foo3.test':
        sub_zf_template.format('bar.foo3.test',
                               zf_default_url.format('bar.foo3.test')),
    }

    zonefiles = {
        'foo1.test':
        zf_template.format(
            'foo1.test',
            subdomains.make_subdomain_txt('bar.foo1.test', 'foo1.test',
                                          wallets[4].addr, 0,
                                          subdomain_zonefiles['bar.foo1.test'],
                                          wallets[4].privkey)),
        'foo2.test':
        zf_template.format(
            'foo2.test',
            subdomains.make_subdomain_txt('bar.foo2.test', 'foo2.test',
                                          wallets[4].addr, 0,
                                          subdomain_zonefiles['bar.foo2.test'],
                                          wallets[4].privkey)),
        'foo3.test':
        zf_template.format(
            'foo3.test',
            subdomains.make_subdomain_txt('bar.foo3.test', 'foo3.test',
                                          wallets[4].addr, 0,
                                          subdomain_zonefiles['bar.foo3.test'],
                                          wallets[4].privkey)),
    }

    testlib.blockstack_name_register(
        "foo1.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test']))
    testlib.blockstack_name_register(
        "foo2.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test']))
    testlib.blockstack_name_register(
        "foo3.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test']))
    testlib.next_block(**kw)

    # sign and put profiles
    for subd in ['bar.foo1.test', 'bar.foo2.test', 'bar.foo3.test']:
        profile_data = {
            'type': 'Person',
            'name': subd,
        }
        profile_jwt = testlib.blockstack_make_profile(profile_data,
                                                      wallets[4].privkey)
        path = os.path.join(working_dir, subd)
        with open(path, 'w') as f:
            f.write(profile_jwt)

    # whois
    for i in xrange(1, 4):
        name = 'foo{}.test'.format(i)

        res = testlib.blockstack_cli_whois(name)
        if 'error' in res:
            print res
            return False

        if not res.has_key('zonefile_hash') or res[
                'zonefile_hash'] != storage.get_zonefile_data_hash(
                    zonefiles[name]):
            print res
            return False

        if res['owner_address'] != wallets[3].addr:
            print res
            return False

        # upload zonefile
        assert testlib.blockstack_put_zonefile(zonefiles[name])

    subdomain_zonefiles_2 = {
        'bar.foo1.test':
        zf_template.format('bar.foo1.test',
                           zf_default_url_2.format('bar.foo1.test')),
        'bar.foo2.test':
        zf_template.format('bar.foo2.test',
                           zf_default_url_2.format('bar.foo2.test')),
        'bar.foo3.test':
        zf_template.format('bar.foo3.test',
                           zf_default_url_2.format('bar.foo3.test')),
    }

    zonefiles = {
        'foo1.test':
        zf_template.format(
            'foo1.test',
            subdomains.make_subdomain_txt('bar.foo1.test', 'foo1.test',
                                          wallets[4].addr, 1,
                                          subdomain_zonefiles['bar.foo1.test'],
                                          wallets[4].privkey)),
        'foo2.test':
        zf_template.format(
            'foo2.test',
            subdomains.make_subdomain_txt('bar.foo2.test', 'foo2.test',
                                          wallets[4].addr, 1,
                                          subdomain_zonefiles['bar.foo2.test'],
                                          wallets[4].privkey)),
        'foo3.test':
        zf_template.format(
            'foo3.test',
            subdomains.make_subdomain_txt('bar.foo3.test', 'foo3.test',
                                          wallets[4].addr, 1,
                                          subdomain_zonefiles['bar.foo3.test'],
                                          wallets[4].privkey)),
    }

    # update zone files
    testlib.blockstack_name_update(
        'foo1.test', storage.get_zonefile_data_hash(zonefiles['foo1.test']),
        wallets[3].privkey)
    testlib.blockstack_name_update(
        'foo2.test', storage.get_zonefile_data_hash(zonefiles['foo2.test']),
        wallets[3].privkey)
    testlib.blockstack_name_update(
        'foo3.test', storage.get_zonefile_data_hash(zonefiles['foo3.test']),
        wallets[3].privkey)
    testlib.next_block(**kw)

    assert testlib.blockstack_put_zonefile(zonefiles['foo1.test'])
    assert testlib.blockstack_put_zonefile(zonefiles['foo2.test'])
    assert testlib.blockstack_put_zonefile(zonefiles['foo3.test'])

    # kick off subdomain indexing
    testlib.next_block(**kw)

    # start API daemon
    print 'starting API daemon'
    wallet_keys = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", wallets[0].privkey, wallets[1].privkey,
        wallets[2].privkey)

    # authenticate
    pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex()
    res = testlib.blockstack_cli_app_signin("foo.test", pk, 'register.app', [
        'names', 'register', 'prices', 'zonefiles', 'blockchain', 'node_read',
        'user_read'
    ])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    ses = res['token']

    # query each subdomain
    proxy = testlib.make_proxy()

    # test 301 redirects.
    res = testlib.blockstack_REST_call('GET',
                                       '/v1/names/baz.foo1.test',
                                       ses,
                                       allow_redirects=False)
    if 'error' in res:
        res['test'] = 'Failed to query non-registered name.'
        print json.dumps(res)
        return False
    if res['http_status'] != 301:
        res['test'] = 'Failed to get a redirect.'
        print json.dumps(res)
        return False

    for i in xrange(1, 4):
        fqn = 'bar.foo{}.test'.format(i)

        # test REST whois
        res = testlib.blockstack_REST_call('GET', '/v1/names/{}'.format(fqn),
                                           ses)
        if 'error' in res:
            res['test'] = 'Failed to query name'
            print json.dumps(res)
            return False

        if res['http_status'] != 200 and res['http_status'] != 404:
            res['test'] = 'HTTP status {}, response = {} on name lookup'.format(
                res['http_status'], res['response'])
            print json.dumps(res)
            return False

        if res['response']['zonefile'] != subdomain_zonefiles[fqn]:
            print 'wrong zone file'
            print res
            print 'expected'
            print zonefiles['foo{}.test'.format(i)]
            return False

        if res['response']['status'] != 'registered_subdomain':
            print 'wrong status'
            print res
            return False

        # test CLI lookup
        res = testlib.blockstack_cli_lookup(fqn)
        if 'error' in res:
            print res
            return False

        print res
        if res['profile'] != {'type': 'Person', 'name': fqn}:
            print 'wrong profile'
            print res['profile']
            return False

        # test REST lookup
        res = testlib.blockstack_REST_call("GET", "/v1/users/{}".format(fqn),
                                           ses)
        if 'error' in res:
            res['test'] = 'Failed to query name profile'
            print json.dumps(res)
            return False

        if res['http_status'] != 200 and res['http_status'] != 404:
            res['test'] = 'HTTP status {}, response = {} on name profile lookup'.format(
                res['http_status'], res['response'])
            print json.dumps(res)
            return False

        print res
        if res['response'] != {'type': 'Person', 'name': fqn}:
            print 'wrong profile on REST call'
            print res
            return False

        # test CLI lookup by address
        res = testlib.blockstack_cli_get_names_owned_by_address(
            wallets[4].addr)
        if 'error' in res:
            print 'failed to get subdomains owned by {}'.format(
                wallets[4].addr)
            print res
            return False

        if fqn not in res:
            print '{} not in list'.format(fqn)
            print res
            return False

        # test REST lookup by address
        res = testlib.blockstack_REST_call(
            'GET', '/v1/addresses/bitcoin/{}'.format(wallets[4].addr), ses)
        if 'error' in res:
            res['test'] = 'Failed to query names owned by address'
            print json.dumps(res)
            return False

        if res['http_status'] != 200 and res['http_status'] != 404:
            res['test'] = 'HTTP status {}, response = {} on address lookup'.format(
                res['http_status'], res['response'])
            print json.dumps(res)
            return False

        if fqn not in res['response']['names']:
            print '{} not in REST list'.format(fqn)
            print res
            return False

        # test REST get name history
        res = testlib.blockstack_REST_call('GET',
                                           '/v1/names/{}/history'.format(fqn),
                                           ses)
        if 'error' in res:
            res['test'] = 'Failed to query subdomain history'
            print json.dumps(res)
            return False

        if res['http_status'] != 200 and res['http_status'] != 404:
            res['test'] = 'HTTP status {}, response = {} on subdomain history lookup'.format(
                res['http_status'], res['response'])
            print json.dumps(res)
            return False

        blocks = res['response']
        if len(blocks.keys()) != 2:
            print 'expected two updates'
            print blocks
            return False

        # get each historic zone file
        for block_height in blocks:
            for prev_state in blocks[block_height]:
                value_hash = prev_state['value_hash']
                res = testlib.blockstack_REST_call(
                    'GET', '/v1/names/{}/zonefile/{}'.format(fqn, value_hash),
                    ses)
                if 'error' in res:
                    print 'failed to query zone file {} for {}'.format(
                        value_hash, fqn)
                    print json.dumps(res)
                    return False

    # reindex
    assert testlib.check_subdomain_db(**kw)
Esempio n. 3
0
def scenario(wallets, **kw):

    global preorder_info, register_info, update_info, balance_before, balance_after, names_owned_before, names_owned_after, whois, blockchain_record, deposit_info, price_info
    global blockchain_history, zonefile_info, all_names_info, namespace_names_info, wallet_info, lookup_info, update_history, zonefile_history, names_info

    testlib.blockstack_namespace_preorder("test", wallets[1].addr,
                                          wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

    wallet = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", wallets[2].privkey, wallets[3].privkey,
        wallets[4].privkey)

    balance_before = testlib.blockstack_cli_balance()
    deposit_info = testlib.blockstack_cli_deposit()
    price_info = testlib.blockstack_cli_price("foo.test",
                                              password="******")
    wallet_info = testlib.blockstack_cli_wallet("0123456789abcdef")

    resp = testlib.blockstack_cli_register("foo.test", "0123456789abcdef")
    if 'error' in resp:
        print >> sys.stderr, json.dumps(resp, indent=4, sort_keys=True)
        return False

    # wait for the preorder to get confirmed
    for i in xrange(0, 5):
        testlib.next_block(**kw)

    # queued?
    preorder_info = testlib.blockstack_cli_info()
    names_owned_before = testlib.blockstack_cli_get_names_owned_by_address(
        wallets[3].addr)

    for i in xrange(0, 7):
        testlib.next_block(**kw)

    # wait for the poller to pick it up
    print >> sys.stderr, "Waiting 10 seconds for the backend to submit the register"
    time.sleep(10)

    # wait for the register to get confirmed
    for i in xrange(0, 5):
        testlib.next_block(**kw)

    # registered?
    register_info = testlib.blockstack_cli_info()
    names_info = testlib.blockstack_cli_names()

    for i in xrange(0, 7):
        testlib.next_block(**kw)

    print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge registration"
    time.sleep(10)

    # wait for update to get confirmed
    for i in xrange(0, 5):
        testlib.next_block(**kw)

    update_info = testlib.blockstack_cli_info()
    names_owned_after = testlib.blockstack_cli_get_names_owned_by_address(
        wallets[3].addr)
    whois = testlib.blockstack_cli_whois("foo.test")

    for i in xrange(0, 7):
        testlib.next_block(**kw)

    print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge update"
    time.sleep(10)

    # put some immutable data
    put_immutable_info = testlib.blockstack_cli_put_immutable(
        "foo.test", "hello_world", '{"hello": "world"}')
    if 'error' in put_immutable_info:
        print "put_immutable failed"
        print json.dumps(put_immutable_info, indent=4, sort_keys=True)
        return False

    # wait for update to be confirmed
    for i in xrange(0, 12):
        testlib.next_block(**kw)

    print >> sys.stderr, "Waiting 10 seconds for backend to acknowledge put-immutable update"
    time.sleep(10)

    balance_after = testlib.blockstack_cli_balance()
    blockchain_history = testlib.blockstack_cli_get_name_blockchain_history(
        "foo.test")
    zonefile_info = testlib.blockstack_cli_get_name_zonefile("foo.test",
                                                             json=False)
    all_names_info = testlib.blockstack_cli_get_all_names(0)
    namespace_names_info = testlib.blockstack_cli_get_names_in_namespace(
        "test", 0)
    lookup_info = testlib.blockstack_cli_lookup("foo.test")
    update_history = testlib.blockstack_cli_list_update_history("foo.test")
    zonefile_history = testlib.blockstack_cli_list_zonefile_history("foo.test")
    blockchain_record = testlib.blockstack_cli_get_name_blockchain_record(
        "foo.test")
Esempio n. 4
0
def scenario(wallets, **kw):

    testlib.blockstack_namespace_preorder("test", wallets[1].addr,
                                          wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

    testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.next_block(**kw)

    working_dir = testlib.get_working_dir(**kw)

    sub_zf_template = '$ORIGIN {}\n$TTL 3600\n{}'
    zf_template = '$ORIGIN {}\n$TTL 3600\n_http._tcp URI 10 1 "http://www.foo.com"\n_resolver URI 10 1 "http://resolver.foo"\n{}'
    zf_default_url = '_file URI 10 1 "http://localhost:4000/hub/{}/profile.json'
    zf_default_url_2 = '_file URI 20 1 "http://localhost:4000/hub/{}/profile.json'

    subdomain_zonefiles = {
        'bar.foo1.test':
        sub_zf_template.format(
            'bar.foo1.test',
            zf_default_url.format(
                virtualchain.address_reencode(wallets[0].addr,
                                              network='mainnet'))),
        'bar.foo2.test':
        sub_zf_template.format(
            'bar.foo2.test',
            zf_default_url.format(
                virtualchain.address_reencode(wallets[1].addr,
                                              network='mainnet'))),
        'bar.foo3.test':
        sub_zf_template.format(
            'bar.foo3.test',
            zf_default_url.format(
                virtualchain.address_reencode(wallets[2].addr,
                                              network='mainnet'))),
    }

    zonefiles = {
        'foo1.test':
        zf_template.format(
            'foo1.test',
            subdomains.make_subdomain_txt('bar.foo1.test', 'foo1.test',
                                          wallets[0].addr, 0,
                                          subdomain_zonefiles['bar.foo1.test'],
                                          wallets[0].privkey)),
        'foo2.test':
        zf_template.format(
            'foo2.test',
            subdomains.make_subdomain_txt('bar.foo2.test', 'foo2.test',
                                          wallets[1].addr, 0,
                                          subdomain_zonefiles['bar.foo2.test'],
                                          wallets[1].privkey)),
        'foo3.test':
        zf_template.format(
            'foo3.test',
            subdomains.make_subdomain_txt('bar.foo3.test', 'foo3.test',
                                          wallets[2].addr, 0,
                                          subdomain_zonefiles['bar.foo3.test'],
                                          wallets[2].privkey)),
    }

    testlib.blockstack_name_register(
        "foo1.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test']))
    testlib.blockstack_name_register(
        "foo2.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test']))
    testlib.blockstack_name_register(
        "foo3.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test']))
    testlib.next_block(**kw)

    # sign and put profiles
    for i, subd in enumerate(
        ['bar.foo1.test', 'bar.foo2.test', 'bar.foo3.test']):
        profile_data = {
            'type': 'Person',
            'name': subd,
        }
        profile_jwt = testlib.blockstack_make_profile(profile_data,
                                                      wallets[i].privkey)
        testlib.blockstack_put_profile(None, profile_jwt, wallets[i].privkey,
                                       'http://localhost:4000')

    # whois
    for i in xrange(1, 4):
        name = 'foo{}.test'.format(i)

        res = testlib.blockstack_cli_whois(name)
        if 'error' in res:
            print res
            return False

        if not res.has_key('zonefile_hash') or res[
                'zonefile_hash'] != storage.get_zonefile_data_hash(
                    zonefiles[name]):
            print res
            return False

        if res['owner_address'] != wallets[3].addr:
            print res
            return False

        # upload zonefile
        assert testlib.blockstack_put_zonefile(zonefiles[name])

    subdomain_zonefiles_2 = {
        'bar.foo1.test':
        sub_zf_template.format(
            'bar.foo1.test',
            zf_default_url_2.format(
                virtualchain.address_reencode(wallets[0].addr,
                                              network='mainnet'))),
        'bar.foo2.test':
        sub_zf_template.format(
            'bar.foo2.test',
            zf_default_url_2.format(
                virtualchain.address_reencode(wallets[1].addr,
                                              network='mainnet'))),
        'bar.foo3.test':
        sub_zf_template.format(
            'bar.foo3.test',
            zf_default_url_2.format(
                virtualchain.address_reencode(wallets[2].addr,
                                              network='mainnet'))),
    }

    zonefiles = {
        'foo1.test':
        zf_template.format(
            'foo1.test',
            subdomains.make_subdomain_txt('bar.foo1.test', 'foo1.test',
                                          wallets[0].addr, 1,
                                          subdomain_zonefiles['bar.foo1.test'],
                                          wallets[0].privkey)),
        'foo2.test':
        zf_template.format(
            'foo2.test',
            subdomains.make_subdomain_txt('bar.foo2.test', 'foo2.test',
                                          wallets[1].addr, 1,
                                          subdomain_zonefiles['bar.foo2.test'],
                                          wallets[1].privkey)),
        'foo3.test':
        zf_template.format(
            'foo3.test',
            subdomains.make_subdomain_txt('bar.foo3.test', 'foo3.test',
                                          wallets[2].addr, 1,
                                          subdomain_zonefiles['bar.foo3.test'],
                                          wallets[2].privkey)),
    }

    # update zone files
    testlib.blockstack_name_update(
        'foo1.test', storage.get_zonefile_data_hash(zonefiles['foo1.test']),
        wallets[3].privkey)
    testlib.blockstack_name_update(
        'foo2.test', storage.get_zonefile_data_hash(zonefiles['foo2.test']),
        wallets[3].privkey)
    testlib.blockstack_name_update(
        'foo3.test', storage.get_zonefile_data_hash(zonefiles['foo3.test']),
        wallets[3].privkey)
    testlib.next_block(**kw)

    assert testlib.blockstack_put_zonefile(zonefiles['foo1.test'])
    assert testlib.blockstack_put_zonefile(zonefiles['foo2.test'])
    assert testlib.blockstack_put_zonefile(zonefiles['foo3.test'])

    # kick off subdomain indexing
    testlib.next_block(**kw)

    # query each subdomain
    # test 301 redirects.
    res = testlib.blockstack_REST_call('GET',
                                       '/v1/names/baz.foo1.test',
                                       allow_redirects=False)
    if 'error' in res:
        res['test'] = 'Failed to query non-registered name.'
        print json.dumps(res)
        return False

    if res['http_status'] != 301:
        res['test'] = 'Failed to get a redirect.'
        print json.dumps(res)
        return False

    for i in xrange(1, 4):
        fqn = 'bar.foo{}.test'.format(i)

        # test REST whois
        res = testlib.blockstack_REST_call('GET', '/v1/names/{}'.format(fqn))
        if 'error' in res:
            res['test'] = 'Failed to query name'
            print json.dumps(res)
            return False

        if res['http_status'] != 200 and res['http_status'] != 404:
            res['test'] = 'HTTP status {}, response = {} on name lookup'.format(
                res['http_status'], res['response'])
            print json.dumps(res)
            return False

        if res['response']['zonefile'] != subdomain_zonefiles[fqn]:
            print 'wrong zone file'
            print res
            print 'expected'
            print zonefiles['foo{}.test'.format(i)]
            return False

        if res['response']['status'] != 'registered_subdomain':
            print 'wrong status'
            print res
            return False

        # test CLI lookup
        res = testlib.blockstack_cli_lookup(fqn)
        if 'error' in res:
            print res
            return False

        print res
        if res['profile'] != {'type': 'Person', 'name': fqn}:
            print 'wrong profile'
            print res['profile']
            return False

        # test REST lookup
        res = testlib.blockstack_REST_call("GET", "/v1/users/{}".format(fqn))
        if 'error' in res:
            res['test'] = 'Failed to query name profile'
            print json.dumps(res)
            return False

        if res['http_status'] != 200 and res['http_status'] != 404:
            res['test'] = 'HTTP status {}, response = {} on name profile lookup'.format(
                res['http_status'], res['response'])
            print json.dumps(res)
            return False

        print res
        if res['response'] != {'type': 'Person', 'name': fqn}:
            print 'wrong profile on REST call'
            print res
            return False

        # test CLI lookup by address
        res = testlib.blockstack_cli_get_names_owned_by_address(
            wallets[i - 1].addr)
        if 'error' in res:
            print 'failed to get subdomains owned by {}'.format(
                wallets[i - 1].addr)
            print res
            return False

        if fqn not in res:
            print '{} not in list'.format(fqn)
            print res
            return False

        # test REST lookup by address
        res = testlib.blockstack_REST_call(
            'GET', '/v1/addresses/bitcoin/{}'.format(wallets[i - 1].addr))
        if 'error' in res:
            res['test'] = 'Failed to query names owned by address'
            print json.dumps(res)
            return False

        if res['http_status'] != 200 and res['http_status'] != 404:
            res['test'] = 'HTTP status {}, response = {} on address lookup'.format(
                res['http_status'], res['response'])
            print json.dumps(res)
            return False

        if fqn not in res['response']['names']:
            print '{} not in REST list'.format(fqn)
            print res
            return False

        # test REST get name history
        res = testlib.blockstack_REST_call('GET',
                                           '/v1/names/{}/history'.format(fqn))
        if 'error' in res:
            res['test'] = 'Failed to query subdomain history'
            print json.dumps(res)
            return False

        if res['http_status'] != 200 and res['http_status'] != 404:
            res['test'] = 'HTTP status {}, response = {} on subdomain history lookup'.format(
                res['http_status'], res['response'])
            print json.dumps(res)
            return False

        blocks = res['response']
        if len(blocks.keys()) != 2:
            print 'expected two updates'
            print blocks
            return False

        # get each historic zone file
        for block_height in blocks:
            for prev_state in blocks[block_height]:
                value_hash = prev_state['value_hash']
                res = testlib.blockstack_REST_call(
                    'GET', '/v1/names/{}/zonefile/{}'.format(fqn, value_hash))
                if 'error' in res:
                    print 'failed to query zone file {} for {}'.format(
                        value_hash, fqn)
                    print json.dumps(res)
                    return False

    # reindex
    assert testlib.check_subdomain_db(**kw)