def add_subdomains(subdomains, domain_fqa, zonefile_json, filter_function = None): if filter_function is None: filter_function = (lambda subdomain, domain: True) zf = copy.deepcopy(zonefile_json) if "txt" in zf: zf["txt"] = list([ x for x in zf["txt"] if not is_subdomain_record(x)]) if len(set(subdomains)) != len(subdomains): raise Exception("Same subdomain listed multiple times") subdomains_failed = [] for ix, subdomain in enumerate(subdomains): # step 1: see if this resolves to an already defined subdomain filter_passed = filter_function(subdomain.subdomain_name, domain_fqa) if not filter_passed: subdomains_failed.append(ix) else: # step 2: create the subdomain record, adding it to zf try: _extend_with_subdomain(zf, subdomain) except Exception as e: subdomains_failed.append(ix) zf_txt = blockstack_zones.make_zone_file(zf) return zf_txt, subdomains_failed
def serialize_zonefile( zonefile_data ): """ Serialize a zonefile to string """ zonefile_txt = blockstack_zones.make_zone_file( zonefile_data ) return zonefile_txt
def add_subdomains(subdomains, domain_fqa, zonefile_json, filter_function=None): if filter_function is None: filter_function = (lambda subdomain, domain: True) zf = copy.deepcopy(zonefile_json) if "txt" in zf: zf["txt"] = list([x for x in zf["txt"] if not is_subdomain_record(x)]) if len(set(subdomains)) != len(subdomains): raise Exception("Same subdomain listed multiple times") subdomains_failed = [] for ix, subdomain in enumerate(subdomains): # step 1: see if this resolves to an already defined subdomain filter_passed = filter_function(subdomain.subdomain_name, domain_fqa) if not filter_passed: subdomains_failed.append(ix) else: # step 2: create the subdomain record, adding it to zf try: _extend_with_subdomain(zf, subdomain) except Exception as e: subdomains_failed.append(ix) zf_txt = blockstack_zones.make_zone_file(zf) return zf_txt, subdomains_failed
def store_name_zonefile(name, user_zonefile, txid, storage_drivers=None): """ Store JSON user zonefile data to the immutable storage providers, synchronously. This is only necessary if we've added/changed/removed immutable data. Return (True, hash(user zonefile)) on success Return (False, None) on failure """ storage_drivers = [] if storage_drivers is None else storage_drivers assert not blockstack_profiles.is_profile_in_legacy_format( user_zonefile), 'User zonefile is a legacy profile' assert user_db.is_user_zonefile( user_zonefile), 'Not a user zonefile (maybe a custom legacy profile?)' # serialize and send off user_zonefile_txt = blockstack_zones.make_zone_file(user_zonefile, origin=name, ttl=USER_ZONEFILE_TTL) return store_name_zonefile_data(name, user_zonefile_txt, txid, storage_drivers=storage_drivers)
def store_zonefile_to_storage(zonefile_dict, required=[]): """ Upload a zonefile to our storage providers. Return True if at least one provider got it. Return False otherwise. """ zonefile_hash = hash_zonefile(zonefile_dict) name = zonefile_dict['$origin'] zonefile_text = blockstack_zones.make_zone_file(zonefile_dict) # find the tx that paid for this zonefile txid = get_zonefile_txid(zonefile_dict) if txid is None: log.error("No txid for zonefile hash '%s' (for '%s')" % (zonefile_hash, name)) return False rc = blockstack_client.storage.put_immutable_data(None, txid, data_hash=zonefile_hash, data_text=zonefile_text, required=required) if not rc: log.error("Failed to store zonefile '%s' (%s) for '%s'" % (zonefile_hash, txid, name)) return False return True
def test_zone_file_creation_txt(self): json_zone_file = zone_file_objects["sample_txt_1"] zone_file = make_zone_file(json_zone_file) print zone_file self.assertTrue(isinstance(zone_file, (unicode, str))) self.assertTrue("$ORIGIN" in zone_file) self.assertTrue("$TTL" in zone_file) self.assertTrue("@ IN SOA" in zone_file) zone_file = parse_zone_file(zone_file) self.assertTrue(isinstance(zone_file, dict)) self.assertTrue("soa" in zone_file) self.assertTrue("mx" in zone_file) self.assertTrue("ns" in zone_file) self.assertTrue("a" in zone_file) self.assertTrue("cname" in zone_file) self.assertTrue("$ttl" in zone_file) self.assertTrue("$origin" in zone_file) self.assertTrue("txt" in zone_file) self.assertEqual(zone_file["txt"][0]["name"], "single") self.assertEqual(zone_file["txt"][0]["txt"], "everything I do") self.assertEqual(zone_file["txt"][1]["name"], "singleTTL") self.assertEqual(zone_file["txt"][1]["ttl"], 100) self.assertEqual(zone_file["txt"][1]["txt"], "everything I do") self.assertEqual(zone_file["txt"][2]["name"], "multi") self.assertEqual(zone_file["txt"][2]["txt"], ["everything I do", "I do for you"]) self.assertEqual(zone_file["txt"][3]["name"], "multiTTL") self.assertEqual(zone_file["txt"][3]["ttl"], 100) self.assertEqual(zone_file["txt"][3]["txt"], ["everything I do", "I do for you"])
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_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_zone_file_creation_2(self): json_zone_file = zone_file_objects["sample_2"] zone_file = make_zone_file(json_zone_file) print(zone_file) self.assertTrue(isinstance(zone_file, (str, bytes))) self.assertTrue("$ORIGIN" in zone_file) self.assertTrue("$TTL" in zone_file) self.assertTrue("@ IN SOA" in zone_file)
def test_zone_file_creation_3(self): json_zone_file = zone_file_objects["sample_3"] zone_file = make_zone_file(json_zone_file) print zone_file self.assertTrue(isinstance(zone_file, (unicode, str))) self.assertTrue("$ORIGIN" in zone_file) self.assertTrue("$TTL" in zone_file) self.assertTrue("@ IN SOA" in zone_file)
def test_zone_file_creation_1(self): json_zone_file = zone_file_objects["sample_1"] zone_file = make_zone_file(json_zone_file) print(zone_file) self.assertTrue(isinstance(zone_file, (str, str))) self.assertTrue("$ORIGIN" in zone_file) self.assertTrue("$TTL" in zone_file) self.assertTrue("@ 1D URI" in zone_file)
def hash_zonefile( zonefile_json ): """ Given a JSON-ized zonefile, calculate its hash """ assert "$origin" in zonefile_json.keys(), "Missing $origin" assert "$ttl" in zonefile_json.keys(), "Missing $ttl" user_zonefile_txt = blockstack_zones.make_zone_file( zonefile_json ) data_hash = get_zonefile_data_hash( user_zonefile_txt ) return data_hash
def hash_zonefile( zonefile_json ): """ Given a JSON-ized zonefile, calculate its hash """ assert "$origin" in zonefile_json.keys(), "Missing $origin" assert "$ttl" in zonefile_json.keys(), "Missing $ttl" user_zonefile_txt = blockstack_zones.make_zone_file( zonefile_json ) data_hash = get_zonefile_data_hash( user_zonefile_txt ) return data_hash
def replicate_profile_data( cls, name_data, servers, wallet_data, storage_drivers, config_path, proxy=None ): """ Given an update queue entry, replicate the zonefile to as many blockstack servers as we can. If given, replicate the profile as well. @servers should be a list of (host, port) Return {'status': True} on success Return {'error': ...} on error """ # is the zonefile hash replicated? zonefile_data = name_data['zonefile'] if zonefile_data is None: log.debug("No zonefile set for %s" % name_data['fqu']) return {'status': True} zonefile_hash = hash_zonefile( zonefile_data ) name_rec = get_name_blockchain_record( name_data['fqu'], proxy=proxy ) if 'error' in name_rec: return name_rec if str(name_rec['value_hash']) != zonefile_hash: log.error("Zonefile %s has not been replicated yet" % zonefile_hash) return {'error': 'Zonefile hash not yet replicated'} res = zonefile_publish( name_data['fqu'], name_data['zonefile'], servers, wallet_keys=wallet_data ) if 'error' in res: return res log.info("Replicated zonefile for %s to %s server(s)" % (name_data['fqu'], len(res['servers']))) # replicate to our own storage providers as well serialized_zonefile = blockstack_zones.make_zone_file( zonefile_data ) rc = put_immutable_data( None, name_data['tx_hash'], data_hash=zonefile_hash, data_text=serialized_zonefile, required=storage_drivers ) if not rc: log.info("Failed to replicate zonefile for %s" % (name_data['fqu'])) return {'error': 'Failed to store user zonefile'} # replicate profile to storage, if given # use the data keypair if name_data.has_key('profile') and name_data['profile'] is not None: _, data_privkey = get_data_keypair( zonefile_data, wallet_keys=wallet_data, config_path=config_path ) log.info("Replicate profile data for %s to %s" % (name_data['fqu'], ",".join(storage_drivers))) rc = put_mutable_data( name_data['fqu'], name_data['profile'], data_privkey, required=storage_drivers ) if not rc: log.info("Failed to replicate profile for %s" % (name_data['fqu'])) return {'error': 'Failed to store profile'} else: log.info("Replicated profile for %s" % (name_data['fqu'])) return {'status': True} else: log.info("No profile to replicate for '%s'" % (name_data['fqu'])) return {'status': True}
def test_zone_file_creation_2(self): json_zone_file = zone_file_objects["sample_2"] zone_file = make_zone_file(json_zone_file) print(zone_file) self.assertTrue(isinstance(zone_file, (str, bytes))) self.assertTrue("$ORIGIN" in zone_file) self.assertTrue("$TTL" in zone_file) self.assertTrue("@ IN SOA" in zone_file) # www has a TTL and a class self.assertTrue("www 3600 IN A 127.0.0.1" in zone_file) # mail has "_missing_class" set, confirm no class is output self.assertTrue("mail 3600 A 127.0.0.1" in zone_file)
def store_zonefile_to_storage( zonefile_dict, required=None, skip=None, cache=False, zonefile_dir=None ): """ Upload a zonefile to our storage providers. Return True if at least one provider got it. Return False otherwise. """ try: zonefile_data = blockstack_zones.make_zone_file( zonefile_dict ) except Exception, e: log.exception(e) log.error("Invalid zonefile dict") return False
def store_zonefile_to_storage( zonefile_dict, required=None, skip=None, cache=False, zonefile_dir=None ): """ Upload a zonefile to our storage providers. Return True if at least one provider got it. Return False otherwise. """ try: zonefile_data = blockstack_zones.make_zone_file( zonefile_dict ) except Exception, e: log.exception(e) log.error("Invalid zonefile dict") return False
def store_cached_zonefile(zonefile_dict, zonefile_dir=None): """ Store a validated zonefile. zonefile_data should be a dict. The caller should first authenticate the zonefile. Return True on success Return False on error """ try: zonefile_data = blockstack_zones.make_zone_file(zonefile_dict) except Exception, e: log.exception(e) log.error("Invalid zonefile dict") return False
def store_cached_zonefile( zonefile_dict, zonefile_dir=None ): """ Store a validated zonefile. zonefile_data should be a dict. The caller should first authenticate the zonefile. Return True on success Return False on error """ try: zonefile_data = blockstack_zones.make_zone_file( zonefile_dict ) except Exception, e: log.exception(e) log.error("Invalid zonefile dict") return False
def scenario( wallets, **kw ): 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 ) driver_urls = blockstack_client.storage.make_mutable_data_urls('foo.test', use_only=['dht', 'disk']) zonefile = blockstack_client.zonefile.make_empty_zonefile('foo.test', wallets[4].pubkey_hex, urls=driver_urls) zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='foo.test', ttl=3600 ) wallet = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[2].privkey, wallets[3].privkey, None ) resp = testlib.blockstack_cli_register( "foo.test", "0123456789abcdef", zonefile=zonefile_txt, recipient_address=wallets[4].addr ) if 'error' in resp: print >> sys.stderr, json.dumps(resp, indent=4, sort_keys=True) return False # wait for the preorder to get confirmed for i in xrange(0, 12): testlib.next_block( **kw ) # wait for the poller to pick it up print >> sys.stderr, "Waiting 10 seconds for the backend to submit the register" time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 12): testlib.next_block( **kw ) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge registration" time.sleep(10) # wait for update to get confirmed for i in xrange(0, 12): testlib.next_block( **kw ) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge update" time.sleep(10) # wait for transfer to get confirmed for i in xrange(0, 12): testlib.next_block( **kw ) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge transfer" time.sleep(10)
def make_zone_file_for_hosted_data(origin, token_file_url, ttl=3600): if "://" not in token_file_url: raise ValueError("Invalid token file URL") json_zone_file = { "$ttl": ttl, "$origin": origin, "uri": [{ "name": "_http._tcp", "priority": 10, "weight": 1, "target": token_file_url }] } zone_file = make_zone_file(json_zone_file) return zone_file
def zonefile_publish(fqu, zonefile_json, server_list, wallet_keys=None): """ Replicate a zonefile to as many blockstack servers as possible. @server_list is a list of (host, port) tuple Return {'status': True, 'servers': ...} on success, if we succeeded to replicate at least once. 'servers' will be a list of (host, port) tuples Return {'error': ...} if we failed on all accounts. """ zonefile_txt = blockstack_zones.make_zone_file( zonefile_json ) successful_servers = [] for server_host, server_port in server_list: try: log.debug("Replicate zonefile to %s:%s" % (server_host, server_port)) srv = BlockstackRPCClient( server_host, server_port ) res = srv.put_zonefiles( [zonefile_txt] ) if 'error' in res: log.error("Failed to publish zonefile to %s:%s: %s" % (server_host, server_port, res['error'])) continue if 'status' not in res: log.error("Invalid server reply: no status") continue if type(res['status']) != bool or not res['status']: log.error("Invalid server reply: invalid status") continue if 'saved' not in res: log.error("Invalid server reply: no 'saved' key") continue if type(res['saved']) != list: log.error("Invalid server reply: no saved vector") continue if len(res['saved']) < 1 or res['saved'][0] != 1: log.error("Server %s:%s failed to save zonefile" % (server_host, server_port)) continue log.debug("Replicated zonefile to %s:%s" % (server_host, server_port)) successful_servers.append( (server_host, server_port) ) except Exception, e: log.exception(e) log.error("Failed to publish zonefile to %s:%s" % (server_host, server_port)) continue
def generate_zone_file(zone_name): """ Generate a zone file containing all the records for a zone. """ # Load the base records for the zone from a static zone file zone_base = build_zone_base_template(zone_name) records = parse_zone_file(zone_base) # Check if we are generating the zone that returns proxy A records proxy_domain = current_app.config["PROXY_ZONE"] if proxy_domain.endswith(zone_name): # Determine the subdomain where proxy A records will be listed proxy_subdomain = proxy_domain.split(zone_name)[0].strip(".") # Add all online entry proxies to round-robin on this subdomain proxy_records = select_proxy_a_records(proxy_subdomain) for record_type in ["a", "aaaa"]: records[record_type].extend(proxy_records[record_type]) # Add all subdomains and associated TXT records for this zone domains = Domain.query.filter_by(zone=zone_name, deleted=False).all() for domain in domains: # Create the CNAME or ALIAS record pointing to the proxy record = { 'name': domain.subdomain, 'ttl': current_app.config["A_RECORD_TTL"] } if current_app.config.get("USE_ALIAS_RECORDS"): record["host"] = current_app.config["PROXY_ZONE"] records["alias"].append(record) else: record["alias"] = current_app.config["PROXY_ZONE"] records["cname"].append(record) # Create the TXT record with the domain->onion address mapping records["txt"].append({ 'name': domain.txt_label, 'txt': "onion={}".format(domain.onion_address), 'ttl': current_app.config["TXT_RECORD_TTL"] }) # Fixes a bug in `zone_file` which places the SOA record inside a list records["soa"] = records["soa"].pop() # Bump the serial number in the SOA records["soa"]["serial"] = int(time.time()) return make_zone_file(records)
def make_zone_file_for_hosted_data(origin, token_file_url, ttl=3600): if "://" not in token_file_url: raise ValueError("Invalid token file URL") json_zone_file = { "$ttl": ttl, "$origin": origin, "uri": [{ "name": "_http._tcp", "priority": 10, "weight": 1, "target": token_file_url }] } zone_file = make_zone_file(json_zone_file) return zone_file
def store_name_zonefile(name, user_zonefile, txid, storage_drivers=None): """ Store JSON user zonefile data to the immutable storage providers, synchronously. This is only necessary if we've added/changed/removed immutable data. Return (True, hash(user zonefile)) on success Return (False, None) on failure """ storage_drivers = [] if storage_drivers is None else storage_drivers assert not blockstack_profiles.is_profile_in_legacy_format(user_zonefile), 'User zonefile is a legacy profile' assert user_db.is_user_zonefile(user_zonefile), 'Not a user zonefile (maybe a custom legacy profile?)' # serialize and send off user_zonefile_txt = blockstack_zones.make_zone_file(user_zonefile, origin=name, ttl=USER_ZONEFILE_TTL) return store_name_zonefile_data(name, user_zonefile_txt, txid, storage_drivers=storage_drivers)
def store_cached_zonefile( zonefile_dict, zonefile_dir=None ): """ Store a validated zonefile. zonefile_data should be a dict. The caller should first authenticate the zonefile. Return True on success Return False on error """ if zonefile_dir is None: zonefile_dir = get_zonefile_dir() if not os.path.exists(zonefile_dir): os.makedirs(zonefile_dir, 0700 ) try: zonefile_data = blockstack_zones.make_zone_file( zonefile_dict ) except Exception, e: log.exception(e) log.error("Invalid zonefile dict") return False
def store_cached_zonefile(zonefile_dict, zonefile_dir=None): """ Store a validated zonefile. zonefile_data should be a dict. The caller should first authenticate the zonefile. Return True on success Return False on error """ if zonefile_dir is None: zonefile_dir = get_zonefile_dir() if not os.path.exists(zonefile_dir): os.makedirs(zonefile_dir, 0700) try: zonefile_data = blockstack_zones.make_zone_file(zonefile_dict) except Exception, e: log.exception(e) log.error("Invalid zonefile dict") return False
def store_zonefile_to_storage( zonefile_dict, required=[] ): """ Upload a zonefile to our storage providers. Return True if at least one provider got it. Return False otherwise. """ zonefile_hash = hash_zonefile( zonefile_dict ) name = zonefile_dict['$origin'] zonefile_text = blockstack_zones.make_zone_file( zonefile_dict ) # find the tx that paid for this zonefile txid = get_zonefile_txid( zonefile_dict ) if txid is None: log.error("No txid for zonefile hash '%s' (for '%s')" % (zonefile_hash, name)) return False rc = blockstack_client.storage.put_immutable_data( None, txid, data_hash=zonefile_hash, data_text=zonefile_text, required=required ) if not rc: log.error("Failed to store zonefile '%s' (%s) for '%s'" % (zonefile_hash, txid, name)) return False return True
def store_name_zonefile( name, user_zonefile, txid ): """ Store JSON user zonefile data to the immutable storage providers, synchronously. This is only necessary if we've added/changed/removed immutable data. Return (True, hash(user)) on success Return (False, None) on failure """ assert not blockstack_profiles.is_profile_in_legacy_format(user_zonefile), "User zonefile is a legacy profile" assert user_db.is_user_zonefile(user_zonefile), "Not a user zonefile (maybe a custom legacy profile?)" # serialize and send off user_zonefile_txt = blockstack_zones.make_zone_file( user_zonefile, origin=name, ttl=USER_ZONEFILE_TTL ) data_hash = storage.get_zonefile_data_hash( user_zonefile_txt ) result = storage.put_immutable_data(None, txid, data_hash=data_hash, data_text=user_zonefile_txt ) rc = None if result is None: rc = False else: rc = True return (rc, data_hash)
def scenario( wallets, **kw ): global wallet_keys, wallet_keys_2, error, index_file_data, resource_data wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[4].privkey ) test_proxy = testlib.TestAPIProxy() blockstack_client.set_default_proxy( test_proxy ) testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) testlib.blockstack_name_preorder( "foo.test", wallets[2].privkey, wallets[3].addr ) testlib.next_block( **kw ) testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr ) testlib.next_block( **kw ) # migrate profiles res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys ) if 'error' in res: res['test'] = 'Failed to initialize foo.test profile' print json.dumps(res, indent=4, sort_keys=True) error = True return # tell serialization-checker that value_hash can be ignored here print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block( **kw ) config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None) # make a session datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex() res = testlib.blockstack_cli_app_signin("foo.test", datastore_pk, 'register.app', ['names', 'register', 'prices', 'zonefiles', 'blockchain', 'node_read', 'wallet_write']) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) error = True return ses = res['token'] # for funsies, get the price of .test res = testlib.blockstack_REST_call('GET', '/v1/prices/namespaces/test', ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get price of .test' print json.dumps(res) return False test_price = res['response']['satoshis'] print '\n\n.test costed {} satoshis\n\n'.format(test_price) # get the price for bar.test res = testlib.blockstack_REST_call('GET', '/v1/prices/names/bar.test', ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get price of bar.test' print json.dumps(res) return False bar_price = res['response']['total_estimated_cost']['satoshis'] print "\n\nbar.test will cost {} satoshis\n\n".format(bar_price) # let's set the key to skip the transfer. config_dir = os.path.dirname(config_path) conf = blockstack_client.get_config(config_path) assert conf api_pass = conf['api_password'] res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass, data=new_key) if res['http_status'] != 200 or 'error' in res: print 'failed to set owner key' print res return False # make zonefile for recipient driver_urls = blockstack_client.storage.make_mutable_data_urls('bar.test', use_only=['dht', 'disk']) zonefile = blockstack_client.zonefile.make_empty_zonefile('bar.test', wallets[4].pubkey_hex, urls=driver_urls) zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='bar.test', ttl=3600 ) # leaving the call format of this one the same to make sure that our registrar correctly # detects that the requested TRANSFER is superfluous # register the name bar.test res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data={'name': 'bar.test', 'zonefile': zonefile_txt, 'owner_address': new_addr }) if 'error' in res: res['test'] = 'Failed to register user' print json.dumps(res) error = True return False print res tx_hash = res['response']['transaction_hash'] # wait for preorder to get confirmed... for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'preorder', tx_hash ) if not res: return False # wait for the preorder to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) # wait for register to go through print 'Wait for register to be submitted' time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'register', None ) if not res: return False for i in xrange(0, 6): testlib.next_block( **kw ) print 'Wait for update to be submitted' time.sleep(10) # wait for update to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'update', None ) if not res: return False for i in xrange(0, 6): testlib.next_block( **kw ) print 'Wait for transfer to be submitted' time.sleep(10) # wait for transfer to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'transfer', None ) if res: print "Wrongly issued a TRANSFER" return False for i in xrange(0, 6): testlib.next_block( **kw ) print 'Wait for transfer to be confirmed' time.sleep(10) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False zonefile_hash = res['response']['zonefile_hash'] # should still be registered if res['response']['status'] != 'registered': print "register not complete" print json.dumps(res) return False # do we have the history for the name? res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history", ses ) if 'error' in res or res['http_status'] != 200: res['test'] = "Failed to get name history for foo.test" print json.dumps(res) return False # valid history? hist = res['response'] if len(hist.keys()) != 3: res['test'] = 'Failed to get update history' res['history'] = hist print json.dumps(res, indent=4, sort_keys=True) return False # get the zonefile res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/zonefile/{}".format(zonefile_hash), ses ) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name zonefile' print json.dumps(res) return False # same zonefile we put? if res['response']['zonefile'] != zonefile_txt: res['test'] = 'mismatched zonefile, expected\n{}\n'.format(zonefile_txt) print json.dumps(res) return False ### Now, we'll do it again, but this time, we're going to CHANGE THE KEY in the middle of registrations. ### to test the different paths, I'll start 3 registrations: # 1 has submitted preorder # 1 has submitted register # 1 has submitted update ### And then I'll issue a change-key # make zonefile for recipients zonefiles = [] for i in [1,2,3]: name = "tricky{}.test".format(i) driver_urls = blockstack_client.storage.make_mutable_data_urls(name, use_only=['dht', 'disk']) zonefile = blockstack_client.zonefile.make_empty_zonefile(name, wallets[4].pubkey_hex, urls=driver_urls) zonefiles.append(blockstack_zones.make_zone_file( zonefile, origin=name, ttl=3600 )) # leaving the call format of this one the same to make sure that our registrar correctly # detects that the requested TRANSFER is superfluous res = testlib.blockstack_REST_call( 'POST', '/v1/names', ses, data={'name':'tricky1.test', 'zonefile':zonefiles[0], 'owner_address':new_addr}) if 'error' in res: res['test'] = 'Failed to register tricky1.test' print json.dumps(res) error = True return False tx_hash = res['response']['transaction_hash'] # wait for preorder to get confirmed... for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.blockstack_REST_call( 'POST', '/v1/names', ses, data={'name':'tricky2.test', 'zonefile':zonefiles[1], 'owner_address':new_addr}) if 'error' in res: res['test'] = 'Failed to register tricky2.test' print json.dumps(res) error = True return False # wait for the preorder to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) # wait for register to go through print 'Wait for register to be submitted' time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.blockstack_REST_call( 'POST', '/v1/names', ses, data={'name':'tricky3.test', 'zonefile':zonefiles[2], 'owner_address':new_addr}) if 'error' in res: res['test'] = 'Failed to register tricky3.test' print json.dumps(res) error = True return False for i in xrange(0, 6): testlib.next_block( **kw ) print 'Wait for update to be submitted' time.sleep(10) for i in xrange(0, 1): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'tricky1.test', 'update', None) res = testlib.verify_in_queue(ses, 'tricky2.test', 'register', None) res = testlib.verify_in_queue(ses, 'tricky3.test', 'preorder', None) # let's go crazy. res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass, data=insanity_key) if res['http_status'] != 200 or 'error' in res: print 'failed to set owner key' print res return False # wait for preorder to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) # wake up registrar, submit register time.sleep(10) for i in xrange(0, 12): testlib.next_block( **kw ) # wake up registrar, submit update time.sleep(10) for i in xrange(0, 12): testlib.next_block( **kw ) # wake up registrar, propogate zonefile time.sleep(10)
def scenario( wallets, **kw ): 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 testlib.expect_snv_fail_at( "foo.test", testlib.get_current_block(**kw)+1) # 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( "foo.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( "foo.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 synchronized, value_hash import blockstack_integration_tests.atlas_network as atlas_network 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 ) # set up RPC daemon 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'] ) # register 10 names for i in xrange(0, 10): res = testlib.blockstack_name_preorder( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) for i in xrange(0, 10): res = testlib.blockstack_name_register( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # make 10 empty zonefiles and propagate them for i in xrange(0, 10): data_pubkey = virtualchain.BitcoinPrivateKey(wallet_keys['data_privkey']).public_key().to_hex() empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)] ) empty_zonefile_str = blockstack_zones.make_zone_file( empty_zonefile ) value_hash = blockstack_client.hash_zonefile( empty_zonefile ) res = testlib.blockstack_name_update( "foo_{}.test".format(i), value_hash, wallets[3].privkey ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # propagate res = testlib.blockstack_cli_sync_zonefile('foo_{}.test'.format(i), zonefile_string=empty_zonefile_str) if 'error' in res: print json.dumps(res) return False # start up an Atlas test network with 9 nodes: the main one doing the test, and 8 subordinate ones that treat it as a seed peer # only the seed node will be publicly routable; the other 8 will be unable to directly talk to each other. atlas_nodes = [17000, 17001, 17002, 17003, 17004, 17005, 17006, 17007] atlas_topology = {} for node_port in atlas_nodes: atlas_topology[node_port] = [16264] def nat_drop(src_hostport, dest_hostport): if dest_hostport is None: return 0.0 host, port = blockstack_client.config.url_to_host_port( dest_hostport ) if port in atlas_nodes: # connections to the above nodes will always fail, since they're NAT'ed return 1.0 else: # connections to the seed node always succeed return 0.0 network_des = atlas_network.atlas_network_build( atlas_nodes, atlas_topology, {}, os.path.join( testlib.working_dir(**kw), "atlas_network" ) ) atlas_network.atlas_network_start( network_des, drop_probability=nat_drop ) print "Waiting 60 seconds for the altas peers to catch up" time.sleep(60.0) # wait at most 30 seconds for atlas network to converge synchronized = False for i in xrange(0, 30): atlas_network.atlas_print_network_state( network_des ) if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block( **kw ) - 1, 1 ): print "Synchronized!" synchronized = True break else: time.sleep(1.0) # shut down atlas_network.atlas_network_stop( network_des ) return synchronized
def scenario( wallets, **kw ): global value_hashes 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 ) # register 10 names for i in xrange(0, 10): res = testlib.blockstack_name_preorder( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) for i in xrange(0, 10): res = testlib.blockstack_name_register( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # make 10 empty zonefiles and propagate them for i in xrange(0, 10): data_pubkey = wallets[4].pubkey_hex empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)] ) empty_zonefile_str = blockstack_zones.make_zone_file( empty_zonefile ) value_hash = blockstack_client.hash_zonefile( empty_zonefile ) res = testlib.blockstack_name_update( "foo_{}.test".format(i), value_hash, wallets[3].privkey ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # propagate res = testlib.blockstack_cli_sync_zonefile('foo_{}.test'.format(i), zonefile_string=empty_zonefile_str) if 'error' in res: print json.dumps(res) return False value_hashes.append(value_hash) config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG") assert config_path restore_dir = os.path.join(os.path.dirname(config_path), "snapshot_dir") # snapshot the latest backup snapshot_path = os.path.join( os.path.dirname(config_path), "snapshot.bsk" ) rc = blockstack.fast_sync_snapshot( snapshot_path, wallets[3].privkey, None ) if not rc: print "Failed to fast_sync_snapshot" return False if not os.path.exists(snapshot_path): print "Failed to create snapshot {}".format(snapshot_path) return False # sign with more keys for i in xrange(4, 6): rc = blockstack.fast_sync_sign_snapshot( snapshot_path, wallets[i].privkey ) if not rc: print "Failed to sign with key {}".format(i) return False # restore! rc = restore( snapshot_path, restore_dir, [wallets[3].pubkey_hex, wallets[4].pubkey_hex, wallets[5].pubkey_hex], 3 ) if not rc: print "failed to restore snapshot {}".format(snapshot_path) return False rc = restore( snapshot_path, restore_dir, [wallets[5].pubkey_hex, wallets[4].pubkey_hex, wallets[3].pubkey_hex], 3 ) if not rc: print "failed to restore snapshot {}".format(snapshot_path) return False rc = restore( snapshot_path, restore_dir, [wallets[3].pubkey_hex, wallets[4].pubkey_hex], 2 ) if not rc: print "failed to restore snapshot {}".format(snapshot_path) return False rc = restore( snapshot_path, restore_dir, [wallets[3].pubkey_hex, wallets[5].pubkey_hex], 2 ) if not rc: print "failed to restore snapshot {}".format(snapshot_path) return False rc = restore( snapshot_path, restore_dir, [wallets[4].pubkey_hex, wallets[5].pubkey_hex], 2 ) if not rc: print "failed to restore snapshot {}".format(snapshot_path) return False rc = restore( snapshot_path, restore_dir, [wallets[3].pubkey_hex], 1 ) if not rc: print "failed to restore snapshot {}".format(snapshot_path) return False rc = restore( snapshot_path, restore_dir, [wallets[4].pubkey_hex, wallets[0].pubkey_hex], 1 ) if not rc: print "failed to restore snapshot {}".format(snapshot_path) return False rc = restore( snapshot_path, restore_dir, [wallets[0].pubkey_hex, wallets[1].pubkey_hex, wallets[5].pubkey_hex], 1 ) if not rc: print "failed to restore snapshot {}".format(snapshot_path) return False # should fail rc = restore( snapshot_path, restore_dir, [wallets[3].pubkey_hex], 2 ) if rc: print "restored insufficient signatures snapshot {}".format(snapshot_path) return False shutil.rmtree(restore_dir) # should fail rc = restore( snapshot_path, restore_dir, [wallets[3].pubkey_hex, wallets[4].pubkey_hex], 3 ) if rc: print "restored insufficient signatures snapshot {}".format(snapshot_path) return False shutil.rmtree(restore_dir) # should fail rc = restore( snapshot_path, restore_dir, [wallets[0].pubkey_hex], 1 ) if rc: print "restored wrongly-signed snapshot {}".format(snapshot_path) return False shutil.rmtree(restore_dir) # should fail rc = restore( snapshot_path, restore_dir, [wallets[0].pubkey_hex, wallets[3].pubkey_hex], 2 ) if rc: print "restored wrongly-signed snapshot {}".format(snapshot_path) return False shutil.rmtree(restore_dir) # should fail rc = restore( snapshot_path, restore_dir, [wallets[0].pubkey_hex, wallets[3].pubkey_hex, wallets[4].pubkey_hex], 3 ) if rc: print "restored wrongly-signed snapshot {}".format(snapshot_path) return False shutil.rmtree(restore_dir)
def scenario( wallets, **kw ): global wallet_keys, wallet_keys_2, error, index_file_data, resource_data wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[4].privkey ) test_proxy = testlib.TestAPIProxy() blockstack_client.set_default_proxy( test_proxy ) testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) testlib.blockstack_name_preorder( "foo.test", wallets[2].privkey, wallets[3].addr ) testlib.next_block( **kw ) testlib.blockstack_name_register( "foo.test", wallets[2].privkey, wallets[3].addr ) testlib.next_block( **kw ) # migrate profiles res = testlib.migrate_profile( "foo.test", proxy=test_proxy, wallet_keys=wallet_keys ) if 'error' in res: res['test'] = 'Failed to initialize foo.test profile' print json.dumps(res, indent=4, sort_keys=True) error = True return # tell serialization-checker that value_hash can be ignored here print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block( **kw ) config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None) # make a session datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex() res = testlib.blockstack_cli_app_signin("foo.test", datastore_pk, 'register.app', ['names', 'register', 'prices', 'zonefiles', 'blockchain', 'node_read', 'wallet_write']) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) error = True return ses = res['token'] # let's set the key to skip the transfer. config_dir = os.path.dirname(config_path) conf = blockstack_client.get_config(config_path) assert conf api_pass = conf['api_password'] new_payment_key = { 'private_key' : wallets[1].privkey, 'persist_change' : True } res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/payment', None, api_pass=api_pass, data=new_payment_key) if res['http_status'] != 200 or 'error' in res: print 'failed to set payment key' print res return False testlib.stop_api() testlib.start_api('0123456789abcdef') res = testlib.blockstack_REST_call('GET', '/v1/wallet/payment_address', None, api_pass = api_pass) if res['http_status'] != 200 or 'error' in res: res['test'] = 'Failed to get payment address' print res return False if res['response']['address'] != wallets[1].addr: res['test'] = 'Got wrong payer address, expected {}, got {}'.format( wallets[1].addr, res['response']['address']) print res return False res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass, data=new_key) if res['http_status'] != 200 or 'error' in res: print 'failed to set owner key' print res return False # make zonefile for recipient driver_urls = blockstack_client.storage.make_mutable_data_urls('bar.test', use_only=['dht', 'disk']) zonefile = blockstack_client.zonefile.make_empty_zonefile('bar.test', wallets[4].pubkey_hex, urls=driver_urls) zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='bar.test', ttl=3600 ) # leaving the call format of this one the same to make sure that our registrar correctly # detects that the requested TRANSFER is superfluous # register the name bar.test res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data={'name': 'bar.test', 'zonefile': zonefile_txt, 'owner_address': new_addr }) if 'error' in res: res['test'] = 'Failed to register user' print json.dumps(res) error = True return False print res tx_hash = res['response']['transaction_hash'] # wait for preorder to get confirmed... for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'preorder', tx_hash ) if not res: return False # wait for the preorder to get confirmed for i in xrange(0, 4): testlib.next_block( **kw ) # wait for register to go through print 'Wait for register to be submitted' time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'register', None ) if not res: return False for i in xrange(0, 4): testlib.next_block( **kw ) print 'Wait for update to be submitted' time.sleep(10) # wait for update to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'update', None ) if not res: return False for i in xrange(0, 4): testlib.next_block( **kw ) print 'Wait for transfer to be submitted' time.sleep(10) # wait for transfer to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(ses, 'bar.test', 'transfer', None ) if res: print res print "Wrongly issued a TRANSFER" return False for i in xrange(0, 4): testlib.next_block( **kw ) print 'Wait for transfer to be confirmed' time.sleep(10) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False zonefile_hash = res['response']['zonefile_hash'] # should still be registered if res['response']['status'] != 'registered': print "register not complete" print json.dumps(res) return False # do we have the history for the name? res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history", ses ) if 'error' in res or res['http_status'] != 200: res['test'] = "Failed to get name history for foo.test" print json.dumps(res) return False # valid history? hist = res['response'] if len(hist.keys()) != 3: res['test'] = 'Failed to get update history' res['history'] = hist print json.dumps(res, indent=4, sort_keys=True) return False # get the zonefile res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/zonefile/{}".format(zonefile_hash), ses ) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name zonefile' print json.dumps(res) return False # same zonefile we put? if res['response']['zonefile'] != zonefile_txt: res['test'] = 'mismatched zonefile, expected\n{}\n'.format(zonefile_txt) print json.dumps(res) return False
def scenario( wallets, **kw ): global wallet_keys, wallet_keys_2, error, index_file_data, resource_data wallet_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 scenario(wallets, **kw): global synchronized, value_hash import blockstack_integration_tests.atlas_network as atlas_network 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) # set up RPC daemon 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']) # register 10 names for i in xrange(0, 10): res = testlib.blockstack_name_preorder("foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) for i in xrange(0, 10): res = testlib.blockstack_name_register("foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) # make 10 empty zonefiles and propagate them for i in xrange(0, 10): data_pubkey = virtualchain.BitcoinPrivateKey( wallet_keys['data_privkey']).public_key().to_hex() empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)]) empty_zonefile_str = blockstack_zones.make_zone_file(empty_zonefile) value_hash = blockstack_client.hash_zonefile(empty_zonefile) res = testlib.blockstack_name_update("foo_{}.test".format(i), value_hash, wallets[3].privkey) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) # propagate res = testlib.blockstack_cli_sync_zonefile( 'foo_{}.test'.format(i), zonefile_string=empty_zonefile_str) if 'error' in res: print json.dumps(res) return False # start up an Atlas test network with 9 nodes: the main one doing the test, and 8 subordinate ones that treat it as a seed peer # only the seed node will be publicly routable; the other 8 will be unable to directly talk to each other. atlas_nodes = [17000, 17001, 17002, 17003, 17004, 17005, 17006, 17007] atlas_topology = {} for node_port in atlas_nodes: atlas_topology[node_port] = [16264] def nat_drop(src_hostport, dest_hostport): if dest_hostport is None: return 0.0 host, port = blockstack_client.config.url_to_host_port(dest_hostport) if port in atlas_nodes: # connections to the above nodes will always fail, since they're NAT'ed return 1.0 else: # connections to the seed node always succeed return 0.0 network_des = atlas_network.atlas_network_build( atlas_nodes, atlas_topology, {}, os.path.join(testlib.working_dir(**kw), "atlas_network")) atlas_network.atlas_network_start(network_des, drop_probability=nat_drop) print "Waiting 60 seconds for the altas peers to catch up" time.sleep(60.0) # wait at most 30 seconds for atlas network to converge synchronized = False for i in xrange(0, 30): atlas_network.atlas_print_network_state(network_des) if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block(**kw) - 1, 1): print "Synchronized!" synchronized = True break else: time.sleep(1.0) # shut down atlas_network.atlas_network_stop(network_des) return synchronized
def scenario( wallets, **kw ): global wallet_keys, wallet_keys_2, error, index_file_data, resource_data wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[4].privkey ) test_proxy = testlib.TestAPIProxy() blockstack_client.set_default_proxy( test_proxy ) testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) # tell serialization-checker that value_hash can be ignored here print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block( **kw ) config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None) # let's set the key to skip the transfer. config_dir = os.path.dirname(config_path) conf = blockstack_client.get_config(config_path) assert conf api_pass = conf['api_password'] res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass, data=new_key) if res['http_status'] != 200 or 'error' in res: print 'failed to set owner key' print res return False # make zonefile for recipient driver_urls = blockstack_client.storage.make_mutable_data_urls('bar.test', use_only=['dht', 'disk']) zonefile = blockstack_client.zonefile.make_empty_zonefile('bar.test', wallets[4].pubkey_hex, urls=driver_urls) zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='bar.test', ttl=3600 ) # leaving the call format of this one the same to make sure that our registrar correctly # detects that the requested TRANSFER is superfluous # register the name bar.test res = testlib.blockstack_REST_call( 'POST', '/v1/names', None, api_pass=api_pass, data={ 'name': 'bar.test', 'zonefile': zonefile_txt, 'owner_address': new_addr }) if 'error' in res: res['test'] = 'Failed to register user' print json.dumps(res) error = True return False print res tx_hash = res['response']['transaction_hash'] # wait for preorder to get confirmed... for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(None, 'bar.test', 'preorder', tx_hash, api_pass = api_pass ) if not res: return False # wait for the preorder to get confirmed for i in xrange(0, 4): testlib.next_block( **kw ) # wait for register to go through print 'Wait for register to be submitted' time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(None, 'bar.test', 'register', None, api_pass = api_pass ) if not res: return False for i in xrange(0, 4): testlib.next_block( **kw ) print 'Wait for update to be submitted' time.sleep(10) # wait for update to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(None, 'bar.test', 'update', None, api_pass = api_pass ) if not res: print res print "update error in first update" return False for i in xrange(0, 4): testlib.next_block( **kw ) print 'Wait for transfer to be submitted' time.sleep(10) # wait for transfer to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(None, 'bar.test', 'transfer', None, api_pass = api_pass ) if res: print "Wrongly issued a TRANSFER" return False res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", None, api_pass=api_pass) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False zonefile_hash = res['response']['zonefile_hash'] # should still be registered if res['response']['status'] != 'registered': print "register not complete" print json.dumps(res) return False # do we have the history for the name? res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history", None, api_pass=api_pass ) if 'error' in res or res['http_status'] != 200: res['test'] = "Failed to get name history for foo.test" print json.dumps(res) return False # valid history? hist = res['response'] if len(hist.keys()) != 3: res['test'] = 'Failed to get update history' res['history'] = hist print json.dumps(res, indent=4, sort_keys=True) return False # get the zonefile res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/zonefile/{}".format(zonefile_hash), None, api_pass=api_pass ) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name zonefile' print json.dumps(res) return False # same zonefile we put? if res['response']['zonefile'] != zonefile_txt: res['test'] = 'mismatched zonefile, expected\n{}\n'.format(zonefile_txt) print json.dumps(res) return False # okay, now let's try to do a transfer. # FIRST, I want to change the key to a key that # doesn't own the name and a payment key that has no money res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/owner', None, api_pass=api_pass, data=insanity_key) if res['http_status'] != 200 or 'error' in res: print 'failed to set owner key' print res return False res = testlib.blockstack_REST_call('PUT', '/v1/wallet/keys/payment', None, api_pass=api_pass, data=insanity_key) if res['http_status'] != 200 or 'error' in res: print 'failed to set owner key' print res return False payment_key = wallets[1].privkey # let's do this with the bad key res = testlib.blockstack_REST_call( 'PUT', '/v1/names/bar.test/owner', None, api_pass=api_pass, data={ 'owner': destination_owner, 'payment_key' : payment_key }) if 'error' in res or res['http_status'] != 202: res['test'] = '(Correctly) failed to transfer user' print json.dumps(res) # let's do this with the good one! res = testlib.blockstack_REST_call( 'PUT', '/v1/names/bar.test/owner', None, api_pass=api_pass, data={ 'owner': destination_owner, 'owner_key' : new_key, 'payment_key' : payment_key }) if 'error' in res or res['http_status'] != 202: res['test'] = '(Wrongly) failed to transfer user' print json.dumps(res) error = True return False else: print "Submitted transfer!" print res print 'Wait for transfer to be submitted' time.sleep(10) # wait to get confirmed for i in xrange(0, 6): testlib.next_block( **kw ) res = testlib.verify_in_queue(None, 'bar.test', 'transfer', None, api_pass = api_pass ) if not res: print "transfer error" print res return False for i in xrange(0, 4): testlib.next_block( **kw ) # wait for zonefile to propagate time.sleep(10) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", None, api_pass=api_pass) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False cur_owner_address = res['response']['address'] if cur_owner_address != destination_owner: print "After transfer, unexpected owner. Expected {}, Actual {}".format( destination_owner, cur_owner_address) return False
def scenario(wallets, **kw): global wallet_keys, wallet_keys_2, error, index_file_data, resource_data empty_key = ECPrivateKey().to_hex() wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", empty_key, empty_key, empty_key) test_proxy = testlib.TestAPIProxy() blockstack_client.set_default_proxy(test_proxy) testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw) # tell serialization-checker that value_hash can be ignored here print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block(**kw) config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None) config_dir = os.path.dirname(config_path) conf = blockstack_client.get_config(config_path) assert conf api_pass = conf['api_password'] payment_key = wallets[1].privkey # make zonefile for recipient driver_urls = blockstack_client.storage.make_mutable_data_urls( 'bar.test', use_only=['dht', 'disk']) zonefile = blockstack_client.zonefile.make_empty_zonefile( 'bar.test', wallets[4].pubkey_hex, urls=driver_urls) zonefile_txt = blockstack_zones.make_zone_file(zonefile, origin='bar.test', ttl=3600) no_key_postage = {'name': 'bar.test', 'zonefile': zonefile_txt} key_postage = dict(no_key_postage) key_postage['payment_key'] = payment_key key_postage['owner_key'] = new_key res = testlib.blockstack_REST_call('POST', '/v1/names', None, api_pass=api_pass, data=no_key_postage) if 'error' not in res['response']: print "Successfully registered user with should-have-been-bad keys" print res return False # let's do a small withdraw res = testlib.blockstack_REST_call( 'POST', '/v1/wallet/balance', None, api_pass=api_pass, data={ 'address': virtualchain.get_privkey_address(empty_key), 'amount': int(1e4), 'payment_key': payment_key }) if 'error' in res['response']: res['test'] = 'Failed to perform withdraw' print json.dumps(res) error = True return False for i in xrange(0, 1): testlib.next_block(**kw) print 'Waiting for the withdraw to go through' res = testlib.blockstack_REST_call('GET', '/v1/wallet/balance/0', None, api_pass=api_pass) if 'error' in res['response']: res['test'] = 'Failed to get wallet balance' print json.dumps(res) error = True return False if int(res['response']['balance']['satoshis']) <= 0: res['test'] = 'Wallet balance did not increment!' print json.dumps(res) error = True return False res = testlib.blockstack_REST_call('POST', '/v1/names', None, api_pass=api_pass, data=key_postage) if 'error' in res['response']: res['test'] = 'Failed to register user' print json.dumps(res) error = True return False print "Registering bar.test" for i in xrange(0, 6): testlib.next_block(**kw) if not res: return False # wait for the preorder to get confirmed for i in xrange(0, 6): testlib.next_block(**kw) # wait for register to go through print 'Wait for register to be submitted' time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(None, 'bar.test', 'register', None, api_pass=api_pass) if not res: return False for i in xrange(0, 6): testlib.next_block(**kw) print 'Wait for update to be submitted' time.sleep(10) # wait for update to get confirmed for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(None, 'bar.test', 'update', None, api_pass=api_pass) if not res: print res print "update error in first update" return False for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", None, api_pass=api_pass) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False zonefile_hash = res['response']['zonefile_hash'] # should still be registered if res['response']['status'] != 'registered': print "register not complete" print json.dumps(res) return False # do we have the history for the name? res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history", None, api_pass=api_pass) if 'error' in res or res['http_status'] != 200: res['test'] = "Failed to get name history for foo.test" print json.dumps(res) return False # valid history? hist = res['response'] if len(hist.keys()) != 3: res['test'] = 'Failed to get update history' res['history'] = hist print json.dumps(res, indent=4, sort_keys=True) return False # get the zonefile res = testlib.blockstack_REST_call( "GET", "/v1/names/bar.test/zonefile/{}".format(zonefile_hash), None, api_pass=api_pass) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name zonefile' print json.dumps(res) return False # same zonefile we put? if res['response']['zonefile'] != zonefile_txt: res['test'] = 'mismatched zonefile, expected\n{}\n'.format( zonefile_txt) print json.dumps(res) return False # okay, now let's try to do an update. # make zonefile for recipient driver_urls = blockstack_client.storage.make_mutable_data_urls( 'bar.test', use_only=['http', 'disk']) zonefile = blockstack_client.zonefile.make_empty_zonefile( 'bar.test', wallets[3].pubkey_hex, urls=driver_urls) zonefile_txt = blockstack_zones.make_zone_file(zonefile, origin='bar.test', ttl=3600) # let's do this update. res = testlib.blockstack_REST_call('PUT', '/v1/names/bar.test/zonefile', None, api_pass=api_pass, data={ 'zonefile': zonefile_txt, 'owner_key': new_key, 'payment_key': payment_key }) if 'error' in res or res['http_status'] != 202: res['test'] = 'Failed to register user' print json.dumps(res) error = True return False else: print "Submitted update!" print res print 'Wait for update to be submitted' time.sleep(10) # wait for update to get confirmed for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(None, 'bar.test', 'update', None, api_pass=api_pass) if not res: print "update error in second update" print res return False for i in xrange(0, 6): testlib.next_block(**kw) # wait for zonefile to propagate time.sleep(10) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", None, api_pass=api_pass) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False zonefile_hash = res['response']['zonefile_hash'] # get the zonefile res = testlib.blockstack_REST_call( "GET", "/v1/names/bar.test/zonefile/{}".format(zonefile_hash), None, api_pass=api_pass) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name zonefile' print json.dumps(res) return False # same zonefile we put? if res['response']['zonefile'] != zonefile_txt: res['test'] = 'mismatched zonefile, expected\n{}\n'.format( zonefile_txt) print json.dumps(res) return False
def scenario(wallets, **kw): global synchronized, value_hash import blockstack_integration_tests.atlas_network as atlas_network 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) # set up RPC daemon 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']) # register 10 names for i in xrange(0, 10): res = testlib.blockstack_name_preorder("foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) for i in xrange(0, 10): res = testlib.blockstack_name_register("foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) # make 10 empty zonefiles and propagate them for i in xrange(0, 10): data_pubkey = virtualchain.BitcoinPrivateKey( wallet_keys['data_privkey']).public_key().to_hex() empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)]) empty_zonefile_str = blockstack_zones.make_zone_file(empty_zonefile) value_hash = blockstack_client.hash_zonefile(empty_zonefile) res = testlib.blockstack_name_update("foo_{}.test".format(i), value_hash, wallets[3].privkey) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) # propagate res = testlib.blockstack_cli_sync_zonefile( 'foo_{}.test'.format(i), zonefile_string=empty_zonefile_str) if 'error' in res: print json.dumps(res) return False # start up an atlas network with 16 peers, 8 of which will be active at once. # every second, have one peer come online, and one peer go offline. # have them all start out knowing about the same seed node. atlas_nodes = [ 17000, 17001, 17002, 17003, 17004, 17005, 17006, 17007, 17008, 17009, 17010, 17011, 17012, 17013, 17014, 17015, 17016 ] atlas_topology = {} for i in xrange(0, 9): atlas_topology[atlas_nodes[i]] = [16264] for i in xrange(9, len(atlas_nodes)): atlas_topology[atlas_nodes[i]] = [17008] atlas_topology[atlas_nodes[-1]].append(16264) # put the seed after the first four all_peers = atlas_nodes[:4] + [16264] + atlas_nodes[4:] time_start = int(time.time()) + 60 def churn_drop(src_hostport, dest_hostport): if src_hostport is None: return 0.0 src_host, src_port = blockstack_client.config.url_to_host_port( src_hostport) dest_host, dest_port = blockstack_client.config.url_to_host_port( dest_hostport) now = int(time.time()) offset = (now - time_start) % len(all_peers) sample = all_peers + all_peers active_range = sample[offset:offset + 8] print "Active range: %s, request (%s --> %s)" % (active_range, src_port, dest_port) if src_port not in active_range: # dead return 1.0 if dest_port not in active_range: # dead return 1.0 return 0.0 network_des = atlas_network.atlas_network_build( atlas_nodes, atlas_topology, {}, os.path.join(testlib.working_dir(**kw), "atlas_network")) atlas_network.atlas_network_start(network_des, drop_probability=churn_drop) print "Waiting 60 seconds for the altas peers to catch up" time.sleep(60.0) # wait at most 30 seconds for atlas network to converge synchronized = False for i in xrange(0, 30): atlas_network.atlas_print_network_state(network_des) if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block(**kw) - 1, 1): print "Synchronized!" synchronized = True break else: time.sleep(1.0) # shut down atlas_network.atlas_network_stop(network_des) return synchronized
def 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 scenario( wallets, **kw ): global synchronized import blockstack_integration_tests.atlas_network as atlas_network 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 ) # set up RPC daemon 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'] ) # register 10 names for i in xrange(0, 10): res = testlib.blockstack_name_preorder( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) for i in xrange(0, 10): res = testlib.blockstack_name_register( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # start up a simple Atlas test network with two nodes: the main one doing the test, and a subordinate one that treats it as a seed peer. network_des = atlas_network.atlas_network_build( [17000], {17000: [16264]}, {}, os.path.join( testlib.working_dir(**kw), "atlas_network" )) atlas_network.atlas_network_start( network_des ) time.sleep(5.0) # make 10 empty zonefiles and propagate them for i in xrange(0, 10): data_pubkey = virtualchain.BitcoinPrivateKey(wallet_keys['data_privkey']).public_key().to_hex() empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)] ) empty_zonefile_str = blockstack_zones.make_zone_file( empty_zonefile ) value_hash = blockstack_client.hash_zonefile( empty_zonefile ) res = testlib.blockstack_name_update( "foo_{}.test".format(i), value_hash, wallets[3].privkey ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # propagate res = testlib.blockstack_cli_sync_zonefile('foo_{}.test'.format(i), zonefile_string=empty_zonefile_str) if 'error' in res: print json.dumps(res) return False # wait at most 10 seconds for atlas network to converge synchronized = False for i in xrange(0, 10): atlas_network.atlas_print_network_state( network_des ) if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block( **kw ) - 1, 1 ): print "Synchronized!" synchronized = True break else: time.sleep(1.0) # shut down atlas_network.atlas_network_stop( network_des ) return synchronized
def scenario( wallets, **kw ): global synchronized, value_hash import blockstack_integration_tests.atlas_network as atlas_network 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 ) # set up RPC daemon 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'] ) # register 10 names for i in xrange(0, 10): res = testlib.blockstack_name_preorder( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) for i in xrange(0, 10): res = testlib.blockstack_name_register( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # make 10 empty zonefiles and propagate them for i in xrange(0, 10): data_pubkey = virtualchain.BitcoinPrivateKey(wallet_keys['data_privkey']).public_key().to_hex() empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)] ) empty_zonefile_str = blockstack_zones.make_zone_file( empty_zonefile ) value_hash = blockstack_client.hash_zonefile( empty_zonefile ) res = testlib.blockstack_name_update( "foo_{}.test".format(i), value_hash, wallets[3].privkey ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # propagate res = testlib.blockstack_cli_sync_zonefile('foo_{}.test'.format(i), zonefile_string=empty_zonefile_str) if 'error' in res: print json.dumps(res) return False # start up an atlas network with 16 peers, 8 of which will be active at once. # every second, have one peer come online, and one peer go offline. # have them all start out knowing about the same seed node. atlas_nodes = [17000, 17001, 17002, 17003, 17004, 17005, 17006, 17007, 17008, 17009, 17010, 17011, 17012, 17013, 17014, 17015, 17016] atlas_topology = {} for i in xrange(0, 9): atlas_topology[atlas_nodes[i]] = [16264] for i in xrange(9, len(atlas_nodes)): atlas_topology[atlas_nodes[i]] = [17008] atlas_topology[atlas_nodes[-1]].append( 16264 ) # put the seed after the first four all_peers = atlas_nodes[:4] + [16264] + atlas_nodes[4:] time_start = int(time.time()) + 60 def churn_drop(src_hostport, dest_hostport): if src_hostport is None: return 0.0 src_host, src_port = blockstack_client.config.url_to_host_port( src_hostport ) dest_host, dest_port = blockstack_client.config.url_to_host_port( dest_hostport ) now = int(time.time()) # offset = (now - time_start) % len(all_peers) offset = now % len(all_peers) sample = all_peers + all_peers active_range = sample[offset: offset + 8] print "Active range: %s, request (%s --> %s)" % (active_range, src_port, dest_port) if src_port not in active_range: # dead return 1.0 if dest_port not in active_range: # dead return 1.0 return 0.0 network_des = atlas_network.atlas_network_build( atlas_nodes, atlas_topology, {}, os.path.join( testlib.working_dir(**kw), "atlas_network" ) ) atlas_network.atlas_network_start( network_des, drop_probability=churn_drop ) print "Waiting 120 seconds for the altas peers to catch up" time.sleep(120.0) # wait at most 30 seconds for atlas network to converge synchronized = False for i in xrange(0, 30): atlas_network.atlas_print_network_state( network_des ) if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block( **kw ) - 1, 1 ): print "Synchronized!" synchronized = True break else: time.sleep(1.0) # shut down atlas_network.atlas_network_stop( network_des ) return synchronized
def scenario(wallets, **kw): global synchronized import blockstack_integration_tests.atlas_network as atlas_network 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) # set up RPC daemon 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']) # register 10 names for i in xrange(0, 10): res = testlib.blockstack_name_preorder("foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) for i in xrange(0, 10): res = testlib.blockstack_name_register("foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) # start up a simple Atlas test network with two nodes: the main one doing the test, and a subordinate one that treats it as a seed peer. network_des = atlas_network.atlas_network_build( [17000], {17000: [16264]}, {}, os.path.join(testlib.working_dir(**kw), "atlas_network")) atlas_network.atlas_network_start(network_des) time.sleep(5.0) # make 10 empty zonefiles and propagate them for i in xrange(0, 10): data_pubkey = virtualchain.BitcoinPrivateKey( wallet_keys['data_privkey']).public_key().to_hex() empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)]) empty_zonefile_str = blockstack_zones.make_zone_file(empty_zonefile) value_hash = blockstack_client.hash_zonefile(empty_zonefile) res = testlib.blockstack_name_update("foo_{}.test".format(i), value_hash, wallets[3].privkey) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) # propagate res = testlib.blockstack_cli_sync_zonefile( 'foo_{}.test'.format(i), zonefile_string=empty_zonefile_str) if 'error' in res: print json.dumps(res) return False # wait at most 10 seconds for atlas network to converge synchronized = False for i in xrange(0, 10): atlas_network.atlas_print_network_state(network_des) if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block(**kw) - 1, 1): print "Synchronized!" synchronized = True break else: time.sleep(1.0) # shut down atlas_network.atlas_network_stop(network_des) return synchronized
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 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 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 ) config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None) config_dir = os.path.dirname(config_path) conf = blockstack_client.get_config(config_path) assert conf api_pass = conf['api_password'] # make sure we can do REST calls res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/pending', None, api_pass=api_pass ) if 'error' in res: res['test'] = 'Failed to get queues' print json.dumps(res) return False # make sure we can do REST calls with different app names and user names res = testlib.blockstack_REST_call('GET', '/v1/blockchains/bitcoin/pending', None, api_pass=api_pass ) if 'error' in res: res['test'] = 'Failed to get queues' print json.dumps(res) return False # can we even get to the wallet? res = testlib.blockstack_REST_call('POST', '/v1/wallet/balance', None, api_pass=api_pass, data={'address': wallets[4].addr, 'amount': 100000} ) if res['http_status'] != 200: res['test'] = 'failed to transfer funds' # make zonefile for recipient driver_urls = blockstack_client.storage.make_mutable_data_urls('foo.test', use_only=['dht', 'disk']) zonefile = blockstack_client.zonefile.make_empty_zonefile('foo.test', wallets[4].pubkey_hex, urls=driver_urls) zonefile_txt = blockstack_zones.make_zone_file( zonefile, origin='foo.test', ttl=3600 ) # register the name bar.test, with min 3 confirmations on its UTXOs data = { 'name': 'bar.test', 'zonefile': zonefile_txt, 'owner_address': wallets[4].addr, 'min_confs': 3 } # should fail res = testlib.blockstack_REST_call('POST', '/v1/names', None, api_pass=api_pass, data=data) if res['http_status'] == 200: res['test'] = 'succeeded in sending bar.test' print json.dumps(res) error = True return False # wait for confirmations for i in xrange(0, 3): testlib.next_block( **kw ) # should succeed res = testlib.blockstack_REST_call('POST', '/v1/names', None, api_pass=api_pass, data=data) if 'error' in res or 'error' in res['response']: res['test'] = 'failed to send bar.test' print json.dumps(res) error = True return False # wait for update to get confirmed for i in xrange(0, 48): if i % 12 == 0: print "waiting for RPC daemon to catch up" time.sleep(10) testlib.next_block( **kw ) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", None, api_pass=api_pass) if 'error' in res: res['test'] = 'Failed to query name' print json.dumps(res) error = True return False if res['http_status'] != 200: res['test'] = 'HTTP status {}, response = {}'.format(res['http_status'], res['response']) print json.dumps(res) error = True return False # should now be registered if res['response']['status'] != 'registered': print "register not complete" print json.dumps(res) return False
def 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 scenario(wallets, **kw): global synchronized, value_hash import blockstack_integration_tests.atlas_network as atlas_network 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) # set up RPC daemon 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']) # register 10 names for i in xrange(0, 10): res = testlib.blockstack_name_preorder("foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) for i in xrange(0, 10): res = testlib.blockstack_name_register("foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) # start up an Atlas test network with 9 nodes: the main one doing the test, and 8 subordinate ones that treat it as a seed peer # organize nodes into a linear chain: node n is neighbor to n-1 and n+1, with the seed at one end. # nodes cannot talk to anyone else. atlas_nodes = [17000, 17001, 17002, 17003, 17004, 17005, 17006, 17007] atlas_topology = {} atlas_topology[17000] = [16264, 17001] atlas_topology[17007] = [17006] for i in xrange(1, len(atlas_nodes) - 1): atlas_topology[atlas_nodes[i]] = [ atlas_nodes[i - 1], atlas_nodes[i + 1] ] def chain_drop(src_hostport, dest_hostport): if src_hostport is None: return 0.0 src_host, src_port = blockstack_client.config.url_to_host_port( src_hostport) dest_host, dest_port = blockstack_client.config.url_to_host_port( dest_hostport) if (src_port == 16264 and dest_port == 17000) or (src_port == 17000 and dest_port == 16264): # seed end of the chain return 0.0 if abs(src_port - dest_port) <= 1: # chain link return 0.0 # drop otherwise return 1.0 network_des = atlas_network.atlas_network_build( atlas_nodes, atlas_topology, {}, os.path.join(testlib.working_dir(**kw), "atlas_network")) atlas_network.atlas_network_start(network_des, drop_probability=chain_drop) print "Waiting 25 seconds for the altas peers to catch up" time.sleep(25.0) # make 10 empty zonefiles and propagate them for i in xrange(0, 10): data_pubkey = virtualchain.BitcoinPrivateKey( wallet_keys['data_privkey']).public_key().to_hex() empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)]) empty_zonefile_str = blockstack_zones.make_zone_file(empty_zonefile) value_hash = blockstack_client.hash_zonefile(empty_zonefile) res = testlib.blockstack_name_update("foo_{}.test".format(i), value_hash, wallets[3].privkey) if 'error' in res: print json.dumps(res) return False testlib.next_block(**kw) # propagate res = testlib.blockstack_cli_sync_zonefile( 'foo_{}.test'.format(i), zonefile_string=empty_zonefile_str) if 'error' in res: print json.dumps(res) return False # wait at most 30 seconds for atlas network to converge synchronized = False for i in xrange(0, 30): atlas_network.atlas_print_network_state(network_des) if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block(**kw) - 1, 1): print "Synchronized!" sys.stdout.flush() synchronized = True break else: time.sleep(1.0) # shut down atlas_network.atlas_network_stop(network_des) if not synchronized: print "Not synchronized" sys.stdout.flush() return synchronized
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, 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 ) 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, 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 synchronized, value_hash import blockstack_integration_tests.atlas_network as atlas_network 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 ) # set up RPC daemon 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'] ) # register 10 names for i in xrange(0, 10): res = testlib.blockstack_name_preorder( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) for i in xrange(0, 10): res = testlib.blockstack_name_register( "foo_{}.test".format(i), wallets[2].privkey, wallets[3].addr ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # start up an Atlas test network with 9 nodes: the main one doing the test, and 8 subordinate ones that treat it as a seed peer # organize nodes into a linear chain: node n is neighbor to n-1 and n+1, with the seed at one end. # nodes cannot talk to anyone else. atlas_nodes = [17000, 17001, 17002, 17003, 17004, 17005, 17006, 17007] atlas_topology = {} atlas_topology[17000] = [16264, 17001] atlas_topology[17007] = [17006] for i in xrange(1, len(atlas_nodes)-1): atlas_topology[atlas_nodes[i]] = [atlas_nodes[i-1], atlas_nodes[i+1]] def chain_drop(src_hostport, dest_hostport): if src_hostport is None: return 0.0 src_host, src_port = blockstack_client.config.url_to_host_port( src_hostport ) dest_host, dest_port = blockstack_client.config.url_to_host_port( dest_hostport ) if (src_port == 16264 and dest_port == 17000) or (src_port == 17000 and dest_port == 16264): # seed end of the chain return 0.0 if abs(src_port - dest_port) <= 1: # chain link return 0.0 # drop otherwise return 1.0 network_des = atlas_network.atlas_network_build( atlas_nodes, atlas_topology, {}, os.path.join( testlib.working_dir(**kw), "atlas_network" ) ) atlas_network.atlas_network_start( network_des, drop_probability=chain_drop ) print "Waiting 25 seconds for the altas peers to catch up" time.sleep(25.0) # make 10 empty zonefiles and propagate them for i in xrange(0, 10): data_pubkey = virtualchain.BitcoinPrivateKey(wallet_keys['data_privkey']).public_key().to_hex() empty_zonefile = blockstack_client.zonefile.make_empty_zonefile( "foo_{}.test".format(i), data_pubkey, urls=["file:///tmp/foo_{}.test".format(i)] ) empty_zonefile_str = blockstack_zones.make_zone_file( empty_zonefile ) value_hash = blockstack_client.hash_zonefile( empty_zonefile ) res = testlib.blockstack_name_update( "foo_{}.test".format(i), value_hash, wallets[3].privkey ) if 'error' in res: print json.dumps(res) return False testlib.next_block( **kw ) # propagate res = testlib.blockstack_cli_sync_zonefile('foo_{}.test'.format(i), zonefile_string=empty_zonefile_str) if 'error' in res: print json.dumps(res) return False # wait at most 30 seconds for atlas network to converge synchronized = False for i in xrange(0, 30): atlas_network.atlas_print_network_state( network_des ) if atlas_network.atlas_network_is_synchronized( network_des, testlib.last_block( **kw ) - 1, 1 ): print "Synchronized!" sys.stdout.flush() synchronized = True break else: time.sleep(1.0) # shut down atlas_network.atlas_network_stop( network_des ) if not synchronized: print "Not synchronized" sys.stdout.flush() return synchronized
def scenario( wallets, **kw ): global zonefile_hash 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 ) wallet = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[2].privkey, wallets[3].privkey, wallets[4].privkey ) resp = testlib.blockstack_cli_register( "foo.test", "0123456789abcdef" ) if 'error' in resp: print >> sys.stderr, json.dumps(resp, indent=4, sort_keys=True) return False # wait for the preorder to get confirmed for i in xrange(0, 12): testlib.next_block( **kw ) # wait for the poller to pick it up print >> sys.stderr, "Waiting 10 seconds for the backend to submit the register" time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 12): # warn the serialization checker that this changes behavior from 0.13 print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block( **kw ) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge registration" time.sleep(10) # wait for initial update to get confirmed for i in xrange(0, 12): # warn the serialization checker that this changes behavior from 0.13 print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block( **kw ) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge update" time.sleep(10) # store a new zonefile data_pubkey = wallet['data_pubkey'] zonefile = blockstack_client.user.make_empty_user_zonefile( "foo.test", data_pubkey ) assert blockstack_client.user.put_immutable_data_zonefile( zonefile, "testdata", blockstack_client.get_data_hash("testdata") ) zonefile_txt = blockstack_zones.make_zone_file( zonefile ) zonefile_hash = blockstack_client.storage.get_zonefile_data_hash( zonefile_txt ) print >> sys.stderr, "\n\nzonefile hash: %s\nzonefile:\n%s\n\n" % (zonefile_hash, zonefile_txt) # will store to queue test_proxy = testlib.make_proxy() config_path = test_proxy.config_path conf = blockstack_client.config.get_config(config_path) queuedb_path = conf['queue_path'] # update the zonefile hash, but not the zonefile. resp = testlib.blockstack_cli_set_zonefile_hash( "foo.test", zonefile_hash ) if 'error' in resp: print >> sys.stderr, "\nFailed to set zonefile hash: %s\n" % resp return False txhash = resp['transaction_hash'] for i in xrange(0, 12): # warn the serialization checker that this changes behavior from 0.13 print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block( **kw ) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge update" time.sleep(10) # stop endpoint print >> sys.stderr, "\nstopping RPC daemon\n" config_dir = os.path.dirname(test_proxy.config_path) blockstack_client.rpc.local_rpc_stop(config_dir=config_dir) time.sleep(3) # store to queue res = blockstack_client.backend.queue.queue_append("update", "foo.test", txhash, payment_address=wallets[2].addr, owner_address=wallets[3].addr, config_path=test_proxy.config_path, zonefile_data=zonefile_txt, zonefile_hash=zonefile_hash, path=queuedb_path ) # verify that we can sync the zonefile, using the in-queue zonefile resp = testlib.blockstack_cli_sync_zonefile( "foo.test" ) if 'error' in resp: print >> sys.stderr, "\nfailed to sync zonefile: %s\n" % resp return False blockstack_client.backend.queue.queuedb_remove("update", "foo.test", txhash, path=queuedb_path ) print >> sys.stderr, "\nstarting RPC daemon\n" blockstack_client.actions.start_rpc_endpoint(config_dir, password="******") time.sleep(3) # store a new zonefile zonefile = blockstack_client.user.make_empty_user_zonefile( "foo.test", data_pubkey ) blockstack_client.user.put_immutable_data_zonefile( zonefile, "testdata2", blockstack_client.get_data_hash("testdata") ) zonefile_txt = blockstack_zones.make_zone_file( zonefile ) zonefile_hash = blockstack_client.storage.get_zonefile_data_hash( zonefile_txt ) # store locally res = blockstack_client.profile.store_name_zonefile("foo.test", zonefile, None, storage_drivers=['disk']) if 'error' in res: print >> sys.stderr, "\nFailed to store zonefile: %s\n" % res return False # update the zonefile hash, but not the zonefile. resp = testlib.blockstack_cli_set_zonefile_hash( "foo.test", zonefile_hash ) if 'error' in resp: print >> sys.stderr, "\nFailed to set zonefile hash: %s\n" % resp return False for i in xrange(0, 12): # warn the serialization checker that this changes behavior from 0.13 print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block( **kw ) # verify that we can sync the zonefile, using the on-disk zonefile resp = testlib.blockstack_cli_sync_zonefile( "foo.test" ) if 'error' in resp: print >> sys.stderr, "update error: %s" % resp['error'] return False # wait for it to go through for i in xrange(0, 12): testlib.next_block( **kw ) print >> sys.stderr, "Waiting 10 seconds for the backend to acknowedge the update" time.sleep(10)