예제 #1
0
    def test_signed_transition(self):
        fake_privkey_hex = "5512612ed6ef10ea8c5f9839c63f62107c73db7306b98588a46d0cd2c3d15ea5"
        sk = keylib.ECPrivateKey(fake_privkey_hex)
        pk = sk.public_key()

        start_json = {
            "pubkey": subdomains.encode_pubkey_entry(sk),
            "n": 3,
            "urls":
            ["https://foobar.com/profile", "https://dropbox.com/profile2"]
        }

        next_json = {
            "pubkey": "data:echex:0",
            "n": 4,
            "name": "foo",
            "urls": ["https://none.com"]
        }

        subdomain1 = subdomains.Subdomain("bar.id", "foo",
                                          subdomains.encode_pubkey_entry(sk),
                                          3, "")
        subdomain2 = subdomains.Subdomain("bar.id", "bar",
                                          subdomains.encode_pubkey_entry(sk),
                                          4, "")

        subdomain2.add_signature(sk)
        self.assertTrue(subdomains._transition_valid(subdomain1, subdomain2))
예제 #2
0
    def test_basic_with_multisig(self):
        test_zf = """$ORIGIN bar.id
$TTL 3600
pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
registrar URI 10 1 "bsreg://foo.com:8234"
foo TXT "owner={}" "seqn=3" "parts=0"
        """

        my_keys = [keylib.ECPrivateKey() for _ in range(3)]
        my_pubkeys = [k.public_key().to_hex() for k in my_keys]
        owner_addr = virtualchain.make_multisig_address(my_pubkeys, 3)

        test_zf = test_zf.format(owner_addr)

        domain_name = "bar.id"

        zf_json = zonefile.decode_name_zonefile(domain_name, test_zf)

        self.assertEqual(zf_json['$origin'], domain_name)

        subds = subdomains.parse_zonefile_subdomains(domain_name, zf_json)
        self.assertEqual(len(subds), 1)
        sub = subds[0]
        self.assertEqual(sub.n, 3)
        self.assertEqual(sub.sig, None)

        self.assertEqual(sub.subdomain_name, "foo")
예제 #3
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 = blockstack_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))
예제 #4
0
    def test_basic(self):
        test_zf = """$ORIGIN bar.id
$TTL 3600
pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
registrar URI 10 1 "bsreg://foo.com:8234"
foo TXT "owner={}" "seqn=3" "parts=0"
        """

        fake_privkey_hex = "5512612ed6ef10ea8c5f9839c63f62107c73db7306b98588a46d0cd2c3d15ea5"
        sk = keylib.ECPrivateKey(fake_privkey_hex)
        pk = sk.public_key()

        test_zf = test_zf.format(subdomains.encode_pubkey_entry(pk))

        domain_name = "bar.id"

        zf_json = zonefile.decode_name_zonefile(domain_name, test_zf)

        self.assertEqual(zf_json['$origin'], domain_name)

        subds = subdomains.parse_zonefile_subdomains(domain_name, zf_json)
        self.assertEqual(len(subds), 1)
        sub = subds[0]
        self.assertEqual(sub.n, 3)
        self.assertEqual(sub.sig, None)

        self.assertEqual(sub.subdomain_name, "foo")
예제 #5
0
def decrypt_wallet_legacy(data, key_defaults, password):
    """
    Decrypt 0.14.1 and earlier wallets, given the wallet data, the default key values,
    and the password.

    Return {'status': True, 'wallet': wallet} on success 
    Raise on error
    """
    new_wallet = {}

    # NOTE: 'owner' must come before 'data', since we may use it to generate the data key
    keynames = ['payment', 'owner', 'data']
    for keyname in keynames:

        # get the key's private key info and address
        keyname_privkey = '{}_privkey'.format(keyname)
        keyname_addresses = '{}_addresses'.format(keyname)
        encrypted_keyname = 'encrypted_{}_privkey'.format(keyname)

        if encrypted_keyname in data:
            # This key was explicitly defined in the wallet.
            # It is not guaranteed to be a child key of the
            # master private key.
            field = decrypt_private_key_info(data[encrypted_keyname], password)

            if 'error' in field:
                ret = {
                    'error':
                    "Failed to decrypt {}: {}".format(encrypted_keyname,
                                                      field['error'])
                }
                log.debug('Failed to decrypt {}: {}'.format(
                    encrypted_keyname, field['error']))
                return ret

            new_wallet[keyname_privkey] = field['private_key_info']
            new_wallet[keyname_addresses] = [field['address']]

        else:

            # Legacy migration: this key is not defined in the wallet
            # use the appopriate default key
            assert keyname in key_defaults, 'BUG: no legacy private key for {}'.format(
                keyname)

            default_privkey = key_defaults[keyname]
            new_wallet[keyname_privkey] = default_privkey
            new_wallet[keyname_addresses] = [
                virtualchain.address_reencode(
                    keylib.ECPrivateKey(
                        default_privkey,
                        compressed=False).public_key().address())
            ]

    return {'status': True, 'wallet': new_wallet}
    def __init__(self, pk_wif, value_str):
        pk = pybitcoin.BitcoinPrivateKey(pk_wif)

        self._pk = pk
        self.privkey = pk_wif
        self.pubkey_hex = pk.public_key().to_hex(
        )  # coordinate (uncompressed) EC public key
        self.ec_pubkey_hex = keylib.ECPrivateKey(pk_wif).public_key().to_hex(
        )  # parameterized (compressed) EC public key
        self.addr = pk.public_key().address()
        self.value = int(value_str)
예제 #7
0
    def test_high_volume_derivation(self):
        number_of_keys = 10
        public_keychain = PublicKeychain.from_public_key(self.public_key_hex)
        private_keychain = PrivateKeychain.from_private_key(self.private_key_hex)
        keypairs = []
        print ""
        for i in range(number_of_keys):
            print "making key %i of %i" % (i+1, number_of_keys)
            public_key = public_keychain.child(i).public_key()
            private_key = private_keychain.child(i).private_key()
            keypairs.append({ 'public': public_key, 'private': private_key })

        for i in range(len(keypairs)):
            keypair = keypairs[i]
            print "checking key %i of %i" % (i+1, number_of_keys)
            # self.assertEqual(privkey_to_pubkey(keypair['private']), keypair['public'])
            self.assertEqual(keylib.ECPrivateKey(keypair['private']).public_key().to_hex(), keylib.ECPublicKey(keypair['public']).to_hex())
예제 #8
0
    def test_sign_verify_multisig(self):
        my_keys = [keylib.ECPrivateKey() for _ in range(9)]
        my_pubkeys = [k.public_key().to_hex() for k in my_keys]
        my_sk_hexes = [k.to_hex() for k in my_keys]

        blob = "bar_the_foo"
        hash_hex = binascii.hexlify(hashlib.sha256(blob).digest())

        attempted_pairs = [(1, 1), (1, 2), (1, 3), (3, 3), (2, 4), (3, 4),
                           (2, 7), (5, 5)]

        for m, n in attempted_pairs:
            script_pubkeys = my_pubkeys[:n]
            redeem_script = virtualchain.make_multisig_script(
                script_pubkeys, m)
            owner_addr = virtualchain.make_multisig_address(script_pubkeys, m)

            sks_to_use = list(my_sk_hexes[:n])
            if m < n:
                # force 1 failed sig check during verify
                sks_to_use = sks_to_use[1:]

            sigb64 = subdomains.sign_multisig(hash_hex, redeem_script,
                                              sks_to_use)

            self.assertTrue(subdomains.verify(owner_addr, blob, sigb64))

        # try to mess with the plaintext blob
        self.assertFalse(subdomains.verify(owner_addr, blob + "0", sigb64))

        for m, n in [(2, 3)]:
            script_pubkeys = my_pubkeys[:n]
            redeem_script = virtualchain.make_multisig_script(
                script_pubkeys, m)
            owner_addr = virtualchain.make_multisig_address(script_pubkeys, m)

            # try with a wrong redeem script
            redeem_script_broke = virtualchain.make_multisig_script(
                script_pubkeys, m - 1)
            sigb64 = subdomains.sign_multisig(hash_hex, redeem_script_broke,
                                              my_sk_hexes)
            self.assertFalse(subdomains.verify(owner_addr, blob, sigb64))
예제 #9
0
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

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

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

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

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

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

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

    testlib.next_block( **kw )

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

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

    ses = res['token']

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

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

    api_pass = conf['api_password']

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

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


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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # same zonefile we put?
    if res['response']['zonefile'] != zonefile_txt:
        res['test'] = 'mismatched zonefile, expected\n{}\n'.format(zonefile_txt)
        print json.dumps(res)
        return False
예제 #10
0
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("""
[blockstack-snapshots]
private_key = {}
logfile = {}
""".format(privkey_path, os.path.join(virtualchain_dir, 'snapshots.log')))

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

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

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

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

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

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

    testlib.blockstack_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.blockstack_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 = blockstack_client.zonefile.make_empty_zonefile(
        "foo.test", wallets[0].pubkey_hex)
    zonefile_txt = blockstack_zones.make_zone_file(zonefile)
    zonefile_hash = blockstack_client.storage.get_zonefile_data_hash(
        zonefile_txt)

    value_hashes.append(zonefile_hash)

    assert blockstack_client.storage.put_immutable_data(
        zonefile_txt, '00' * 32, data_hash=zonefile_hash)

    testlib.blockstack_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
def check( state_engine ):

    global wallet_keys, wallet_keys_2, datasets, zonefile_hash, zonefile_hash_2


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

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

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

    # not preordered
    names = ['foo.test', 'bar.test']
    wallet_keys_list = [wallet_keys, wallet_keys_2]
    zonefile_hashes = [zonefile_hash[:], zonefile_hash_2[:]]

    for i in xrange(0, len(names)):
        name = names[i]
        wallet_payer = 3 * (i+1) - 1
        wallet_owner = 3 * (i+1)
        wallet_data_pubkey = 3 * (i+1)  # same as owner key
        wallet_keys = wallet_keys_list[i]
        zonefile_hash = zonefile_hashes[i]

        preorder = state_engine.get_name_preorder( name, virtualchain.make_payment_script(wallets[wallet_payer].addr), wallets[wallet_owner].addr )
        if preorder is not None:
            print "still have preorder"
            return False
    
        # registered 
        name_rec = state_engine.get_name( name )
        if name_rec is None:
            print "name does not exist"
            return False 

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

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

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

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

        # still have all the right info 
        user_profile = ysi_client.profile.get_profile( name, user_zonefile=user_zonefile )
        if user_profile is None or 'error' in user_profile:
            if user_profile is not None:
                print json.dumps(user_profile, indent=4, sort_keys=True)
            else:
                print "\n\nprofile is None\n\n"

            return False

    # can get mutable data with owner address
    res = testlib.ysi_cli_get_mutable( "bar.test", "hello_world_mutable" )

    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        return False
    
    if json.loads(res['data']) != {'hello': 'world'}:
        print 'invalid data: {}'.format(res['data'])
        return False

    # can get mutable data with explicit public key
    res = testlib.ysi_cli_get_mutable( "bar.test", "hello_world_mutable", public_key=keylib.ECPrivateKey(wallet_keys_2['data_privkey']).public_key().to_hex() )
    print 'mutable: {}'.format(res)

    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        return False
    
    if json.loads(res['data']) != {'hello': 'world'}:
        print 'invalid data: {}'.format(res['data'])
        return False

    # can get immutable data by name
    res = testlib.ysi_cli_get_immutable( 'foo.test', 'hello_world_immutable' )
    print 'immutable by name: {}'.format(res)

    if 'error' in res:
        return res

    if json.loads(res['data']) != {'hello': 'world_immutable'}:
        print 'invalid immutable data: {}'.format(res['data'])
        return False

    # can get immutable data by hash
    hsh = res['hash']
    res = testlib.ysi_cli_get_immutable( 'foo.test', hsh )
    print 'immutable: {}'.format(res)

    if 'error' in res:
        return res

    if json.loads(res['data']) != {'hello': 'world_immutable'}:
        print 'invalid immutable data by hash: {}'.format(res['data'])
        return False

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

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

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

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

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

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

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

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

    testlib.next_block(**kw)

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

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

    ses = res['token']

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

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

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

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

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

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

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

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

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

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

    # get the zonefile
    res = testlib.blockstack_REST_call(
        "GET", "/v1/names/bar.test/zonefile/{}".format(zonefile_hash), 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
예제 #13
0
        return {'error': 'Wallet already exists (%s)' % wallet_path}

    if password is None:
        assert interactive
        password = ""
        while len(password) < config.WALLET_PASSWORD_LENGTH:
            res = wallet.make_wallet_password(
                prompt="Creating new application wallet", password=password)
            if 'error' in res:
                print res['error']
                continue
            else:
                password = res['password']
                break

    pk_hex = keylib.ECPrivateKey().to_hex()
    res = wallet.initialize_wallet(password=password,
                                   interactive=interactive,
                                   hex_privkey=pk_hex,
                                   config_dir=config_dir,
                                   wallet_path=wallet_path)
    if 'error' in res:
        log.error("Failed to create wallet '%s.%s@%s': %s" %
                  (app_account_id, app_name, name, res['error']))
        return res

    pub_hex = keylib.ECPrivateKey(pk_hex).public_key().to_hex()

    # preferred storage drivers?
    conf = config.get_config(config_path)
    if app_storage_drivers is None:
예제 #14
0
def scenario(wallets, **kw):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

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

    # try to preorder another namespace; it should fail
    res = testlib.blockstack_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.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    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.blockstack_namespace_reveal(
        "test", wallets[1].addr, 52595, 250, 4,
        [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10,
        wallets[0].privkey)
    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.blockstack_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.blockstack_namespace_ready("test", wallets[1].privkey)
    if 'error' in res:
        print res
        return False

    testlib.next_block(**kw)

    testlib.blockstack_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.blockstack_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.blockstack_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.blockstack_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.blockstack_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 = blockstack_client.storage.make_mutable_data_urls(
        'bar.test', use_only=['dht', 'disk'])
    zonefile = blockstack_client.zonefile.make_empty_zonefile(
        'bar.test', wallets[4].pubkey_hex, urls=driver_urls)
    zonefile_txt = blockstack_zones.make_zone_file(zonefile,
                                                   origin='bar.test',
                                                   ttl=3600)

    # register the name bar.test (no zero-conf, should fail)
    res = testlib.blockstack_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.blockstack_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.blockstack_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.blockstack_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.blockstack_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, 6):
        testlib.next_block(**kw)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # get the zonefile
    res = testlib.blockstack_REST_call(
        "GET", "/v1/names/bar.test/zonefile/{}".format(zonefile_hash), 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
예제 #15
0
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

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

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

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

    testlib.next_block( **kw )

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

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

    ses = res['token']

    # my own KEYS

    owner_key = new_key

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

    api_pass = conf['api_password']

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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


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

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

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

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

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

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

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

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

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

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

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



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

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


    # wait for preorder to get confirmed
    for i in xrange(0, 6):
        testlib.next_block( **kw )
    # wake up registrar, submit register
    time.sleep(10)
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    # wake up registrar, submit update
    time.sleep(10)
    for i in xrange(0, 12):
        testlib.next_block( **kw )
    # wake up registrar, propogate zonefile
    time.sleep(10)
예제 #16
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(blockstack_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(blockstack_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)
예제 #17
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(blockstack_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(blockstack_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 wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

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

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

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

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

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

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

    testlib.next_block(**kw)

    data_pk = wallets[-1].privkey
    data_pub = wallets[-1].pubkey_hex

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

    # make a session
    datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex()
    res = testlib.blockstack_cli_app_signin(
        "foo.test", datastore_pk, 'register.app', [
            'names', 'register', 'update', 'prices', 'zonefiles', 'blockchain',
            'node_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
    res = testlib.blockstack_REST_call('POST',
                                       '/v1/names',
                                       ses,
                                       data={'name': 'bar.test'})
    if 'error' in res:
        res['test'] = 'Failed to register user'
        print json.dumps(res)
        error = True
        return False

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # update
    res = testlib.blockstack_REST_call("PUT",
                                       "/v1/names/bar.test/zonefile",
                                       ses,
                                       data={'zonefile_hash': '11' * 20})
    if 'error' in res or res['http_status'] != 202:
        res['test'] = 'failed to update zonefile hash'
        print json.dumps(res)
        return False

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

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

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

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

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

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

    # update with nonstandard zonefile
    res = testlib.blockstack_REST_call("PUT",
                                       "/v1/names/bar.test/zonefile",
                                       ses,
                                       data={'zonefile': 'hello world'})
    if 'error' in res or res['http_status'] != 202:
        res['test'] = 'failed to update zonefile hash'
        print json.dumps(res)
        return False

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

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

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

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

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

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

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

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

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

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

    if res['response']['zonefile'] != 'hello world':
        res['test'] = 'Failed to set zonefile data'
        print json.dumps(res)
        return False
def scenario(wallets, **kw):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

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

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

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

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

    # migrate profiles, 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.blockstack_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 = blockstack_client.zonefile.make_empty_zonefile(
        'bar.test', None)
    old_user_zonefile_txt = blockstack_zones.make_zone_file(old_user_zonefile)

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

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

    # get the zonefile
    res = testlib.blockstack_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 = blockstack_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 = blockstack_client.zonefile.make_empty_zonefile(
        'bar.test', wallets[3].pubkey_hex)
    new_user_zonefile_txt = blockstack_zones.make_zone_file(new_user_zonefile)

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

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

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

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

    # get the zonefile
    res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/zonefile",
                                       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 = blockstack_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.blockstack_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
예제 #20
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)

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

    testlib.ysi_client_set_wallet("0123456789abcdef", wallets[5].privkey,
                                  wallets[3].privkey, wallets[4].privkey)

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

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

    testlib.next_block(**kw)

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

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

    ses = res['token']

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # nothing should be here
    res = testlib.ysi_REST_call(
        'GET',
        '/v1/stores/{}/directories'.format(datastore_name),
        ses,
        path='/')
    if res['http_status'] != 404:
        print 'got HTTP {} on getting deleted store'.format(res['http_status'])
        print json.dumps(res)
        return False
예제 #21
0
def scenario(wallets, **kw):

    global put_result, wallet_keys, legacy_profile, zonefile_hash, zonefile_hash_2, immutable_hash, datastore_name

    wallet_keys = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", wallets[8].privkey, wallets[3].privkey,
        wallets[4].privkey)
    wallet_keys_2 = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", wallets[9].privkey, wallets[6].privkey,
        wallets[7].privkey)

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

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

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

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

    testlib.blockstack_name_preorder("foo.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.blockstack_name_preorder("bar.test", wallets[5].privkey,
                                     wallets[6].addr)
    testlib.next_block(**kw)

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

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

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

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

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

    testlib.next_block(**kw)

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

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

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

    testlib.next_block(**kw)

    # start up RPC for 'foo.test'
    testlib.blockstack_client_set_wallet("0123456789abcdef",
                                         wallet_keys['payment_privkey'],
                                         wallet_keys['owner_privkey'],
                                         wallet_keys['data_privkey'])

    # put immutable
    put_result = testlib.blockstack_cli_put_immutable(
        "foo.test",
        "hello_world_immutable",
        json.dumps({'hello': 'world'}),
        password='******')
    log.debug("put immutable for foo.test")
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        error = True
        return

    immutable_hash = put_result['immutable_data_hash']
    testlib.expect_atlas_zonefile(put_result['zonefile_hash'])

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

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

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

    # start up RPC for 'bar.test'
    testlib.blockstack_client_set_wallet("0123456789abcdef",
                                         wallet_keys_2['payment_privkey'],
                                         wallet_keys_2['owner_privkey'],
                                         wallet_keys_2['data_privkey'])
    log.debug("put mutable for bar.test")
    put_result = testlib.blockstack_cli_put_mutable(
        'bar.test',
        'hello_world_mutable',
        json.dumps({'hello': 'world'}),
        password='******')
    if 'error' in put_result:
        print json.dumps(put_result, indent=4, sort_keys=True)
        return False

    testlib.next_block(**kw)

    # put mutable data again
    testlib.blockstack_client_set_wallet("0123456789abcdef",
                                         wallet_keys['payment_privkey'],
                                         wallet_keys['owner_privkey'],
                                         wallet_keys['data_privkey'])
    res = testlib.blockstack_cli_put_mutable('foo.test',
                                             'foo_data2',
                                             json.dumps({'hello2': 'world2'}),
                                             password='******')
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        return False

    # put immutable data with the URL
    # start up RPC for 'foo.test'
    log.debug("put immutable for foo.test (2)")
    res = testlib.blockstack_cli_put_immutable('foo.test',
                                               'foo_immutable',
                                               json.dumps({'hello3':
                                                           'world3'}),
                                               password='******')
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        return False

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

    testlib.next_block(**kw)

    datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex()
    datastore_id_res = testlib.blockstack_cli_datastore_get_id(datastore_pk)
    datastore_name = datastore_id_res['datastore_id']

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

    # put a file into the datastore
    data = 'hello datastore'
    log.debug("putfile")
    res = testlib.blockstack_cli_datastore_putfile(datastore_pk,
                                                   '/hello_datastore', data)
    if 'error' in res:
        print 'failed to putfile /hello_datastore: {}'.format(res['error'])
        return False

    # make a directory
    log.debug("mkdir")
    res = testlib.blockstack_cli_datastore_mkdir(datastore_pk, '/hello_dir')
    if 'error' in res:
        print 'failed to mkdir /hello_dir: {}'.format(res['error'])
        return False

    # put a file into the directory
    data = 'hello dir datastore'
    log.debug("putfile in dir")
    res = testlib.blockstack_cli_datastore_putfile(
        datastore_pk, '/hello_dir/hello_dir_datastore', data)
    if 'error' in res:
        print 'failed to putfile /hello_dir/hello_dir_datastore: {}'.format(
            res['error'])
        return False

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

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

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

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

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

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

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

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

    ses = res['token']

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

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

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

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

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

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

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

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

    # wait for the preorder to get confirmed
    for i in xrange(0, 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, 12):
        testlib.next_block( **kw )
  
    print 'Wait for update to be confirmed'
    time.sleep(10)

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

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

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

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

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

    # now, let's set a new zonefile
    zf_str = "$ORIGIN bar.test\n$TTL 3600\nmy_vote TXT \"045a501e341fbf1b403ce3a6e66836a3a40a\""
    res = testlib.blockstack_REST_call("PUT", "/v1/names/bar.test/zonefile/", ses,
                                       ses, data={'zonefile' : zf_str})

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

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

    if res['raw'] != zf_str:
        print "Zonefile wasn't updated."
        print "Expected: {}".format(zf_str)
        print "Received: {}".format(res['response']['zonefile'])
예제 #23
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)

    data_pk = wallets[-1].privkey
    data_pub = wallets[-1].pubkey_hex

    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', 'transfer', 'prices', 'zonefiles',
            'blockchain', 'node_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
    res = testlib.ysi_REST_call('POST',
                                '/v1/names',
                                ses,
                                data={'name': 'bar.test'})
    if 'error' in res:
        res['test'] = 'Failed to register user'
        print json.dumps(res)
        error = True
        return False

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

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

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

    # wait for the preorder to get confirmed
    for i in xrange(0, 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 update 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']

    # transfer it
    res = testlib.ysi_REST_call("PUT",
                                "/v1/names/bar.test/owner",
                                ses,
                                data={'owner': wallets[7].addr})
    if 'error' in res or res['http_status'] != 202:
        res['test'] = 'Failed to transfer name'
        print json.dumps(res)
        return False

    # 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 'waiting for transfer to get confirmed'
    time.sleep(10)

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

    # new owner?
    if not res['response'].has_key('address'):
        res['test'] = 'No address given'
        print json.dumps(res)
        return False

    address_testnet = virtualchain.address_reencode(str(
        res['response']['address']),
                                                    network='testnet')
    if address_testnet != wallets[7].addr:
        res['test'] = 'Failed to transfer name to new address {}'.format(
            wallets[7].addr)
        res['owner_address_testnet'] = address_testnet
        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
예제 #24
0
def fast_sync_sign_snapshot( snapshot_path, private_key, first=False ):
    """
    Append a signature to the end of a snapshot path
    with the given private key.

    If first is True, then don't expect the signature trailer.

    Return True on success
    Return False on error
    """
   
    if not os.path.exists(snapshot_path):
        log.error("No such file or directory: {}".format(snapshot_path))
        return False

    file_size = 0
    payload_size = 0
    write_offset = 0
    try:
        sb = os.stat(snapshot_path)
        file_size = sb.st_size
        assert file_size > 8
    except Exception as e:
        log.exception(e)
        return False
    
    num_sigs = 0
    snapshot_hash = None
    with open(snapshot_path, 'r+') as f:

        if not first:
            info = fast_sync_inspect(f)
            if 'error' in info:
                log.error("Failed to inspect {}: {}".format(snapshot_path, info['error']))
                return False

            num_sigs = len(info['signatures'])
            write_offset = info['sig_append_offset']
            payload_size = info['payload_size']
 
        else:
            # no one has signed yet.
            write_offset = file_size
            num_sigs = 0
            payload_size = file_size

        # hash the file and sign the (bin-encoded) hash
        privkey_hex = keylib.ECPrivateKey(private_key).to_hex()
        hash_hex = get_file_hash( f, hashlib.sha256, fd_len=payload_size )
        sigb64 = sign_digest( hash_hex, privkey_hex, hashfunc=hashlib.sha256 )
      
        if BLOCKSTACK_TEST:
            log.debug("Signed {} with {} to make {}".format(hash_hex, keylib.ECPrivateKey(private_key).public_key().to_hex(), sigb64))

        # append
        f.seek(write_offset, os.SEEK_SET)
        f.write(sigb64)
        f.write('{:08x}'.format(len(sigb64)))

        # append number of signatures
        num_sigs += 1
        f.write('{:08x}'.format(num_sigs))
    
        f.flush()
        os.fsync(f.fileno())

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

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

    wallet_keys = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", wallets[5].privkey, wallets[3].privkey,
        wallets[4].privkey)
    wallet_keys_2 = testlib.blockstack_client_initialize_wallet(
        "0123456789abcdef", wallets[9].privkey, wallets[7].privkey,
        wallets[8].privkey)

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

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

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

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

    testlib.blockstack_name_preorder("foo.test", wallets[2].privkey,
                                     wallets[3].addr)
    testlib.blockstack_name_preorder("bar.test", wallets[6].privkey,
                                     wallets[7].addr)
    testlib.next_block(**kw)

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

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

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

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

    testlib.next_block(**kw)

    res = testlib.start_api("0123456789abcdef")
    if 'error' in res:
        print 'failed to start API: {}'.format(res)
        return False

    data_pk = wallets[-1].privkey
    data_pub = wallets[-1].pubkey_hex

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

    # make an index file
    index_file_path = "/tmp/name_preorder_register_update_app_auth.foo.test.index.html"
    with open(index_file_path, "w") as f:
        f.write(index_file_data)

    testlib.blockstack_client_set_wallet("0123456789abcdef",
                                         wallets[5].privkey,
                                         wallets[3].privkey,
                                         wallets[4].privkey)

    res = testlib.start_api("0123456789abcdef")
    if 'error' in res:
        print 'failed to start API: {}'.format(res)
        return False

    # register an application under foo.test
    res = testlib.blockstack_cli_app_publish("foo.test",
                                             "ping.app",
                                             "node_read",
                                             index_file_path,
                                             password="******")
    if 'error' in res:
        res['test'] = 'Failed to register foo.test/bar app'
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    # activate bar.test
    testlib.blockstack_client_set_wallet("0123456789abcdef",
                                         wallets[9].privkey,
                                         wallets[7].privkey,
                                         wallets[8].privkey)

    res = testlib.start_api("0123456789abcdef")
    if 'error' in res:
        print 'failed to start API: {}'.format(res)
        return False

    # sign in
    pk = 'ce100586279d3b127b7dcc137fcc2f18b272bb2b43bdaea3584d0ea17087ec0201'
    pubk = keylib.ECPrivateKey(pk).public_key().to_hex()
    res = testlib.blockstack_cli_app_signin("foo.test", pk, "ping.app",
                                            ["node_read"])
    if 'error' in res:
        res['test'] = 'Failed to signin: {}'.format(res['error'])
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

    ses = res['token']

    res = testlib.blockstack_REST_call("GET", "/v1/ping", ses)
    if res['http_status'] != 200:
        print "failed to GET /api/v1/ping"
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return False

    if res['response']['status'] != 'alive':
        print "failed to GET /api/v1/ping"
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return False

    # access index.html
    res = testlib.blockstack_REST_call(
        "GET",
        "/v1/resources/foo.test/ping.app?name=index.html&pubkey={}".format(
            wallets[4].pubkey_hex), ses)
    if 'error' in res or res['http_status'] != 200:
        print 'failed to GET /v1/resources?name=/index.html'
        print json.dumps(res)
        error = True
        return False

    if res['raw'] != index_file_data:
        print 'expected {}\ngot {}\n'.format(index_file_data, res['raw'])
        print json.dumps(res)
        error = True
        return False

    testlib.next_block(**kw)
예제 #26
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 = {}
core_endpoint = http://localhost:{}
core_auth_token = False
""".format(
            os.getenv('BSK_SUBDOMAIN_REGTEST_BIND', 'localhost'),
            blockstack_client.config.read_config_file()['blockstack-client']
            ['api_endpoint_port'])
        out_f.write(file_out)

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

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

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

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

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

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

    # wait for the poller to pick it up
    print >> sys.stderr, "Waiting 10 seconds for the backend to submit the register"
    time.sleep(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 = blockstack_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 = blockstack_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 = blockstack_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)
예제 #27
0
   current_dir =  os.path.abspath(os.path.dirname(__file__))
   sys.path.insert(0, current_dir)
   
   current_dir =  os.path.abspath(os.path.join( os.path.dirname(__file__), "..") )
   sys.path.insert(0, current_dir)
   
   from blockstack_client.storage import parse_mutable_data, serialize_mutable_data
   from blockstack_client.config import log, get_config
   
   CONFIG_PATH = os.environ.get('BLOCKSTACK_CONFIG_PATH', None)
   assert CONFIG_PATH, "Missing BLOCKSTACK_CONFIG_PATH from environment"

   conf = get_config(CONFIG_PATH)
   print json.dumps(conf, indent=4, sort_keys=True)

   pk = keylib.ECPrivateKey()
   data_privkey = pk.to_hex()
   data_pubkey = pk.public_key().to_hex()

   test_data = [
      ["my_first_datum",        "hello world",                              1, "unused", None],
      ["/my/second/datum",      "hello world 2",                            2, "unused", None],
      ["user\"_profile",          '{"name":{"formatted":"judecn"},"v":"2"}',  3, "unused", None],
      ["empty_string",          "",                                         4, "unused", None],
   ]
   
   def hash_data( d ):
      return hex_hash160( d )
   
   rc = storage_init(conf)
   if not rc:
def scenario(wallets, **kw):
    global value_hashes, namespace_ids

    virtualchain_dir = kw['working_dir']
    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("""
[blockstack-snapshots]
private_key = {}
logfile = {}
""".format(privkey_path, os.path.join(virtualchain_dir, 'snapshots.log')))

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

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

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

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

    zonefile = blockstack_client.zonefile.make_empty_zonefile(
        "foo.test", wallets[0].pubkey_hex)
    zonefile_txt = blockstack_zones.make_zone_file(zonefile)
    zonefile_hash = blockstack_client.storage.get_zonefile_data_hash(
        zonefile_txt)

    value_hashes.append(zonefile_hash)

    namespace_ids.append('test')

    resp = testlib.blockstack_name_import("imported.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)

    # store zonefile
    res = testlib.blockstack_put_zonefile(zonefile_txt)
    assert res

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

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

    assert take_snapshot(config_file, virtualchain_dir, snapshot_dir, 3)

    testlib.blockstack_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.blockstack_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 = blockstack_client.zonefile.make_empty_zonefile(
        "foo.test", wallets[0].pubkey_hex)
    zonefile_txt = blockstack_zones.make_zone_file(zonefile)
    zonefile_hash = blockstack_client.storage.get_zonefile_data_hash(
        zonefile_txt)

    value_hashes.append(zonefile_hash)

    testlib.blockstack_name_update('foo.test', zonefile_hash,
                                   wallets[3].privkey)
    testlib.next_block(**kw)

    time.sleep(1.0)

    # store zonefile
    res = testlib.blockstack_put_zonefile(zonefile_txt)
    assert res

    # 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(virtualchain_dir, os.path.join(snapshot_dir, 'snapshot.bsk'),
                  restore_dir, [wallets[4].pubkey_hex], 1)
    assert res
예제 #29
0
def scenario(wallets, **kw):

    global wallet_keys, error, index_file_data, resource_data

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

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

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

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

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

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

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

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

    testlib.next_block(**kw)

    res = testlib.start_api("0123456789abcdef")
    if 'error' in res:
        print 'failed to start API: {}'.format(res)
        return False

    # sign in and make a token
    datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex()
    res = testlib.blockstack_cli_app_signin(
        "foo.test", datastore_pk, 'foo-app.com',
        ['store_read', 'store_write', 'store_admin'])
    if 'error' in res:
        print json.dumps(res, indent=4, sort_keys=True)
        error = True
        return

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

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

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

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

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

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

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

    # list directories
    for dpath, expected in [('/', ['dir1', 'dir2']), ('/dir1', ['dir3']),
                            ('/dir1/dir3', ['dir4']), ('/dir1/dir3/dir4', [])]:
        print 'listdir {}'.format(dpath)
        res = testlib.blockstack_cli_datastore_listdir('foo.test',
                                                       datastore_id, dpath,
                                                       ses)

        if 'error' in res:
            print 'failed to listdir {}: {}'.format(dpath, res['error'])
            return False

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    testlib.next_block(**kw)
예제 #30
0
def scenario( wallets, **kw ):

    global wallet_keys, wallet_keys_2, error, index_file_data, resource_data

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

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

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

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

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

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

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

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

    ses = res['token']

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # renew it
    res = testlib.blockstack_REST_call("POST", "/v1/names", ses, data={'name': 'bar.test'} )
    if 'error' in res or res['http_status'] != 202:
        res['test'] = 'Failed to transfer 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, 6):
        testlib.next_block( **kw )

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

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

    # do we have the history for the name?
    res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history", 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()) != 4:
        res['test'] = 'Failed to get update history'
        res['history'] = hist
        print json.dumps(res, indent=4, sort_keys=True)
        return False

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

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