def blockstack_name_transfer(name,
                             address,
                             keepdata,
                             privatekey,
                             user_public_key=None,
                             subsidy_key=None,
                             consensus_hash=None,
                             safety_checks=False):

    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    resp = blockstack_client.do_transfer(name,
                                         address,
                                         keepdata,
                                         privatekey,
                                         privatekey,
                                         test_proxy,
                                         test_proxy,
                                         consensus_hash=consensus_hash,
                                         config_path=test_proxy.config_path,
                                         proxy=test_proxy,
                                         safety_checks=safety_checks)
    api_call_history.append(APICallRecord("transfer", name, resp))
    return resp
def blockstack_get_zonefile(zonefile_hash):
    """
    Get a zonefile from the RPC endpoint
    Return None if not given
    MEANT FOR DIAGNOSTIC PURPOSES ONLY
    """
    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    zonefile_result = test_proxy.get_zonefiles([zonefile_hash])
    if 'error' in zonefile_result:
        return None

    if zonefile_hash not in zonefile_result['zonefiles'].keys():
        return None

    zonefile = blockstack_zones.parse_zone_file(
        zonefile_result['zonefiles'][zonefile_hash])

    # verify
    if zonefile_hash != blockstack_client.hash_zonefile(zonefile):
        return None

    return blockstack_zones.parse_zone_file(
        zonefile_result['zonefiles'][zonefile_hash])
def blockstack_namespace_reveal(namespace_id,
                                register_addr,
                                lifetime,
                                coeff,
                                base,
                                bucket_exponents,
                                nonalpha_discount,
                                no_vowel_discount,
                                privatekey,
                                safety_checks=False):

    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    resp = blockstack_client.do_namespace_reveal(
        namespace_id,
        register_addr,
        lifetime,
        coeff,
        base,
        bucket_exponents,
        nonalpha_discount,
        no_vowel_discount,
        privatekey,
        test_proxy,
        test_proxy,
        config_path=test_proxy.config_path,
        proxy=test_proxy)
    api_call_history.append(
        APICallRecord("namespace_reveal", namespace_id, resp))
    return resp
def blockstack_name_renew(name,
                          privatekey,
                          register_addr=None,
                          subsidy_key=None,
                          user_public_key=None,
                          safety_checks=False):

    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    name_cost_info = test_proxy.get_name_cost(name)
    if register_addr is None:
        register_addr = pybitcoin.BitcoinPrivateKey(
            privatekey).public_key().address()
    else:
        assert register_addr == pybitcoin.BitcoinPrivateKey(
            privatekey).public_key().address()

    resp = blockstack_client.do_renewal(name,
                                        privatekey,
                                        privatekey,
                                        name_cost_info['satoshis'],
                                        test_proxy,
                                        test_proxy,
                                        config_path=test_proxy.config_path,
                                        proxy=test_proxy,
                                        safety_checks=safety_checks)

    api_call_history.append(APICallRecord("renew", name, resp))
    return resp
def scenario( wallets, **kw ):

    global put_result, wallet_keys, datasets, zonefile_hash, dataset_change

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey )

    # migrate profile
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 
    else:
        zonefile_hash = res['zonefile_hash']

    testlib.next_block( **kw )

    put_result = blockstack_client.put_mutable( "foo.test", "hello_world_1", datasets[0], proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    testlib.next_block( **kw )

    put_result = blockstack_client.put_mutable( "foo.test", "hello_world_2", datasets[1], proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    put_result = blockstack_client.put_mutable( "foo.test", "hello_world_3", datasets[2], proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    # increment version too
    datasets[0]['buf'] = []
    for i in xrange(0, 5):
        datasets[0]["dataset_change"] = dataset_change
        datasets[0]['buf'].append(i)

        put_result = blockstack_client.put_mutable( "foo.test", "hello_world_1", datasets[0], proxy=test_proxy, wallet_keys=wallet_keys )
        if 'error' in put_result:
            print json.dumps(put_result, indent=4, sort_keys=True )

    testlib.next_block( **kw )
def blockstack_name_preorder(name,
                             privatekey,
                             register_addr,
                             subsidy_key=None,
                             consensus_hash=None,
                             safety_checks=False):

    global api_call_history

    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    name_cost_info = test_proxy.get_name_cost(name)
    resp = blockstack_client.do_preorder(name,
                                         privatekey,
                                         register_addr,
                                         name_cost_info['satoshis'],
                                         test_proxy,
                                         test_proxy,
                                         consensus_hash=consensus_hash,
                                         config_path=test_proxy.config_path,
                                         proxy=test_proxy,
                                         safety_checks=safety_checks)

    api_call_history.append(APICallRecord("preorder", name, resp))
    return resp
Example #7
0
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

    empty_key = ECPrivateKey().to_hex()

    wallet_keys = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", wallets[1].privkey, wallets[2].privkey, wallets[0].privkey)
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    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 )

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()

    testlib.next_block( **kw )

    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)

    config_dir = os.path.dirname(config_path)
    conf = blockstack_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    # let's do a withdraw of all
    res = testlib.blockstack_REST_call('POST', '/v1/wallet/balance', None, api_pass=api_pass, data= {
        'address' : virtualchain.get_privkey_address(empty_key),
        })
    if 'error' in res['response']:
        res['test'] = 'Failed to perform withdraw'
        print json.dumps(res)
        error = True
        return False
    for i in xrange (0, 1):
        testlib.next_block( **kw )
    print 'Waiting for the withdraw to go through'
    res = testlib.blockstack_REST_call('GET', '/v1/wallet/balance/0', None, api_pass=api_pass)
    if 'error' in res['response']:
        res['test'] = 'Failed to get wallet balance'
        print json.dumps(res)
        error = True
        return False

    res = testlib.blockstack_REST_call('GET', '/v1/wallet/balance/0', None, api_pass=api_pass)
    if 'error' in res['response']:
        res['test'] = 'Failed to get wallet balance'
        print json.dumps(res)
        error = True
        return False
def check(state_engine):

    global last_consensus, snv_block_id

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # not preordered
    for i in xrange(0, len(wallets)):
        preorder = state_engine.get_name_preorder(
            "foo.test", pybitcoin.make_pay_to_address_script(wallets[i].addr),
            wallets[(i + 1) % 5].addr)
        if preorder is not None:
            print "preordered"
            return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "no name"
        return False

    # updated, and data preserved
    if name_rec['value_hash'] != "22" * 20:
        print "wrong value hash"
        return False

    # transferred
    if name_rec['address'] != wallets[4].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        print "wrong owner"
        return False

    # snv lookup works
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)
    spv_headers_path = test_proxy.spv_headers_path

    snv_rec = blockstack_client.snv_lookup("foo.test",
                                           snv_block_id,
                                           last_consensus,
                                           proxy=test_proxy)
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4)
        return False

    print snv_rec

    return True
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, key_names, error


    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, data_privkey=wallets[4].privkey )

    # migrate profiles 
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    testlib.next_block( **kw )

    # make an account 
    res = blockstack_client.put_account("foo.test", "serviceFoo", "serviceFooID", "foo://bar.com", proxy=test_proxy, wallet_keys=wallet_keys, foofield="foo!" )
    if 'error' in res:
        res['test'] = 'Failed to create foo.test account'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    res = blockstack_client.put_account("foo.test", "deletedService", "deletedServiceID", "foo://deleted", proxy=test_proxy, wallet_keys=wallet_keys, barfield="bar!") 
    if 'error' in res:
        res['test'] = 'Failed to create foo.test deletedService account'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    # delete an account 
    res = blockstack_client.delete_account("foo.test", "deletedService", "deletedServiceID", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to delete foo.test deletedService'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block( **kw )
def check( state_engine ):

    global wallet_keys, datasets, zonefile_hash

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "still have preorder"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned 
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False 

    # have right hash 
    if name_rec['value_hash'] != zonefile_hash:
        print "Invalid zonefile hash"
        return False 

    # have no data
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    for i in xrange(0, len(datasets)):
        print "get hello_world_%s" % (i+1)
        dat = blockstack_client.get_mutable( "foo.test", "hello_world_%s" % (i+1) )
        if dat is not None and 'error' not in dat:
            print "still have '%s'\n%s" % ("hello_world_%s" % (i+1), json.dumps(dat,indent=4,sort_keys=True))
            return False

        if 'error' in dat and dat['error'] != 'No such mutable datum':
            print json.dumps(dat, indent=4, sort_keys=True)
            return False
    
    return True
Example #11
0
def check( state_engine ):

    global wallet_keys, datasets, zonefile_hash

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "still have preorder"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned 
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False 

    # have right hash 
    if name_rec['value_hash'] != zonefile_hash:
        print "Invalid zonefile hash"
        return False 

    # have no data
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    for i in xrange(0, len(datasets)):
        print "get hello_world_%s" % (i+1)
        dat = testlib.blockstack_cli_get_mutable( "foo.test", "hello_world_%s" % (i+1) )
        if dat is not None and 'error' not in dat:
            print "still have '%s'\n%s" % ("hello_world_%s" % (i+1), json.dumps(dat,indent=4,sort_keys=True))
            return False

        if 'error' in dat and dat['error'] != 'Failed to fetch mutable data':
            print json.dumps(dat, indent=4, sort_keys=True)
            return False

    return True
Example #12
0
def check(state_engine):

    global wallet_keys, datasets, zonefile_hash

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace not ready"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print "still have preorder"
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "name does not exist"
        return False

    # owned
    if name_rec['address'] != wallets[3].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False

    # have right hash
    if name_rec['value_hash'] != zonefile_hash:
        print "Invalid zonefile hash"
        return False

    # have right data
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)
    res = testlib.blockstack_cli_lookup("foo.test")
    if 'error' in res:
        print 'error looking up profile: {}'.format(res)
        return False

    assert 'profile' in res
    assert 'zonefile' in res

    return True
def blockstack_rpc_names():
    """
    Get the list of nams owned by the local wallet
    """
    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    args = CLIArgs()
    resp = cli_names(args, config_path=test_proxy.config_path)
    return resp
def check(state_engine):

    global snv_block_id, last_consensus

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", virtualchain.make_payment_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print "preorder exists"
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "no such name"
        return False

    # owned by
    if name_rec['address'] != wallets[3].addr or name_rec[
            'sender'] != virtualchain.make_payment_script(wallets[3].addr):
        print "wrong owner"
        return False

    # revoked
    if not name_rec['revoked']:
        return False

    # snv lookup works
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    snv_rec = blockstack_client.snv_lookup("foo.test",
                                           snv_block_id,
                                           last_consensus,
                                           proxy=test_proxy)
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4)
        return False

    print snv_rec

    return True
def check(state_engine):

    global snv_block_id, last_block_id, last_consensus

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        return False

    # owned by
    if name_rec['address'] != wallets[3].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        return False

    # renewed (11 blocks later)
    if name_rec['last_renewed'] - 11 != name_rec['first_registered']:
        print name_rec['last_renewed']
        print name_rec['first_registered']
        return False

    # snv lookup works
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    # snv_rec = snv_client.snv( "foo.test", lastblock, lastconsensus, snv_block_id, snv_consensus, proxy=test_proxy )
    snv_rec = blockstack_client.snv_lookup("foo.test",
                                           snv_block_id,
                                           last_consensus,
                                           proxy=test_proxy)
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4)
        return False

    print snv_rec
    return True
def check( state_engine ):

    global wallet_keys, datasets, zonefile_hash

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "still have preorder"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned 
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False 

    # have right hash 
    if name_rec['value_hash'] != zonefile_hash:
        print "Invalid zonefile hash"
        return False 

    # have right data 
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    res = testlib.blockstack_cli_lookup("foo.test")
    if 'error' in res:
        print 'error looking up profile: {}'.format(res)
        return False

    assert 'profile' in res
    assert 'zonefile' in res

    return True
Example #17
0
def check(state_engine):

    global wallet_keys, data_history_1, data_history_2, data_history_3

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace not ready"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print "still have preorder"
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "name does not exist"
        return False

    # owned
    if name_rec['address'] != wallets[3].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False

    # have right data history
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    hist = [data_history_1, data_history_2, data_history_3]
    for i in xrange(0, len(hist)):
        test_hist = blockstack_client.list_immutable_data_history(
            "foo.test", "hello_world_%s" % (i + 1))
        if test_hist != hist[i]:
            print "hello_world_%s expected: %s" % (i + 1, ",".join(hist[i]))
            print "hello_world_%s got:      %s" % (i + 1, ",".join(test_hist))
            return False

    return True
Example #18
0
def check(state_engine):

    global snv_block_id, snv_consensus

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "'test' not revealed"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "'test' not found"
        return False

    if ns['namespace_id'] != 'test':
        print "'test' not returned"
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print "'foo.test' still preordered"
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "'foo.test' not registered"
        return False

    # transferred
    if name_rec['address'] != wallets[4].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        print "'foo.test' invalid owner"
        return False

    # snv lookup works
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    snv_rec = blockstack_client.snv_lookup("foo.test",
                                           snv_block_id,
                                           snv_consensus,
                                           proxy=test_proxy)
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4)
        return False

    print snv_rec
    return True
def check( state_engine ):

    global last_consensus, snv_block_id

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered 
    for i in xrange(0, len(wallets)):
        preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[i].addr), wallets[(i+1)%5].addr )
        if preorder is not None:
            print "preordered"
            return False

    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "no name"
        return False 

    # updated, and data preserved
    if name_rec['value_hash'] != "22" * 20:
        print "wrong value hash"
        return False 

    # transferred 
    if name_rec['address'] != wallets[4].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script( wallets[4].addr ):
        print "wrong owner"
        return False

    # snv lookup works
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    spv_headers_path = test_proxy.spv_headers_path

    snv_rec = blockstack_client.snv_lookup( "foo.test", snv_block_id, last_consensus, proxy=test_proxy )
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4 )
        return False

    print snv_rec 

    return True
def blockstack_rpc_set_zonefile_hash(name, zonefile_hash):
    """
    Set the zonefile hash directly
    """
    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    args = CLIArgs()
    args.name = name
    args.zonefile_hash = zonefile_hash

    resp = cli_advanced_set_zonefile_hash(args,
                                          config_path=test_proxy.config_path)
    return resp
def check( state_engine ):

    global snv_block_id, last_consensus

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "preorder exists"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "no such name"
        return False 

    # owned by
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "wrong owner"
        return False 

    # revoked 
    if not name_rec['revoked']:
        return False 

    # snv lookup works
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    snv_rec = blockstack_client.snv_lookup( "foo.test", snv_block_id, last_consensus, proxy=test_proxy )
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4 )
        return False

    print snv_rec 

    return True
def check( state_engine ):

    global wallet_keys, data_history_1, data_history_2, data_history_3

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "still have preorder"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned 
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False 

    # have right data history
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    hist = [data_history_1, data_history_2, data_history_3]
    for i in xrange(0, len(hist)):
        test_hist = blockstack_client.list_immutable_data_history( "foo.test", "hello_world_%s" % (i+1))
        if test_hist != hist[i]:
            print "hello_world_%s expected: %s" % (i+1, ",".join(hist[i]))
            print "hello_world_%s got:      %s" % (i+1, ",".join(test_hist))
            return False

    return True
Example #23
0
def check(state_engine):

    global update_hashes

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace not ready"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    name = "foo.test"
    preorder = state_engine.get_name_preorder(
        name, pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print "still have preorder"
        return False

    # registered
    name_rec = state_engine.get_name(name)
    if name_rec is None:
        print "name does not exist"
        return False

    # owned
    if name_rec['address'] != wallets[4].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        print "name has wrong owner"
        return False

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    update_history = blockstack_client.list_update_history(name)
    if update_history != update_hashes:
        print "update history: %s" % ",".join(update_history)
        print "update hashes:  %s" % ",".join(update_hashes)
        return False

    return True
def blockstack_rpc_register(name, password):
    """
    Register a name, using the backend RPC endpoint
    """
    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    args = CLIArgs()
    args.name = name
    resp = cli_register(args,
                        config_path=test_proxy.config_path,
                        password=password,
                        interactive=False,
                        proxy=test_proxy)
    return resp
def blockstack_rpc_update(name, zonefile_json, password):
    """
    Update a name's value hash to point to the new zonefile
    """
    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    args = CLIArgs()
    args.name = name
    args.data = zonefile_json

    resp = cli_update(args,
                      config_path=test_proxy.config_path,
                      password=password)
    return resp
def blockstack_rpc_transfer(name, new_owner_address, password):
    """
    transfer a name to a new address
    """
    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    args = CLIArgs()
    args.name = name
    args.address = new_owner_address

    resp = cli_transfer(args,
                        config_path=test_proxy.config_path,
                        password=password)
    return resp
def blockstack_namespace_ready(namespace_id, privatekey, safety_checks=False):

    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    resp = blockstack_client.do_namespace_ready(
        namespace_id,
        privatekey,
        test_proxy,
        test_proxy,
        config_path=test_proxy.config_path,
        proxy=test_proxy,
        safety_checks=safety_checks)
    api_call_history.append(
        APICallRecord("namespace_ready", namespace_id, resp))
    return resp
def check(state_engine):

    global snv_block_id, last_consensus

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        return False

    if ns['namespace_id'] != 'test':
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        return False

    # not registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is not None:
        print "Not expired:"
        print json.dumps(name_rec, indent=4)
        return False

    #  snv lookup works
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    snv_rec = blockstack_client.snv_lookup("foo.test",
                                           snv_block_id,
                                           last_consensus,
                                           proxy=test_proxy)
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4)
        print "Expected (%s, %s) from (%s, %s)" % (snv_block_id, snv_consensus,
                                                   lastblock, lastconsensus)
        return False

    print snv_rec
    return True
def check( state_engine ):

    global update_hashes

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    name = "foo.test"
    preorder = state_engine.get_name_preorder( name, pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "still have preorder"
        return False
    
    # registered 
    name_rec = state_engine.get_name( name )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned 
    if name_rec['address'] != wallets[4].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[4].addr):
        print "name has wrong owner"
        return False 

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    update_history = blockstack_client.list_update_history( name )
    if update_history != update_hashes:
        print "update history: %s" % ",".join(update_history)
        print "update hashes:  %s" % ",".join(update_hashes)
        return False

    return True
def blockstack_announce(message,
                        privatekey,
                        user_public_key=None,
                        subsidy_key=None,
                        safety_checks=False):

    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    resp = blockstack_client.do_announce(message,
                                         privatekey,
                                         test_proxy,
                                         test_proxy,
                                         config_path=test_proxy.config_path,
                                         proxy=test_proxy,
                                         safety_checks=safety_checks)
    api_call_history.append(APICallRecord("announce", message, resp))
    return resp
def blockstack_get_profile(name):
    """
    Get a profile from the RPC endpoint
    Return None if not given
    MEANT FOR DIAGNOSTIC PURPOSES ONLY
    """
    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    profile_result = test_proxy.get_profile(name)
    if 'error' in profile_result:
        return None

    if 'profile' not in profile_result or 'status' not in profile_result or not profile_result[
            'status']:
        return None

    return profile_result['profile']
def blockstack_name_revoke(name,
                           privatekey,
                           tx_only=False,
                           subsidy_key=None,
                           user_public_key=None,
                           safety_checks=False):

    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    resp = blockstack_client.do_revoke(name,
                                       privatekey,
                                       privatekey,
                                       test_proxy,
                                       test_proxy,
                                       config_path=test_proxy.config_path,
                                       proxy=test_proxy,
                                       safety_checks=safety_checks)
    api_call_history.append(APICallRecord("revoke", name, resp))
    return resp
def blockstack_rpc_sync_zonefile(name, zonefile_string=None, txid=None):
    """
    Forcibly synchronize the zonefile
    """
    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    args = CLIArgs()
    args.name = name

    if zonefile_string is not None:
        args.zonefile = zonefile_string

    if txid is not None:
        args.txid = txid

    resp = cli_advanced_sync_zonefile(args,
                                      config_path=test_proxy.config_path,
                                      proxy=test_proxy)
    return resp
def blockstack_name_import(name,
                           recipient_address,
                           update_hash,
                           privatekey,
                           safety_checks=False):

    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    resp = blockstack_client.do_name_import(name,
                                            privatekey,
                                            recipient_address,
                                            update_hash,
                                            test_proxy,
                                            test_proxy,
                                            config_path=test_proxy.config_path,
                                            proxy=test_proxy,
                                            safety_checks=safety_checks)
    api_call_history.append(APICallRecord("name_import", name, resp))
    return resp
def check( state_engine ):

    global snv_block_id, last_consensus 

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        return False
    
    # not registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is not None:
        print "Not expired:"
        print json.dumps( name_rec, indent=4 )
        return False 

    #  snv lookup works
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    snv_rec = blockstack_client.snv_lookup( "foo.test", snv_block_id, last_consensus, proxy=test_proxy )
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4 )
        print "Expected (%s, %s) from (%s, %s)" % (snv_block_id, snv_consensus, lastblock, lastconsensus)
        return False

    print snv_rec 
    return True 
def blockstack_namespace_preorder(namespace_id,
                                  register_addr,
                                  privatekey,
                                  consensus_hash=None,
                                  safety_checks=False):

    test_proxy = make_proxy()
    blockstack_client.set_default_proxy(test_proxy)

    namespace_cost = test_proxy.get_namespace_cost(namespace_id)
    resp = blockstack_client.do_namespace_preorder(
        namespace_id,
        namespace_cost['satoshis'],
        privatekey,
        register_addr,
        test_proxy,
        test_proxy,
        consensus_hash=consensus_hash,
        config_path=test_proxy.config_path,
        proxy=test_proxy,
        safety_checks=safety_checks)
    api_call_history.append(
        APICallRecord("namespace_preorder", namespace_id, resp))
    return resp
def scenario( wallets, **kw ):

    global datasets, immutable_data_hashes, put_result, last_hash

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey )
    
    # migrate profile
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    testlib.next_block( **kw )

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_1", datasets[0], data_url="http://www.example.unroutable", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    immutable_data_hashes.append( put_result['immutable_data_hash'] )

    testlib.next_block( **kw )

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_2", datasets[1], data_url="http://www.example.unroutable", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    immutable_data_hashes.append( put_result['immutable_data_hash'] )

    testlib.next_block( **kw )

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_3", datasets[2], data_url="http://www.example.unroutable", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    immutable_data_hashes.append( put_result['immutable_data_hash'] )
    last_hash = put_result['zonefile_hash']

    testlib.next_block( **kw )

    # should succeed (name collision)
    datasets[0][u'newdata'] = u"asdf"
    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_1", datasets[0], data_url="http://www.example.unroutable", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' not in put_result:
        immutable_data_hashes[0] = put_result['immutable_data_hash']
    else:
        print json.dumps(put_result, indent=4, sort_keys=True )

    last_hash = put_result['zonefile_hash']
    testlib.next_block( **kw )
def scenario( wallets, **kw ):

    global datasets, immutable_data_hashes, put_result, last_hash

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, payment_privkey=wallets[5].privkey )
    
    # migrate profile
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    testlib.next_block( **kw )
    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallet_keys['payment_privkey'], wallet_keys['owner_privkey'], wallet_keys['data_privkey'] ) 

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_1", datasets[0], data_url="http://www.example.unroutable", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    immutable_data_hashes.append( put_result['immutable_data_hash'] )

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    # wait for confirmation 
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    print "waiting for confirmation"
    time.sleep(10)

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_2", datasets[1], data_url="http://www.example.unroutable", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    immutable_data_hashes.append( put_result['immutable_data_hash'] )

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    print "waiting for confirmation"
    time.sleep(10)

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_3", datasets[2], data_url="http://www.example.unroutable", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    immutable_data_hashes.append( put_result['immutable_data_hash'] )
    last_hash = put_result['zonefile_hash']

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    print "waiting for confirmation"
    time.sleep(10)

    # should succeed (name collision)
    datasets[0][u'newdata'] = u"asdf"
    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_1", datasets[0], data_url="http://www.example.unroutable", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' not in put_result:
        immutable_data_hashes[0] = put_result['immutable_data_hash']
    else:
        print json.dumps(put_result, indent=4, sort_keys=True )

    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    last_hash = put_result['zonefile_hash']

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    print "waiting for confirmation"
    time.sleep(10)
def check(state_engine):

    global error

    # not revealed, but ready
    ns = state_engine.get_namespace_reveal("test")
    if ns is not None:
        print "namespace not ready"
        return False

    ns = state_engine.get_namespace("test")
    if ns is None:
        print "no namespace"
        return False

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False

    # not preordered
    preorder = state_engine.get_name_preorder(
        "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr),
        wallets[3].addr)
    if preorder is not None:
        print "still have preorder"
        return False

    # registered
    name_rec = state_engine.get_name("foo.test")
    if name_rec is None:
        print "name does not exist"
        return False

    # owned
    if name_rec['address'] != wallets[3].addr or name_rec[
            'sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False

    # have right data
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)

    # should always work
    for i in xrange(1, len(datasets)):
        immutable_data = blockstack_client.get_immutable_by_name(
            "foo.test", "hello_world_%s_immutable" % (i + 1), proxy=test_proxy)
        if immutable_data is None:
            print "No data received for immutable dataset %s" % i
            return False

        if 'error' in immutable_data:
            print "No data received for immutable dataset %s: %s" % (
                i, immutable_data['error'])
            return False

        if not immutable_data.has_key('data'):
            print "Missing data\n%s" % json.dumps(
                immutable_data, indent=4, sort_keys=True)
            return False

        data_json = immutable_data['data']
        if data_json != datasets[i]:
            print "did not get dataset %s\ngot %s\nexpected %s" % (
                i, data_json, datasets[i])
            return False

        mutable_data = blockstack_client.get_mutable("foo.test",
                                                     "hello_world_%s_mutable" %
                                                     (i + 1),
                                                     proxy=test_proxy)
        if mutable_data is None:
            print "No data received for mutable dataset %s" % (i + 1)
            return False

        if 'error' in mutable_data:
            print "No data received for mutable dataset %s: %s" % (
                i + 1, mutable_data['error'])
            return False

        data_json = mutable_data['data']
        if data_json != datasets[i]:
            print "did not get dataset %s\ngot %s\nexpected %s" % (
                i + 1, data_json, datasets[i])
            return False

    # should fail
    immutable_data = blockstack_client.get_immutable_by_name(
        "foo.test", "hello_world_1_immutable", proxy=test_proxy)
    if immutable_data is not None and 'error' not in immutable_data:
        print "Got deleted immutable dataset"
        return False

    mutable_data = blockstack_client.get_mutable("foo.tesT",
                                                 "hello_world_1_mutable",
                                                 proxy=test_proxy)
    if mutable_data is not None and 'error' not in mutable_data:
        print "Got deleted mutable dataset"
        return False

    return True
def scenario( wallets, **kw ):

    global synchronized, value_hash

    import blockstack_integration_tests.atlas_network as atlas_network

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    # set up RPC daemon
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, data_privkey=wallets[4].privkey, payment_privkey=wallets[5].privkey )
    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallet_keys['payment_privkey'], wallet_keys['owner_privkey'], wallet_keys['data_privkey'] )

    # start up an atlas network with 16 peers, 8 of which will be active at once.
    # every second, have one peer come online, and one peer go offline.
    # have them all start out knowing about the same seed node.
    atlas_nodes = [17000, 17001, 17002, 17003, 17004, 17005, 17006, 17007, 17008, 17009, 17010, 17011, 17012, 17013, 17014, 17015, 17016]
    atlas_topology = {}
    for i in xrange(0, 9):
        atlas_topology[atlas_nodes[i]] = [16264]

    for i in xrange(9, len(atlas_nodes)):
        atlas_topology[atlas_nodes[i]] = [17008]

    atlas_topology[atlas_nodes[-1]].append( 16264 )

    time_start = int(time.time())
    
    # put the seed after the first four
    all_peers = atlas_nodes[:4] + [16264] + atlas_nodes[4:]

    def churn_drop(src_hostport, dest_hostport):
        if src_hostport is None:
            return 0.0

        src_host, src_port = blockstack_client.config.url_to_host_port( src_hostport )
        dest_host, dest_port = blockstack_client.config.url_to_host_port( dest_hostport )

        now = int(time.time())
        offset = (now - time_start) % len(all_peers)
        sample = all_peers + all_peers
        active_range = sample[offset: offset + 8]

        print "Active range: %s, request (%s --> %s)" % (active_range, src_port, dest_port)

        if src_port not in active_range:
            # dead 
            return 1.0

        if dest_port not in active_range:
            # dead
            return 1.0

        return 0.0

    network_des = atlas_network.atlas_network_build( atlas_nodes, atlas_topology, {}, os.path.join( testlib.working_dir(**kw), "atlas_network" ) )
    atlas_network.atlas_network_start( network_des, drop_probability=churn_drop )

    print "Waiting 25 seconds for the altas peers to catch up"
    time.sleep(25.0)

    # make an empty zonefile
    data_pubkey = virtualchain.BitcoinPrivateKey(wallet_keys['data_privkey']).public_key().to_hex()
    empty_zonefile = blockstack_client.user.make_empty_user_zonefile( "foo.test", data_pubkey, urls=["file:///tmp/foo.test"] )
    empty_zonefile_str = json.dumps(empty_zonefile) 
    value_hash = blockstack_client.hash_zonefile( empty_zonefile )

    # propagate the zonefile
    res = testlib.blockstack_cli_update( "foo.test", empty_zonefile_str, "0123456789abcdef" )

    for i in xrange(0, 12):
        testlib.next_block( **kw )
        
    print "Waiting for zonefile propagation"
    time.sleep(10.0)

    # wait at most 30 seconds for atlas network to converge
    synchronized = False
    for i in xrange(0, 30):
        atlas_network.atlas_print_network_state( network_des )
        if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block( **kw ) - 1, 1 ):
            print "Synchronized!"
            synchronized = True
            break

        else:
            time.sleep(1.0)
    
    # shut down 
    atlas_network.atlas_network_stop( network_des )
    return synchronized
def check( state_engine ):

    global snv_block_id_foo, snv_txid_bar, last_consensus

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    # not preordered 
    for i in xrange(0, len(wallets)):
        for name in ["foo.test", "bar.test", "baz.test"]:
            preorder = state_engine.get_name_preorder( name, pybitcoin.make_pay_to_address_script(wallets[i].addr), wallets[(i+1)%5].addr )
            if preorder is not None:
                print "preordered"
                return False

    # but still registered 
    for name in ["foo.test", "bar.test", "baz.test"]:
        name_rec = state_engine.get_name( name )
        if name_rec is None:
            print "no name"
            return False 
 
    # updated, and data preserved
    name_rec = state_engine.get_name( "baz.test" )
    if name_rec['value_hash'] != "22" * 20:
        print "wrong value hash"
        return False 

    # transferred 
    name_rec = state_engine.get_name( "bar.test" )
    if name_rec['address'] != wallets[4].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script( wallets[4].addr ):
        print "wrong owner"
        return False

    # snv lookup works
    # NOTE: cannot use serial numbers here, since a NAME_IMPORT does not contain a consensus hash.
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    snv_rec = blockstack_client.snv_lookup( "foo.test", snv_block_id_foo, last_consensus, proxy=test_proxy ) 
    if 'error' in snv_rec:
        print json.dumps(snv_rec, indent=4 )
        print "failed to look up foo.test from consensus hash %s" % last_consensus
        return False

    # can use bar.test's NAME_TRANSFER txid to verify foo.test, since it has a consensus hash 
    snv_rec_bar_tx = blockstack_client.snv_lookup( "foo.test", snv_block_id_foo, snv_txid_bar, proxy=test_proxy )
    if 'error' in snv_rec_bar_tx:
        print json.dumps( snv_rec_bar_tx, indent=4 )
        print "failed to look up foo.test from transaction %s" % snv_txid_bar
        return False 

    if snv_rec != snv_rec_bar_tx:
        print "--------"
        print json.dumps(snv_rec, indent=4 )
        print ""
        print json.dumps(snv_rec_bar_tx, indent=4 )
        print ""
        print "Not equal"
        return False

    print snv_rec 


    return True
def scenario( wallets, **kw ):

    global datasets, zonefile_hashes, put_result, last_hash

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, None )

    # migrate profile
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    testlib.next_block( **kw )

    print "put hello_world_1"
    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallet_keys['payment_privkey'], wallet_keys['owner_privkey'], wallet_keys['data_privkey'] )
 
    res = testlib.start_api("0123456789abcdef")
    if 'error' in res:
        print 'failed to start API: {}'.format(res)
        return False

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_1", json.dumps(datasets[0], sort_keys=True), proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        return False

    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    zonefile_hashes.append( put_result['immutable_data_hash'] )

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    # wait for confirmation
    for i in xrange(0, 12):
        testlib.next_block( **kw )
        
    print "waiting for confirmation"
    time.sleep(10)

    print "put hello_world_2"
    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_2", json.dumps(datasets[1], sort_keys=True), proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        return False

    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    zonefile_hashes.append( put_result['immutable_data_hash'] )

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    # wait for confirmation
    for i in xrange(0, 12):
        testlib.next_block( **kw )

    print "waiting for confirmation"
    time.sleep(10)

    print "put hello_world_3"
    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_3", json.dumps(datasets[2], sort_keys=True), proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        return False

    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    zonefile_hashes.append( put_result['immutable_data_hash'] )

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    print "waiting for confirmation"
    time.sleep(10)

    # should succeed (name collision)
    datasets[0]['newdata'] = "asdf"
    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_1", json.dumps(datasets[0], sort_keys=True), proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        return False
        
    zonefile_hashes[0] = put_result['immutable_data_hash']

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    del datasets[0]['newdata']

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

    print "waiting for confirmation"
    time.sleep(10)

    # delete everything
    for i in xrange(0, len(datasets)):
        print "delete %s" % zonefile_hashes[i]
        put_result = blockstack_client.delete_immutable( "foo.test", zonefile_hashes[i], wallet_keys=wallet_keys )
        if 'error' in put_result:
            print json.dumps(put_result, indent=4, sort_keys=True)
            print "delete_immutable collision failed"
            return False

        testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    
        # tell serialization-checker that value_hash can be ignored here
        print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
        sys.stdout.flush()
        
        for i in xrange(0, 12):
            testlib.next_block(**kw)

        print "waiting for confirmation"
        time.sleep(10)

    last_hash = put_result['zonefile_hash']
def scenario( wallets, **kw ):

    global synchronized, value_hash

    import blockstack_integration_tests.atlas_network as atlas_network

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    # set up RPC daemon
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, data_privkey=wallets[4].privkey, payment_privkey=wallets[5].privkey )
    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallet_keys['payment_privkey'], wallet_keys['owner_privkey'], wallet_keys['data_privkey'] )

    # start up an Atlas test network with 9 nodes: the main one doing the test, and 8 subordinate ones that treat it as a seed peer
    # organize nodes into a linear chain: node n is neighbor to n-1 and n+1, with the seed at one end.
    # nodes cannot talk to anyone else.
    atlas_nodes = [17000, 17001, 17002, 17003, 17004, 17005, 17006, 17007]
    atlas_topology = {}
    
    atlas_topology[17000] = [16264, 17001]
    atlas_topology[17007] = [17006]

    for i in xrange(1, len(atlas_nodes)-1):
        atlas_topology[atlas_nodes[i]] = [atlas_nodes[i-1], atlas_nodes[i+1]]

    def chain_drop(src_hostport, dest_hostport):
        if src_hostport is None:
            return 0.0

        src_host, src_port = blockstack_client.config.url_to_host_port( src_hostport )
        dest_host, dest_port = blockstack_client.config.url_to_host_port( dest_hostport )

        if (src_port == 16264 and dest_port == 17000) or (src_port == 17000 and dest_port == 16264):
            # seed end of the chain
            return 0.0
        
        if abs(src_port - dest_port) <= 1:
            # chain link 
            return 0.0

        # drop otherwise
        return 1.0

    network_des = atlas_network.atlas_network_build( atlas_nodes, atlas_topology, {}, os.path.join( testlib.working_dir(**kw), "atlas_network" ) )
    atlas_network.atlas_network_start( network_des, drop_probability=chain_drop )

    print "Waiting 25 seconds for the altas peers to catch up"
    time.sleep(25.0)

    # make an empty zonefile
    data_pubkey = virtualchain.BitcoinPrivateKey(wallet_keys['data_privkey']).public_key().to_hex()
    empty_zonefile = blockstack_client.user.make_empty_user_zonefile( "foo.test", data_pubkey, urls=["file:///tmp/foo.test"] )
    empty_zonefile_str = json.dumps(empty_zonefile) 
    value_hash = blockstack_client.hash_zonefile( empty_zonefile )

    # propagate the zonefile
    res = testlib.blockstack_cli_update( "foo.test", empty_zonefile_str, "0123456789abcdef" )

    for i in xrange(0, 12):
        testlib.next_block( **kw )
        
    print "Waiting for zonefile propagation"
    sys.stdout.flush()

    time.sleep(10.0)

    # wait at most 30 seconds for atlas network to converge
    synchronized = False
    for i in xrange(0, 30):
        atlas_network.atlas_print_network_state( network_des )
        if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block( **kw ) - 1, 1 ):
            print "Synchronized!"
            sys.stdout.flush()
            synchronized = True
            break

        else:
            time.sleep(1.0)
    
    # shut down 
    atlas_network.atlas_network_stop( network_des )
    if not synchronized:
        print "Not synchronized"
        sys.stdout.flush()

    return synchronized
def check( state_engine ):

    global wallet_keys, datasets, zonefile_hash

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "still have preorder"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned 
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False 

    # have right hash 
    if name_rec['value_hash'] != zonefile_hash:
        print "Invalid zonefile hash"
        return False 

    # zonefile is NOT legacy 
    user_zonefile = blockstack_client.zonefile.load_name_zonefile( 'foo.test', zonefile_hash )
    if 'error' in user_zonefile:
        print json.dumps(user_zonefile, indent=4, sort_keys=True)
        return False 

    if blockstack_profiles.is_profile_in_legacy_format( user_zonefile ):
        print "legacy still"
        print json.dumps(user_zonefile, indent=4, sort_keys=True)
        return False

    # zonefile has no key 
    zonefile_key = blockstack_client.user.user_zonefile_data_pubkey(user_zonefile)
    if zonefile_key is not None:
        print 'still have zonefile key'
        print json.dumps(user_zonefile, indent=4, sort_keys=True)
        return False

    # have right data 
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    for i in xrange(0, len(datasets)):
        print "get hello_world_%s" % (i+1)
        dat = testlib.blockstack_cli_get_mutable( "foo.test", "hello_world_{}".format(i+1), public_key=wallets[4].pubkey_hex )
        if dat is None:
            print "No data '%s'" % ("hello_world_%s" % (i+1))
            return False

        if 'error' in dat:
            print json.dumps(dat, indent=4, sort_keys=True)
            return False

        if json.loads(dat['data']) != datasets[i]:
            print "Mismatch %s: %s != %s" % (i, dat, datasets[i])
            return False
    
    res = testlib.blockstack_cli_lookup("foo.test")
    if 'error' in res:
        print 'error looking up profile: {}'.format(res)
        return False

    assert 'profile' in res
    assert 'zonefile' in res

    return True
def scenario( wallets, **kw ):

    global put_result, wallet_keys, legacy_profile, zonefile_hash, zonefile_hash_2


    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.blockstack_name_preorder( "bar.test", wallets[5].privkey, wallets[6].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.blockstack_name_register( "bar.test", wallets[5].privkey, wallets[6].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, payment_privkey=wallets[8].privkey )
    wallet_keys_2 = blockstack_client.make_wallet_keys( owner_privkey=wallets[6].privkey, payment_privkey=wallets[9].privkey )

    # set up legacy profile hash
    legacy_txt = json.dumps(legacy_profile,sort_keys=True)
    legacy_hash = pybitcoin.hex_hash160( legacy_txt )

    result_1 = testlib.blockstack_name_update( "foo.test", legacy_hash, wallets[3].privkey )
    result_2 = testlib.blockstack_name_update( "bar.test", legacy_hash, wallets[6].privkey )
    testlib.next_block( **kw )

    rc = blockstack_client.storage.put_immutable_data( None, result_1['transaction_hash'], data_hash=legacy_hash, data_text=legacy_txt )
    assert rc is not None

    rc = blockstack_client.storage.put_immutable_data( None, result_2['transaction_hash'], data_hash=legacy_hash, data_text=legacy_txt )
    assert rc is not None

    testlib.next_block( **kw )

    # migrate profiles 
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    zonefile_hash = res['zonefile_hash']

    res = testlib.migrate_profile( "bar.test", proxy=test_proxy, wallet_keys=wallet_keys_2 )
    if 'error' in res:
        res['test'] = 'Failed to initialize bar.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    zonefile_hash_2 = res['zonefile_hash']

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    testlib.next_block( **kw )

    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallet_keys['payment_privkey'], wallet_keys['owner_privkey'], wallet_keys['data_privkey'] )

    # see that put_immutable works
    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_immutable", {"hello": "world"}, proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True )

    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])
    
    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    # wait for confirmation
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    print "waiting for confirmation"
    time.sleep(10)

    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallet_keys_2['payment_privkey'], wallet_keys_2['owner_privkey'], wallet_keys_2['data_privkey'] )

    # see that put_mutable works
    put_result = blockstack_client.put_mutable( "bar.test", "hello_world_mutable", {"hello": "world"}, proxy=test_proxy, wallet_keys=wallet_keys_2 )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True )
    
    testlib.next_block( **kw )
def scenario( wallets, **kw ):

    global put_result, wallet_keys, legacy_profile, zonefile_hash, zonefile_hash_2


    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.blockstack_name_preorder( "bar.test", wallets[5].privkey, wallets[6].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.blockstack_name_register( "bar.test", wallets[5].privkey, wallets[6].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey )
    wallet_keys_2 = blockstack_client.make_wallet_keys( owner_privkey=wallets[6].privkey )

    # set up legacy profile hash
    legacy_txt = json.dumps(legacy_profile,sort_keys=True)
    legacy_hash = pybitcoin.hex_hash160( legacy_txt )

    result_1 = testlib.blockstack_name_update( "foo.test", legacy_hash, wallets[3].privkey )
    result_2 = testlib.blockstack_name_update( "bar.test", legacy_hash, wallets[6].privkey )
    testlib.next_block( **kw )

    rc = blockstack_client.storage.put_immutable_data( None, result_1['transaction_hash'], data_hash=legacy_hash, data_text=legacy_txt )
    assert rc is not None

    rc = blockstack_client.storage.put_immutable_data( None, result_2['transaction_hash'], data_hash=legacy_hash, data_text=legacy_txt )
    assert rc is not None

    testlib.next_block( **kw )

    # migrate profiles 
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    zonefile_hash = res['zonefile_hash']

    res = testlib.migrate_profile( "bar.test", proxy=test_proxy, wallet_keys=wallet_keys_2 )
    if 'error' in res:
        res['test'] = 'Failed to initialize bar.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    zonefile_hash_2 = res['zonefile_hash']

    testlib.next_block( **kw )

    # see that put_immutable works
    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_immutable", {"hello": "world"}, proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True )

    testlib.next_block( **kw )

    # see that put_mutable works
    put_result = blockstack_client.put_mutable( "bar.test", "hello_world_mutable", {"hello": "world"}, proxy=test_proxy, wallet_keys=wallet_keys_2 )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True )
    
    testlib.next_block( **kw )
def check( state_engine ):

    global last_consensus, snv_block_id

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        return False 

    if ns['namespace_id'] != 'test':
        return False 

    names = ['foo.test', 'bar.test', 'baz.test']
    name_preorder_wallets = [wallets[2], wallets[3], wallets[4]]
    name_register_wallets = [wallets[5], wallets[6], wallets[7]]
    name_transfer_wallets = [wallets[6], wallets[7], wallets[5]]

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    for i in xrange(0, len(names)):

        name = names[i]
        name_preorder_wallet = name_preorder_wallets[i]
        name_register_wallet = name_register_wallets[i]
        name_transfer_wallet = name_transfer_wallets[i]

        # not preordered
        preorder = state_engine.get_name_preorder( name, pybitcoin.make_pay_to_address_script(name_preorder_wallet.addr), name_register_wallet.addr )
        if preorder is not None:
            return False
        
        # registered 
        name_rec = state_engine.get_name( name )
        if name_rec is None:
            return False 

        # data is gone
        if name_rec['value_hash'] is not None:
            return False 

        # owned by the right transfer wallet 
        if name_rec['address'] != name_transfer_wallet.addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(name_transfer_wallet.addr):
            return False

        # renewed 
        if name_rec['last_renewed'] == name_rec['first_registered']:
            return False 

        # revoked 
        if not name_rec['revoked']:
            return False 

        # snv lookup works
        snv_rec = blockstack_client.snv_lookup( name, snv_block_id, last_consensus, proxy=test_proxy )
        if 'error' in snv_rec:
            print json.dumps(snv_rec, indent=4 )
            return False

    return True
def scenario( wallets, **kw ):

    global wallet_keys, error, foo_output, bar_output, baz_output, config_paths, put_benchmark_data, get_benchmark_data, aws_key, aws_secret

    print "patch '%s'" % os.environ.get("BLOCKSTACK_CLIENT_CONFIG")
    with open( os.environ.get('BLOCKSTACK_CLIENT_CONFIG'), "a+" ) as f:
        f.write( s3_config )
        f.flush()

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.blockstack_name_preorder( "bar.test", wallets[5].privkey, wallets[6].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.blockstack_name_register( "bar.test", wallets[5].privkey, wallets[6].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys['foo.test'] = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, data_privkey=wallets[4].privkey )
    wallet_keys['bar.test'] = blockstack_client.make_wallet_keys( owner_privkey=wallets[6].privkey, data_privkey=wallets[7].privkey )

    # migrate profiles 
    for name in ['foo.test', 'bar.test']:
        res = testlib.migrate_profile( name, proxy=test_proxy, wallet_keys=wallet_keys[name] )
        if 'error' in res:
            res['test'] = 'Failed to initialize %s profile' % name
            print json.dumps(res, indent=4, sort_keys=True)
            error = True
            return 

    testlib.next_block( **kw )

    # set up config file 
    config_path = os.environ['BLOCKSTACK_FILE_CONFIG']
    with open(config_path, "w") as f:
        f.write(TEST_CONFIG_FILE)

    config_paths = {}

    # set up config file and upload file for each principal 
    for name in ['foo.test', 'bar.test']:
        config_dir = os.path.dirname(config_path) + "." + name
        os.makedirs(config_dir)
        name_config_path = os.path.join(config_dir, os.path.basename(config_path))
        config_paths[name] = name_config_path

        # config path
        with open(config_paths[name], "w") as f:
            f.write(TEST_CONFIG_FILE)

        # upload paths 
        for sz in file_sizes:
            upload_path = make_local_upload_path( config_path, name, sz )
            with open(upload_path, "w") as f:
                with open("/dev/urandom", "r") as r:
                    # generate file
                    file_data = r.read(sz)
                    f.write(file_data)
                    f.flush()

    foo_output = os.path.join( os.path.dirname(config_path), 'foo.test-out.txt' )
    foo_fail_output = os.path.join( os.path.dirname(config_path), 'foo.test-out-fail.txt' )
    bar_output = os.path.join( os.path.dirname(config_path), 'bar.test-out.txt' )
    bar_fail_output = os.path.join( os.path.dirname(config_path), 'bar.test-out-fail.txt' )

    # initialize file app
    res = blockstack_file.file_key_regenerate( "foo.test", "localhost", config_path=config_paths['foo.test'], wallet_keys=wallet_keys['foo.test'] )
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return
    
    res = blockstack_file.file_key_regenerate( "bar.test", "localhost", config_path=config_paths['bar.test'], wallet_keys=wallet_keys['bar.test'] )
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    # send a file from foo.test to bar.test
    # do so many times 
    for sz in file_sizes:
        put_benchmark_data[sz] = []
        for i in xrange(0, samples):
            upload_name = make_upload_name( 'foo.test', i, sz )
            local_path = make_local_upload_path(config_path, 'foo.test', sz)
            
            begin = time.time()
            res = blockstack_file.file_put( 'foo.test', 'localhost', ['bar.test'], upload_name, local_path,
                                        config_path=config_paths['foo.test'], wallet_keys=wallet_keys['foo.test'] )

            end = time.time()

            if 'error' in res:
                print json.dumps(res, indent=4, sort_keys=True)
                error = True
                return

            put_benchmark_data[sz].append( end - begin )

    # get a file from foo.test, as bar.test
    # do so many times
    for sz in file_sizes:
        get_benchmark_data[sz] = []
        for i in xrange(0, samples):
            upload_name = make_upload_name( 'foo.test', i, sz )
            src_local_path = make_local_upload_path(config_path, 'foo.test', sz)
            local_path = make_local_upload_path( config_path, 'bar.test', sz )
            
            begin = time.time()
            res = blockstack_file.file_get( 'bar.test', 'localhost', 'foo.test', upload_name, local_path,
                                            config_path=config_paths['bar.test'], wallet_keys=wallet_keys['bar.test'] )
            end = time.time()
            if 'error' in res:
                print json.dumps(res, indent=4, sort_keys=True)
                error = True
                return 
       
            rc = os.system("cmp \"%s\" \"%s\"" % (src_local_path, local_path))
            if rc != 0:
                raise Exception("Not equal: \"%s\" and \"%s\"" % (src_local_path, local_path))
            try:
                os.unlink(output_path)
            except:
                pass


            get_benchmark_data[sz].append( end - begin )

    # delete 
    for sz in file_sizes:
        for i in xrange(0, samples):
            upload_name = make_upload_name( 'foo.test', i, sz )
            res = blockstack_file.file_delete( 'foo.test', upload_name, config_path=config_paths['foo.test'], wallet_keys=wallet_keys['foo.test'] )
            if 'error' in res:
                print json.dumps(res, indent=4, sort_keys=True)
                error = True
                return
def scenario( wallets, **kw ):

    global put_result, wallet_keys, datasets, zonefile_hash, dataset_change

    wallet = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, None )
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = wallet

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    # migrate profile
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys, zonefile_has_data_key=False )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 
    else:
        zonefile_hash = res['zonefile_hash']

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    testlib.next_block( **kw )

    # should fail, since no zone file key
    put_result = testlib.blockstack_cli_put_mutable( "foo.test", "hello_world_1", json.dumps(datasets[0]), password='******')
    if 'error' not in put_result:
        print 'accidentally put data without a zonefile key'
        print json.dumps(put_result, indent=4, sort_keys=True)
        return False
    
    # should succeed, since we have a given private key
    put_result = testlib.blockstack_cli_put_mutable( "foo.test", "hello_world_1", json.dumps(datasets[0]), password='******', private_key=wallets[4].privkey )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        return False

    testlib.next_block( **kw )

    put_result = testlib.blockstack_cli_put_mutable( "foo.test", "hello_world_2", json.dumps(datasets[1]), password='******', private_key=wallets[4].privkey )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        return False

    put_result = testlib.blockstack_cli_put_mutable( "foo.test", "hello_world_3", json.dumps(datasets[2]), password='******', private_key=wallets[4].privkey )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        return False

    # increment version too
    datasets[0]['buf'] = []
    for i in xrange(0, 5):
        datasets[0]["dataset_change"] = dataset_change
        datasets[0]['buf'].append(i)

        put_result = testlib.blockstack_cli_put_mutable( "foo.test", "hello_world_1", json.dumps(datasets[0]), password='******', private_key=wallets[4].privkey )
        if 'error' in put_result:
            print json.dumps(put_result, indent=4, sort_keys=True )

    testlib.next_block( **kw )
def scenario( wallets, **kw ):

    global synchronized, value_hash

    import blockstack_integration_tests.atlas_network as atlas_network

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    # set up RPC daemon
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, data_privkey=wallets[4].privkey, payment_privkey=wallets[5].privkey )
    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallet_keys['payment_privkey'], wallet_keys['owner_privkey'], wallet_keys['data_privkey'] )

    # register 10 names
    for i in xrange(0, 10):
        res = testlib.blockstack_name_preorder( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr )
        if 'error' in res:
            print json.dumps(res)
            return False

    testlib.next_block( **kw )
    
    for i in xrange(0, 10):
        res = testlib.blockstack_name_register( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr )
        if 'error' in res:
            print json.dumps(res)
            return False

    testlib.next_block( **kw )
    
    # make 10 empty zonefiles and propagate them 
    for i in xrange(0, 10):
        data_pubkey = virtualchain.BitcoinPrivateKey(wallet_keys['data_privkey']).public_key().to_hex()
        empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)] )
        empty_zonefile_str = blockstack_zones.make_zone_file( empty_zonefile )
        value_hash = blockstack_client.hash_zonefile( empty_zonefile )

        res = testlib.blockstack_name_update( "foo_{}.test".format(i), value_hash, wallets[3].privkey )
        if 'error' in res:
            print json.dumps(res)
            return False

        testlib.next_block( **kw )

        # propagate 
        res = testlib.blockstack_cli_sync_zonefile('foo_{}.test'.format(i), zonefile_string=empty_zonefile_str)
        if 'error' in res:
            print json.dumps(res)
            return False

    # start up an Atlas test network with 9 nodes: the main one doing the test, and 8 subordinate ones that treat it as a seed peer
    # only the seed node will be publicly routable; the other 8 will be unable to directly talk to each other.
    atlas_nodes = [17000, 17001, 17002, 17003, 17004, 17005, 17006, 17007]
    atlas_topology = {}
    for node_port in atlas_nodes:
        atlas_topology[node_port] = [16264]

    def nat_drop(src_hostport, dest_hostport):
        if dest_hostport is None:
            return 0.0
        
        host, port = blockstack_client.config.url_to_host_port( dest_hostport )
        if port in atlas_nodes:
            # connections to the above nodes will always fail, since they're NAT'ed
            return 1.0

        else:
            # connections to the seed node always succeed
            return 0.0

    network_des = atlas_network.atlas_network_build( atlas_nodes, atlas_topology, {}, os.path.join( testlib.working_dir(**kw), "atlas_network" ) )
    atlas_network.atlas_network_start( network_des, drop_probability=nat_drop )

    print "Waiting 60 seconds for the altas peers to catch up"
    time.sleep(60.0)

    # wait at most 30 seconds for atlas network to converge
    synchronized = False
    for i in xrange(0, 30):
        atlas_network.atlas_print_network_state( network_des )
        if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block( **kw ) - 1, 1 ):
            print "Synchronized!"
            synchronized = True
            break

        else:
            time.sleep(1.0)
    
    # shut down 
    atlas_network.atlas_network_stop( network_des )
    return synchronized
def check( state_engine ):

    global wallet_keys, dataset_1, data_hash_1, dataset_2, data_hash_2

    # not revealed, but ready 
    ns = state_engine.get_namespace_reveal( "test" )
    if ns is not None:
        print "namespace not ready"
        return False 

    ns = state_engine.get_namespace( "test" )
    if ns is None:
        print "no namespace"
        return False 

    if ns['namespace_id'] != 'test':
        print "wrong namespace"
        return False 

    # not preordered
    preorder = state_engine.get_name_preorder( "foo.test", pybitcoin.make_pay_to_address_script(wallets[2].addr), wallets[3].addr )
    if preorder is not None:
        print "still have preorder"
        return False
    
    # registered 
    name_rec = state_engine.get_name( "foo.test" )
    if name_rec is None:
        print "name does not exist"
        return False 

    # owned 
    if name_rec['address'] != wallets[3].addr or name_rec['sender'] != pybitcoin.make_pay_to_address_script(wallets[3].addr):
        print "name has wrong owner"
        return False 

    # have right hash 
    if name_rec['value_hash'] != last_hash:
        print "Invalid zonefile hash (%s != %s)" % (name_rec['value_hash'], last_hash)
        return False 

    # have no data 
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    for i in xrange(0, len(datasets)):
        immutable_data = blockstack_client.get_immutable( "foo.test", zonefile_hashes[i] )
        if immutable_data is not None and 'error' not in immutable_data:
            print "still have data for dataset %s\n%s" % (i, json.dumps(immutable_data,indent=4,sort_keys=True))
            return False 

        if immutable_data['error'] != 'No such immutable datum':
            print json.dumps(immutable_data,indent=4,sort_keys=True)
            return False

        immutable_data_by_name = blockstack_client.get_immutable_by_name( "foo.test", "hello_world_%s" % (i+1) )
        if immutable_data_by_name is not None and 'error' not in immutable_data:
            print "still have data for dataset hello_world_%s\n%s" % (i, json.dumps(immutable_data,indent=4,sort_keys=True))
            return False 

        if immutable_data['error'] != 'No such immutable datum':
            print json.dumps(immutable_data,indent=4,sort_keys=True)
            return False

    return True
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, key_names, error, gpghome


    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.blockstack_name_preorder( "bar.test", wallets[5].privkey, wallets[6].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.blockstack_name_register( "bar.test", wallets[5].privkey, wallets[6].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, data_privkey=wallets[4].privkey )
    wallet_keys_2 = blockstack_client.make_wallet_keys( owner_privkey=wallets[6].privkey, data_privkey=wallets[7].privkey )

    # migrate profiles 
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    res = testlib.migrate_profile( "bar.test", proxy=test_proxy, wallet_keys=wallet_keys_2 )
    if 'error' in res:
        res['test'] = 'Failed to initialize bar.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block( **kw )

    # add account keys 
    res = blockstack_gpg.gpg_profile_create_key( "foo.test", "foo_test_account_key", immutable=False,
                                                proxy=test_proxy, wallet_keys=wallet_keys, config_dir=testlib.get_working_dir(**kw),
                                                gpghome=testlib.gpg_key_dir(**kw), use_key_server=False )

    if 'error' in res:
        res['test'] = 'Failed to create foo.test account key'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    else:
        key_names['foo.test'].append( res )

    res = blockstack_gpg.gpg_profile_create_key( "bar.test", "bar_test_account_key", immutable=False,
                                                proxy=test_proxy, wallet_keys=wallet_keys_2, config_dir=testlib.get_working_dir(**kw),
                                                gpghome=testlib.gpg_key_dir(**kw), use_key_server=False )

    if 'error' in res:
        res['test'] = 'Failed to create bar.test account key'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    else:
        key_names['bar.test'].append( res )

    testlib.next_block( **kw )

    # add immutable app keys 
    res = blockstack_gpg.gpg_app_create_key( "foo.test", "secure_messaging", "foo_test_immutable_secmsg_key", immutable=True,
                                              proxy=test_proxy, wallet_keys=wallet_keys, config_dir=testlib.get_working_dir(**kw) )

    if 'error' in res:
        res['test'] = 'Failed to create foo.test immutable app key'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 
    else:
        key_names['foo.test'].append( res )

    testlib.next_block( **kw )
    res = blockstack_gpg.gpg_app_create_key( "bar.test", "secure_messaging", "bar_test_immutable_secmsg_key", immutable=True,
                                                proxy=test_proxy, wallet_keys=wallet_keys_2, config_dir=testlib.get_working_dir(**kw) )

    if 'error' in res:
        res['test'] = 'Failed to create bar.test immutable app key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True
        return
    else:
        key_names['bar.test'].append( res )

    testlib.next_block( **kw )

    # add mutable app keys 
    res = blockstack_gpg.gpg_app_create_key( "foo.test", "less-secure_messaging", "foo_test_mutable_secmsg_key",
                                                proxy=test_proxy, wallet_keys=wallet_keys, config_dir=testlib.get_working_dir(**kw) )

    if 'error' in res:
        res['test'] = 'Failed to create foo.test mutable app key'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return
    else:
        key_names['foo.test'].append( res )

    testlib.next_block( **kw )
    res = blockstack_gpg.gpg_app_create_key( "bar.test", "less-secure_messaging", "bar_test_mutable_secmsg_key",
                                                proxy=test_proxy, wallet_keys=wallet_keys_2, config_dir=testlib.get_working_dir(**kw) )

    if 'error' in res:
        res['test'] = 'Failed to create bar.test mutable app key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True
        return
    else:
        key_names['bar.test'].append( res )

    testlib.next_block( **kw )

    # add profile keys that we'll delete
    res = blockstack_gpg.gpg_profile_create_key( "foo.test", "foo_test_deleted_account_key", immutable=True,
                                                proxy=test_proxy, wallet_keys=wallet_keys, config_dir=testlib.get_working_dir(**kw),
                                                gpghome=testlib.gpg_key_dir(**kw), use_key_server=False)

    foo_profile_delete_key_id = None
    if 'error' in res:
        res['test'] = 'Failed to create deletable foo.test account key'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return
    else:
        key_names['foo.test'].append( res )
        foo_profile_delete_key_id = res['key_id']

    testlib.next_block( **kw )
    res = blockstack_gpg.gpg_profile_create_key( "bar.test", "bar_test_deleted_account_key", immutable=True,
                                                proxy=test_proxy, wallet_keys=wallet_keys_2, config_dir=testlib.get_working_dir(**kw),
                                                gpghome=testlib.gpg_key_dir(**kw), use_key_server=False)

    bar_profile_delete_key_id = None
    if 'error' in res:
        res['test'] = 'Failed to create deletable bar.test account key'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return
    else:
        key_names['bar.test'].append( res )
        bar_profile_delete_key_id = res['key_id']

    testlib.next_block( **kw )

    # add immutable app keys, which we can delete
    res = blockstack_gpg.gpg_app_create_key( "foo.test", "immutable_delete", "foo_test_deleted_immutable_secmsg_key", immutable=True,
                                                proxy=test_proxy, wallet_keys=wallet_keys, config_dir=testlib.get_working_dir(**kw) )

    foo_immutable_delete_key_id = None
    if 'error' in res:
        res['test'] = 'Failed to create deletable foo.test immutable app key'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return
    else:
        key_names['foo.test'].append( res )
        foo_immutable_delete_key_id = res['key_id']

    testlib.next_block( **kw )
    res = blockstack_gpg.gpg_app_create_key( "bar.test", "immutable_delete", "bar_test_deleted_immutable_secmsg_key", immutable=True,
                                                proxy=test_proxy, wallet_keys=wallet_keys_2, config_dir=testlib.get_working_dir(**kw) )
    
    bar_immutable_delete_key_id = None
    if 'error' in res:
        res['test'] = 'Failed to create deletable bar.test immutable app key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True
        return
    else:
        key_names['bar.test'].append( res )
        bar_immutable_delete_key_id = res['key_id']

    testlib.next_block( **kw )

    # add mutable app keys which we can delete
    res = blockstack_gpg.gpg_app_create_key( "foo.test", "mutable_delete", "foo_test_deleted_mutable_secmsg_key",
                                                proxy=test_proxy, wallet_keys=wallet_keys, config_dir=testlib.get_working_dir(**kw) )

    foo_mutable_delete_key_id = None
    if 'error' in res:
        res['test'] = 'Failed to create deletable mutable foo.test app key'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return
    else:
        key_names['foo.test'].append( res )
        foo_mutable_delete_key_id = res['key_id']

    testlib.next_block( **kw )
    res = blockstack_gpg.gpg_app_create_key( "bar.test", "mutable_delete", "bar_test_deleted_mutable_secmsg_key",
                                                proxy=test_proxy, wallet_keys=wallet_keys_2, config_dir=testlib.get_working_dir(**kw) )

    bar_mutable_delete_key_id = None
    if 'error' in res:
        res['test'] = 'Failed to create deletable mutable bar.test app key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True
        return
    else:
        key_names['bar.test'].append( res )
        bar_mutable_delete_key_id = res['key_id']

    testlib.next_block( **kw )

    # delete profile keys
    res = blockstack_gpg.gpg_profile_delete_key( "foo.test", foo_profile_delete_key_id, proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to create deletable account foo.test profile key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True
        return

    testlib.next_block( **kw )
    res = blockstack_gpg.gpg_profile_delete_key( "bar.test", bar_profile_delete_key_id, proxy=test_proxy, wallet_keys=wallet_keys_2 )
    if 'error' in res:
        res['test'] = 'Failed to create deletable account bar.test profile key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True
        return 

    # delete immutable app keys 
    res = blockstack_gpg.gpg_app_delete_key( "foo.test", "immutable_delete", "foo_test_deleted_immutable_secmsg_key", 
                                            immutable=True, proxy=test_proxy, wallet_keys=wallet_keys, config_dir=testlib.get_working_dir(**kw))

    if 'error' in res:
        res['test'] = 'Failed to create deletable foo.test immutable app key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True
        return 

    testlib.next_block( **kw )
    res = blockstack_gpg.gpg_app_delete_key( "bar.test", "immutable_delete", "bar_test_deleted_immutable_secmsg_key",
                                            immutable=True, proxy=test_proxy, wallet_keys=wallet_keys_2, config_dir=testlib.get_working_dir(**kw))

    if 'error' in res:
        res['test'] = 'Failed to create deletable bar.test immutable app key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True
        return 

    testlib.next_block( **kw )

    # delete mutable app keys
    res = blockstack_gpg.gpg_app_delete_key( "foo.test", "mutable_delete", "foo_test_deleted_mutable_secmsg_key",
                                            proxy=test_proxy, wallet_keys=wallet_keys, config_dir=testlib.get_working_dir(**kw))

    if 'error' in res:
        res['test'] = 'Failed to create deletable foo.test mutable app key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True 
        return 

    testlib.next_block( **kw )
    res = blockstack_gpg.gpg_app_delete_key( "bar.test", "mutable_delete", "bar_test_deleted_mutable_secmsg_key",
                                            proxy=test_proxy, wallet_keys=wallet_keys_2, config_dir=testlib.get_working_dir(**kw))

    if 'error' in res:
        res['test'] = 'Failed to create deletable bar.test mutable app key'
        print json.dumps(res, indent=4, sort_keys=True )
        error = True 
        return 

    testlib.next_block( **kw )
 
    gpghome = testlib.gpg_key_dir(**kw)
def scenario( wallets, **kw ):

    global synchronized, value_hash

    import blockstack_integration_tests.atlas_network as atlas_network

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    # set up RPC daemon
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, data_privkey=wallets[4].privkey, payment_privkey=wallets[5].privkey )
    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallet_keys['payment_privkey'], wallet_keys['owner_privkey'], wallet_keys['data_privkey'] )

    # start up a simple Atlas test network with two nodes: the main one doing the test, and a subordinate one that treats it as a seed peer.
    network_des = atlas_network.atlas_network_build( [17000], {17000: [16264]}, {}, os.path.join( testlib.working_dir(**kw), "atlas_network" ))
    atlas_network.atlas_network_start( network_des )

    time.sleep(5.0)
    
    # make an empty zonefile
    data_pubkey = virtualchain.BitcoinPrivateKey(wallet_keys['data_privkey']).public_key().to_hex()
    empty_zonefile = blockstack_client.user.make_empty_user_zonefile( "foo.test", data_pubkey, urls=["file:///tmp/foo.test"] )
    empty_zonefile_str = json.dumps(empty_zonefile) 
    value_hash = blockstack_client.hash_zonefile( empty_zonefile )

    # propagate the zonefile
    res = testlib.blockstack_cli_update( "foo.test", empty_zonefile_str, "0123456789abcdef" )
    if 'error' in res:
        raise Exception("Failed to update: %s" % res['error'])

    for i in xrange(0, 12):
        testlib.next_block( **kw )
        
    print "Waiting for zonefile propagation"
    time.sleep(10.0)

    # wait at most 10 seconds for atlas network to converge
    synchronized = False
    for i in xrange(0, 10):
        atlas_network.atlas_print_network_state( network_des )
        if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block( **kw ) - 1, 1 ):
            print "Synchronized!"
            synchronized = True
            break

        else:
            time.sleep(1.0)
    
    # shut down 
    atlas_network.atlas_network_stop( network_des )
    return synchronized
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, key_names, error


    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, payment_privkey=wallets[5].privkey )

    # migrate profiles 
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()

    testlib.next_block( **kw )

    data_pk = wallets[4].privkey
    data_pub = wallets[4].pubkey_hex

    res = blockstack_client.create_app_account("foo.test", "serviceFoo", "serviceFooID", "foo://bar.com", ["disk"], data_pub, proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to create foo.test account'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return
    
    # put some data into the account
    res = blockstack_client.put_app_data( "foo.test", "serviceFoo", "serviceFooID", "foo_data", "foo_payload", data_pk, proxy=test_proxy )
    if 'error' in res:
        res['test'] = 'Failed to put app data'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return
    
    # put some data to delete into the account
    res = blockstack_client.put_app_data( "foo.test", "serviceFoo", "serviceFooID", "foo_data_delete", "foo_payload_delete", data_pk, proxy=test_proxy )
    if 'error' in res:
        res['test'] = 'Failed to put app data'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    res = blockstack_client.delete_app_data( "foo.test", "serviceFoo", "serviceFooID", "foo_data_delete", data_pk, proxy=test_proxy )
    if 'error' in res:
        res['test'] = 'Failed to put app data'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block( **kw )
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

    wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[4].privkey )
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    # migrate profiles 
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    testlib.next_block( **kw )

    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)

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

    ses = res['token']

    # for funsies, get the price of .test
    res = testlib.blockstack_REST_call('GET', '/v1/prices/namespaces/test', ses )
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get price of .test'
        print json.dumps(res)
        return False

    test_price = res['response']['satoshis']
    print '\n\n.test costed {} satoshis\n\n'.format(test_price)

    # get the price for bar.test
    res = testlib.blockstack_REST_call('GET', '/v1/prices/names/bar.test', ses )
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get price of bar.test'
        print json.dumps(res)
        return False

    bar_price = res['response']['total_estimated_cost']['satoshis']
    print "\n\nbar.test will cost {} satoshis\n\n".format(bar_price)

    # register the name bar.test. autogenerate the rest 
    res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data={'name': 'bar.test'} )
    if 'error' in res:
        res['test'] = 'Failed to register user'
        print json.dumps(res)
        error = True
        return False

    print res
    tx_hash = res['response']['transaction_hash']

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

    res = testlib.verify_in_queue(ses, 'bar.test', 'preorder', tx_hash )
    if not res:
        return False

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

    # wait for register to go through 
    print 'Wait for register to be submitted'
    time.sleep(10)

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

    res = testlib.verify_in_queue(ses, 'bar.test', 'register', None )
    if not res:
        return False

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

    print 'Wait for update to be submitted'
    time.sleep(10)

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

    res = testlib.verify_in_queue(ses, 'bar.test', 'update', None )
    if not res:
        return False

    for i in xrange(0, 12):
        testlib.next_block( **kw )
  
    print 'Wait for update to be confirmed'
    time.sleep(10)

    res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", ses)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name bar.test'
        print json.dumps(res)
        return False

    zonefile_hash = res['response']['zonefile_hash']

    # do we have the history for the name?
    res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history", ses )
    if 'error' in res or res['http_status'] != 200:
        res['test'] = "Failed to get name history for bar.test"
        print json.dumps(res)
        return False

    # valid history?
    hist = res['response']
    if len(hist.keys()) != 3:
        res['test'] = 'Failed to get update history'
        res['history'] = hist
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    # get the zonefile
    res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/zonefile/{}".format(zonefile_hash), ses )
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name zonefile'
        print json.dumps(res)
        return False
def scenario(wallets, **kw):

    global datasets

    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("foo.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.next_block(**kw)

    testlib.blockstack_name_register("foo.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.next_block(**kw)

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy(test_proxy)
    wallet_keys = blockstack_client.make_wallet_keys(
        owner_privkey=wallets[3].privkey)

    # migrate profile (but no data key)
    res = testlib.migrate_profile("foo.test",
                                  proxy=test_proxy,
                                  wallet_keys=wallet_keys)
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block(**kw)

    # put immutable (with owner key)
    log.debug("put immutable 1 with owner key")
    put_result = blockstack_client.put_immutable(
        "foo.test",
        "hello_world_1_immutable",
        datasets[0],
        data_url="http://www.example.unroutable",
        proxy=test_proxy,
        wallet_keys=wallet_keys)
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block(**kw)

    # put immutable (with owner key)
    log.debug("put immutable 2 with owner key")
    put_result = blockstack_client.put_immutable(
        "foo.test",
        "hello_world_2_immutable",
        datasets[1],
        data_url="http://www.example.unroutable",
        proxy=test_proxy,
        wallet_keys=wallet_keys)
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block(**kw)

    # put mutable (with owner key)
    log.debug("put mutable 1 with owner key")
    put_result = blockstack_client.put_mutable("foo.test",
                                               "hello_world_1_mutable",
                                               datasets[0],
                                               proxy=test_proxy,
                                               wallet_keys=wallet_keys)
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        error = True
        return

    # put mutable (with owner key)
    log.debug("put mutable 2 with owner key")
    put_result = blockstack_client.put_mutable("foo.test",
                                               "hello_world_2_mutable",
                                               datasets[1],
                                               proxy=test_proxy,
                                               wallet_keys=wallet_keys)
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block(**kw)

    # add data signing key
    res = blockstack_client.set_data_pubkey("foo.test",
                                            wallets[4].pubkey_hex,
                                            wallet_keys=wallet_keys,
                                            proxy=test_proxy)
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    wallet_keys['data_privkey'] = wallets[4].privkey
    wallet_keys['data_pubkey'] = wallets[4].pubkey_hex

    testlib.next_block(**kw)

    # put immutable (with new key)
    log.debug("put immutable with new key")
    put_result = blockstack_client.put_immutable(
        "foo.test",
        "hello_world_3_immutable",
        datasets[2],
        data_url="http://www.example.unroutable",
        proxy=test_proxy,
        wallet_keys=wallet_keys)
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block(**kw)

    # put mutable (with new key)
    log.debug("put mutable with new key")
    put_result = blockstack_client.put_mutable("foo.test",
                                               "hello_world_3_mutable",
                                               datasets[2],
                                               proxy=test_proxy,
                                               wallet_keys=wallet_keys)
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block(**kw)

    # delete immutable (new key)
    log.debug("delete immutable with new key")
    result = blockstack_client.delete_immutable(
        "foo.test",
        None,
        data_id="hello_world_1_immutable",
        proxy=test_proxy,
        wallet_keys=wallet_keys)
    if 'error' in result:
        print json.dumps(result, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block(**kw)

    # delete mutable (new key)
    log.debug("delete mutable with new key")
    result = blockstack_client.delete_mutable("foo.test",
                                              "hello_world_1_mutable",
                                              proxy=test_proxy,
                                              wallet_keys=wallet_keys)
    if 'error' in result:
        print json.dumps(result, indent=4, sort_keys=True)
        error = True
        return

    testlib.next_block(**kw)
def scenario( wallets, **kw ):

    global wallet_keys, error, index_file_data, resource_data

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )
    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey, data_privkey=wallets[4].privkey, payment_privkey=wallets[5].privkey )
    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallet_keys['payment_privkey'], wallet_keys['owner_privkey'], wallet_keys['data_privkey'] )

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    # migrate profiles 
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 
    
    res = testlib.start_api("0123456789abcdef")
    if 'error' in res:
        print 'failed to start API: {}'.format(res)
        return False

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    testlib.next_block( **kw )
   
    # sign in and make a token 
    datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex()
    res = testlib.blockstack_cli_app_signin("foo.test", datastore_pk, 'http://localhost:8888', ['store_read', 'store_write', 'store_admin'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    # export to environment 
    blockstack_client.set_secret("BLOCKSTACK_API_SESSION", res['token'])
    
    ses = res['token']

    datastore_id_res = testlib.blockstack_cli_datastore_get_id( datastore_pk )
    datastore_id = datastore_id_res['datastore_id']

    # use random data for file 
    file_data = None
    with open('/dev/urandom', 'r') as f:
        file_data = f.read(16384)

    # make datastore 
    res = testlib.blockstack_cli_create_datastore( 'foo.test', datastore_pk, ['disk'], ses )
    if 'error' in res:
        print "failed to create datastore: {}".format(res['error'])
        return False

    # make directories
    for dpath in ['/dir1', '/dir2', '/dir1/dir3', '/dir1/dir3/dir4']:
        print 'mkdir {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_mkdir( "foo.test", datastore_pk, dpath, ses )
        if 'error' in res:
            print 'failed to mkdir {}: {}'.format(dpath, res['error'])
            return False

    # make directories again (should fail with EEXIST)
    for dpath in ['/dir1', '/dir2', '/dir1/dir3', '/dir1/dir3/dir4']:
        print 'mkdir {} (should fail)'.format(dpath)
        res = testlib.blockstack_cli_datastore_mkdir( "foo.test", datastore_pk, dpath, ses )
        if 'error' not in res:
            print 'accidentally succeeded to mkdir {}: {}'.format(dpath, res)
            return False

        if not res.has_key('errno'):
            print 'no errno in error {}'.format(res)
            return False

        if res['errno'] != errno.EEXIST:
            print 'wrong errno in error {}'.format(res)
            return False

    # stat directories 
    for dpath in ['/dir1', '/dir2', '/dir1/dir3', '/dir1/dir3/dir4']:
        print 'stat {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_stat( "foo.test", datastore_id, dpath, None )
        if 'error' in res:
            print 'failed to stat {}: {}'.format(dpath, res['error'])
            return False

        if res['type'] != blockstack_client.schemas.MUTABLE_DATUM_DIR_TYPE:
            print 'not a directory: {}, {}'.format(dpath, res)
            return False

    # list directories 
    for dpath, expected in [('/', ['dir1', 'dir2']), ('/dir1', ['dir3']), ('/dir1/dir3', ['dir4']), ('/dir1/dir3/dir4', [])]:
        print 'listdir {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_listdir( "foo.test", datastore_id, dpath, None )
        if 'error' in res:
            print 'failed to listdir {}: {}'.format(dpath, res['error'])
            return False

        print res
        if len(res['children'].keys()) != len(expected):
            print 'invalid directory: expected:\n{}\ngot:\n{}\n'.format(expected, res)
            return False

        for child in expected: 
            if not res['children'].has_key(child):
                print 'invalid directory: missing {} in {}'.format(child, res)
                return False

    # put files 
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'putfile {}'.format(dpath)
        data = '{} hello {}'.format(file_data, dpath)
        res = testlib.blockstack_cli_datastore_putfile( "foo.test", datastore_pk, dpath, data, ses )
        if 'error' in res:
            print 'failed to putfile {}: {}'.format(dpath, res['error'])
            return False

    # stat files
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'stat {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_stat( "foo.test", datastore_id, dpath, None )
        if 'error' in res:
            print 'failed to stat {}: {}'.format(dpath, res['error'])
            return False

        if res['type'] != blockstack_client.schemas.MUTABLE_DATUM_FILE_TYPE:
            print 'not a file: {}, {}'.format(dpath, res)
            return False

    # list directories again 
    for dpath, expected in [('/', ['dir1', 'dir2', 'file1', 'file2']), ('/dir1', ['dir3', 'file3']), ('/dir1/dir3', ['dir4', 'file4']), ('/dir1/dir3/dir4', ['file5'])]:
        print 'listdir {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_listdir( "foo.test", datastore_id, dpath, None )
        if 'error' in res:
            print 'failed to listdir {}: {}'.format(dpath, res['error'])
            return False

        if len(res['children'].keys()) != len(expected):
            print 'invalid directory: expected:\n{}\ngot:\n{}\n'.format(expected, res)
            return False

        for child in expected: 
            if not res['children'].has_key(child):
                print 'invalid directory: missing {} in {}'.format(child, res)
                return False
     
    # get files
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'getfile {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_getfile( "foo.test", datastore_id, dpath, None )
        if 'error' in res:
            print 'failed to getfile {}: {}'.format(dpath, res['error'])
            return False

        if res != '{} hello {}'.format(file_data, dpath):
            print 'failed to read {}'.format(dpath)
            return False

    # put files again! 
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'putfile {}'.format(dpath)
        data = '{} hello 2 {}'.format(file_data, dpath)
        res = testlib.blockstack_cli_datastore_putfile( "foo.test", datastore_pk, dpath, data, ses )
        if 'error' in res:
            print 'failed to putfile {}: {}'.format(dpath, res['error'])
            return False

    # get files again!
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'getfile {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_getfile( "foo.test", datastore_id, dpath, None )
        if 'error' in res:
            print 'failed to getfile {}: {}'.format(dpath, res['error'])
            return False

        if res != '{} hello 2 {}'.format(file_data, dpath):
            print 'failed to read {}'.format(dpath)
            return False

    # remove files
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'deletefile {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_deletefile( "foo.test", datastore_pk, dpath, ses )
        if 'error' in res:
            print 'failed to deletefile {}: {}'.format(dpath, res['error'])
            return False

    # stat files (should all fail)
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'stat {} (expect failure)'.format(dpath)
        res = testlib.blockstack_cli_datastore_stat( "foo.test", datastore_id, dpath, None )
        if 'error' not in res or 'errno' not in res:
            print 'accidentally succeeded to stat {}: {}'.format(dpath, res)
            return False

        if res['errno'] != errno.ENOENT:
            print 'wrong errno: {}'.format(res)
            return False
 
    # get files (should all fail)
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'getfile {} (expect failure)'.format(dpath)
        res = testlib.blockstack_cli_datastore_getfile( "foo.test", datastore_id, dpath, None )
        if 'error' not in res or 'errno' not in res:
            print 'accidentally succeeded to get {}: {}'.format(dpath, res)
            return False

        if res['errno'] != errno.ENOENT:
            print 'wrong errno: {}'.format(res)
            return False

    # list directories, 3rd time 
    for dpath, expected in [('/', ['dir1', 'dir2']), ('/dir1', ['dir3']), ('/dir1/dir3', ['dir4']), ('/dir1/dir3/dir4', [])]:
        print 'listdir {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_listdir( "foo.test", datastore_id, dpath, None )
        if 'error' in res:
            print 'failed to listdir {}: {}'.format(dpath, res['error'])
            return False

        if len(res['children'].keys()) != len(expected):
            print 'invalid directory: expected:\n{}\ngot:\n{}\n'.format(expected, res)
            return False

        for child in expected: 
            if not res['children'].has_key(child):
                print 'invalid directory: missing {} in {}'.format(child, res)
                return False

    # remove directories 
    for dpath in ['/dir1/dir3/dir4', '/dir1/dir3', '/dir2', '/dir1']:
        print 'rmdir {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_rmdir( "foo.test", datastore_pk, dpath, ses )
        if 'error' in res:
            print 'failed to rmdir {}: {}'.format(dpath, res['error'])
            return False

    # stat directories (should all fail)
    for dpath in ['/dir1/dir3/dir4', '/dir1/dir3', '/dir2', '/dir1']:
        print 'stat {} (expect failure)'.format(dpath)
        res = testlib.blockstack_cli_datastore_stat( "foo.test", datastore_id, dpath, None )
        if 'error' not in res or 'errno' not in res:
            print 'accidentally succeeded to stat {}: {}'.format(dpath, res)
            return False

        if res['errno'] != errno.ENOENT:
            print 'wrong errno: {}'.format(res)
            return False

    # list directories (should all fail) 
    for dpath, expected in [('/dir1', ['dir3']), ('/dir1/dir3', ['dir4']), ('/dir1/dir3/dir4', [])]:
        print 'listdir {} (expect failure)'.format(dpath)
        res = testlib.blockstack_cli_datastore_listdir( "foo.test", datastore_id, dpath, None )
        if 'error' not in res or 'errno' not in res:
            print 'accidentally succeeded to list {}: {}'.format(dpath, res)
            return False

        if res['errno'] != errno.ENOENT:
            print 'wrong errno: {}'.format(res)
            return False

    # remove directories again (should fail) 
    for dpath in ['/dir1/dir3/dir4', '/dir1/dir3', '/dir2', '/dir1']:
        print 'rmdir {} (expect failure)'.format(dpath)
        res = testlib.blockstack_cli_datastore_rmdir( "foo.test", datastore_pk, dpath, ses )
        if 'error' not in res:
            print 'accidentally succeeded to rmdir twice: {}'.format(res)
            return False

        if res.get('errno') != errno.ENOENT:
            print 'wrong errno on rmdir: {}'.format(res)
            return False

    # root should be empty 
    print 'listdir {}'.format('/')
    res = testlib.blockstack_cli_datastore_listdir( "foo.test", datastore_id, '/', None )
    if 'error' in res:
        print 'failed to listdir /: {}'.format(res['error'])
        return False

    if len(res['children'].keys()) > 0:
        print 'root still has children: {}'.format(res['children'].keys())
        return False

    # delete datastore 
    print 'delete datastore'
    res = testlib.blockstack_cli_delete_datastore( "foo.test", datastore_pk, ses )
    if 'error' in res:
        print 'failed to delete foo-app.com datastore'
        print json.dumps(res)
        return False

    # no more data in disk driver 
    names = os.listdir("/tmp/blockstack-disk/mutable")
    if names != ['foo.test']:
        print 'improper cleanup'
        return False

    testlib.next_block( **kw )
def scenario( wallets, **kw ):

    global datasets, zonefile_hashes, put_result, last_hash

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    wallet_keys = blockstack_client.make_wallet_keys( owner_privkey=wallets[3].privkey )

    # migrate profile
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    testlib.next_block( **kw )

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_1", datasets[0], proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    zonefile_hashes.append( put_result['immutable_data_hash'] )

    testlib.next_block( **kw )

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_2", datasets[1], proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    zonefile_hashes.append( put_result['immutable_data_hash'] )

    testlib.next_block( **kw )

    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_3", datasets[2], proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)

    zonefile_hashes.append( put_result['immutable_data_hash'] )

    testlib.next_block( **kw )

    # should fail (name collision)
    datasets[0]['newdata'] = "asdf"
    put_result = blockstack_client.put_immutable( "foo.test", "hello_world_1", datasets[0], proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' not in put_result:
        zonefile_hashes[0] = put_result['immutable_data_hash']

    del datasets[0]['newdata']

    testlib.next_block( **kw )

    # delete everything
    for i in xrange(0, len(datasets)):
        print "delete %s" % zonefile_hashes[i]
        put_result = blockstack_client.delete_immutable( "foo.test", zonefile_hashes[i], wallet_keys=wallet_keys )
        if 'error' in put_result:
            print json.dumps(put_result, indent=4, sort_keys=True)

        testlib.next_block(**kw)

    last_hash = put_result['zonefile_hash']
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

    wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[4].privkey )
    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    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( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )

    test_proxy = testlib.TestAPIProxy()
    blockstack_client.set_default_proxy( test_proxy )

    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[4].privkey )
    
    # migrate profiles 
    res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys )
    if 'error' in res:
        res['test'] = 'Failed to initialize foo.test profile'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    testlib.next_block( **kw )

    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)

    # make a session 
    datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex()
    res = testlib.blockstack_cli_app_signin(datastore_pk, 'register.app', ['names', 'register', 'prices', 'zonefiles', 'blockchain', 'node_read', 'store_admin', 'store_read', 'store_write'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    ses = res['token']

    # make a datastore 
    res = testlib.blockstack_REST_call('POST', '/v1/stores', ses )
    if 'error' in res or res['http_status'] != 200:
        print 'failed to create datastore'
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    # get the data store id
    res = testlib.blockstack_REST_call('GET', '/v1/stores/register.app', ses)
    if 'error' in res or res['http_status'] != 200:
        print 'failed to get store'
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    if 'error' in res['response']:
        print 'failed to get datastore'
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    datastore_info = res['response']
    datastore_name = datastore_info['datastore_id']

    # get the data store name
    res = testlib.blockstack_REST_call('GET', '/v1/stores/register.app', ses)
    if 'error' in res or res['http_status'] != 200:
        print 'failed to get datastore'
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    if 'error' in res['response']:
        print 'failed to get datastore'
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    datastore_info = res['response']
    datastore_name = datastore_info['datastore_id']

    # make directories
    for dpath in ['/dir1', '/dir2', '/dir1/dir3', '/dir1/dir3/dir4']:
        print 'mkdir {}'.format(dpath)
        res = testlib.blockstack_REST_call('POST', '/v1/stores/{}/directories'.format(datastore_name), ses, path=dpath)
        if 'error' in res or res['http_status'] != 200:
            print 'failed to mkdir {}: {}'.format(dpath, res['http_status'])
            return False

    # stat directories 
    for dpath in ['/dir1', '/dir2', '/dir1/dir3', '/dir1/dir3/dir4']:
        print 'stat {}'.format(dpath)
        res = testlib.blockstack_REST_call('GET', '/v1/stores/{}/inodes'.format(datastore_name), ses, path=dpath)
        if 'error' in res or res['http_status'] != 200:
            print 'failed to stat {}: {}'.format(dpath, res['http_status'])
            return False

        inode_info = res['response']
        if inode_info['type'] != blockstack_client.schemas.MUTABLE_DATUM_DIR_TYPE:
            print 'not a directory: {}, {}'.format(dpath, res)
            return False

    # list directories 
    for dpath, expected in [('/', ['dir1', 'dir2']), ('/dir1', ['dir3']), ('/dir1/dir3', ['dir4']), ('/dir1/dir3/dir4', [])]:
        print 'listdir {}'.format(dpath)
        res = testlib.blockstack_REST_call('GET', '/v1/stores/{}/directories'.format(datastore_name), ses, path=dpath)
        if 'error' in res or res['http_status'] != 200:
            print 'failed to listdir {}: {}'.format(dpath, res['http_status'])
            return False

        dirinfo = res['response']
        if len(dirinfo.keys()) != len(expected):
            print 'invalid directory: expected:\n{}\ngot:\n{}\n'.format(expected, dirinfo)
            return False

        for child in expected: 
            if not dirinfo.has_key(child):
                print 'invalid directory: missing {} in {}'.format(child, dirinfo)
                print json.dumps(res, indent=4, sort_keys=True)
                return False

    # put files 
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'putfile {}'.format(dpath)
        data = 'hello {}'.format(os.path.basename(dpath))
        res = testlib.blockstack_REST_call('POST', '/v1/stores/{}/files'.format(datastore_name), ses, raw_data=data, path=dpath)
        if 'error' in res or res['http_status'] != 200:
            print 'failed to putfile {}: {}'.format(dpath, res['http_status'])
            return False

    # stat files
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'stat {}'.format(dpath)
        res = testlib.blockstack_REST_call('GET', '/v1/stores/{}/inodes'.format(datastore_name), ses, path=dpath)
        if 'error' in res or res['http_status'] != 200:
            print 'failed to stat {}: {}'.format(dpath, res['http_status'])
            return False

        inode_data = res['response']
        if inode_data['type'] != blockstack_client.schemas.MUTABLE_DATUM_FILE_TYPE:
            print 'not a file: {}, {}'.format(dpath, res)
            return False

    # list directories again 
    for dpath, expected in [('/', ['dir1', 'dir2', 'file1', 'file2']), ('/dir1', ['dir3', 'file3']), ('/dir1/dir3', ['dir4', 'file4']), ('/dir1/dir3/dir4', ['file5'])]:
        print 'listdir {}'.format(dpath)
        res = testlib.blockstack_REST_call('GET', '/v1/stores/{}/directories'.format(datastore_name), ses, path=dpath)
        if 'error' in res or res['http_status'] != 200:
            print 'failed to listdir {}: {}'.format(dpath, res['http_status'])
            return False

        dirinfo = res['response']
        if len(dirinfo.keys()) != len(expected):
            print 'invalid directory: expected:\n{}\ngot:\n{}\n'.format(expected, dirinfo)
            return False

        for child in expected: 
            if not dirinfo.has_key(child):
                print 'invalid directory: missing {} in {}'.format(child, dirinfo)
                return False
     
    # get files
    for dpath in ['/file1', '/file2', '/dir1/file3', '/dir1/dir3/file4', '/dir1/dir3/dir4/file5']:
        print 'getfile {}'.format(dpath)
        res = testlib.blockstack_REST_call('GET', '/v1/stores/{}/files'.format(datastore_name), ses, path=dpath)
        if 'error' in res or res['http_status'] != 200:
            print 'failed to getfile {}: {}'.format(dpath, res['http_status'])
            return False

        filedata = res['raw']
        if filedata != 'hello {}'.format(os.path.basename(dpath)):
            print 'failed to read {}: got "{}"'.format(dpath, filedata)
            return False

    # delete datastore
    res = testlib.blockstack_REST_call("DELETE", "/v1/stores", ses)
    if res['http_status'] != 200:
        print 'failed to delete datastore'
        print json.dumps(res)
        return False

    # nothing should be here
    res = testlib.blockstack_REST_call('GET', '/v1/stores/{}/directories'.format(datastore_name), ses, path='/')
    if res['http_status'] != 404:
        print 'got HTTP {} on getting deleted store'.format(res['http_status'])
        print json.dumps(res)
        return False