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 wallet_keys, error, foo_output, bar_output, baz_output, config_paths

    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.blockstack_name_preorder("baz.test", wallets[8].privkey,
                                     wallets[9].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.blockstack_name_register("baz.test", wallets[8].privkey,
                                     wallets[9].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)
    wallet_keys['bar.test'] = blockstack_client.make_wallet_keys(
        owner_privkey=wallets[6].privkey)
    wallet_keys['baz.test'] = blockstack_client.make_wallet_keys(
        owner_privkey=wallets[9].privkey)

    # migrate profiles
    for name in ['foo.test', 'bar.test', 'baz.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 directory for each principal
    for name in ['foo.test', 'bar.test', 'baz.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

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

    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')
    baz_output = os.path.join(os.path.dirname(config_path), 'baz.test-out.txt')
    baz_fail_output = os.path.join(os.path.dirname(config_path),
                                   'baz.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

    res = blockstack_file.file_key_regenerate(
        "bar.test",
        "mobile-phone",
        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

    res = blockstack_file.file_key_regenerate(
        "baz.test",
        "laptop",
        config_path=config_paths['baz.test'],
        wallet_keys=wallet_keys['baz.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 and baz.test
    res = blockstack_file.file_put('foo.test',
                                   'localhost', ['bar.test', 'baz.test'],
                                   'config-file-from-foo.test',
                                   config_path,
                                   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

    # send a file from bar.test's mobile phone to foo.test (but not baz.test)
    res = blockstack_file.file_put('bar.test',
                                   'mobile-phone', ['foo.test'],
                                   'config-file-from-bar.test',
                                   config_path,
                                   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 baz.test's laptop to baz.test's laptop (and no one else)
    res = blockstack_file.file_put('baz.test',
                                   'laptop', [],
                                   'config-file-from-baz.test',
                                   config_path,
                                   config_path=config_paths['baz.test'],
                                   wallet_keys=wallet_keys['baz.test'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    # have foo.test receive bar.test's file
    log.debug("foo.test receives bar.test's file")
    res = blockstack_file.file_get('foo.test',
                                   'localhost',
                                   'bar.test',
                                   'config-file-from-bar.test',
                                   foo_output,
                                   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

    # have bar.test receive bar.test's file to localhost
    log.debug("bar.test receives bar.tests's file")
    res = blockstack_file.file_get('bar.test',
                                   'localhost',
                                   'bar.test',
                                   'config-file-from-bar.test',
                                   bar_output,
                                   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

    # have baz.test receive foo.test's file
    log.debug("baz.test recieves foo.test's file")
    res = blockstack_file.file_get('baz.test',
                                   'laptop',
                                   'foo.test',
                                   'config-file-from-foo.test',
                                   baz_output,
                                   config_path=config_paths['baz.test'],
                                   wallet_keys=wallet_keys['baz.test'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    # have bar.test receive foo.test's file to its mobile-phone key
    log.debug("bar.test receives foo.test's file")
    res = blockstack_file.file_get('bar.test',
                                   'mobile-phone',
                                   'foo.test',
                                   'config-file-from-foo.test',
                                   bar_output,
                                   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

    # have baz.test try to receive bar.test's file (should fail)
    log.debug("baz.test receives bar.test's file (should fail)")
    res = blockstack_file.file_get('baz.test',
                                   'laptop',
                                   'bar.test',
                                   'config-file-from-bar.test',
                                   baz_fail_output,
                                   config_path=config_paths['baz.test'],
                                   wallet_keys=wallet_keys['baz.test'])
    print json.dumps(res, indent=4, sort_keys=True)
    if 'error' not in res or res['error'] != 'Failed to decrypt data':
        print 'baz decrypting hidden file: succeeded when we should not have, or failed incorrectly: %s' % res
        error = True
        return

    # have foo.test and bar.test try to receive baz.test's file (should fail)
    for (name, failpath) in [('foo.test', foo_fail_output),
                             ('bar.test', bar_fail_output)]:
        log.debug("%s receives baz.test's file (should fail)" % name)
        res = blockstack_file.file_get(name,
                                       'localhost',
                                       'baz.test',
                                       'config-file-from-baz.test',
                                       failpath,
                                       config_path=config_paths[name],
                                       wallet_keys=wallet_keys[name])
        print json.dumps(res, indent=4, sort_keys=True)
        if 'error' not in res or res['error'] != 'Failed to decrypt data':
            print '%s decrypting hidden file: succeeded when we should not have, or fialed incorrectly: %s' % (
                name, res)
            error = True
            return

    # regenerate everyone's keys
    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

    res = blockstack_file.file_key_regenerate(
        "bar.test",
        "mobile-phone",
        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

    res = blockstack_file.file_key_regenerate(
        "baz.test",
        "laptop",
        config_path=config_paths['baz.test'],
        wallet_keys=wallet_keys['baz.test'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    # have foo.test receive bar.test's file, despite regeneration
    log.debug("foo.test receives bar.test's file, despite regeneration")
    res = blockstack_file.file_get('foo.test',
                                   'localhost',
                                   'bar.test',
                                   'config-file-from-bar.test',
                                   foo_output,
                                   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

    if 'warning' not in res or res['warning'] != 'Used stale key':
        print json.dumps(res, indent=4, sort_keys=True)
        print "did not use stale key"
        error = True
        return

    # have bar.test receive bar.test's file to localhost
    log.debug("bar.test receives bar.tests's file, despite regeneration")
    res = blockstack_file.file_get('bar.test',
                                   'localhost',
                                   'bar.test',
                                   'config-file-from-bar.test',
                                   bar_output,
                                   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

    if 'warning' not in res or res['warning'] != 'Used stale key':
        print json.dumps(res, indent=4, sort_keys=True)
        print "did not use stale key"
        error = True
        return

    # have baz.test receive foo.test's file
    log.debug("baz.test recieves foo.test's file, despite regeneration")
    res = blockstack_file.file_get('baz.test',
                                   'laptop',
                                   'foo.test',
                                   'config-file-from-foo.test',
                                   baz_output,
                                   config_path=config_paths['baz.test'],
                                   wallet_keys=wallet_keys['baz.test'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    if 'warning' not in res or res['warning'] != 'Used stale key':
        print json.dumps(res, indent=4, sort_keys=True)
        print "did not use stale key"
        error = True
        return

    # have bar.test receive foo.test's file to its mobile-phone key
    log.debug("bar.test receives foo.test's file, despite regeneration")
    res = blockstack_file.file_get('bar.test',
                                   'mobile-phone',
                                   'foo.test',
                                   'config-file-from-foo.test',
                                   bar_output,
                                   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

    if 'warning' not in res or res['warning'] != 'Used stale key':
        print json.dumps(res, indent=4, sort_keys=True)
        print "did not use stale key"
        error = True
        return

    # delete the file from foo
    log.debug("delete foo.test's file")
    res = blockstack_file.file_delete('foo.test',
                                      'config-file-from-foo.test',
                                      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

    # delete the file from bar
    log.debug("delete bar.test's file")
    res = blockstack_file.file_delete('bar.test',
                                      'config-file-from-bar.test',
                                      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

    # verify that no one can read foo's file
    for (name, host, failpath) in [('foo.test', 'localhost', foo_fail_output),
                                   ('bar.test', 'mobile-phone',
                                    bar_fail_output),
                                   ('baz.test', 'laptop', baz_fail_output)]:
        log.debug("%s receives foo.test's deleted file (should fail)" % name)
        res = blockstack_file.file_get(name,
                                       host,
                                       'foo.test',
                                       'config-file-from-foo.test',
                                       failpath,
                                       config_path=config_paths[name],
                                       wallet_keys=wallet_keys[name])
        print json.dumps(res, indent=4, sort_keys=True)
        if 'error' not in res or res['error'] != 'Failed to get encrypted file':
            print 'reading deleted file: succeeded when we should not have, or failed incorrectly: %s' % res
            error = True
            return
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,
        payment_privkey=wallets[8].privkey)
    wallet_keys['bar.test'] = blockstack_client.make_wallet_keys(
        owner_privkey=wallets[6].privkey,
        data_privkey=wallets[7].privkey,
        payment_privkey=wallets[9].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 wallet_keys, error, foo_output, bar_output, baz_output, config_paths

    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.blockstack_name_preorder( "baz.test", wallets[8].privkey, wallets[9].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.blockstack_name_register( "baz.test", wallets[8].privkey, wallets[9].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, payment_privkey=wallets[10].privkey )
    wallet_keys['bar.test'] = blockstack_client.make_wallet_keys( owner_privkey=wallets[6].privkey, payment_privkey=wallets[11].privkey )
    wallet_keys['baz.test'] = blockstack_client.make_wallet_keys( owner_privkey=wallets[9].privkey, payment_privkey=wallets[12].privkey )

    # migrate profiles 
    for name in ['foo.test', 'bar.test', 'baz.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 

    # tell serialization-checker that value_hash can be ignored here
    print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
    sys.stdout.flush()
    
    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 directory for each principal 
    for name in ['foo.test', 'bar.test', 'baz.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

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

    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' )
    baz_output = os.path.join( os.path.dirname(config_path), 'baz.test-out.txt' )
    baz_fail_output = os.path.join( os.path.dirname(config_path), 'baz.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

    res = blockstack_file.file_key_regenerate( "bar.test", "mobile-phone", 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

    res = blockstack_file.file_key_regenerate( "baz.test", "laptop", config_path=config_paths['baz.test'], wallet_keys=wallet_keys['baz.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 and baz.test 
    res = blockstack_file.file_put( 'foo.test', 'localhost', ['bar.test', 'baz.test'], 'config-file-from-foo.test', config_path, 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

    # send a file from bar.test's mobile phone to foo.test (but not baz.test)
    res = blockstack_file.file_put( 'bar.test', 'mobile-phone', ['foo.test'], 'config-file-from-bar.test', config_path, 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 baz.test's laptop to baz.test's laptop (and no one else)
    res = blockstack_file.file_put( 'baz.test', 'laptop', [], 'config-file-from-baz.test', config_path, config_path=config_paths['baz.test'], wallet_keys=wallet_keys['baz.test'] )
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    # have foo.test receive bar.test's file
    log.debug("foo.test receives bar.test's file")
    res = blockstack_file.file_get( 'foo.test', 'localhost', 'bar.test', 'config-file-from-bar.test', foo_output, 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

    # have bar.test receive bar.test's file to localhost 
    log.debug("bar.test receives bar.tests's file")
    res = blockstack_file.file_get( 'bar.test', 'localhost', 'bar.test', 'config-file-from-bar.test', bar_output, 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

    # have baz.test receive foo.test's file 
    log.debug("baz.test recieves foo.test's file")
    res = blockstack_file.file_get( 'baz.test', 'laptop', 'foo.test', 'config-file-from-foo.test', baz_output, config_path=config_paths['baz.test'], wallet_keys=wallet_keys['baz.test'] )
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    # have bar.test receive foo.test's file to its mobile-phone key
    log.debug("bar.test receives foo.test's file")
    res = blockstack_file.file_get( 'bar.test', 'mobile-phone', 'foo.test', 'config-file-from-foo.test', bar_output, 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

    # have baz.test try to receive bar.test's file (should fail)
    log.debug("baz.test receives bar.test's file (should fail)")
    res = blockstack_file.file_get( 'baz.test', 'laptop', 'bar.test', 'config-file-from-bar.test', baz_fail_output, config_path=config_paths['baz.test'], wallet_keys=wallet_keys['baz.test'] )
    print json.dumps(res, indent=4, sort_keys=True)
    if 'error' not in res or res['error'] != 'Failed to decrypt data':
        print 'baz decrypting hidden file: succeeded when we should not have, or failed incorrectly: %s' % res
        error = True
        return

    # have foo.test and bar.test try to receive baz.test's file (should fail)
    for (name, failpath) in [('foo.test', foo_fail_output), ('bar.test', bar_fail_output)]:
        log.debug("%s receives baz.test's file (should fail)" % name)
        res = blockstack_file.file_get( name, 'localhost', 'baz.test', 'config-file-from-baz.test', failpath, config_path=config_paths[name], wallet_keys=wallet_keys[name] )
        print json.dumps(res, indent=4, sort_keys=True)
        if 'error' not in res or res['error'] != 'Failed to decrypt data':
            print '%s decrypting hidden file: succeeded when we should not have, or fialed incorrectly: %s' % (name, res)
            error = True
            return

    # regenerate everyone's keys
    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

    res = blockstack_file.file_key_regenerate( "bar.test", "mobile-phone", 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

    res = blockstack_file.file_key_regenerate( "baz.test", "laptop", config_path=config_paths['baz.test'], wallet_keys=wallet_keys['baz.test'] )
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    # have foo.test receive bar.test's file, despite regeneration
    log.debug("foo.test receives bar.test's file, despite regeneration")
    res = blockstack_file.file_get( 'foo.test', 'localhost', 'bar.test', 'config-file-from-bar.test', foo_output, 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

    if 'warning' not in res or res['warning'] != 'Used stale key':
        print json.dumps(res, indent=4, sort_keys=True)
        print "did not use stale key"
        error = True
        return

    # have bar.test receive bar.test's file to localhost 
    log.debug("bar.test receives bar.tests's file, despite regeneration")
    res = blockstack_file.file_get( 'bar.test', 'localhost', 'bar.test', 'config-file-from-bar.test', bar_output, 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

    if 'warning' not in res or res['warning'] != 'Used stale key':
        print json.dumps(res, indent=4, sort_keys=True)
        print "did not use stale key"
        error = True
        return

    # have baz.test receive foo.test's file 
    log.debug("baz.test recieves foo.test's file, despite regeneration")
    res = blockstack_file.file_get( 'baz.test', 'laptop', 'foo.test', 'config-file-from-foo.test', baz_output, config_path=config_paths['baz.test'], wallet_keys=wallet_keys['baz.test'] )
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    if 'warning' not in res or res['warning'] != 'Used stale key':
        print json.dumps(res, indent=4, sort_keys=True)
        print "did not use stale key"
        error = True
        return

    # have bar.test receive foo.test's file to its mobile-phone key
    log.debug("bar.test receives foo.test's file, despite regeneration")
    res = blockstack_file.file_get( 'bar.test', 'mobile-phone', 'foo.test', 'config-file-from-foo.test', bar_output, 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

    if 'warning' not in res or res['warning'] != 'Used stale key':
        print json.dumps(res, indent=4, sort_keys=True)
        print "did not use stale key"
        error = True
        return

    # delete the file from foo
    log.debug("delete foo.test's file")
    res = blockstack_file.file_delete( 'foo.test', 'config-file-from-foo.test', 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 

    # delete the file from bar
    log.debug("delete bar.test's file")
    res = blockstack_file.file_delete( 'bar.test', 'config-file-from-bar.test', 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

    # verify that no one can read foo's file 
    for (name, host, failpath) in [('foo.test', 'localhost', foo_fail_output), ('bar.test', 'mobile-phone', bar_fail_output), ('baz.test', 'laptop', baz_fail_output)]:
        log.debug("%s receives foo.test's deleted file (should fail)" % name)
        res = blockstack_file.file_get( name, host, 'foo.test', 'config-file-from-foo.test', failpath, config_path=config_paths[name], wallet_keys=wallet_keys[name])
        print json.dumps(res, indent=4, sort_keys=True)
        if 'error' not in res or res['error'] != 'Failed to get encrypted file':
            print 'reading deleted file: succeeded when we should not have, or failed incorrectly: %s' % res
            error = True
            return