Exemple #1
0
def add_subdomains(subdomains,
                   domain_fqa,
                   zonefile_json,
                   filter_function=None):
    if filter_function is None:
        filter_function = (lambda subdomain, domain: True)

    zf = copy.deepcopy(zonefile_json)
    if "txt" in zf:
        zf["txt"] = list([x for x in zf["txt"] if not is_subdomain_record(x)])

    if len(set(subdomains)) != len(subdomains):
        raise Exception("Same subdomain listed multiple times")

    subdomains_failed = []
    for ix, subdomain in enumerate(subdomains):
        # step 1: see if this resolves to an already defined subdomain
        filter_passed = filter_function(subdomain.subdomain_name, domain_fqa)
        if not filter_passed:
            subdomains_failed.append(ix)
        else:
            # step 2: create the subdomain record, adding it to zf
            try:
                _extend_with_subdomain(zf, subdomain)
            except Exception as e:
                subdomains_failed.append(ix)

    zf_txt = ysi_zones.make_zone_file(zf)
    return zf_txt, subdomains_failed
Exemple #2
0
    def test_sigs(self):
        fake_privkey_hex = "5512612ed6ef10ea8c5f9839c63f62107c73db7306b98588a46d0cd2c3d15ea5"
        sk = keylib.ECPrivateKey(fake_privkey_hex)
        pk = sk.public_key()

        for t in ["foo", "bar", "bassoon"]:
            self.assertTrue(
                subdomains.verify(pk.address(), t, subdomains.sign(sk, t)), t)

        subdomain = subdomains.Subdomain("bar.id", "foo",
                                         subdomains.encode_pubkey_entry(sk), 3,
                                         "")

        user_zf = {'$origin': 'foo', '$ttl': 3600, 'txt': [], 'uri': []}

        user_zf['uri'].append(
            zonefile.url_to_uri_record("https://foo_foo.com/profile.json"))
        jsonschema.validate(user_zf, USER_ZONEFILE_SCHEMA)

        subdomain.zonefile_str = ysi_zones.make_zone_file(user_zf)

        subdomain.add_signature(sk)

        self.assertTrue(subdomain.verify_signature(pk.address()))

        parsed_zf = zonefile.decode_name_zonefile(subdomain.subdomain_name,
                                                  subdomain.zonefile_str)
        urls = user_db.user_zonefile_urls(parsed_zf)

        self.assertEqual(len(urls), 1)
        self.assertIn("https://foo_foo.com/profile.json", urls)

        self.assertRaises(
            NotImplementedError,
            lambda: subdomains.encode_pubkey_entry(fake_privkey_hex))
Exemple #3
0
def store_name_zonefile(name, user_zonefile, txid, storage_drivers=None):
    """
    Store JSON user zonefile data to the immutable storage providers, synchronously.
    This is only necessary if we've added/changed/removed immutable data.

    Return (True, hash(user zonefile)) on success
    Return (False, None) on failure
    """

    storage_drivers = [] if storage_drivers is None else storage_drivers

    assert not ysi_profiles.is_profile_in_legacy_format(
        user_zonefile), 'User zonefile is a legacy profile'
    assert user_db.is_user_zonefile(
        user_zonefile), 'Not a user zonefile (maybe a custom legacy profile?)'

    # serialize and send off
    user_zonefile_txt = ysi_zones.make_zone_file(user_zonefile,
                                                 origin=name,
                                                 ttl=USER_ZONEFILE_TTL)

    return store_name_zonefile_data(name,
                                    user_zonefile_txt,
                                    txid,
                                    storage_drivers=storage_drivers)
Exemple #4
0
def hash_zonefile(zonefile_json):
    """
    Given a JSON-ized zonefile, calculate its hash
    """
    assert '$origin' in zonefile_json.keys(), 'Missing $origin'
    assert '$ttl' in zonefile_json.keys(), 'Missing $ttl'

    user_zonefile_txt = ysi_zones.make_zone_file(zonefile_json)
    data_hash = get_zonefile_data_hash(user_zonefile_txt)

    return data_hash
Exemple #5
0
def store_zonefile_to_storage( zonefile_dict, required=None, skip=None, cache=False, zonefile_dir=None ):
    """
    Upload a zonefile to our storage providers.
    Return True if at least one provider got it.
    Return False otherwise.
    """

    try:
        zonefile_data = ysi_zones.make_zone_file( zonefile_dict )
    except Exception, e:
        log.exception(e)
        log.error("Invalid zonefile dict")
        return False
Exemple #6
0
def store_cached_zonefile( zonefile_dict, zonefile_dir=None ):
    """
    Store a validated zonefile.
    zonefile_data should be a dict.
    The caller should first authenticate the zonefile.
    Return True on success
    Return False on error
    """
    try:
        zonefile_data = ysi_zones.make_zone_file( zonefile_dict )
    except Exception, e:
        log.exception(e)
        log.error("Invalid zonefile dict")
        return False
Exemple #7
0
    def test_db_builder_bad_transitions(self):
        history = [
            """$ORIGIN bar.id
$TTL 3600
pubkey TXT "pubkey:data:0"
registrar URI 10 1 "bsreg://foo.com:8234"
foo TXT "owner={}" "seqn=0" "parts=0"
""",
            """$ORIGIN bar.id
$TTL 3600
pubkey TXT "pubkey:data:0"
registrar URI 10 1 "bsreg://foo.com:8234"
bar TXT "owner={}" "seqn=0" "parts=0"
""",
        ]

        foo_bar_sk = keylib.ECPrivateKey()
        bar_bar_sk = keylib.ECPrivateKey()

        history[0] = history[0].format(
            subdomains.encode_pubkey_entry(foo_bar_sk))
        history[1] = history[1].format(
            subdomains.encode_pubkey_entry(bar_bar_sk))

        domain_name = "bar.id"

        empty_zf = """$ORIGIN bar.id
$TTL 3600
pubkey TXT "pubkey:data:0"
registrar URI 10 1 "bsreg://foo.com:8234"
"""

        zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf)
        self.assertEqual(zf_json['$origin'], domain_name)

        # bad transition n=0 -> n=0
        sub1 = subdomains.Subdomain("foo", domain_name,
                                    subdomains.encode_pubkey_entry(foo_bar_sk),
                                    0, "")

        subdomain_util._extend_with_subdomain(zf_json, sub1)

        history.append(ysi_zones.make_zone_file(zf_json))

        # bad transition bad sig.
        zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf)
        self.assertEqual(zf_json['$origin'], domain_name)

        sub2 = subdomains.Subdomain("foo", domain_name,
                                    subdomains.encode_pubkey_entry(bar_bar_sk),
                                    1, "")
        subdomain_util._extend_with_subdomain(zf_json, sub2)
        history.append(ysi_zones.make_zone_file(zf_json))

        subdomain_db = subdomains._build_subdomain_db(
            ["bar.id" for x in range(1)], history[:1])
        self.assertEqual(subdomain_db["foo.bar.id"].n, 0)
        self.assertNotIn("bar.bar.id", subdomain_db)

        subdomain_db = subdomains._build_subdomain_db(
            ["bar.id" for x in range(2)], history[:2])
        self.assertIn("bar.bar.id", subdomain_db)
        self.assertEqual(subdomain_db["bar.bar.id"].n, 0)

        subdomain_db = subdomains._build_subdomain_db(
            ["bar.id" for x in range(3)], history[:3])
        self.assertEqual(subdomain_db["foo.bar.id"].n, 0)
        self.assertEqual(subdomain_db["bar.bar.id"].n, 0)

        # handle repeated zonefile

        subdomain_db = subdomains._build_subdomain_db(
            ["bar.id" for x in range(3)], history[:3])
        self.assertEqual(subdomain_db["foo.bar.id"].n, 0)
        self.assertEqual(subdomain_db["bar.bar.id"].n, 0)
        subdomains._build_subdomain_db(["bar.id" for x in range(3)],
                                       history[:3],
                                       subdomain_db=subdomain_db)
        self.assertEqual(subdomain_db["foo.bar.id"].n, 0)
        self.assertEqual(subdomain_db["bar.bar.id"].n, 0)
def scenario(wallets, **kw):

    global value_hashes

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

    testlib.ysi_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.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

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

    testlib.next_block(**kw)

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

    testlib.next_block(**kw)

    # make 10 empty zonefiles and propagate them
    for i in xrange(0, 10):
        data_pubkey = wallets[4].pubkey_hex
        empty_zonefile = ysi_client.zonefile.make_empty_zonefile(
            "foo_{}.test".format(i),
            data_pubkey,
            urls=["file:///tmp/foo_{}.test".format(i)])
        empty_zonefile_str = ysi_zones.make_zone_file(empty_zonefile)
        value_hash = ysi_client.hash_zonefile(empty_zonefile)

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

        testlib.next_block(**kw)

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

        value_hashes.append(value_hash)

    print 'waiting for all zone files to replicate'
    time.sleep(10)

    config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG")
    assert config_path
    restore_dir = os.path.join(os.path.dirname(config_path), "snapshot_dir")

    # snapshot the latest backup
    snapshot_path = os.path.join(os.path.dirname(config_path), "snapshot.bsk")
    rc = ysi.fast_sync_snapshot(snapshot_path, wallets[3].privkey, None)
    if not rc:
        print "Failed to fast_sync_snapshot"
        return False

    if not os.path.exists(snapshot_path):
        print "Failed to create snapshot {}".format(snapshot_path)
        return False

    # sign with more keys
    for i in xrange(4, 6):
        rc = ysi.fast_sync_sign_snapshot(snapshot_path, wallets[i].privkey)
        if not rc:
            print "Failed to sign with key {}".format(i)
            return False

    # restore!
    rc = restore(
        snapshot_path, restore_dir,
        [wallets[3].pubkey_hex, wallets[4].pubkey_hex, wallets[5].pubkey_hex],
        3)
    if not rc:
        print "failed to restore snapshot {}".format(snapshot_path)
        return False

    rc = restore(
        snapshot_path, restore_dir,
        [wallets[5].pubkey_hex, wallets[4].pubkey_hex, wallets[3].pubkey_hex],
        3)
    if not rc:
        print "failed to restore snapshot {}".format(snapshot_path)
        return False

    rc = restore(snapshot_path, restore_dir,
                 [wallets[3].pubkey_hex, wallets[4].pubkey_hex], 2)
    if not rc:
        print "failed to restore snapshot {}".format(snapshot_path)
        return False

    rc = restore(snapshot_path, restore_dir,
                 [wallets[3].pubkey_hex, wallets[5].pubkey_hex], 2)
    if not rc:
        print "failed to restore snapshot {}".format(snapshot_path)
        return False

    rc = restore(snapshot_path, restore_dir,
                 [wallets[4].pubkey_hex, wallets[5].pubkey_hex], 2)
    if not rc:
        print "failed to restore snapshot {}".format(snapshot_path)
        return False

    rc = restore(snapshot_path, restore_dir, [wallets[3].pubkey_hex], 1)
    if not rc:
        print "failed to restore snapshot {}".format(snapshot_path)
        return False

    rc = restore(snapshot_path, restore_dir,
                 [wallets[4].pubkey_hex, wallets[0].pubkey_hex], 1)
    if not rc:
        print "failed to restore snapshot {}".format(snapshot_path)
        return False

    rc = restore(
        snapshot_path, restore_dir,
        [wallets[0].pubkey_hex, wallets[1].pubkey_hex, wallets[5].pubkey_hex],
        1)
    if not rc:
        print "failed to restore snapshot {}".format(snapshot_path)
        return False

    # should fail
    rc = restore(snapshot_path, restore_dir, [wallets[3].pubkey_hex], 2)
    if rc:
        print "restored insufficient signatures snapshot {}".format(
            snapshot_path)
        return False

    shutil.rmtree(restore_dir)

    # should fail
    rc = restore(snapshot_path, restore_dir,
                 [wallets[3].pubkey_hex, wallets[4].pubkey_hex], 3)
    if rc:
        print "restored insufficient signatures snapshot {}".format(
            snapshot_path)
        return False

    shutil.rmtree(restore_dir)

    # should fail
    rc = restore(snapshot_path, restore_dir, [wallets[0].pubkey_hex], 1)
    if rc:
        print "restored wrongly-signed snapshot {}".format(snapshot_path)
        return False

    shutil.rmtree(restore_dir)

    # should fail
    rc = restore(snapshot_path, restore_dir,
                 [wallets[0].pubkey_hex, wallets[3].pubkey_hex], 2)
    if rc:
        print "restored wrongly-signed snapshot {}".format(snapshot_path)
        return False

    shutil.rmtree(restore_dir)

    # should fail
    rc = restore(
        snapshot_path, restore_dir,
        [wallets[0].pubkey_hex, wallets[3].pubkey_hex, wallets[4].pubkey_hex],
        3)
    if rc:
        print "restored wrongly-signed snapshot {}".format(snapshot_path)
        return False

    shutil.rmtree(restore_dir)
Exemple #9
0
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

    wallet_keys = testlib.ysi_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[3].privkey )
    test_proxy = testlib.TestAPIProxy()
    ysi_client.set_default_proxy( test_proxy )

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

    testlib.ysi_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.ysi_namespace_ready( "test", wallets[1].privkey )
    testlib.next_block( **kw )

    testlib.ysi_name_preorder( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.ysi_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    # migrate profiles, but no data key in the zone file 
    res = testlib.migrate_profile( "foo.test", zonefile_has_data_key=False, 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.ysi_cli_app_signin("foo.test", datastore_pk, 'register.app', ['names', 'register', 'prices', 'zonefiles', 'blockchain', 'node_read', 'user_read'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    ses = res['token']

    # register the name bar.test. autogenerate the rest 
    old_user_zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test', None)
    old_user_zonefile_txt = ysi_zones.make_zone_file(old_user_zonefile)

    res = testlib.ysi_REST_call('POST', '/v1/names', ses, data={'name': 'bar.test', 'zonefile': old_user_zonefile_txt, 'make_profile': True} )
    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/update 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, 3):
        testlib.next_block( **kw )

    # should have nine confirmations now
    res = testlib.get_queue(ses, 'register')
    if 'error' in res:
        print res
        return False
    
    if len(res) != 1:
        print res
        return False

    reg = res[0]
    confs = ysi_client.get_tx_confirmations(reg['tx_hash'])
    if confs != 9:
        print 'wrong number of confs for {} (expected 9): {}'.format(reg['tx_hash'], confs)
        return False

    # stop the API server
    testlib.stop_api()

    # advance blockchain 
    testlib.next_block(**kw)
    testlib.next_block(**kw)

    confs = ysi_client.get_tx_confirmations(reg['tx_hash'])
    if confs != 11:
        print 'wrong number of confs for {} (expected 11): {}'.format(reg['tx_hash'], confs)
        return False

    # make sure the registrar does not process reg/up zonefile replication
    # (i.e. we want to make sure that the zonefile gets processed even if the blockchain goes too fast)
    os.environ['BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_REGUP_REPLICATION'] = '1'
    testlib.start_api("0123456789abcdef")

    print 'Wait to verify that we do not remove the zone file just because the tx is confirmed'
    time.sleep(10)

    # verify that this is still in the queue
    res = testlib.get_queue(ses, 'register')
    if 'error' in res:
        print res
        return False
    
    if len(res) != 1:
        print res
        return False
    
    # clear the fault
    print 'Clearing regup replication fault'
    testlib.ysi_test_setenv("BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_REGUP_REPLICATION", "0")

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

    res = testlib.ysi_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

    old_expire_block = res['response']['expire_block']

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

    # zonefile must not have a public key listed
    zonefile_txt = res['response']['zonefile']
    print zonefile_txt

    parsed_zonefile = ysi_zones.parse_zone_file(zonefile_txt)
    if parsed_zonefile.has_key('txt'):
        print 'have txt records'
        print parsed_zonefile
        return False

    # renew it, but put the *current* owner key as the zonefile's *new* public key
    new_user_zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test', wallets[3].pubkey_hex )
    new_user_zonefile_txt = ysi_zones.make_zone_file(new_user_zonefile)

    res = testlib.ysi_REST_call("POST", "/v1/names", ses, data={'name': 'bar.test', 'zonefile': new_user_zonefile_txt} )
    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(ses, 'bar.test', 'renew', None )
    if not res:
        return False

    for i in xrange(0, 3):
        testlib.next_block( **kw )
 
    # should have nine confirmations now
    res = testlib.get_queue(ses, 'renew')
    if 'error' in res:
        print res
        return False
    
    if len(res) != 1:
        print res
        return False

    reg = res[0]
    confs = ysi_client.get_tx_confirmations(reg['tx_hash'])
    if confs != 9:
        print 'wrong number of confs for {} (expected 9): {}'.format(reg['tx_hash'], confs)
        return False

    # stop the API server
    testlib.stop_api()

    # advance blockchain 
    testlib.next_block(**kw)
    testlib.next_block(**kw)

    confs = ysi_client.get_tx_confirmations(reg['tx_hash'])
    if confs != 11:
        print 'wrong number of confs for {} (expected 11): {}'.format(reg['tx_hash'], confs)
        return False

    # make the registrar skip the first few steps, so the only thing it does is clear out confirmed updates
    # (i.e. we want to make sure that the renewal's zonefile gets processed even if the blockchain goes too fast)
    os.environ['BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_RENEWAL_REPLICATION'] = '1'
    testlib.start_api("0123456789abcdef")

    # wait a while
    print 'Wait to verify that clearing out confirmed transactions does NOT remove zonefiles'
    time.sleep(10)

    # verify that this is still in the queue
    res = testlib.get_queue(ses, 'renew')
    if 'error' in res:
        print res
        return False
    
    if len(res) != 1:
        print res
        return False

    # clear the fault
    print 'Clearing renewal replication fault'
    testlib.ysi_test_setenv("BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_RENEWAL_REPLICATION", "0")

    # now the renewal zonefile should replicate
    print 'Wait for renewal zonefile to replicate'
    time.sleep(10)

    # new expire block
    res = testlib.ysi_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

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

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

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

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

    # zonefile must have old owner key
    zonefile_txt = res['response']['zonefile']
    parsed_zonefile = ysi_zones.parse_zone_file(zonefile_txt)
    if not parsed_zonefile.has_key('txt'):
        print 'missing txt'
        print parsed_zonefile
        return False

    found = False
    for txtrec in parsed_zonefile['txt']:
        if txtrec['name'] == 'pubkey' and txtrec['txt'] == 'pubkey:data:{}'.format(wallets[3].pubkey_hex):
            found = True

    if not found:
        print 'missing public key {}'.format(wallets[3].pubkey_hex)
        return False

    # profile lookup must work 
    res = testlib.ysi_REST_call("GET", "/v1/users/bar.test", ses)
    if 'error' in res or res['http_status'] != 200:
        res['text'] = 'failed to get profile for bar.test'
        print json.dumps(res)
        return False

    print ''
    print json.dumps(res['response'], indent=4, sort_keys=True)
    print ''

    # verify pushed back 
    if old_expire_block + 10 > new_expire_block:
        # didn't go through
        print >> sys.stderr, "Renewal didn't work: %s --> %s" % (old_expire_block, new_expire_block)
        return False
Exemple #10
0
    def test_db_builder(self):
        history = [
            """$ORIGIN bar.id
$TTL 3600
pubkey TXT "pubkey:data:0"
registrar URI 10 1 "bsreg://foo.com:8234"
foo TXT "owner={}" "seqn=0" "parts=0"
""",
            """$ORIGIN bar.id
$TTL 3600
pubkey TXT "pubkey:data:0"
registrar URI 10 1 "bsreg://foo.com:8234"
bar TXT "owner={}" "seqn=0" "parts=0"
""",
        ]

        foo_bar_sk = keylib.ECPrivateKey()
        bar_bar_sk = keylib.ECPrivateKey()

        history[0] = history[0].format(
            subdomains.encode_pubkey_entry(foo_bar_sk))
        history[1] = history[1].format(
            subdomains.encode_pubkey_entry(bar_bar_sk))

        domain_name = "bar.id"

        empty_zf = """$ORIGIN bar.id
$TTL 3600
pubkey TXT "pubkey:data:0"
registrar URI 10 1 "bsreg://foo.com:8234"
"""

        zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf)
        self.assertEqual(zf_json['$origin'], domain_name)

        sub1 = subdomains.Subdomain(domain_name, "foo",
                                    subdomains.encode_pubkey_entry(foo_bar_sk),
                                    1, "")
        sub2 = subdomains.Subdomain(domain_name, "bar",
                                    subdomains.encode_pubkey_entry(bar_bar_sk),
                                    1, "")
        sub1.add_signature(foo_bar_sk)
        sub2.add_signature(bar_bar_sk)

        subdomain_util._extend_with_subdomain(zf_json, sub2)

        history.append(ysi_zones.make_zone_file(zf_json))

        zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf)
        subdomain_util._extend_with_subdomain(zf_json, sub1)

        history.append(ysi_zones.make_zone_file(zf_json))

        subdomain_db = subdomains._build_subdomain_db(
            ["bar.id" for x in range(1)], history[:1])
        self.assertIn("foo.bar.id", subdomain_db,
                      "Contents actually: {}".format(subdomain_db.keys()))
        self.assertEqual(subdomain_db["foo.bar.id"].n, 0)
        self.assertNotIn("bar.bar.id", subdomain_db)

        subdomain_db = subdomains._build_subdomain_db(
            ["bar.id" for x in range(2)], history[:2])
        self.assertIn("bar.bar.id", subdomain_db)
        self.assertEqual(subdomain_db["bar.bar.id"].n, 0)

        subdomain_db = subdomains._build_subdomain_db(
            ["bar.id" for x in range(3)], history[:3])
        self.assertEqual(subdomain_db["foo.bar.id"].n, 0)
        self.assertEqual(subdomain_db["bar.bar.id"].n, 1)

        subdomain_db = subdomains._build_subdomain_db(
            ["bar.id" for x in range(len(history))], history)
        self.assertEqual(subdomain_db["foo.bar.id"].n, 1)
        self.assertEqual(subdomain_db["bar.bar.id"].n, 1)
def scenario( wallets, **kw ):

    global synchronized, value_hash

    import ysi_integration_tests.atlas_network as atlas_network

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

    testlib.ysi_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.ysi_namespace_ready( "test", wallets[1].privkey )
    testlib.next_block( **kw )

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

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

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

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

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

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

        testlib.next_block( **kw )

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

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

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

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

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

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

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

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

    global first_name_block
    test_proxy = testlib.make_proxy()

    # make a test namespace
    resp = testlib.ysi_namespace_preorder("test", wallets[1].addr,
                                          wallets[0].privkey)
    if 'error' in resp:
        print json.dumps(resp, indent=4)
        return False

    testlib.next_block(**kw)  # end of 689

    resp = testlib.ysi_namespace_reveal(
        "test", wallets[1].addr, 2, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    if 'error' in resp:
        print json.dumps(resp, indent=4)
        return False

    testlib.next_block(**kw)  # 690

    # make a zonefile and a profile
    driver_urls = ysi_client.storage.make_mutable_data_urls(
        'foo.test', use_only=['dht', 'disk'])
    zonefile = ysi_client.zonefile.make_empty_zonefile('foo.test',
                                                       wallets[4].pubkey_hex,
                                                       urls=driver_urls)
    zonefile_txt = ysi_zones.make_zone_file(zonefile,
                                            origin='foo.test',
                                            ttl=4200)

    # make a new keyfile as well
    user_profile = ysi_client.user.make_empty_user_profile()
    '''
    res = ysi_client.key_file.make_initial_key_file(user_profile, wallets[3].privkey)
    if 'error' in res:
        print res
        return res

    keyfile_txt = res['key_file']
    '''
    zonefile_hash = ysi_client.get_zonefile_data_hash(zonefile_txt)

    resp = testlib.ysi_name_import("foo.test", wallets[3].addr, zonefile_hash,
                                   wallets[1].privkey)
    if 'error' in resp:
        print json.dumps(resp, indent=4)
        return False

    testlib.next_block(**kw)  # 691

    # broadcast zonefile
    res = testlib.ysi_cli_sync_zonefile('foo.test',
                                        zonefile_string=zonefile_txt)
    if 'error' in res:
        print res
        return False
    '''
    # upload keyfile
    res = ysi_client.key_file.key_file_put('foo.test', keyfile_txt)
    if 'error' in res:
        print res
        return False
    '''

    rc = ysi_client.profile.put_profile('foo.test',
                                        user_profile,
                                        blockchain_id='foo.test',
                                        user_data_privkey=wallets[4].privkey,
                                        user_zonefile=zonefile,
                                        proxy=test_proxy)
    if not rc:
        print 'failed to put profile'
        return False

    # try lookup
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    first_name_block = testlib.get_current_block(**kw)

    resp = testlib.ysi_namespace_ready("test", wallets[1].privkey)
    if 'error' in resp:
        print json.dumps(resp, indent=4)
        return False

    # try lookup
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)  # end of 692

    whois = testlib.ysi_cli_whois('foo.test')
    if 'error' in whois:
        print 'failed to whois foo.test'
        print json.dumps(whois, indent=4)
        return False

    # this should be the second-to-last block
    if whois['expire_block'] != testlib.get_current_block(**kw) + 2:
        print 'wrong expire block (expect 2 more)'
        print whois
        return False

    # try lookup
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)  # end of 693; begin epoch 2
    # begin epoch 2

    # try lookup
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)  # 694

    # try lookup
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    whois = testlib.ysi_cli_whois('foo.test')
    if 'error' in whois:
        print 'failed to whois foo.test'
        print json.dumps(whois, indent=4)
        return False

    # this should be the last block
    if whois['expire_block'] != testlib.get_current_block(**kw) + 2:
        print 'wrong expire block (expect 2 more)'
        print whois
        return False

    if whois['renewal_deadline'] != testlib.get_current_block(**kw) + 2:
        print 'wrong renewal block (expect 2 more)'
        print whois
        return False

    print whois

    testlib.next_block(**kw)  # 695 (epoch 3 begins)

    # try lookup
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)  # end of 696

    # try lookup (should fail)
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    whois = testlib.ysi_cli_whois('foo.test')
    if 'error' in whois:
        print whois
        return False

    # this should be the expire block
    if whois['expire_block'] != testlib.get_current_block(**kw):
        print 'wrong expire block (now at {})'.format(
            testlib.get_current_block(**kw))
        print whois
        return False

    # should now be a grace period
    if whois['renewal_deadline'] != testlib.get_current_block(**kw) + 5:
        print 'wrong renewal block (now at {})'.format(
            testlib.get_current_block(**kw))
        print whois
        return False

    last_transaction_height = whois['last_transaction_height']

    # begin epoch 3 (grace period)
    testlib.next_block(**kw)  # end of 697

    # try lookup (should fail)
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    testlib.next_block(**kw)  # 698

    # try lookup (should fail)
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    testlib.next_block(**kw)  # 699

    # try lookup (should fail)
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    testlib.next_block(**kw)  # 700

    # try lookup (should fail)
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' not in res:
        print res
        return False

    if 'expired' not in res['error']:
        print res
        return False

    # make a zonefile and a profile
    driver_urls = ysi_client.storage.make_mutable_data_urls(
        'foo.test', use_only=['dht', 'disk'])
    new_zonefile = ysi_client.zonefile.make_empty_zonefile(
        'foo.test', wallets[4].pubkey_hex, urls=driver_urls)
    new_zonefile_txt = ysi_zones.make_zone_file(new_zonefile,
                                                origin='foo.test',
                                                ttl=4200)

    # make a new keyfile as well
    new_user_profile = ysi_client.user.make_empty_user_profile()
    new_user_profile['new_user'] = True
    '''
    res = ysi_client.key_file.make_initial_key_file(new_user_profile, wallets[0].privkey)
    if 'error' in res:
        print res
        return res

    new_keyfile_txt = res['key_file']
    '''
    new_zonefile_hash = ysi_client.get_zonefile_data_hash(new_zonefile_txt)

    rc = ysi_client.profile.put_profile('foo.test',
                                        new_user_profile,
                                        blockchain_id='foo.test',
                                        user_data_privkey=wallets[4].privkey,
                                        user_zonefile=new_zonefile,
                                        proxy=test_proxy)
    if not rc:
        print 'failed to put profile'
        return False

    # renew/xfer/update
    resp = testlib.ysi_name_renew('foo.test',
                                  wallets[3].privkey,
                                  zonefile_hash=new_zonefile_hash,
                                  recipient_addr=wallets[0].addr)
    if 'error' in resp:
        print resp
        return False

    testlib.next_block(**kw)  # end of 701 (end of grace period)

    # try lookup (should succeed again)
    res = testlib.ysi_cli_lookup('foo.test')
    if 'error' in res:
        print res
        return False

    if res['zonefile'] != new_zonefile_txt:
        print 'wrong zonefile'
        print new_zonefile_txt
        print res
        return False

    testlib.next_block(**kw)  # 702 (name can be registered again)
Exemple #13
0
def scenario(wallets, **kw):

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

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

    testlib.ysi_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.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

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

    # make zonefiles:
    # one with a data key
    # one without a data key
    # one with a nonstandard zonefile
    zf1 = ysi_client.zonefile.make_empty_zonefile('foo1.test',
                                                  wallets[4].pubkey_hex)
    zf1_txt = ysi_zones.make_zone_file(zf1)

    zf2 = ysi_client.zonefile.make_empty_zonefile('foo2.test', None)
    zf2_txt = ysi_zones.make_zone_file(zf2)

    zf3_txt = '\x00\x01\x02\x03\x04\x05'

    testlib.ysi_name_register(
        "foo1.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=ysi_client.get_zonefile_data_hash(zf1_txt))
    testlib.ysi_name_register(
        "foo2.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=ysi_client.get_zonefile_data_hash(zf2_txt))
    testlib.ysi_name_register(
        "foo3.test",
        wallets[2].privkey,
        wallets[3].addr,
        zonefile_hash=ysi_client.get_zonefile_data_hash(zf3_txt))
    testlib.next_block(**kw)

    # replicate zonefiles
    proxy = testlib.make_proxy()
    res = ysi_client.proxy.put_zonefiles("localhost:{}".format(
        ysi.RPC_SERVER_PORT), [
            base64.b64encode(zf1_txt),
            base64.b64encode(zf2_txt),
            base64.b64encode(zf3_txt)
        ],
                                         proxy=proxy)
    if 'error' in res:
        print res
        return False

    for s in res['saved']:
        if s != 1:
            print res
            return False

    print 'waiting for zonefiles to be saved...'
    time.sleep(5)

    # store signed profile for each
    working_dir = os.environ['VIRTUALCHAIN_WORKING_DIR']

    for name in ['foo1.test', 'foo2.test', 'foo3.test']:
        profile = ysi_client.user.make_empty_user_profile()
        profile['name'] = name

        profile_path = os.path.join(working_dir, '{}.profile'.format(name))
        with open(profile_path, 'w') as f:
            f.write(json.dumps(profile))

        print 'sign profile for {}'.format(name)

        jwt = testlib.ysi_cli_sign_profile(name, profile_path)
        if 'error' in jwt:
            print jwt
            return False

        jwt_path = os.path.join(working_dir, '{}.profile.jwt'.format(name))
        with open(jwt_path, 'w') as f:
            f.write(jwt)

        print 'verify profile for {}'.format(name)

        res = testlib.ysi_cli_verify_profile(name, jwt_path)
        if 'error' in res:
            print res
            return False

        print 'store profile for {}'.format(name)

        # store the jwt to the right place
        res = ysi_client.storage.put_mutable_data(name,
                                                  jwt,
                                                  sign=False,
                                                  profile=True,
                                                  raw=True)
        if not res:
            print res
            return False

        print 'lookup profile for {}'.format(name)

        # lookup
        res = testlib.ysi_cli_lookup(name)
        if name != 'foo3.test':
            if 'error' in res:
                print res
                return False

            if res['profile'] != profile:
                print 'profile mismatch:'
                print res
                print profile
                return False

        else:
            if 'error' not in res:
                print res
                return False
def scenario(wallets, **kw):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

    testlib.ysi_namespace_preorder("test", wallets[1].addr, wallets[0].privkey)

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

    # try to preorder another namespace; it should fail
    res = testlib.ysi_namespace_preorder("test2", wallets[1].addr,
                                         wallets[0].privkey)
    if 'error' not in res:
        print 'accidentally succeeded to preorder test2'
        return False

    # try to reveal; it should fail
    res = testlib.ysi_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)
    if 'error' not in res:
        print 'accidentally succeeded to reveal test'
        return False

    testlib.expect_snv_fail_at("test2", testlib.get_current_block(**kw) + 1)
    testlib.expect_snv_fail_at("test", testlib.get_current_block(**kw) + 1)

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

    # should succeed
    res = testlib.ysi_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)
    if 'error' in res:
        print res
        return False

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

    # should fail, since we have an unusable address
    res = testlib.ysi_namespace_ready("test", wallets[1].privkey)
    if 'error' not in res:
        print res
        return False

    testlib.expect_snv_fail_at("test", testlib.get_current_block(**kw) + 1)

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

    # should work now
    res = testlib.ysi_namespace_ready("test", wallets[1].privkey)
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)

    testlib.ysi_name_preorder("foo.test", wallets[2].privkey, wallets[3].addr)

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

    # should fail to re-preorder, since address isn't ready
    res = testlib.ysi_name_preorder("foo2.test", wallets[2].privkey,
                                    wallets[3].addr)
    if 'error' not in res:
        print 'accidentally succeeded to preorder foo2.test'
        return False

    testlib.expect_snv_fail_at("foo2.test",
                               testlib.get_current_block(**kw) + 1)

    # should fail for the same reason: the payment address is not ready
    res = testlib.ysi_name_register("foo.test", wallets[2].privkey,
                                    wallets[3].addr)
    if 'error' not in res:
        print 'accidentally succeeded to register foo.test'
        return False

    testlib.expect_snv_fail_at("foo.test", testlib.get_current_block(**kw) + 1)

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

    # should succeed now that it's confirmed
    res = testlib.ysi_name_register("foo.test", wallets[2].privkey,
                                    wallets[3].addr)
    if 'error' in res:
        print res
        return False

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

    # should fail; address not ready
    res = testlib.migrate_profile("foo.test",
                                  proxy=test_proxy,
                                  wallet_keys=wallet_keys)
    if 'error' not in res:
        print 'accidentally succeeded to migrate profile'
        return False

    testlib.expect_snv_fail_at("foo.test", testlib.get_current_block(**kw) + 1)

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

    # migrate profiles (should succeed now)
    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()

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

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

    ses = res['token']

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

    # register the name bar.test (no zero-conf, should fail)
    res = testlib.ysi_REST_call('POST',
                                '/v1/names',
                                ses,
                                data={
                                    'name': 'bar.test',
                                    'zonefile': zonefile_txt,
                                    'owner_address': wallets[4].addr
                                })
    if res['http_status'] == 200:
        print 'accidentally succeeded to register bar.test'
        print res
        return False

    # let's test /v1/wallet/balance
    res = testlib.ysi_REST_call('GET', '/v1/wallet/balance', ses)
    if res['http_status'] != 200:
        print '/v1/wallet/balance returned ERR'
        print json.dumps(res)
        return False
    if res['response']['balance']['satoshis'] > 0:
        print '/v1/wallet/balance accidentally incorporated 0-conf txns in balance register bar.test'
        print json.dumps(res['response'])
        return False

    # let's test /v1/wallet/balance with minconfs=0
    res = testlib.ysi_REST_call('GET', '/v1/wallet/balance/0', ses)
    if res['http_status'] != 200:
        print '/v1/wallet/balance/0 returned ERR'
        print json.dumps(res)
        return False
    if res['response']['balance']['satoshis'] < 1e6:
        print "/v1/wallet/balance/0 didn't incorporate 0-conf txns"
        print json.dumps(res['response'])
        return False

    # register the name bar.test (1-conf, should fail)
    res = testlib.ysi_REST_call('POST',
                                '/v1/names',
                                ses,
                                data={
                                    'name': 'bar.test',
                                    'zonefile': zonefile_txt,
                                    'owner_address': wallets[4].addr,
                                    'min_confs': 1
                                })
    if res['http_status'] == 200:
        print 'accidentally succeeded to register bar.test'
        print res
        return False

    # register the name bar.test (zero-conf, should succeed)
    res = testlib.ysi_REST_call('POST',
                                '/v1/names',
                                ses,
                                data={
                                    'name': 'bar.test',
                                    'zonefile': zonefile_txt,
                                    'owner_address': wallets[4].addr,
                                    'min_confs': 0
                                })
    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 not res:
        return False

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

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

    res = testlib.ysi_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.ysi_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()) != 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.ysi_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 synchronized, value_hash

    import ysi_integration_tests.atlas_network as atlas_network

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

    testlib.ysi_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.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

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

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

    testlib.next_block(**kw)

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

    testlib.next_block(**kw)

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

    atlas_topology[17000] = [16264, 17001]
    atlas_topology[17007] = [17006]

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

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

        src_host, src_port = ysi_client.utils.url_to_host_port(src_hostport)
        dest_host, dest_port = ysi_client.utils.url_to_host_port(dest_hostport)

        if (src_port == 16264
                and dest_port == 17000) or (src_port == 17000
                                            and dest_port == 16264):
            # seed end of the chain
            return 0.0

        if abs(src_port - dest_port) <= 1:
            # chain link
            return 0.0

        # drop otherwise
        return 1.0

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

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

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

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

        testlib.next_block(**kw)

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

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

        else:
            time.sleep(1.0)

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

    return synchronized
Exemple #16
0
def scenario( wallets, **kw ):

    global zonefile_hash, final_balance, new_expire_block

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

    testlib.ysi_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.ysi_namespace_ready( "test", wallets[1].privkey )
    testlib.next_block( **kw )

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

    # wait for the preorder to get confirmed
    for i in xrange(0, 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):
        # warn the serialization checker that this changes behavior from 0.13
        print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
        sys.stdout.flush()

        testlib.next_block( **kw )

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

    # what's the name's renewal block?
    proxy = testlib.make_proxy()
    res = ysi_client.get_name_blockchain_record( "foo.test", proxy=proxy )
    if 'error' in res:
        print >> sys.stderr, json.dumps(res, indent=4, sort_keys=True)
        return False

    old_expire_block = res['expire_block']

    new_zonefile = ysi_client.zonefile.make_empty_zonefile('foo.test', None)
    new_zonefile_txt = ysi_zones.make_zone_file(new_zonefile)

    print 'renew with:'
    print new_zonefile_txt

    # renew it
    resp = testlib.ysi_cli_renew( "foo.test", "0123456789abcdef", new_zonefile_txt=new_zonefile_txt )
    if 'error' in resp:
        print >> sys.stderr, "Renewal request failed:\n%s" % json.dumps(resp, indent=4, sort_keys=True)
        return False

    # wait for it to go through
    for i in xrange(0, 6):
        # warn the serialization checker that this changes behavior from 0.13
        print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
        sys.stdout.flush()

        testlib.next_block( **kw )

    # verify that it's in the queue
    queue_state = testlib.ysi_cli_info()
    if 'error' in queue_state:
        print json.dumps(queue_state)
        return False

    if not queue_state.has_key('queues'):
        print 'no queues'
        print json.dumps(queue_state)
        return False

    if not queue_state['queues'].has_key('renew'):
        print 'no renew queue'
        print json.dumps(queue_state)
        return False

    if len(queue_state['queues']['renew']) != 1:
        print 'wrong renew state'
        print json.dumps(queue_state)
        return False

    if queue_state['queues']['renew'][0]['name'] != 'foo.test':
        print 'wrong name'
        print json.dumps(queue_state)
        return False

    # wait for it to go through
    for i in xrange(0, 6):
        # warn the serialization checker that this changes behavior from 0.13
        print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
        sys.stdout.flush()

        testlib.next_block( **kw )

    proxy = testlib.make_proxy()
    res = ysi_client.get_name_blockchain_record( "foo.test", proxy=proxy )
    if 'error' in res:
        print >> sys.stderr, json.dumps(res, indent=4, sort_keys=True)
        return False

    zonefile_hash = res['value_hash']

    zf = testlib.ysi_cli_get_name_zonefile("foo.test")
    if 'error' in zf:
        print zf
        return False

    print zf
    if zf != new_zonefile_txt:
        print 'zonefile mismatch'
        print 'expected:'
        print new_zonefile_txt
        print 'got:'
        print zf
        return False

    new_expire_block = res['expire_block']
    if old_expire_block >= new_expire_block + 12:
        # didn't go through
        print >> sys.stderr, "Renewal didn't go through: %s --> %s" % (old_expire_block, new_expire_block)
        return False

    if res['op'] != ysi_client.config.NAME_REGISTRATION + ":":
        print >> sys.stderr, "Renewal didn't go through (last op is %s)" % res['op']
        error = True
        return False

    final_balance = testlib.getbalance( wallets[2].addr )
Exemple #17
0
def scenario(wallets, **kw):
    # write our subdomain_registrar config
    client_dir = os.path.normpath(
        os.path.dirname(os.environ["BLOCKSTACK_CLIENT_CONFIG"]) +
        "/../subdomain_registrar")
    if not os.path.exists(client_dir):
        os.makedirs(client_dir)
    os.environ["BLOCKSTACK_SUBDOMAIN_CONFIG"] = client_dir + "/config.ini"
    with open(client_dir + "/config.ini", "w") as out_f:
        file_out = """[registrar-config]
maximum_entries_per_zonefile = 100
bind_port = 7103
transaction_frequency = 15
bind_address = localhost
core_endpoint = http://localhost:{}
core_auth_token = False
""".format(ysi_client.config.read_config_file()['ysi-client']
           ['api_endpoint_port'])
        out_f.write(file_out)

    # spawn the registrar
    SUBPROC = subprocess.Popen(["ysi-subdomain-registrar", "start", "foo.id"])

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

    testlib.ysi_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.ysi_namespace_ready("id", wallets[1].privkey)
    testlib.next_block(**kw)

    wallet = testlib.ysi_client_initialize_wallet("0123456789abcdef",
                                                  wallets[2].privkey,
                                                  wallets[3].privkey,
                                                  wallets[4].privkey)
    resp = testlib.ysi_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(SLEEP_TIME)

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

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

    print >> sys.stderr, "Waiting for subdomain to start up"
    time.sleep(SLEEP_TIME)

    baz_sk = keylib.ECPrivateKey()
    uri_rec = ysi_client.zonefile.url_to_uri_record(
        "file:///tmp/baz.profile.json")

    owner_address = baz_sk.public_key().address()

    zonefile_obj = {'$origin': "bar", '$ttl': 3600, 'uri': [uri_rec]}
    zonefile_str = ysi_zones.make_zone_file(zonefile_obj)

    requests.post("http://*****:*****@type": "Person",
            "description": "Lorem Ipsum Bazorem"
        }
    }
    # as of now, can't use storage's put_mutable_data, because it tries to figure out
    #  where to write things based on a user's zonefile and subdomains don't have
    #  zonefiles :\

    serialized_data = ysi_client.storage.serialize_mutable_data(
        profile_raw,
        data_privkey=baz_sk.to_hex(),
        data_pubkey=None,
        data_signature=None,
        profile=True)
    with open("/tmp/baz.profile.json", 'w') as f_out:
        f_out.write(serialized_data)

    print >> sys.stderr, "Waiting for the registrar to propagate the name"
    time.sleep(30)
    for i in xrange(0, 12):
        sys.stdout.flush()
        testlib.next_block(**kw)

    print >> sys.stderr, "Waiting for the update to be acknowledged"
    time.sleep(SLEEP_TIME)

    atexit.register(killer, SUBPROC)
def scenario( wallets, **kw ):
    global value_hashes

    virtualchain_dir = os.environ.get('VIRTUALCHAIN_WORKING_DIR', None)
    assert virtualchain_dir

    privkey = keylib.ECPrivateKey(wallets[4].privkey).to_hex()
    config_file = os.path.join(virtualchain_dir, 'snapshots.ini')
    privkey_path = os.path.join(virtualchain_dir, 'snapshots.pkey')
    snapshot_dir = os.path.join(virtualchain_dir, 'snapshots')

    with open(privkey_path, 'w') as f:
        f.write(privkey)

    with open(config_file, 'w') as f:
        f.write("""
[ysi-snapshots]
private_key = {}
logfile = {}
""".format(privkey_path, os.path.join(virtualchain_dir, 'snapshots.log')))

    testlib.ysi_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey )
    testlib.next_block( **kw )
    
    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

    testlib.ysi_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 )
    
    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

    testlib.ysi_namespace_ready( "test", wallets[1].privkey )
    testlib.next_block( **kw )
    
    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

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

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

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

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

    zonefile = ysi_client.zonefile.make_empty_zonefile( "foo.test", wallets[0].pubkey_hex )
    zonefile_txt = ysi_zones.make_zone_file( zonefile )
    zonefile_hash = ysi_client.storage.get_zonefile_data_hash( zonefile_txt )
 
    value_hashes.append(zonefile_hash)

    assert ysi_client.storage.put_immutable_data( zonefile_txt, '00' * 32, data_hash=zonefile_hash )
    
    testlib.ysi_name_update('foo.test', zonefile_hash, wallets[3].privkey)
    testlib.next_block( **kw )

    # there must be three snapshots 
    res = os.listdir(snapshot_dir)
    assert len(res) == 4
    assert 'snapshot.bsk' in res

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 1)

    # now there's only one 
    res = os.listdir(snapshot_dir)
    assert len(res) == 2
    assert 'snapshot.bsk' in res

    # restore it
    restore_dir = os.path.join(snapshot_dir, 'test_restore')
    res = restore(os.path.join(snapshot_dir, 'snapshot.bsk'), restore_dir, [wallets[4].pubkey_hex], 1)
    assert res
Exemple #19
0
def scenario(wallets, **kw):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

    testlib.ysi_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.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

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

    testlib.ysi_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.ysi_cli_app_signin("foo.test", datastore_pk, 'register.app',
                                     [
                                         'names', 'register', 'prices',
                                         'zonefiles', 'blockchain', 'node_read'
                                     ])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    ses = res['token']

    # for funsies, get the price of .test
    res = testlib.ysi_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.ysi_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)

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

    # register the name bar.test
    res = testlib.ysi_REST_call('POST',
                                '/v1/names',
                                ses,
                                data={
                                    'name': 'bar.test',
                                    'zonefile': zonefile_txt,
                                    'owner_address': wallets[4].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 not res:
        return False

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

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

    res = testlib.ysi_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.ysi_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()) != 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.ysi_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
Exemple #20
0
def scenario( wallets, **kw ):

    global error
    global names, owner_wallets, payment_wallets, recipients

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

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

    testlib.ysi_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.ysi_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.ysi_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.ysi_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 = ysi_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 = ysi_client.storage.make_mutable_data_urls(name, use_only=['dht', 'disk'])
        zonefile = ysi_client.zonefile.make_empty_zonefile(name, None, urls=driver_urls)
        zonefile_txt = ysi_zones.make_zone_file( zonefile, origin=name, ttl=3600 )

        res = testlib.ysi_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
def scenario(wallets, **kw):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

    testlib.ysi_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.ysi_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 = ysi_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    res = testlib.ysi_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 = ysi_client.storage.make_mutable_data_urls(
        'bar.test', use_only=['dht', 'disk'])
    zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test',
                                                       wallets[4].pubkey_hex,
                                                       urls=driver_urls)
    zonefile_txt = ysi_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.ysi_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.ysi_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.ysi_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.ysi_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.ysi_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.ysi_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.ysi_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.ysi_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.ysi_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
def scenario(wallets, **kw):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

    testlib.ysi_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.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

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

    testlib.ysi_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 = ysi_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    # make sure we can do REST calls
    res = testlib.ysi_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.ysi_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.ysi_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 = ysi_client.storage.make_mutable_data_urls(
        'foo.test', use_only=['dht', 'disk'])
    zonefile = ysi_client.zonefile.make_empty_zonefile('foo.test',
                                                       wallets[4].pubkey_hex,
                                                       urls=driver_urls)
    zonefile_txt = ysi_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.ysi_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.ysi_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.ysi_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 zonefile_hash

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

    testlib.ysi_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.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

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

    # wait for the preorder to get confirmed
    for i in xrange(0, 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):
        # warn the serialization checker that this changes behavior from 0.13
        print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
        sys.stdout.flush()

        testlib.next_block(**kw)

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

    # wait for initial update to get confirmed
    for i in xrange(0, 12):
        # warn the serialization checker that this changes behavior from 0.13
        print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
        sys.stdout.flush()

        testlib.next_block(**kw)

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

    # store a new zonefile
    data_pubkey = wallet['data_pubkey']
    zonefile = ysi_client.zonefile.make_empty_zonefile("foo.test", data_pubkey)
    assert ysi_client.user.put_immutable_data_zonefile(
        zonefile, "testdata", ysi_client.get_data_hash("testdata"))

    zonefile_txt = ysi_zones.make_zone_file(zonefile)
    zonefile_hash = ysi_client.storage.get_zonefile_data_hash(zonefile_txt)

    print >> sys.stderr, "\n\nzonefile hash: %s\nzonefile:\n%s\n\n" % (
        zonefile_hash, zonefile_txt)

    # will store to queue
    test_proxy = testlib.make_proxy()
    config_path = test_proxy.config_path
    conf = ysi_client.config.get_config(config_path)
    queuedb_path = conf['queue_path']

    # update the zonefile hash, but not the zonefile.
    resp = testlib.ysi_cli_set_zonefile_hash("foo.test", zonefile_hash)
    if 'error' in resp:
        print >> sys.stderr, "\nFailed to set zonefile hash: %s\n" % resp
        return False

    txhash = resp['transaction_hash']
    for i in xrange(0, 12):
        # warn the serialization checker that this changes behavior from 0.13
        print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
        sys.stdout.flush()

        testlib.next_block(**kw)

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

    # stop endpoint
    print >> sys.stderr, "\nstopping RPC daemon\n"
    testlib.stop_api()
    time.sleep(3)

    # store to queue
    res = ysi_client.backend.queue.queue_append(
        "update",
        "foo.test",
        txhash,
        payment_address=wallets[2].addr,
        owner_address=wallets[3].addr,
        config_path=test_proxy.config_path,
        zonefile_data=zonefile_txt,
        zonefile_hash=zonefile_hash,
        path=queuedb_path)

    # verify that we can sync the zonefile, using the in-queue zonefile
    resp = testlib.ysi_cli_sync_zonefile("foo.test")
    if 'error' in resp:
        print >> sys.stderr, "\nfailed to sync zonefile: %s\n" % resp
        return False

    ysi_client.backend.queue.queuedb_remove("update",
                                            "foo.test",
                                            txhash,
                                            path=queuedb_path)

    print >> sys.stderr, "\nstarting RPC daemon\n"
    testlib.start_api("0123456789abcdef")

    # store a new zonefile
    zonefile = ysi_client.zonefile.make_empty_zonefile("foo.test", data_pubkey)
    ysi_client.user.put_immutable_data_zonefile(
        zonefile, "testdata2", ysi_client.get_data_hash("testdata"))

    zonefile_txt = ysi_zones.make_zone_file(zonefile)
    zonefile_hash = ysi_client.storage.get_zonefile_data_hash(zonefile_txt)

    # store locally
    res = ysi_client.zonefile.store_name_zonefile("foo.test",
                                                  zonefile,
                                                  None,
                                                  storage_drivers=['disk'])
    if 'error' in res:
        print >> sys.stderr, "\nFailed to store zonefile: %s\n" % res
        return False

    # update the zonefile hash, but not the zonefile.
    resp = testlib.ysi_cli_set_zonefile_hash("foo.test", zonefile_hash)
    if 'error' in resp:
        print >> sys.stderr, "\nFailed to set zonefile hash: %s\n" % resp
        return False

    for i in xrange(0, 12):
        # warn the serialization checker that this changes behavior from 0.13
        print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash"
        sys.stdout.flush()

        testlib.next_block(**kw)

    # verify that we can sync the zonefile, using the on-disk zonefile
    resp = testlib.ysi_cli_sync_zonefile("foo.test")

    if 'error' in resp:
        print >> sys.stderr, "update error: %s" % resp['error']
        return False

    # wait for it to go through
    for i in xrange(0, 12):
        testlib.next_block(**kw)

    print >> sys.stderr, "Waiting 10 seconds for the backend to acknowedge the update"
    time.sleep(10)
def scenario(wallets, **kw):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

    testlib.ysi_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.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

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

    testlib.ysi_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.ysi_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 = ysi_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.ysi_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.ysi_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.ysi_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 = ysi_client.storage.make_mutable_data_urls(
        'bar.test', use_only=['dht', 'disk'])
    zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test',
                                                       wallets[4].pubkey_hex,
                                                       urls=driver_urls)
    zonefile_txt = ysi_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.ysi_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 "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.ysi_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.ysi_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.ysi_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):

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

    testlib.ysi_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.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

    driver_urls = ysi_client.storage.make_mutable_data_urls(
        'foo.test', use_only=['dht', 'disk'])
    zonefile = ysi_client.zonefile.make_empty_zonefile('foo.test',
                                                       wallets[4].pubkey_hex,
                                                       urls=driver_urls)
    zonefile_txt = ysi_zones.make_zone_file(zonefile,
                                            origin='foo.test',
                                            ttl=3600)

    wallet = testlib.ysi_client_initialize_wallet("0123456789abcdef",
                                                  wallets[2].privkey,
                                                  wallets[3].privkey,
                                                  wallets[4].privkey)
    resp = testlib.ysi_cli_register("foo.test",
                                    "0123456789abcdef",
                                    zonefile=zonefile_txt,
                                    recipient_address=wallets[4].addr)
    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)

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

    print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge transfer"
    time.sleep(10)
def scenario( wallets, **kw ):

    global synchronized

    import ysi_integration_tests.atlas_network as atlas_network

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

    testlib.ysi_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.ysi_namespace_ready( "test", wallets[1].privkey )
    testlib.next_block( **kw )

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

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

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

    testlib.next_block( **kw )

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

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

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

        testlib.next_block( **kw )

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

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

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

    global synchronized, value_hash

    import ysi_integration_tests.atlas_network as atlas_network

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

    testlib.ysi_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.ysi_namespace_ready("test", wallets[1].privkey)
    testlib.next_block(**kw)

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

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

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

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

    testlib.next_block(**kw)

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

    testlib.next_block(**kw)

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

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

        testlib.next_block(**kw)

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

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

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

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

    # put the seed after the first four
    all_peers = atlas_nodes[:4] + [16264] + atlas_nodes[4:]

    time_start = int(time.time()) + 60

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

        src_host, src_port = ysi_client.utils.url_to_host_port(src_hostport)
        dest_host, dest_port = ysi_client.utils.url_to_host_port(dest_hostport)

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

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

        if src_port not in active_range:
            # dead
            return 1.0

        if dest_port not in active_range:
            # dead
            return 1.0

        return 0.0

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

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

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

        else:
            time.sleep(1.0)

    # shut down
    atlas_network.atlas_network_stop(network_des)
    return synchronized
Exemple #28
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.ysi_client_initialize_wallet("0123456789abcdef",
                                                       empty_key, empty_key,
                                                       empty_key)
    test_proxy = testlib.TestAPIProxy()
    ysi_client.set_default_proxy(test_proxy)

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

    testlib.ysi_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.ysi_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 = ysi_client.get_config(config_path)
    assert conf

    api_pass = conf['api_password']

    payment_key = wallets[1].privkey

    # make zonefile for recipient
    driver_urls = ysi_client.storage.make_mutable_data_urls(
        'bar.test', use_only=['dht', 'disk'])
    zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test',
                                                       wallets[4].pubkey_hex,
                                                       urls=driver_urls)
    zonefile_txt = ysi_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.ysi_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.ysi_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.ysi_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.ysi_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, 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 zonefile to be sent'
    time.sleep(10)

    res = testlib.ysi_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

    print res['response']

    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.ysi_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.ysi_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 = ysi_client.storage.make_mutable_data_urls(
        'bar.test', use_only=['http', 'disk'])
    zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test',
                                                       wallets[3].pubkey_hex,
                                                       urls=driver_urls)
    zonefile_txt = ysi_zones.make_zone_file(zonefile,
                                            origin='bar.test',
                                            ttl=3600)

    # let's do this update.
    res = testlib.ysi_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, 4):
        testlib.next_block(**kw)

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

    res = testlib.ysi_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.ysi_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 #29
0
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

    wallet_keys = testlib.ysi_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[3].privkey )
    test_proxy = testlib.TestAPIProxy()
    ysi_client.set_default_proxy( test_proxy )

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

    testlib.ysi_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.ysi_namespace_ready( "test", wallets[1].privkey )
    testlib.next_block( **kw )

    testlib.ysi_name_preorder( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    testlib.ysi_name_register( "foo.test", wallets[2].privkey, wallets[3].addr )
    testlib.next_block( **kw )
    
    # migrate profiles, but no data key in the zone file 
    res = testlib.migrate_profile( "foo.test", zonefile_has_data_key=False, 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.ysi_cli_app_signin("foo.test", datastore_pk, 'register.app', ['names', 'register', 'prices', 'zonefiles', 'blockchain', 'node_read', 'user_read'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return 

    ses = res['token']

    # register the name bar.test. autogenerate the rest 
    old_user_zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test', None)
    old_user_zonefile_txt = ysi_zones.make_zone_file(old_user_zonefile)

    res = testlib.ysi_REST_call('POST', '/v1/names', ses, data={'name': 'bar.test', 'zonefile': old_user_zonefile_txt, 'make_profile': True} )
    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/update 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 )

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

    res = testlib.ysi_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

    old_expire_block = res['response']['expire_block']

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

    # zonefile must not have a public key listed
    zonefile_txt = res['response']['zonefile']
    print zonefile_txt

    parsed_zonefile = ysi_zones.parse_zone_file(zonefile_txt)
    if parsed_zonefile.has_key('txt'):
        print 'have txt records'
        print parsed_zonefile
        return False

    # renew it, but put the *current* owner key as the zonefile's *new* public key
    new_user_zonefile = ysi_client.zonefile.make_empty_zonefile('bar.test', wallets[3].pubkey_hex )
    new_user_zonefile_txt = ysi_zones.make_zone_file(new_user_zonefile)

    res = testlib.ysi_REST_call("POST", "/v1/names", ses, data={'name': 'bar.test', 'zonefile': new_user_zonefile_txt} )
    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(ses, 'bar.test', 'renew', None )
    if not res:
        return False

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

    # new expire block
    res = testlib.ysi_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

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

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

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

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

    # zonefile must have old owner key
    zonefile_txt = res['response']['zonefile']
    parsed_zonefile = ysi_zones.parse_zone_file(zonefile_txt)
    if not parsed_zonefile.has_key('txt'):
        print 'missing txt'
        print parsed_zonefile
        return False

    found = False
    for txtrec in parsed_zonefile['txt']:
        if txtrec['name'] == 'pubkey' and txtrec['txt'] == 'pubkey:data:{}'.format(wallets[3].pubkey_hex):
            found = True

    if not found:
        print 'missing public key {}'.format(wallets[3].pubkey_hex)
        return False

    # profile lookup must work 
    res = testlib.ysi_REST_call("GET", "/v1/users/bar.test", ses)
    if 'error' in res or res['http_status'] != 200:
        res['text'] = 'failed to get profile for bar.test'
        print json.dumps(res)
        return False

    print ''
    print json.dumps(res['response'], indent=4, sort_keys=True)
    print ''

    # 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