def check_wallet(payment_privkey, owner_privkey, data_privkey):
    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']

    res = testlib.blockstack_REST_call('GET',
                                       '/v1/wallet/keys',
                                       None,
                                       api_pass=api_pass)
    if 'error' in res:
        print 'failed to get wallet'
        print res
        return False

    res = res['response']
    if res['payment_privkey'] != payment_privkey:
        print 'wrong payment privkey'
        return False

    if res['owner_privkey'] != owner_privkey:
        print 'wrong owner privkey'
        return False

    if res['data_privkey'] != data_privkey:
        print 'wrong data privkey'
        return False

    return True
Exemple #2
0
def get_blockstack_client_session( new_blockstack_client_session_opts=None ):
    """
    Get or instantiate our storage API session.
    """
    global blockstack_client_session
    global blockstack_client_session_opts

    # do we have storage?
    if blockstack_client is None:
        return None

    opts = None
    if new_blockstack_client_session_opts is not None:
        opts = new_blockstack_client_session_opts
    else:
        opts = blockstack_client.get_config()

    if opts is None:
        return None

    blockstack_client_session = blockstack_client.session( conf=opts )
    if blockstack_client_session is not None:

        if new_blockstack_client_session_opts is not None:
            blockstack_client_session_opts = new_blockstack_client_session_opts

    return blockstack_client_session
def blockstack_app_session( blockchain_id, app_privkey, app_domain, config_path ):
    """
    Make a session for the given application
    Returns {'error': ...} on error
    """
    conf = blockstack_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']
    api_port = int(conf['api_endpoint_port'])

    req = {
        'version': 1,
        'blockchain_id': blockchain_id,
        'app_domain': app_domain,
        'app_public_keys': [{'public_key': virtualchain.lib.ecdsalib.get_pubkey_hex(app_privkey), 'device_id': '0'}],
        'methods': ['store_write'],
        'app_private_key': app_privkey,
        'device_id': '0',
    }

    signer = jsontokens.TokenSigner()
    token = signer.sign( req, app_privkey )

    url = 'http://localhost:{}/v1/auth?authRequest={}'.format(api_port, token)
    resp = requests.get( url, headers={'Authorization': 'bearer {}'.format(api_pass), 'Origin': 'http://localhost:8888'} )
    if resp.status_code != 200:
        print "GET {} status code {}".format(url, resp.status_code)
        return {'error': 'Failed to get session'}

    payload = resp.json()
    ses = payload['token']
    return {'ses': ses}
def check_wallet(payment_privkey, owner_privkey, data_privkey):
    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']

    res = testlib.blockstack_REST_call('GET', '/v1/wallet/keys', None, api_pass=api_pass)
    if 'error' in res:
        print 'failed to get wallet'
        print res
        return False

    res = res['response']
    if res['payment_privkey'] != payment_privkey:
        print 'wrong payment privkey'
        return False

    if res['owner_privkey'] != owner_privkey:
        print 'wrong owner privkey'
        return False

    if res['data_privkey'] != data_privkey:
        print 'wrong data privkey'
        return False

    return True
def get_blockstack_client_session( new_blockstack_client_session_opts=None ):
    """
    Get or instantiate our storage API session.
    """
    global blockstack_client_session
    global blockstack_client_session_opts

    # do we have storage?
    if blockstack_client is None:
        return None

    opts = None
    if new_blockstack_client_session_opts is not None:
        opts = new_blockstack_client_session_opts
    else:
        opts = blockstack_client.get_config()

    if opts is None:
        return None

    blockstack_client_session = blockstack_client.session( conf=opts )
    if blockstack_client_session is not None:

        if new_blockstack_client_session_opts is not None:
            blockstack_client_session_opts = new_blockstack_client_session_opts

    return blockstack_client_session
Exemple #6
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
Exemple #7
0
def get_config_dir(config_dir=None):
    """
    Get the default configuration directory.
    """
    if config_dir is None:
        config = get_config()
        config_dir = config['dir']

    return config_dir
Exemple #8
0
def get_config_dir( config_dir=None ):
    """
    Get the default configuration directory.
    """
    if config_dir is None:
        config = get_config()
        config_dir = config['dir']

    return config_dir
def blockstack_client_queue_state():
    """
    Get queue information from the client backend
    """
    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)
    assert config_path is not None

    conf = blockstack_client.get_config(config_path)
    queue_info = blockstack_client.backend.queue.get_queue_state(
        path=conf['queue_path'])
    return queue_info
def check(state_engine):

    global error
    global names, owner_wallets, payment_wallets, recipients

    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG")
    assert config_path
    config_dir = os.path.dirname(config_path)
    conf = blockstack_client.get_config(config_path)
    assert conf
    api_pass = conf['api_password']

    if error:
        print "Key operation failed."
        return False

    # 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

    for name, recipient in zip(names, recipients):
        res = testlib.blockstack_REST_call("GET",
                                           "/v1/names/{}".format(name),
                                           None,
                                           api_pass=api_pass)
        if 'error' in res or res['http_status'] != 200:
            res['test'] = 'Failed to get name {}'.format(name)
            print json.dumps(res)
            return False
        if 'address' not in res['response']:
            print res
            return False

        cur_owner_address = res['response']['address']
        if cur_owner_address != recipient:
            print "After transfer, unexpected owner. Expected {}, Actual {}".format(
                recipient, cur_owner_address)
            return False

    return True
Exemple #11
0
def scenario( wallets, **kw ):

    # save the wallet 
    wallet = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[2].privkey, wallets[3].privkey, wallets[4].privkey )
    if 'error' in wallet:
        print 'failed to set wallet: {}'.format(wallet)
        return False

    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']

    if not check_wallet(wallets[2].privkey, wallets[3].privkey, wallets[4].privkey):
        return False

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass, data=wallets[0].privkey)
    if 'error' in res:
        print 'failed to set owner key'
        print res
        return False
       
    if not check_wallet(wallets[2].privkey, wallets[0].privkey, wallets[4].privkey):
        return False

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/payment', None, api_pass=api_pass, data=wallets[1].privkey)
    if 'error' in res:
        print 'failed to set payment key'
        print res
        return False

    if not check_wallet(wallets[1].privkey, wallets[0].privkey, wallets[4].privkey):
        return False

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/data', None, api_pass=api_pass, data=wallets[2].privkey)
    if 'error' in res:
        print 'failed to set payment key'
        print res
        return False

    if not check_wallet(wallets[1].privkey, wallets[0].privkey, wallets[2].privkey):
        return False
def scenario( wallets, **kw ):

    # save the wallet 
    wallet = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[2].privkey, wallets[3].privkey, wallets[4].privkey )
    if 'error' in wallet:
        print 'failed to set wallet: {}'.format(wallet)
        return False

    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']

    if not check_wallet(wallets[2].privkey, wallets[3].privkey, wallets[4].privkey):
        return False

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass, data=wallets[0].privkey)
    if 'error' in res:
        print 'failed to set owner key'
        print res
        return False
       
    if not check_wallet(wallets[2].privkey, wallets[0].privkey, wallets[4].privkey):
        return False

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/payment', None, api_pass=api_pass, data=wallets[1].privkey)
    if 'error' in res:
        print 'failed to set payment key'
        print res
        return False

    if not check_wallet(wallets[1].privkey, wallets[0].privkey, wallets[4].privkey):
        return False

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/data', None, api_pass=api_pass, data=wallets[2].privkey)
    if 'error' in res:
        print 'failed to set payment key'
        print res
        return False

    if not check_wallet(wallets[1].privkey, wallets[0].privkey, wallets[2].privkey):
        return False
def make_proxy():
    """
    Create a blockstack client API proxy
    """
    global utxo_opts

    client_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)
    assert client_path is not None

    client_config = blockstack_client.get_config(client_path)
    proxy = blockstack_client.session(conf=client_config)

    proxy.config_path = client_path

    # add in some UTXO goodness
    proxy.get_unspents = get_unspents
    proxy.broadcast_transaction = broadcast_transaction

    return proxy
Exemple #14
0
def get_zonefile_from_atlas(blockchain_id, config_path, name_record=None):
    """
    Get the zone file from the atlas network
    Return the raw zone file on success
    Raise on eror
    """
    import blockstack_client
    import blockstack_client.proxy as proxy

    conf = blockstack_client.get_config(config_path)
    if not conf:
        raise Exception(
            "Failed to load config file from {}".format(config_path))

    if 'server' not in conf or 'port' not in conf:
        raise Exception("Config file is missing 'server' and/or 'port")

    if name_record is not None:
        name_record = proxy.get_name_blockchain_record(blockchain_id)
        if 'error' in name_record:
            raise Exception(
                "Failed to load name record for {}".format(blockchain_id))

    name_zonefile_hash = name_record['value_hash']

    atlas_host = conf['server']
    atlas_port = conf['port']
    hostport = '{}:{}'.format(atlas_host, atlas_port)

    zonefile_txt = None
    expected_zonefile_hash = str(name_zonefile_hash)

    # load from atlas
    res = proxy.get_zonefiles(hostport, [expected_zonefile_hash])
    if 'error' in res:
        raise Exception("Failed to load {} from Atlas network: {}".format(
            expected_zonefile_hash, res['error']))

    zonefile_txt = res['zonefiles'][expected_zonefile_hash]
    return zonefile_txt
    def __init__(self):
        global utxo_opts

        client_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)
        assert client_path is not None

        client_config = blockstack_client.get_config(client_path)

        self.client = blockstack_client.BlockstackRPCClient(
            client_config['server'], client_config['port'])
        self.config_path = client_path
        self.conf = {
            "start_block": blockstack.FIRST_BLOCK_MAINNET,
            "initial_utxos": utxo_opts,
            "storage_drivers": client_config['storage_drivers'],
            "metadata": client_config['metadata'],
            "path": client_path
        }
        self.spv_headers_path = utxo_opts['spv_headers_path']

        if not os.path.exists(self.conf['metadata']):
            os.makedirs(self.conf['metadata'], 0700)
def get_zonefile_from_atlas(blockchain_id, config_path, name_record=None):
    """
    Get the zone file from the atlas network
    Return the raw zone file on success
    Raise on eror
    """
    import blockstack_client
    import blockstack_client.proxy as proxy
    
    conf = blockstack_client.get_config(config_path)
    if not conf:
        raise Exception("Failed to load config file from {}".format(config_path))

    if 'server' not in conf or 'port' not in conf:
        raise Exception("Config file is missing 'server' and/or 'port")

    if name_record is not None:
        name_record = proxy.get_name_blockchain_record(blockchain_id)
        if 'error' in name_record:
            raise Exception("Failed to load name record for {}".format(blockchain_id))

    name_zonefile_hash = name_record['value_hash']

    atlas_host = conf['server']
    atlas_port = conf['port']
    hostport = '{}:{}'.format( atlas_host, atlas_port )

    zonefile_txt = None
    expected_zonefile_hash = str(name_zonefile_hash)

    # load from atlas
    res = proxy.get_zonefiles( hostport, [expected_zonefile_hash] )
    if 'error' in res:
        raise Exception("Failed to load {} from Atlas network: {}".format(expected_zonefile_hash, res['error']))

    zonefile_txt = res['zonefiles'][expected_zonefile_hash]
    return zonefile_txt
Exemple #17
0
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 )

    # 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)

    # let's set the key to skip the transfer.
    config_dir = os.path.dirname(config_path)
    conf = blockstack_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass,
                                       data=new_key)
    if res['http_status'] != 200 or 'error' in res:
        print 'failed to set owner key'
        print res
        return False

    # make zonefile for recipient
    driver_urls = blockstack_client.storage.make_mutable_data_urls('bar.test', use_only=['dht', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile('bar.test', wallets[4].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='bar.test', ttl=3600 )

    # leaving the call format of this one the same to make sure that our registrar correctly
    #   detects that the requested TRANSFER is superfluous
    # register the name bar.test
    res = testlib.blockstack_REST_call(
        'POST', '/v1/names', None, api_pass=api_pass, data={
            'name': 'bar.test', 'zonefile': zonefile_txt, 'owner_address': new_addr
        })
    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(None, 'bar.test', 'preorder', tx_hash, api_pass = api_pass )
    if not res:
        return False

    # wait for the preorder to get confirmed
    for i in xrange(0, 4):
        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(None, 'bar.test', 'register', None, api_pass = api_pass )
    if not res:
        return False

    for i in xrange(0, 4):
        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(None, 'bar.test', 'update', None, api_pass = api_pass )
    if not res:
        print res
        print "update error in first update"
        return False

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

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

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

    res = testlib.verify_in_queue(None, 'bar.test', 'transfer', None, api_pass = api_pass )
    if res:
        print "Wrongly issued a TRANSFER"
        return False

    res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test",
                                       None, api_pass=api_pass)
    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']

    # should still be registered
    if res['response']['status'] != 'registered':
        print "register not complete"
        print json.dumps(res)
        return False

    # do we have the history for the name?
    res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history",
                                       None, api_pass=api_pass )
    if 'error' in res or res['http_status'] != 200:
        res['test'] = "Failed to get name history for foo.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),
                                       None, api_pass=api_pass )
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name zonefile'
        print json.dumps(res)
        return False

    # same zonefile we put?
    if res['response']['zonefile'] != zonefile_txt:
        res['test'] = 'mismatched zonefile, expected\n{}\n'.format(zonefile_txt)
        print json.dumps(res)
        return False

    # okay, now let's try to do a transfer.
    # FIRST, I want to change the key to a key that
    #  doesn't own the name and a payment key that has no money
    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass,
                                       data=insanity_key)
    if res['http_status'] != 200 or 'error' in res:
        print 'failed to set owner key'
        print res
        return False

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/payment', None, api_pass=api_pass,
                                       data=insanity_key)
    if res['http_status'] != 200 or 'error' in res:
        print 'failed to set owner key'
        print res
        return False

    payment_key = wallets[1].privkey

    # let's do this with the bad key
    res = testlib.blockstack_REST_call(
        'PUT', '/v1/names/bar.test/owner', None, api_pass=api_pass, data={
            'owner': destination_owner, 'payment_key' : payment_key
        })
    if 'error' in res or res['http_status'] != 202:
        res['test'] = '(Correctly) failed to transfer user'
        print json.dumps(res)


    # let's do this with the good one!
    res = testlib.blockstack_REST_call(
        'PUT', '/v1/names/bar.test/owner', None, api_pass=api_pass, data={
            'owner': destination_owner, 'owner_key' : new_key,
            'payment_key' : payment_key
        })
    if 'error' in res or res['http_status'] != 202:
        res['test'] = '(Wrongly) failed to transfer user'
        print json.dumps(res)
        error = True
        return False
    else:
        print "Submitted transfer!"
        print res

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

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

    res = testlib.verify_in_queue(None, 'bar.test', 'transfer', None, api_pass = api_pass )
    if not res:
        print "transfer error"
        print res
        return False

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

    # wait for zonefile to propagate
    time.sleep(10)

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

    cur_owner_address = res['response']['address']
    if cur_owner_address != destination_owner:
        print "After transfer, unexpected owner. Expected {}, Actual {}".format(
            destination_owner, cur_owner_address)
        return False
Exemple #18
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", empty_key, empty_key, empty_key)
    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']

    payment_key = wallets[1].privkey

    # make zonefile for recipient
    driver_urls = blockstack_client.storage.make_mutable_data_urls(
        'bar.test', use_only=['dht', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile(
        'bar.test', wallets[4].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file(zonefile,
                                                   origin='bar.test',
                                                   ttl=3600)

    no_key_postage = {'name': 'bar.test', 'zonefile': zonefile_txt}
    key_postage = dict(no_key_postage)
    key_postage['payment_key'] = payment_key
    key_postage['owner_key'] = new_key

    res = testlib.blockstack_REST_call('POST',
                                       '/v1/names',
                                       None,
                                       api_pass=api_pass,
                                       data=no_key_postage)
    if 'error' not in res['response']:
        print "Successfully registered user with should-have-been-bad keys"
        print res
        return False

    # let's do a small withdraw
    res = testlib.blockstack_REST_call(
        'POST',
        '/v1/wallet/balance',
        None,
        api_pass=api_pass,
        data={
            'address': virtualchain.get_privkey_address(empty_key),
            'amount': int(1e4),
            'payment_key': payment_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

    if int(res['response']['balance']['satoshis']) <= 0:
        res['test'] = 'Wallet balance did not increment!'
        print json.dumps(res)
        error = True
        return False

    res = testlib.blockstack_REST_call('POST',
                                       '/v1/names',
                                       None,
                                       api_pass=api_pass,
                                       data=key_postage)
    if 'error' in res['response']:
        res['test'] = 'Failed to register user'
        print json.dumps(res)
        error = True
        return False

    print "Registering bar.test"
    for i in xrange(0, 6):
        testlib.next_block(**kw)
    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(None,
                                  'bar.test',
                                  'register',
                                  None,
                                  api_pass=api_pass)
    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(None,
                                  'bar.test',
                                  'update',
                                  None,
                                  api_pass=api_pass)
    if not res:
        print res
        print "update error in first update"
        return False
    for i in xrange(0, 6):
        testlib.next_block(**kw)

    res = testlib.blockstack_REST_call("GET",
                                       "/v1/names/bar.test",
                                       None,
                                       api_pass=api_pass)
    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']

    # should still be registered
    if res['response']['status'] != 'registered':
        print "register not complete"
        print json.dumps(res)
        return False

    # do we have the history for the name?
    res = testlib.blockstack_REST_call("GET",
                                       "/v1/names/bar.test/history",
                                       None,
                                       api_pass=api_pass)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = "Failed to get name history for foo.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),
        None,
        api_pass=api_pass)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name zonefile'
        print json.dumps(res)
        return False

    # same zonefile we put?
    if res['response']['zonefile'] != zonefile_txt:
        res['test'] = 'mismatched zonefile, expected\n{}\n'.format(
            zonefile_txt)
        print json.dumps(res)
        return False

    # okay, now let's try to do an update.
    # make zonefile for recipient
    driver_urls = blockstack_client.storage.make_mutable_data_urls(
        'bar.test', use_only=['http', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile(
        'bar.test', wallets[3].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file(zonefile,
                                                   origin='bar.test',
                                                   ttl=3600)

    # let's do this update.
    res = testlib.blockstack_REST_call('PUT',
                                       '/v1/names/bar.test/zonefile',
                                       None,
                                       api_pass=api_pass,
                                       data={
                                           'zonefile': zonefile_txt,
                                           'owner_key': new_key,
                                           'payment_key': payment_key
                                       })
    if 'error' in res or res['http_status'] != 202:
        res['test'] = 'Failed to register user'
        print json.dumps(res)
        error = True
        return False
    else:
        print "Submitted update!"
        print res

    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(None,
                                  'bar.test',
                                  'update',
                                  None,
                                  api_pass=api_pass)
    if not res:
        print "update error in second update"
        print res
        return False

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

    # wait for zonefile to propagate
    time.sleep(10)

    res = testlib.blockstack_REST_call("GET",
                                       "/v1/names/bar.test",
                                       None,
                                       api_pass=api_pass)
    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']
    # get the zonefile
    res = testlib.blockstack_REST_call(
        "GET",
        "/v1/names/bar.test/zonefile/{}".format(zonefile_hash),
        None,
        api_pass=api_pass)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name zonefile'
        print json.dumps(res)
        return False

    # same zonefile we put?
    if res['response']['zonefile'] != zonefile_txt:
        res['test'] = 'mismatched zonefile, expected\n{}\n'.format(
            zonefile_txt)
        print json.dumps(res)
        return False
Exemple #19
0
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)
    conf = blockstack_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    config_dir = os.path.dirname(config_path)

    # make sure we can do REST calls
    res = testlib.blockstack_REST_call('GET',
                                       '/v1/blockchains/bitcoin/pending',
                                       None,
                                       api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

    # make sure we can do REST calls with different app names and user names
    res = testlib.blockstack_REST_call('GET',
                                       '/v1/blockchains/bitcoin/pending',
                                       None,
                                       api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

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

    # wait for update to get confirmed
    for i in xrange(0, 48):
        if i % 12 == 0:
            print "waiting for RPC daemon to catch up"
            time.sleep(10)

        testlib.next_block(**kw)

    res = testlib.blockstack_REST_call("GET",
                                       "/v1/names/bar.test",
                                       None,
                                       api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'Failed to query name'
        print json.dumps(res)
        error = True
        return False

    if res['http_status'] != 200:
        res['test'] = 'HTTP status {}, response = {}'.format(
            res['http_status'], res['response'])
        print json.dumps(res)
        error = True
        return False

    # should now be registered
    if res['response']['status'] != 'registered':
        print "register not complete"
        print json.dumps(res)
        return False
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data, wallet_balance

    wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].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 )

    testlib.blockstack_name_preorder( "foo.test", wallets[2].privkey, wallets[3].addr, wallet=wallets[3])
    testlib.next_block( **kw )
    
    testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr, wallet=wallets[3] )
    testlib.next_block( **kw )
    
    testlib.blockstack_client_set_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[0].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)
    config_dir = os.path.dirname(config_path)
 
    conf = blockstack_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    # make sure we can do REST calls
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/pending', None, api_pass=api_pass )
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

    # make sure we can do REST calls with different app names and user names
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/pending', None, api_pass=api_pass )
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

    # what's the balance?
    res = testlib.blockstack_REST_call('GET', '/v1/wallet/balance', None, api_pass=api_pass )
    if res['http_status'] != 200:
        res['test'] = 'failed to query wallet'
        print json.dumps(res)
        return False

    wallet_balance = res['response']['balance']['satoshis']
    balance_before = testlib.get_balance(wallets[3].addr)

    # can we move the funds?
    res = testlib.blockstack_REST_call('POST', '/v1/wallet/balance', None, api_pass=api_pass, data={'address': wallets[3].addr} )
    if res['http_status'] != 200:
        res['test'] = 'failed to transfer funds'
        print json.dumps(res)
        return False

    if not res['response'].has_key('transaction_hash'):
        res['test'] = 'missing tx hash'
        print json.dumps(res)
        return False

    # confirm it
    for i in xrange(0, 10):
        testlib.next_block(**kw)
  
    new_balance = testlib.get_balance(wallets[5].addr)
    balance_after = testlib.get_balance(wallets[3].addr)

    if new_balance != 0:
        print 'new balance of {} is {}'.format(wallets[5].addr, new_balance)
        return False

    if abs(balance_before + wallet_balance - balance_after) > 10000:
        print "{} + {} !~= {}".format(balance_before, wallet_balance, balance_after)
        return False
def delete_immutable_handler( key, txid, sig_key_txid, **kw ):
    return True

def delete_mutable_handler( data_id, signature, **kw ):
    return True

def get_classes():
    return ['read_public', 'write_private']

if __name__ == "__main__":
    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)
    assert config_path is not None, "You must set BLOCKSTACK_CLIENT_CONFIG"

    import blockstack_client
    config = blockstack_client.get_config(config_path)
    assert config is not None

    print json.dumps(config, indent=4, sort_keys=True)
    storage_init(config)

    assert len(sys.argv) > 1, "You must specify one or more names"
    for name in sys.argv[1:]:
        zonefile = get_data(name, zonefile=True)
        assert zonefile is not None and 'error' not in zonefile, "Bad zonefile: %s" % zonefile
        profile = get_data( name, zonefile=False )
        assert profile is not None and 'error' not in profile, "Bad profile: %s" % profile

        print "zonefile:\n%s" % zonefile
        print "profile:\n%s" % json.dumps(profile, indent=4, sort_keys=True)
        print ""
Exemple #22
0
def main(conf, function, args):
    """
    Fetch and serve the application
    """

    global appdir
    global client_port

    wallet_keys = None
    client_config_path = os.path.join(os.path.dirname(conf['path']),
                                      blockstack_client.CONFIG_FILENAME)

    if function in ["run", "publish", "setup"]:
        # need wallet
        wallet = blockstack_client.get_wallet(config_path=client_config_path)
        if wallet is None or 'error' in wallet:
            print >> sys.stderr, "Failed to get wallet"
            sys.exit(1)

        wallet_keys = wallet

    if function == "run":
        # run the app
        try:
            blockchain_id = args[0]
            appname = args[1]
        except:
            print >> sys.stderr, "Usage: %s-%s [opts] blockchain_id appname [tag [appdir]]" % (
                sys.argv[0], function)
            sys.exit(1)

        # optional arguments
        tag = None
        appdir = None
        try:
            tag = int(args[2])
            appdir = args[3]
        except:
            pass

        # load the app
        res = app_load(conf,
                       blockchain_id,
                       appname,
                       wallet_keys=wallet_keys,
                       tag=tag,
                       appdir=appdir)
        if 'error' in res:
            print >> sys.stderr, "Failed to load app: %s" % res['error']
            sys.exit(1)

        client_conf = blockstack_client.get_config(client_config_path)
        client_port = client_conf.get('api_endpoint_port', None)
        if client_port is None:
            print >> sys.stderr, "Could not determine client RPC port"
            sys.exit(1)

        if appdir is None:
            appdir = res['root']

        httpd = SocketServer.TCPServer(("localhost", conf['port']),
                                       AppRequestHandler)
        httpd.serve_forever()

        return {'status': True}

    elif function == "publish":
        # publish an app
        try:
            appname = args[0]
            appdir = args[1]
        except:
            print >> sys.stderr, "Usage: %s-%s [opts] appname appdir [tag [key_passphrase]]" % (
                sys.argv[0], function)
            sys.exit(1)

        # optional args
        tag = None
        key_passphrase = None
        try:
            tag = int(args[2])
            key_passphrase = args[3]
        except:
            pass

        # TODO: mutable vs immutable
        res = app_publish(conf,
                          appname,
                          appdir,
                          wallet_keys=wallet_keys,
                          version=tag,
                          key_passphrase=key_passphrase)
        if 'error' in res:
            print >> sys.stderr, "Failed to publish app: %s" % res['error']
            sys.exit(1)

        return res

    elif function == 'setup':
        # set up app-publishing
        client_config_path = os.path.join(os.path.dirname(conf['path']),
                                          blockstack_client.CONFIG_FILENAME)
        res = blockstack_file.file_key_regenerate(
            conf['blockchain_id'],
            conf['hostname'],
            config_path=client_config_path,
            wallet_keys=wallet_keys)
        if 'error' in res:
            print >> sys.stderr, "Failed to publish app: %s" % res['error']
            sys.exit(1)

        return res

    else:
        print >> sys.stderr, "Unrecognized directive '%s'" % function
        sys.exit(1)
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)
    config_dir = os.path.dirname(config_path)

    conf = blockstack_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    # make sure we can do REST calls
    res = testlib.blockstack_REST_call('GET',
                                       '/v1/blockchains/bitcoin/pending',
                                       None,
                                       api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

    # make sure we can do REST calls with different app names and user names
    res = testlib.blockstack_REST_call('GET',
                                       '/v1/blockchains/bitcoin/pending',
                                       None,
                                       api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

    # can we even get to the wallet?
    res = testlib.blockstack_REST_call('POST',
                                       '/v1/wallet/balance',
                                       None,
                                       api_pass=api_pass,
                                       data={
                                           'address': wallets[4].addr,
                                           'amount': 100000
                                       })
    if res['http_status'] != 200:
        res['test'] = 'failed to transfer funds'

    # make zonefile for recipient
    driver_urls = blockstack_client.storage.make_mutable_data_urls(
        'foo.test', use_only=['dht', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile(
        'foo.test', wallets[4].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file(zonefile,
                                                   origin='foo.test',
                                                   ttl=3600)

    # register the name bar.test, with min 3 confirmations on its UTXOs
    data = {
        'name': 'bar.test',
        'zonefile': zonefile_txt,
        'owner_address': wallets[4].addr,
        'min_confs': 3
    }

    # should fail
    res = testlib.blockstack_REST_call('POST',
                                       '/v1/names',
                                       None,
                                       api_pass=api_pass,
                                       data=data)
    if res['http_status'] == 200:
        res['test'] = 'succeeded in sending bar.test'
        print json.dumps(res)
        error = True
        return False

    # wait for confirmations
    for i in xrange(0, 3):
        testlib.next_block(**kw)

    # should succeed
    res = testlib.blockstack_REST_call('POST',
                                       '/v1/names',
                                       None,
                                       api_pass=api_pass,
                                       data=data)
    if 'error' in res or 'error' in res['response']:
        res['test'] = 'failed to send bar.test'
        print json.dumps(res)
        error = True
        return False

    # wait for update to get confirmed
    for i in xrange(0, 48):
        if i % 12 == 0:
            print "waiting for RPC daemon to catch up"
            time.sleep(10)

        testlib.next_block(**kw)

    res = testlib.blockstack_REST_call("GET",
                                       "/v1/names/bar.test",
                                       None,
                                       api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'Failed to query name'
        print json.dumps(res)
        error = True
        return False

    if res['http_status'] != 200:
        res['test'] = 'HTTP status {}, response = {}'.format(
            res['http_status'], res['response'])
        print json.dumps(res)
        error = True
        return False

    # should now be registered
    if res['response']['status'] != 'registered':
        print "register not complete"
        print json.dumps(res)
        return False
def delete_immutable_handler( key, txid, sig_key_txid, **kw ):
    return True

def delete_mutable_handler( data_id, signature, **kw ):
    return True

def get_classes():
    return ['read_public', 'write_private']

if __name__ == "__main__":
    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None)
    assert config_path is not None, "You must set BLOCKSTACK_CLIENT_CONFIG"

    import blockstack_client
    config = blockstack_client.get_config(config_path)
    assert config is not None

    print json.dumps(config, indent=4, sort_keys=True)
    storage_init(config)

    assert len(sys.argv) > 1, "You must specify one or more names"
    for name in sys.argv[1:]:
        zonefile = get_data(name, zonefile=True)
        assert zonefile is not None and 'error' not in zonefile, "Bad zonefile: %s" % zonefile
        profile = get_data( name, zonefile=False )
        assert profile is not None and 'error' not in profile, "Bad profile: %s" % profile

        print "zonefile:\n%s" % zonefile
        print "profile:\n%s" % json.dumps(profile, indent=4, sort_keys=True)
        print ""
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', 'wallet_write'])
    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)

    # let's set the key to skip the transfer.

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

    api_pass = conf['api_password']

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass,
                                       data=new_key)
    if res['http_status'] != 200 or 'error' in res:
        print 'failed to set owner key'
        print res
        return False

  
    # make zonefile for recipient
    driver_urls = blockstack_client.storage.make_mutable_data_urls('bar.test', use_only=['dht', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile('bar.test', wallets[4].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='bar.test', ttl=3600 )

    # leaving the call format of this one the same to make sure that our registrar correctly
    #   detects that the requested TRANSFER is superfluous
    # register the name bar.test 
    res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data={'name': 'bar.test', 'zonefile': zonefile_txt, 'owner_address': new_addr })
    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, 6):
        testlib.next_block( **kw )
  
    print 'Wait for transfer to be submitted'
    time.sleep(10)

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

    res = testlib.verify_in_queue(ses, 'bar.test', 'transfer', None )
    if res:
        print "Wrongly issued a TRANSFER"
        return False

    for i in xrange(0, 6):
        testlib.next_block( **kw )
  
    print 'Wait for transfer 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']

    # should still be registered 
    if res['response']['status'] != 'registered':
        print "register not complete"
        print json.dumps(res)
        return False

    # 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 foo.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

    # same zonefile we put?
    if res['response']['zonefile'] != zonefile_txt:
        res['test'] = 'mismatched zonefile, expected\n{}\n'.format(zonefile_txt)
        print json.dumps(res)
        return False


    ### Now, we'll do it again, but this time, we're going to CHANGE THE KEY in the middle of registrations.
    ### to test the different paths, I'll start 3 registrations:
    # 1 has submitted preorder
    # 1 has submitted register
    # 1 has submitted update
    ### And then I'll issue a change-key


    # make zonefile for recipients
    zonefiles = []
    for i in [1,2,3]:
        name = "tricky{}.test".format(i)
        driver_urls = blockstack_client.storage.make_mutable_data_urls(name, use_only=['dht', 'disk'])
        zonefile = blockstack_client.zonefile.make_empty_zonefile(name, wallets[4].pubkey_hex, urls=driver_urls)
        zonefiles.append(blockstack_zones.make_zone_file( zonefile, origin=name, ttl=3600 ))

    # leaving the call format of this one the same to make sure that our registrar correctly
    #   detects that the requested TRANSFER is superfluous
    res = testlib.blockstack_REST_call(
        'POST', '/v1/names', ses, data={'name':'tricky1.test', 'zonefile':zonefiles[0], 'owner_address':new_addr})
    if 'error' in res:
        res['test'] = 'Failed to register tricky1.test'
        print json.dumps(res)
        error = True
        return False

    tx_hash = res['response']['transaction_hash']
    # wait for preorder to get confirmed...
    for i in xrange(0, 6):
        testlib.next_block( **kw )

    res = testlib.blockstack_REST_call(
        'POST', '/v1/names', ses, data={'name':'tricky2.test', 'zonefile':zonefiles[1], 'owner_address':new_addr})
    if 'error' in res:
        res['test'] = 'Failed to register tricky2.test'
        print json.dumps(res)
        error = True
        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.blockstack_REST_call(
        'POST', '/v1/names', ses, data={'name':'tricky3.test', 'zonefile':zonefiles[2], 'owner_address':new_addr})
    if 'error' in res:
        res['test'] = 'Failed to register tricky3.test'
        print json.dumps(res)
        error = True
        return False

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

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

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



    res = testlib.verify_in_queue(ses, 'tricky1.test', 'update', None)
    res = testlib.verify_in_queue(ses, 'tricky2.test', 'register', None)
    res = testlib.verify_in_queue(ses, 'tricky3.test', 'preorder', None)

    # let's go crazy.
    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass,
                                       data=insanity_key)
    if res['http_status'] != 200 or 'error' in res:
        print 'failed to set owner key'
        print res
        return False


    # wait for preorder to get confirmed
    for i in xrange(0, 6):
        testlib.next_block( **kw )
    # wake up registrar, submit register
    time.sleep(10)
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    # wake up registrar, submit update
    time.sleep(10)
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    # wake up registrar, propogate zonefile
    time.sleep(10)
def scenario(wallets, **kw):

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

    testlib.blockstack_namespace_reveal(
        "id", 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("id", wallets[1].privkey)
    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']

    wallet = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", wallets[2].privkey, wallets[3].privkey,
        wallets[4].privkey)
    resp = testlib.blockstack_cli_register("foo.id", "0123456789abcdef")
    if 'error' in resp:
        print >> sys.stderr, json.dumps(resp, indent=4, sort_keys=True)
        return False

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

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

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

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

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

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

    test_data = [{
        'hash': '34fdcde8b75440c5cb82480a14b4f3d731a67dc4',
        'string':
        '$ORIGIN aaron.id\n$TTL 3600\n_http._tcp URI 10 1 "https://gaia.blockstack.org/hub/34bNQUVgyhSrA8XpM4HkerHUUdNmLpiyj7/0/profile.json"',
        'decoded': None,
        'b64': False
    }, {
        'hash': 'd4fbae5d1f66f1ae0431e35bcd5a98782adc29ba',
        'decoded':
        '$ORIGIN baron.id\n$TTL 3600\n_http._tcp URI 10 1 "https://gaia.blockstack.org/hub/34bNQUVgyhSrA8XpM4HkerHUUdNmLpiyj7/0/profile.json"',
        'string':
        'JE9SSUdJTiBiYXJvbi5pZAokVFRMIDM2MDAKX2h0dHAuX3RjcCBVUkkgMTAgMSAiaHR0cHM6Ly9nYWlhLmJsb2Nrc3RhY2sub3JnL2h1Yi8zNGJOUVVWZ3loU3JBOFhwTTRIa2VySFVVZE5tTHBpeWo3LzAvcHJvZmlsZS5qc29uIg==',
        'b64': True
    }]

    for datum in test_data:
        post_data = {}
        if datum['b64']:
            key = 'zonefile_b64'
        else:
            key = 'zonefile'
        post_data[key] = datum['string']

        zfhash = datum['hash']

        res = testlib.blockstack_REST_call("PUT",
                                           "/v1/names/foo.id/zonefile",
                                           None,
                                           api_pass=api_pass,
                                           data={'zonefile_hash': zfhash})

        if 'error' in res or res['http_status'] != 202:
            res['test'] = 'failed to update zonefile hash'
            print json.dumps(res)
            return False

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

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

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

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

        # update set?
        if res['response']['zonefile_hash'] != zfhash:
            res['test'] = 'failed to set zonefile hash'
            print json.dumps(res)
            return False

        res = testlib.blockstack_REST_call("POST",
                                           "/v1/zonefile/",
                                           None,
                                           api_pass=api_pass,
                                           data=post_data)
        if 'error' in res or res['http_status'] != 200:
            res['test'] = 'failed to announce zonefile'
            print json.dumps(res)
            return False

        print 'Broadcasted zonefile'
        time.sleep(10)

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

        if res['response']['zonefile'] != datum['string'] and \
           res['response']['zonefile'] != datum['decoded']:
            res['test'] = 'failed to set zonefile string'
            print json.dumps(res)
            return False
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data, wallet_balance

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

    # get utxos for the payer
    payer_utxos = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=1'.format(wallets[3].addr), None, api_pass=api_pass)
    if 'error' in payer_utxos:
        payer_utxos['test'] = 'failed to get utxos'
        print json.dumps(payer_utxos)
        return False

    # have both the test wallet output and the one the NAME_REGISTRATION sent
    if len(payer_utxos['response']) != 1:
        payer_utxos['test'] = 'wrong utxos'
        print json.dumps(payer_utxos)
        return False

    # last transaction should be the register, and it should have been paid with the owner address (since that's how we sent it above)
    if payer_utxos['response'][0]['transaction_hash'] != register_resp['transaction_hash'] or payer_utxos['response'][0]['confirmations'] != 1:
        payer_utxos['test'] = 'invalid utxos (tx_hash, confirmations)'
        print json.dumps(payer_utxos)
        return False

    # get utxos for the owner wallet
    owner_utxos = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=1'.format(wallets[5].addr), None, api_pass=api_pass)
    if 'error' in owner_utxos:
        owner_utxos['test'] = 'failed to get utxos'
        print json.dumps(owner_utxos)
        return False

    # two utxos: one for the initial wallet fill-up from the test framework, and one from the registration 
    if len(owner_utxos['response']) != 2:
        owner_utxos['test'] = 'wrong utxos'
        print json.dumps(owner_utxos)
        return False

    # last transaction should be the register
    found = False
    for utxo in owner_utxos['response']:
        if utxo['transaction_hash'] == register_resp['transaction_hash'] and utxo['confirmations'] == 1:
            found = True

    if not found:
        owner_utxos['test'] = 'invalid utxos (tx_hash, confirmations)'
        print json.dumps(owner_utxos)
        return False

    # verify that min_confirmations=2 hides these transactions
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=2'.format(wallets[5].addr), None, api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    if len(res['response']) > 1:
        res['test'] = 'got more UTXOs than we expected'
        print json.dumps(res)
        return False

    # count UTXOs in wallets[1]
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=0'.format(wallets[1].addr), None, api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    initial_utxos = res['response']
    if len(initial_utxos) == 0:
        res['test'] = 'test bug: no UTXOs for wallet'
        print json.dumps(res)
        return False

    # send money from one wallet to another
    fund_tx = testlib.send_funds_tx(wallets[0].privkey, 10**8, wallets[1].addr)
    res = testlib.blockstack_REST_call('POST', '/v1/blockchains/bitcoin/txs', None, data={'tx': fund_tx}, api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to send {}'.format(fund_tx)
        print json.dumps(res)
        return False

    if not res['response'].has_key('transaction_hash'):
        res['test'] = 'response is missing transaction hash'
        print json.dumps(res)
        return False

    # verify that it's in the UTXO set with min_confirmations=0
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=0'.format(wallets[1].addr), None, api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    if len(res['response']) != len(initial_utxos) + 1:
        res['test'] = 'missing UTXO'
        print json.dumps(res)
        return False

    current_utxos = res['response']

    # verify that with min_confirmations=1, we have what we started with
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=1'.format(wallets[1].addr), None, api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    if res['response'] != initial_utxos:
        res['test'] = 'initial utxos do not match current utxos'
        print json.dumps(res)
        print json.dumps(initial_utxos)
        return False

    # confirm everything
    for i in xrange(0, 10):
        testlib.next_block(**kw)
      
    # verify that we have what we started with
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/{}/unspent'.format(wallets[1].addr), None, api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    current_utxos_no_confirmation = [dict([(k, v) for (k, v) in filter(lambda (x, y): x != 'confirmations', utxo.items())]) for utxo in current_utxos]
Exemple #28
0
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 )

    # 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', 'wallet_write'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    ses = res['token']

    # my own KEYS

    owner_key = new_key

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

    api_pass = conf['api_password']

    payment_key = wallets[1].privkey
    payer = wallets[1].addr

    # make zonefile for recipient
    driver_urls = blockstack_client.storage.make_mutable_data_urls('bar.test', use_only=['dht', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile('bar.test', wallets[4].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='bar.test', ttl=3600 )


    postage = {'name': 'bar.test', 'zonefile': zonefile_txt, 'owner_address': new_addr,
               'payment_key' : payment_key, 'owner_key' : owner_key}

    # leaving the call format of this one the same to make sure that our registrar correctly
    #   detects that the requested TRANSFER is superfluous
    # register the name bar.test
    res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data=postage)
    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, 6):
        testlib.next_block( **kw )

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

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

    res = testlib.verify_in_queue(ses, 'bar.test', 'transfer', None )
    if res:
        print "Wrongly issued a TRANSFER"
        return False

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

    print 'Wait for transfer 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']

    # should still be registered
    if res['response']['status'] != 'registered':
        print "register not complete"
        print json.dumps(res)
        return False

    # 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 foo.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

    # same zonefile we put?
    if res['response']['zonefile'] != zonefile_txt:
        res['test'] = 'mismatched zonefile, expected\n{}\n'.format(zonefile_txt)
        print json.dumps(res)
        return False


    ### Now, we'll do it again, but this time, we're going to CHANGE THE KEY in the middle of registrations.
    ### to test the different paths, I'll start 3 registrations:
    # 1 has submitted preorder
    # 1 has submitted register
    # 1 has submitted update
    ### And then I'll issue a change-key


    # make zonefile for recipients
    zonefiles = []
    postages = []
    for i in [1,2,3]:
        name = "tricky{}.test".format(i)
        driver_urls = blockstack_client.storage.make_mutable_data_urls(name, use_only=['dht', 'disk'])
        zonefile = blockstack_client.zonefile.make_empty_zonefile(name, wallets[4].pubkey_hex, urls=driver_urls)
        zf_txt = blockstack_zones.make_zone_file( zonefile, origin=name, ttl=3600 )
        zonefiles.append(zf_txt)
        postages.append(
            {'name': name, 'zonefile' : zf_txt, 'owner_address': new_addr,
             'payment_key' : payment_key, 'owner_key' : owner_key})

    res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data=postages[0])
    if 'error' in res:
        res['test'] = 'Failed to register tricky1.test'
        print json.dumps(res)
        error = True
        return False

    tx_hash = res['response']['transaction_hash']
    # wait for preorder to get confirmed...
    for i in xrange(0, 6):
        testlib.next_block( **kw )

    res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data=postages[1])
    if 'error' in res:
        res['test'] = 'Failed to register tricky2.test'
        print json.dumps(res)
        error = True
        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.blockstack_REST_call('POST', '/v1/names', ses, data=postages[2])
    if 'error' in res:
        res['test'] = 'Failed to register tricky3.test'
        print json.dumps(res)
        error = True
        return False

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

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

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



    res = testlib.verify_in_queue(ses, 'tricky1.test', 'update', None)
    res = testlib.verify_in_queue(ses, 'tricky2.test', 'register', None)
    res = testlib.verify_in_queue(ses, 'tricky3.test', 'preorder', None)

    # let's go crazy.
    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass,
                                       data=insanity_key)
    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/payment', None, api_pass=api_pass,
                                       data=insanity_key)
    if res['http_status'] != 200 or 'error' in res:
        print 'failed to set owner key'
        print res
        return False


    # wait for preorder to get confirmed
    for i in xrange(0, 6):
        testlib.next_block( **kw )
    # wake up registrar, submit register
    time.sleep(10)
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    # wake up registrar, submit update
    time.sleep(10)
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    # wake up registrar, propogate zonefile
    time.sleep(10)
Exemple #29
0
def scenario(wallets, **kw):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data, wallet_balance

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

    register_resp = testlib.blockstack_name_register("foo.test",
                                                     wallets[3].privkey,
                                                     wallets[5].addr)
    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']

    # get utxos for the payer
    payer_utxos = testlib.blockstack_REST_call(
        'GET',
        '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=1'.format(
            wallets[3].addr),
        None,
        api_pass=api_pass)
    if 'error' in payer_utxos:
        payer_utxos['test'] = 'failed to get utxos'
        print json.dumps(payer_utxos)
        return False

    # have both the test wallet output and the one the NAME_REGISTRATION sent
    if len(payer_utxos['response']) != 1:
        payer_utxos['test'] = 'wrong utxos'
        print json.dumps(payer_utxos)
        return False

    # last transaction should be the register, and it should have been paid with the owner address (since that's how we sent it above)
    if payer_utxos['response'][0]['transaction_hash'] != register_resp[
            'transaction_hash'] or payer_utxos['response'][0][
                'confirmations'] != 1:
        payer_utxos['test'] = 'invalid utxos (tx_hash, confirmations)'
        print json.dumps(payer_utxos)
        return False

    # get utxos for the owner wallet
    owner_utxos = testlib.blockstack_REST_call(
        'GET',
        '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=1'.format(
            wallets[5].addr),
        None,
        api_pass=api_pass)
    if 'error' in owner_utxos:
        owner_utxos['test'] = 'failed to get utxos'
        print json.dumps(owner_utxos)
        return False

    # two utxos: one for the initial wallet fill-up from the test framework, and one from the registration
    if len(owner_utxos['response']) != 2:
        owner_utxos['test'] = 'wrong utxos'
        print json.dumps(owner_utxos)
        return False

    # last transaction should be the register
    found = False
    for utxo in owner_utxos['response']:
        if utxo['transaction_hash'] == register_resp[
                'transaction_hash'] and utxo['confirmations'] == 1:
            found = True

    if not found:
        owner_utxos['test'] = 'invalid utxos (tx_hash, confirmations)'
        print json.dumps(owner_utxos)
        return False

    # verify that min_confirmations=2 hides these transactions
    res = testlib.blockstack_REST_call(
        'GET',
        '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=2'.format(
            wallets[5].addr),
        None,
        api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    if len(res['response']) > 1:
        res['test'] = 'got more UTXOs than we expected'
        print json.dumps(res)
        return False

    # count UTXOs in wallets[1]
    res = testlib.blockstack_REST_call(
        'GET',
        '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=0'.format(
            wallets[1].addr),
        None,
        api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    initial_utxos = res['response']
    if len(initial_utxos) == 0:
        res['test'] = 'test bug: no UTXOs for wallet'
        print json.dumps(res)
        return False

    # send money from one wallet to another
    fund_tx = testlib.send_funds_tx(wallets[0].privkey, 10**8, wallets[1].addr)
    res = testlib.blockstack_REST_call('POST',
                                       '/v1/blockchains/bitcoin/txs',
                                       None,
                                       data={'tx': fund_tx},
                                       api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to send {}'.format(fund_tx)
        print json.dumps(res)
        return False

    if not res['response'].has_key('transaction_hash'):
        res['test'] = 'response is missing transaction hash'
        print json.dumps(res)
        return False

    # verify that it's in the UTXO set with min_confirmations=0
    res = testlib.blockstack_REST_call(
        'GET',
        '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=0'.format(
            wallets[1].addr),
        None,
        api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    if len(res['response']) != len(initial_utxos) + 1:
        res['test'] = 'missing UTXO'
        print json.dumps(res)
        return False

    current_utxos = res['response']

    # verify that with min_confirmations=1, we have what we started with
    res = testlib.blockstack_REST_call(
        'GET',
        '/v1/blockchains/bitcoin/{}/unspent?min_confirmations=1'.format(
            wallets[1].addr),
        None,
        api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    if res['response'] != initial_utxos:
        res['test'] = 'initial utxos do not match current utxos'
        print json.dumps(res)
        print json.dumps(initial_utxos)
        return False

    # confirm everything
    for i in xrange(0, 10):
        testlib.next_block(**kw)

    # verify that we have what we started with
    res = testlib.blockstack_REST_call(
        'GET',
        '/v1/blockchains/bitcoin/{}/unspent'.format(wallets[1].addr),
        None,
        api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'failed to get utxos'
        print json.dumps(res)
        return False

    current_utxos_no_confirmation = [
        dict([(k, v) for (
            k, v) in filter(lambda (x, y): x != 'confirmations', utxo.items())
              ]) for utxo in current_utxos
    ]
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)
    config_dir = os.path.dirname(config_path)
     
    conf = blockstack_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    # make sure we can do REST calls
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/pending', None, api_pass=api_pass )
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

    # make sure we can do REST calls with different app names and user names
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/pending', None, api_pass=api_pass )
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

    # can we even get to the wallet?
    res = testlib.blockstack_REST_call('POST', '/v1/wallet/balance', None, api_pass=api_pass, data={'address': wallets[4].addr, 'amount': 100000} )
    if res['http_status'] != 200:
        res['test'] = 'failed to transfer funds'

    # make zonefile for recipient
    driver_urls = blockstack_client.storage.make_mutable_data_urls('foo.test', use_only=['dht', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile('foo.test', wallets[4].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='foo.test', ttl=3600 )

    # register the name bar.test, with min 3 confirmations on its UTXOs
    data = {
        'name': 'bar.test',
        'zonefile': zonefile_txt,
        'owner_address': wallets[4].addr,
        'min_confs': 3
    }

    # should fail
    res = testlib.blockstack_REST_call('POST', '/v1/names', None, api_pass=api_pass, data=data)
    if res['http_status'] == 200:
        res['test'] = 'succeeded in sending bar.test'
        print json.dumps(res)
        error = True
        return False

    # wait for confirmations
    for i in xrange(0, 3):
        testlib.next_block( **kw )

    # should succeed
    res = testlib.blockstack_REST_call('POST', '/v1/names', None, api_pass=api_pass, data=data)
    if 'error' in res or 'error' in res['response']:
        res['test'] = 'failed to send bar.test'
        print json.dumps(res)
        error = True
        return False


    # wait for update to get confirmed 
    for i in xrange(0, 48):
        if i % 12 == 0:
            print "waiting for RPC daemon to catch up"
            time.sleep(10)

        testlib.next_block( **kw )

    res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", None, api_pass=api_pass)
    if 'error' in res:
        res['test'] = 'Failed to query name'
        print json.dumps(res)
        error = True
        return False

    if res['http_status'] != 200:
        res['test'] = 'HTTP status {}, response = {}'.format(res['http_status'], res['response'])
        print json.dumps(res)
        error = True
        return False

    # should now be registered 
    if res['response']['status'] != 'registered':
        print "register not complete"
        print json.dumps(res)
        return False
Exemple #31
0
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', 'wallet_write'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    ses = res['token']

    # let's set the key to skip the transfer.

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

    api_pass = conf['api_password']

    new_payment_key = {
        'private_key' : wallets[1].privkey,
        'persist_change' : True
    }

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/payment', None, api_pass=api_pass,
                                       data=new_payment_key)
    if res['http_status'] != 200 or 'error' in res:
        print 'failed to set payment key'
        print res
        return False


    testlib.stop_api()
    testlib.start_api('0123456789abcdef')

    res = testlib.blockstack_REST_call('GET', '/v1/wallet/payment_address', None, api_pass = api_pass)
    if res['http_status'] != 200 or 'error' in res:
        res['test'] = 'Failed to get payment address'
        print res
        return False
    if res['response']['address'] != wallets[1].addr:
        res['test'] = 'Got wrong payer address, expected {}, got {}'.format(
            wallets[1].addr, res['response']['address'])
        print res
        return False

    res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass,
                                       data=new_key)
    if res['http_status'] != 200 or 'error' in res:
        print 'failed to set owner key'
        print res
        return False


    # make zonefile for recipient
    driver_urls = blockstack_client.storage.make_mutable_data_urls('bar.test', use_only=['dht', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile('bar.test', wallets[4].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='bar.test', ttl=3600 )

    # leaving the call format of this one the same to make sure that our registrar correctly
    #   detects that the requested TRANSFER is superfluous
    # register the name bar.test
    res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data={'name': 'bar.test', 'zonefile': zonefile_txt, 'owner_address': new_addr })
    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, 4):
        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, 4):
        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, 4):
        testlib.next_block( **kw )

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

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

    res = testlib.verify_in_queue(ses, 'bar.test', 'transfer', None )
    if res:
        print res
        print "Wrongly issued a TRANSFER"
        return False

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

    print 'Wait for transfer 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']

    # should still be registered
    if res['response']['status'] != 'registered':
        print "register not complete"
        print json.dumps(res)
        return False

    # 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 foo.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

    # same zonefile we put?
    if res['response']['zonefile'] != zonefile_txt:
        res['test'] = 'mismatched zonefile, expected\n{}\n'.format(zonefile_txt)
        print json.dumps(res)
        return False
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data, wallet_balance

    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)
    config_dir = os.path.dirname(config_path)
 
    conf = blockstack_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    # make sure we can do REST calls
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/pending', None, api_pass=api_pass )
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

    # make sure we can do REST calls with different app names and user names
    res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/pending', None, api_pass=api_pass )
    if 'error' in res:
        res['test'] = 'Failed to get queues'
        print json.dumps(res)
        return False

    # what's the balance?
    res = testlib.blockstack_REST_call('GET', '/v1/wallet/balance', None, api_pass=api_pass )
    if res['http_status'] != 200:
        res['test'] = 'failed to query wallet'
        print json.dumps(res)
        return False

    wallet_balance = res['response']['balance']['satoshis']
    balance_before = testlib.get_balance(wallets[8].addr)

    # can we move the funds?
    res = testlib.blockstack_REST_call('POST', '/v1/wallet/balance', None, api_pass=api_pass, data={'address': wallets[8].addr, 'amount': wallet_balance / 2, 'message': "hello world!"})
    if res['http_status'] != 200:
        res['test'] = 'failed to transfer funds'
        print json.dumps(res)
        return False

    if not res['response'].has_key('transaction_hash'):
        res['test'] = 'missing tx hash'
        print json.dumps(res)
        return False

    print "\n\nTransaction: {}\n\n".format(res['response']['transaction_hash'])

    # confirm it
    for i in xrange(0, 12):
        testlib.next_block(**kw)
  
    new_balance = testlib.get_balance(wallets[5].addr)
    balance_after = testlib.get_balance(wallets[8].addr)

    print "wallet balance: {}".format(wallet_balance)
    print "new balance {}: {}".format(wallets[5].addr, new_balance)
    print "balance after {}: {}".format(wallets[8].addr, balance_after)
    print "balance before {}: {}".format(wallets[8].addr, balance_before)

    if new_balance > wallet_balance / 2:
        print 'new balance of {} is {}'.format(wallets[5].addr, new_balance)
        return False

    if abs(balance_after - balance_before) > abs(wallet_balance / 2) + 54500:
        print "{} - {} != {}".format(balance_after, balance_before, wallet_balance / 2)
        return False
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)

    # 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)
    conf = blockstack_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    # register the name bar.test. autogenerate the rest
    postage = {
        'name': 'bar.test',
        'owner_key': owner_key,
        'payment_key': payment_key
    }
    res = testlib.blockstack_REST_call('POST',
                                       '/v1/names',
                                       None,
                                       api_pass=api_pass,
                                       data=postage)
    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(None, '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(None, '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(None, 'bar.test', 'update', None)
    if not res:
        return False

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

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

    res = testlib.blockstack_REST_call("GET",
                                       "/v1/names/bar.test",
                                       None,
                                       api_pass=api_pass)
    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']
    old_expire_block = res['response']['expire_block']

    # renew it
    res = testlib.blockstack_REST_call('POST',
                                       '/v1/names',
                                       None,
                                       api_pass=api_pass,
                                       data=postage)
    if 'error' in res or res['http_status'] != 202:
        res['test'] = 'Failed to renew name'
        print json.dumps(res)
        return False

    # verify in renew queue
    for i in xrange(0, 6):
        testlib.next_block(**kw)

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

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

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

    new_expire_block = res['response']['expire_block']

    # do we have the history for the name?
    res = testlib.blockstack_REST_call("GET",
                                       "/v1/names/bar.test/history",
                                       None,
                                       api_pass=api_pass)
    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()) != 4:
        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),
        None,
        api_pass=api_pass)
    if 'error' in res or res['http_status'] != 200:
        res['test'] = 'Failed to get name zonefile'
        print json.dumps(res)
        return False

    # verify pushed back
    if old_expire_block + 12 >= new_expire_block:
        # didn't go through
        print >> sys.stderr, "Renewal didn't work: %s --> %s" % (
            old_expire_block, new_expire_block)
        return False
def scenario(wallets, **kw):

    global error
    global names, owner_wallets, payment_wallets, recipients

    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)

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

    processed_preorders = 0
    while processed_preorders < len(owner_wallets):
        name, owner = names[processed_preorders], owner_wallets[
            processed_preorders]
        payer_ix = processed_preorders % len(payment_wallets)
        payer = payment_wallets[payer_ix]
        testlib.blockstack_name_preorder(name, payer.privkey, owner.addr)

        processed_preorders += 1
        if payer_ix == (len(payment_wallets) - 1):
            testlib.next_block(**kw)
            testlib.next_block(**kw)

    testlib.next_block(**kw)

    processed_registers = 0
    while processed_registers < len(owner_wallets):
        name, owner = names[processed_registers], owner_wallets[
            processed_registers]
        payer_ix = processed_registers % len(payment_wallets)
        payer = payment_wallets[payer_ix]
        testlib.blockstack_name_register(name, payer.privkey, owner.addr)
        processed_registers += 1

        if payer_ix == (len(payment_wallets) - 1):
            testlib.next_block(**kw)
            testlib.next_block(**kw)

    # now let's go crazy with transfers

    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']

    testlib.next_block(**kw)

    processed_transfers = 0
    while processed_transfers < len(owner_wallets):
        name, owner_privkey, recipient = (
            names[processed_transfers],
            owner_wallets[processed_transfers].privkey,
            recipients[processed_transfers])
        payer_ix = processed_transfers % len(payment_wallets)
        payer = payment_wallets[payer_ix]

        driver_urls = blockstack_client.storage.make_mutable_data_urls(
            name, use_only=['dht', 'disk'])
        zonefile = blockstack_client.zonefile.make_empty_zonefile(
            name, None, urls=driver_urls)
        zonefile_txt = blockstack_zones.make_zone_file(zonefile,
                                                       origin=name,
                                                       ttl=3600)

        res = testlib.blockstack_REST_call('POST',
                                           '/v1/names/',
                                           None,
                                           api_pass=api_pass,
                                           data={
                                               'name': name,
                                               'owner_address': recipient,
                                               'owner_key': owner_privkey,
                                               'payment_key': payer.privkey,
                                               'zonefile': zonefile_txt,
                                           })
        if 'error' in res or res['http_status'] != 202:
            res['test'] = '(Wrongly) failed to renew/transfer/update user'
            print json.dumps(res)
            error = True
            return False
        else:
            print "Submitted transfer!"

        processed_transfers += 1
        if (payer_ix == (len(payment_wallets) - 1)
                or processed_transfers >= len(owner_wallets)):
            print 'Waiting to get more UTXOs and processing transfers'
            time.sleep(10)
            for i in range(11):
                testlib.next_block(**kw)
    return True