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))
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")
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))
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")
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)
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())
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))
def scenario( wallets, **kw ): global wallet_keys, wallet_keys_2, error, index_file_data, resource_data wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[4].privkey ) test_proxy = testlib.TestAPIProxy() blockstack_client.set_default_proxy( test_proxy ) testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) testlib.blockstack_name_preorder( "foo.test", wallets[2].privkey, wallets[3].addr ) testlib.next_block( **kw ) testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr ) testlib.next_block( **kw ) # migrate profiles res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys ) if 'error' in res: res['test'] = 'Failed to initialize foo.test profile' print json.dumps(res, indent=4, sort_keys=True) error = True return # tell serialization-checker that value_hash can be ignored here print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block( **kw ) config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None) # make a session datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex() res = testlib.blockstack_cli_app_signin("foo.test", datastore_pk, 'register.app', ['names', 'register', 'prices', 'zonefiles', 'blockchain', 'node_read', 'wallet_write']) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) error = True return ses = res['token'] # let's set the key to skip the transfer. config_dir = os.path.dirname(config_path) conf = blockstack_client.get_config(config_path) assert conf api_pass = conf['api_password'] new_payment_key = { 'private_key' : wallets[1].privkey, 'persist_change' : True } res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/payment', None, api_pass=api_pass, data=new_payment_key) if res['http_status'] != 200 or 'error' in res: print 'failed to set payment key' print res return False testlib.stop_api() testlib.start_api('0123456789abcdef') res = testlib.blockstack_REST_call('GET', '/v1/wallet/payment_address', None, api_pass = api_pass) if res['http_status'] != 200 or 'error' in res: res['test'] = 'Failed to get payment address' print res return False if res['response']['address'] != wallets[1].addr: res['test'] = 'Got wrong payer address, expected {}, got {}'.format( wallets[1].addr, res['response']['address']) print res return False res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass, data=new_key) if res['http_status'] != 200 or 'error' in res: print 'failed to set owner key' print res return False # make zonefile for recipient driver_urls = blockstack_client.storage.make_mutable_data_urls('bar.test', use_only=['dht', 'disk']) zonefile = blockstack_client.zonefile.make_empty_zonefile('bar.test', wallets[4].pubkey_hex, urls=driver_urls) zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='bar.test', ttl=3600 ) # leaving the call format of this one the same to make sure that our registrar correctly # detects that the requested TRANSFER is superfluous # register the name bar.test res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data={'name': 'bar.test', 'zonefile': zonefile_txt, 'owner_address': new_addr }) if 'error' in res: res['test'] = 'Failed to register user' print json.dumps(res) error = True return False print res tx_hash = res['response']['transaction_hash'] # wait for preorder to get confirmed... for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'preorder', tx_hash ) if not res: return False # wait for the preorder to get confirmed for i in xrange(0, 4): testlib.next_block( **kw ) # wait for register to go through print 'Wait for register to be submitted' time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'register', None ) if not res: return False for i in xrange(0, 4): testlib.next_block( **kw ) print 'Wait for update to be submitted' time.sleep(10) # wait for update to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'update', None ) if not res: return False for i in xrange(0, 4): testlib.next_block( **kw ) print 'Wait for transfer to be submitted' time.sleep(10) # wait for transfer to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'transfer', None ) if res: print res print "Wrongly issued a TRANSFER" return False for i in xrange(0, 4): testlib.next_block( **kw ) print 'Wait for transfer to be confirmed' time.sleep(10) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False zonefile_hash = res['response']['zonefile_hash'] # should still be registered if res['response']['status'] != 'registered': print "register not complete" print json.dumps(res) return False # do we have the history for the name? res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history", ses ) if 'error' in res or res['http_status'] != 200: res['test'] = "Failed to get name history for foo.test" print json.dumps(res) return False # valid history? hist = res['response'] if len(hist.keys()) != 3: res['test'] = 'Failed to get update history' res['history'] = hist print json.dumps(res, indent=4, sort_keys=True) return False # get the zonefile res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/zonefile/{}".format(zonefile_hash), ses ) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name zonefile' print json.dumps(res) return False # same zonefile we put? if res['response']['zonefile'] != zonefile_txt: res['test'] = 'mismatched zonefile, expected\n{}\n'.format(zonefile_txt) print json.dumps(res) return False
def scenario(wallets, **kw): global 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
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:
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
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)
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)
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
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
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'])
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
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)
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)
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
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)
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