def _query_subdomains(subdomain_names, expected_zonefiles, expected_sequence): # query each subdomain. Should get the latest for (fqn, expected_zonefile) in zip(subdomain_names, expected_zonefiles): res = client.get_name_record(fqn, hostport='http://localhost:16264') if 'error' in res: print res print 'failed to query {}'.format(fqn) return False if res['sequence'] != expected_sequence: print 'wrong sequence; expected {}'.format(expected_sequence) print res return False if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False return True
def _query_subdomains(): # query each subdomain. Should get the latest proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False return True
def check(state_engine): global zonefile_hash # not revealed, but ready ns = state_engine.get_namespace_reveal("test") if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace("test") if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name("foo.test") if name_rec is None: print "name does not exist" return False # owned by owner_address = wallets[3].addr if name_rec['address'] != owner_address or name_rec[ 'sender'] != pybitcoin.make_pay_to_address_script(owner_address): print "sender is wrong" return False # value hash if name_rec['value_hash'] != zonefile_hash: print "wrong zonefile hash: %s != %s" % (name_rec['value_hash'], zonefile_hash) return False # replicated? zonefile = testlib.blockstack_get_zonefile(zonefile_hash) if 'error' in zonefile: print "zonefile error: %s" % zonefile['error'] return False # right hash? if blockstack_client.hash_zonefile(zonefile) != zonefile_hash: print "wrong zonefile: %s != %s" % ( blockstack_client.hash_zonefile(zonefile), zonefile_hash) return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps( queue_info, indent=4, sort_keys=True) return False return True
def check( state_engine ): # not revealed, but ready ns = state_engine.get_namespace_reveal( "test" ) if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace( "test" ) if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False names = ['foo.test', 'bar.test', 'baz.test', 'goo.test'] addresses = [wallets[2].addr, wallets[3].addr, wallets[4].addr, wallets[5].addr] zonefiles = ["Hello foo.test!", "Hello bar.test!", "Hello baz.test!", "Hello goo.test!"] for i in xrange(0, len(names)): name = names[i] owner_address = addresses[i] zonefile = zonefiles[i] # registered name_rec = state_engine.get_name( name ) if name_rec is None: print "name {} does not exist".format(name) return False # owned by the right address if name_rec['address'] != owner_address or name_rec['sender'] != virtualchain.make_payment_script(owner_address): print "sender is wrong for {}".format(name) return False # has the right zone file zf = testlib.blockstack_get_zonefile(name_rec['value_hash'], parse=False) if zf is None: print "no zonefile for {}".format(name) return False if zf != zonefile: print "zonefile mismatch: expected {}, got {}".format(zonefile, zf) return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps(queue_info, indent=4, sort_keys=True) return False return True
def check( state_engine ): global zonefile_hash # not revealed, but ready ns = state_engine.get_namespace_reveal( "test" ) if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace( "test" ) if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name( "foo.test" ) if name_rec is None: print "name does not exist" return False # owned by owner_address = wallets[3].addr if name_rec['address'] != owner_address or name_rec['sender'] != virtualchain.make_payment_script(owner_address): print "sender is wrong" return False # value hash if name_rec['value_hash'] != zonefile_hash: print "wrong zonefile hash: %s != %s" % (name_rec['value_hash'], zonefile_hash) return False # replicated? zonefile = testlib.blockstack_get_zonefile( zonefile_hash ) if 'error' in zonefile: print "zonefile error: %s" % zonefile['error'] return False # right hash? if blockstack_client.hash_zonefile( zonefile ) != zonefile_hash: print "wrong zonefile: %s != %s" % (blockstack_client.hash_zonefile(zonefile), zonefile_hash) return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps(queue_info, indent=4, sort_keys=True) return False return True
def check( state_engine ): global zonefile_hash # not revealed, but ready ns = state_engine.get_namespace_reveal( "test" ) if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace( "test" ) if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name( "foo.test" ) if name_rec is None: print "name does not exist" return False # owned by owner_address = wallets[4].addr if name_rec['address'] != owner_address or name_rec['sender'] != pybitcoin.make_pay_to_address_script(owner_address): print "sender is wrong" return False # value hash if name_rec['value_hash'] != zonefile_hash: print "wrong zonefile hash: %s != %s" % (name_rec['value_hash'], zonefile_hash) return False # replicated? zonefile = testlib.blockstack_get_zonefile( zonefile_hash ) if 'error' in zonefile: print "zonefile error: %s" % zonefile['error'] return False # right hash? if blockstack_client.hash_zonefile( zonefile ) != zonefile_hash: print "wrong zonefile: %s != %s" % (blockstack_client.hash_zonefile(zonefile), zonefile_hash) return False # latest key? if not zonefile.has_key("txt"): print "no txt:\n%s" % json.dumps(zonefile, indent=4, sort_keys=True) return False if len(zonefile['txt']) != 2: print "wrong number of txt records:\n%s" % json.dumps(zonefile, indent=4, sort_keys=True) return False for txtrec in zonefile['txt']: if txtrec['name'] == 'pubkey': if new_data_pubkey not in txtrec['txt']: print "wrong pubkey:\n%s" % json.dumps(zonefile, indent=4, sort_keys=True) print "missing %s" % new_data_pubkey return False # doesn't show up in listing names_owned = testlib.blockstack_rpc_names() if 'error' in names_owned: print "rpc names: %s" % names_owned['error'] return False # we updated the wallet; we should own one name if len(names_owned['names_owned']) != 1: print "owned: %s" % names_owned['names_owned'] return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps(queue_info, indent=4, sort_keys=True) return False return True
def check(state_engine): # not revealed, but ready ns = state_engine.get_namespace_reveal("test") if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace("test") if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False names = ['foo.test', 'bar.test', 'baz.test', 'goo.test'] addresses = [ wallets[2].addr, wallets[3].addr, wallets[4].addr, wallets[5].addr ] zonefiles = [ "Hello foo.test!", "Hello bar.test!", "Hello baz.test!", "Hello goo.test!" ] for i in xrange(0, len(names)): name = names[i] owner_address = addresses[i] zonefile = zonefiles[i] # registered name_rec = state_engine.get_name(name) if name_rec is None: print "name {} does not exist".format(name) return False # owned by the right address if name_rec['address'] != owner_address or name_rec[ 'sender'] != virtualchain.make_payment_script(owner_address): print "sender is wrong for {}".format(name) return False # has the right zone file zf = testlib.blockstack_get_zonefile(name_rec['value_hash'], parse=False) if zf is None: print "no zonefile for {}".format(name) return False if zf != zonefile: print "zonefile mismatch: expected {}, got {}".format(zonefile, zf) return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps( queue_info, indent=4, sort_keys=True) return False return True
def check(state_engine): # not revealed, but ready ns = state_engine.get_namespace_reveal("test") if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace("test") if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False for i in xrange(0, 5): # registered name_rec = state_engine.get_name("foo_%s.test" % i) if name_rec is None: print "name does not exist" return False # owned by owner_address = wallets[3].addr if name_rec['address'] != owner_address or name_rec[ 'sender'] != pybitcoin.make_pay_to_address_script( owner_address): print "sender is wrong" return False # have a zonefile zonefile = testlib.blockstack_get_zonefile(name_rec['value_hash']) if zonefile is None or 'error' in zonefile: if zonefile is not None: print "zonefile lookup error: %s" % zonefile['error'] else: print "no zonefile returned" return False # hashes to this zonefile if blockstack_client.hash_zonefile(zonefile) != name_rec['value_hash']: print "wrong zonefile: %s != %s" % ( blockstack_client.hash_zonefile(zonefile), name_rec['value_hash']) return False # verify that the profile is there profile = testlib.blockstack_get_profile("foo_%s.test" % i) if profile is None or 'error' in profile: if profile is None: print "no profile returned" else: print "profile lookup error: %s" % profile['error'] return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps( queue_info, indent=4, sort_keys=True) return False return True
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 ) testlib.blockstack_name_preorder( "foo1.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo2.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo3.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo4.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo5.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo6.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo7.test", wallets[2].privkey, wallets[3].addr ) testlib.next_block( **kw ) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' zonefiles = { 'foo1.test': zf_template.format('foo1.test', subdomains.make_subdomain_txt('bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format('foo2.test', subdomains.make_subdomain_txt('bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format('foo3.test', subdomains.make_subdomain_txt('bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.blockstack_name_register( "foo4.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register( "foo5.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register( "foo6.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register( "foo7.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.next_block( **kw ) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # update and transfer, but if i % 2 == 0, transfer to a different address # use a different domain name in each case. # verify that only transfers on the creator domain are valid. wallet_schedule = [ (4, 0), # won't be accepted due to domain independence (4, 1), # will be accepted (1, 2), # won't be accepted due to domain independence (1, 3), # will be accepted ] sequence_schedule = [ 1, # won't be accepted due to domain independence 1, # will be accepted 2, # won't be accepted due to domain independence 2, # will be accepted ] expected_zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format(4) for i in range(0, 4): zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format(i+1) if i % 2 == 0: names = [ 'foo{}.test'.format(i+4), 'foo{}.test'.format(i+4), 'foo{}.test'.format(i+4), ] else: names = [ 'foo1.test', 'foo2.test', 'foo3.test', ] k = wallet_schedule[i][0] k2 = wallet_schedule[i][1] s = sequence_schedule[i] zonefiles = { 'foo1.test': zf_template.format(names[0], subdomains.make_subdomain_txt('bar.foo1.test', names[0], wallets[k2].addr, s, zf_template.format('bar.foo1.test', zf_default_url), wallets[k].privkey)), 'foo2.test': zf_template.format(names[1], subdomains.make_subdomain_txt('bar.foo2.test', names[1], wallets[k2].addr, s, zf_template.format('bar.foo2.test', zf_default_url), wallets[k].privkey)), 'foo3.test': zf_template.format(names[2], subdomains.make_subdomain_txt('bar.foo3.test', names[2], wallets[k2].addr, s, zf_template.format('bar.foo3.test', zf_default_url), wallets[k].privkey)), } testlib.blockstack_name_update(names[0], storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update(names[1], storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update(names[2], storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # kick off subdomain indexing testlib.next_block(**kw) # query each subdomain proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False if res['sequence'] != 2: print 'wrong sequence' print res return False if virtualchain.address_reencode(str(res['address'])) != virtualchain.address_reencode(wallets[3].addr): print 'wrong owner' print res return False expected_zonefile = zf_template.format(fqn, expected_zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # there should only be three history items per name hist = client.get_name_record(fqn, proxy=proxy, include_history=True) if 'error' in hist: print res return False if len(hist['history']) != 3: print 'wrong history length' print res return False # reindex assert testlib.check_subdomain_db(**kw)
def scenario( wallets, **kw ): # disable subdomains at first subdomaindb_path = None blockstack_opts = blockstack.lib.config.get_blockstack_opts() assert 'subdomaindb_path' in blockstack_opts subdomaindb_path = blockstack_opts['subdomaindb_path'] del blockstack_opts['subdomaindb_path'] blockstack.lib.config.set_blockstack_opts(blockstack_opts) 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( "foo1.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo2.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo3.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo4.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo5.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo6.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo7.test", wallets[2].privkey, wallets[3].addr ) testlib.next_block( **kw ) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' zonefiles = { 'foo1.test': zf_template.format('foo1.test', subdomains.make_subdomain_txt('bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format('foo2.test', subdomains.make_subdomain_txt('bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format('foo3.test', subdomains.make_subdomain_txt('bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } # register initial subdomains testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.blockstack_name_register( "foo4.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register( "foo5.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register( "foo6.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register( "foo7.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.next_block( **kw ) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # send updates, but only on foo1.test. for i in range(0, 3): zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format(i+1) name = 'foo{}.test'.format(i+4) zonefiles = { 'foo1.test': zf_template.format(name, subdomains.make_subdomain_txt('bar.foo1.test', name, wallets[4].addr, i+1, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format(name, subdomains.make_subdomain_txt('bar.foo2.test', name, wallets[4].addr, i+1, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format(name, subdomains.make_subdomain_txt('bar.foo3.test', name, wallets[4].addr, i+1, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_update(name, storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update(name, storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update(name, storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # subdomains should not exist---we haven't indexed them yet for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, hostport='http://localhost:16264') if 'error' not in res: print 'got a subdomain' print res return False # wait until they exist testlib.next_block(**kw) testlib.next_block(**kw) testlib.next_block(**kw) blockstack_opts['subdomaindb_path'] = subdomaindb_path blockstack.lib.config.set_blockstack_opts(blockstack_opts) testlib.next_block(**kw) # query each subdomain for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, hostport='http://localhost:16264') if 'error' in res: print res return False # domain should be foo6.test if res['domain'] != 'foo6.test': print 'wrong domain' print res return False expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(firstblock=256, **kw)
def check(state_engine): global preorder_info, register_info, update_info, balance_before, balance_after, names_owned_before, names_owned_after, whois, blockchain_record, deposit_info, price_info global blockchain_history, zonefile_info, all_names_info, namespace_names_info, wallet_info, lookup_info, update_history, zonefile_history, names_info # not revealed, but ready ns = state_engine.get_namespace_reveal("test") if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace("test") if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name("foo.test") if name_rec is None: print "name does not exist" return False # owned by the right address owner_address = wallets[3].addr if name_rec['address'] != owner_address or name_rec[ 'sender'] != pybitcoin.make_pay_to_address_script(owner_address): print "sender is wrong" return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps( queue_info, indent=4, sort_keys=True) return False # have an update hash if 'value_hash' not in name_rec or name_rec.get('value_hash', None) is None: print "No value hash" return False # have a zonefile zonefile = testlib.blockstack_get_zonefile(name_rec['value_hash']) if zonefile is None or 'error' in zonefile: if zonefile is not None: print "zonefile lookup error: %s" % zonefile['error'] else: print "no zonefile returned" return False # hashes to this zonefile if blockstack_client.hash_zonefile(zonefile) != name_rec['value_hash']: print "wrong zonefile: %s != %s" % ( blockstack_client.hash_zonefile(zonefile), name_rec['value_hash']) return False # verify that the profile is there profile = testlib.blockstack_get_profile("foo.test") if profile is None or 'error' in profile: if profile is None: print "no profile returned" else: print "profile lookup error: %s" % profile['error'] return False # check queue operations for queue_type, queue_state in [("preorder", preorder_info), ("register", register_info), ("update", update_info)]: if not queue_state.has_key('queues'): print "missing queues:\n%s" % json.dumps( queue_state, indent=4, sort_keys=True) return False for k in ['name', 'confirmations', 'tx_hash']: for q in queue_state['queues'][queue_type]: if not q.has_key(k): print "missing key %s\n%s" % ( k, json.dumps(queue_state, indent=4, sort_keys=True)) return False if q['name'] != 'foo.test': print "wrong name: %s" % queue_state['name'] return False # check price for k in [ 'preorder_tx_fee', 'register_tx_fee', 'update_tx_fee', 'total_estimated_cost', 'name_price' ]: if not price_info.has_key(k): print "bad price info (missing %s):\n%s" % ( k, json.dumps(price_info, indent=4, sort_keys=True)) return False # deposit info if not deposit_info.has_key( 'address') or deposit_info['address'] != wallets[2].addr: print "bad deposit info:\n%s" % json.dumps( deposit_info, indent=4, sort_keys=True) return False # whois info for k in [ 'block_preordered_at', 'block_renewed_at', 'last_transaction_id', 'owner_address', 'owner_script', 'expire_block', 'has_zonefile', 'zonefile_hash' ]: if not whois.has_key(k): print "bad whois: missing %s\n%s" % ( k, json.dumps(whois, indent=4, sort_keys=True)) return False # balance for balance_info in [balance_before, balance_after]: for k in ['total_balance', 'addresses']: if not balance_info.has_key(k): print "missing '%s'\n%s" % ( k, json.dumps(balance_info, indent=4, sort_keys=True)) return False # name listing if len(names_owned_before) != 0: print "owned before: %s" % names_owned_before return False if len(names_owned_after) != 1 or names_owned_after[0] != 'foo.test': print "owned after: %s" % names_owned_after return False # blockchain record for k in [ 'name', 'op', 'op_fee', 'opcode', 'vtxindex', 'txid', 'value_hash', 'sender', 'address', 'history' ]: if not blockchain_record.has_key(k): print "missing %s\n%s" % ( k, json.dumps(blockchain_record, indent=4, sort_keys=True)) return False # blockchain history (should have a preorder, register, and 2 updates) if len(blockchain_history) != 4: print "invalid history\n%s\n" % json.dumps( blockchain_history, indent=4, sort_keys=True) return False block_heights = blockchain_history.keys() block_heights.sort() expected_opcodes = [ 'NAME_PREORDER', 'NAME_REGISTRATION', 'NAME_UPDATE', 'NAME_UPDATE' ] for bh, opcode in zip(block_heights, expected_opcodes): if len(blockchain_history[bh]) != 1: print "invalid history: multiple ops at %s\n%s" % ( bh, json.dumps(blockchain_history, indent=4, sort_keys=True)) return False if blockchain_history[bh][0]['opcode'] != opcode: print "invalid history: expected %s at %s\n%s" % ( opcode, bh, json.dumps(blockchain_history, indent=4, sort_keys=True)) return False # zonefile info if zonefile_info is None or type(zonefile_info) != dict: print "invalid zonefile\n%s\n" % zonefile_info return False if not zonefile_info.has_key('zonefile'): print "missing zonefile\n%s\n" % zonefile_info return False # name query if type(all_names_info) == dict and 'error' in all_names_info: print "error in all_names: %s" % all_names_info return False all_names = all_names_info if len(all_names) != 1 or all_names != ['foo.test']: print "all names: %s" % all_names return False # namespace query if type(namespace_names_info) == dict and 'error' in namespace_names_info: print "error in namesace_names: %s" % namespace_names_info return False namespace_names = namespace_names_info if len(namespace_names) != 1 or namespace_names != ['foo.test']: print "all namespace names: %s" % namespace_names return False # wallet info for k in [ 'payment_privkey', 'owner_privkey', 'data_privkey', 'payment_address', 'owner_address', 'data_pubkey' ]: if not wallet_info.has_key(k): print "missing %s\n%s" % ( k, json.dumps(wallet_info, indent=4, sort_keys=True)) return False # profile info for k in ['profile', 'zonefile']: if not lookup_info.has_key(k): print "missing '%s'\n%s" % ( k, json.dumps(lookup_info, indent=4, sort_keys=True)) return False if lookup_info['zonefile'] != zonefile_info['zonefile']: print "unequal zonefiles:\n%s\n%s" % ( json.dumps(lookup_info['zonefile'], indent=4, sort_keys=True), json.dumps(zonefile_info['zonefile'], indent=4, sort_keys=True)) return False # update history (2 items) if len(update_history ) != 2 or update_history[1] != blockchain_record['value_hash']: print "invalid update history\n%s" % json.dumps( update_history, indent=4, sort_keys=True) return False # zonefile history (expect 2 items) if len(zonefile_history ) != 2 or zonefile_history[1] != zonefile_info['zonefile']: print "invalid zonefile history\n%s" % json.dumps( zonefile_history, indent=4, sort_keys=True) return False # names info if type(names_info) != dict: print "invalid names info: %s" % names_info return False for k in ['names_owned', 'addresses']: if not names_info.has_key(k): print "invalid names info (missing %s): %s" % (k, names_info) return False if len(names_info['addresses']) != 1: print "invalid names info (addresses): %s" % names_info return False if names_info['addresses'][0]['names_owned'] != ['foo.test']: print "invalid names info (names_owned): %s" % names_info return False if names_info['addresses'][0]['address'] != wallets[3].addr: print "invalid names info (addresses.address): %s" % names_info return False # immutable data immutable_data = testlib.blockstack_cli_get_immutable( "foo.test", "hello_world") if 'error' in immutable_data: print "Failed to get immutable data 'hello_world'" print json.dumps(immutable_data, indent=4, sort_keys=True) return False if 'data' not in immutable_data: print "invalid immutable_data: %s" % immutable_data return False if json.loads(immutable_data['data']) != {'hello': 'world'}: print "failed to get immutable data" print 'exected %s, got %s' % ({ 'hello': 'world' }, immutable_data['data']) return False return True
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) testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # send two sequence=1 updates, but withhold the first batch. send the second batch now, and then send the first batch later to confirm # that each subdomain's history gets reorganized. # first sequence=1 update (withheld) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/withheld?index={}"'.format( 1) zf_default_url_reorg = zf_default_url zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 1, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 1, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 1, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } zonefiles_reorg = zonefiles testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) # second sequence=1 update (sent now) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format( 1) zf_default_url_seq1 = zf_default_url zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 1, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 1, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 1, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } zonefiles_seq1 = zonefiles testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # sequence=2 (send now) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format( 1) zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 2, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 2, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 2, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) def _query_subdomains(): # query each subdomain. Should get the latest proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False return True # kick off subdomain indexing testlib.next_block(**kw) assert _query_subdomains() # query each subdomain history. sequence=1 should have test.com, but not 'withheld' for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) proxy = testlib.make_proxy() res = client.get_name_record(fqn, proxy=proxy, include_history=True) if 'error' in res: print res return False # expect zonefile expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # find historic historic_blocks = res['history'].keys() historic_blocks.sort() historic_zfhash = res['history'][str( historic_blocks[1])][0]['value_hash'] # historic zone file (sequence=1) should NOT be withheld zf = testlib.blockstack_get_zonefile(historic_zfhash, parse=False) if not zf: print 'no zone file {} for sequence=1 in atlas'.format( res['value_hash']) return False expected_zonefile = zf_template.format(fqn, zf_default_url_seq1) if zf != expected_zonefile: print 'zonefile mismatch in atlas at sequence=1' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reorg each zonefile's history assert testlib.blockstack_put_zonefile(zonefiles_reorg['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles_reorg['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles_reorg['foo3.test']) # kick off subdomain indexing testlib.next_block(**kw) assert _query_subdomains() # query each subdomain history. sequence=1 should have test.com, but with 'withheld' present in the URL for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) proxy = testlib.make_proxy() res = client.get_name_record(fqn, proxy=proxy, include_history=True) if 'error' in res: print res return False # expect zonefile expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # find historic historic_blocks = res['history'].keys() historic_blocks.sort() historic_zfhash = res['history'][str( historic_blocks[1])][0]['value_hash'] # historic zone file (sequence=1) should NOT be withheld zf = testlib.blockstack_get_zonefile(historic_zfhash, parse=False) if not zf: print 'no zone file {} for sequence=1 in atlas'.format( res['value_hash']) return False expected_zonefile = zf_template.format(fqn, zf_default_url_reorg) if zf != expected_zonefile: print 'zonefile mismatch in atlas at sequence=1' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)
def check( state_engine ): # not revealed, but ready ns = state_engine.get_namespace_reveal( "test" ) if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace( "test" ) if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name( "foo.test" ) if name_rec is None: print "name does not exist" return False # owned by the right address owner_address = wallets[3].addr if name_rec['address'] != owner_address or name_rec['sender'] != virtualchain.make_payment_script(owner_address): print "sender is wrong" print "%s != %s or %s != %s" % (name_rec['address'], owner_address, name_rec['sender'], virtualchain.make_payment_script(owner_address)) return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps(queue_info, indent=4, sort_keys=True) return False # have an update hash if 'value_hash' not in name_rec or name_rec.get('value_hash', None) is None: print "No value hash" return False # have a zonefile zonefile = testlib.blockstack_get_zonefile( name_rec['value_hash'] ) if zonefile is None or 'error' in zonefile: if zonefile is not None: print "zonefile lookup error: %s" % zonefile['error'] else: print "no zonefile returned" return False # hashes to this zonefile if blockstack_client.hash_zonefile( zonefile ) != name_rec['value_hash']: print "wrong zonefile: %s != %s" % (blockstack_client.hash_zonefile(zonefile), name_rec['value_hash']) return False # verify that the profile is there profile = testlib.blockstack_get_profile( "foo.test" ) if profile is None or 'error' in profile: if profile is None: print "no profile returned" else: print "profile lookup error: %s" % profile['error'] return False return True
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) testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.next_block(**kw) # will send these later initial_zonefiles = zonefiles # send updates too for i in range(0, 3): zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format( i + 1) zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, i + 1, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, i + 1, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, i + 1, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # kick off subdomain indexing (nothing should happen) testlib.next_block(**kw) # store directly to Atlas zonefiles dir and wait a few seconds. Atlas should notice that they're here # and queue them for subdomain processing for name in ['foo1.test', 'foo2.test', 'foo3.test']: blockstack.lib.storage.store_atlas_zonefile_data( initial_zonefiles[name], blockstack.lib.get_blockstack_opts()['zonefiles']) print 'wait for atlas to discover that it already has the requisite zone files' time.sleep(10) # now kick it off again testlib.next_block(**kw) # query each subdomain for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, hostport='http://localhost:16264') if 'error' in res: print res return False expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)
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) testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo4.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo5.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo6.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo7.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" subdomain_zonefile_pattern = '$ORIGIN {}\n$TTL 3600\n_https._tcp URI 10 1 "https://raw.githubusercontent.com/bar{}/profile.md' zonefiles = { 'foo1.test': make_subdomain_zone_file('foo1.test', 'bar{}.foo1.test', subdomain_zonefile_pattern, 0, 100, 40960, wallets[4].privkey), 'foo2.test': make_subdomain_zone_file('foo2.test', 'bar{}.foo2.test', subdomain_zonefile_pattern, 0, 100, 40960, wallets[4].privkey), 'foo3.test': make_subdomain_zone_file('foo3.test', 'bar{}.foo3.test', subdomain_zonefile_pattern, 0, 100, 40960, wallets[4].privkey) } # register initial subdomains testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.blockstack_name_register("foo4.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register("foo5.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register("foo6.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register("foo7.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # send updates on different names. for i in range(0, 3): zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format( i + 1) name = 'foo{}.test'.format(i + 4) zonefiles = { 'foo1.test': make_subdomain_zone_file(name, 'bar{}.foo1.test', subdomain_zonefile_pattern, i + 1, 100, 40960, wallets[4].privkey), 'foo2.test': make_subdomain_zone_file(name, 'bar{}.foo2.test', subdomain_zonefile_pattern, i + 1, 100, 40960, wallets[4].privkey), 'foo3.test': make_subdomain_zone_file(name, 'bar{}.foo3.test', subdomain_zonefile_pattern, i + 1, 100, 40960, wallets[4].privkey), } testlib.blockstack_name_update( name, storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( name, storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( name, storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # kick off subdomain indexing testlib.next_block(**kw) # query each subdomain for domain in zonefiles: for i in range(0, 100): fqn = 'bar{}.{}'.format(i, domain) res = client.get_name_record(fqn, hostport='http://localhost:16264') if 'error' in res: print res return False # domain should be foo6.test if res['domain'] != 'foo6.test': print 'wrong domain' print res return False expected_zonefile = subdomain_zonefile_pattern.format(fqn, i) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)
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) testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.next_block(**kw) # whois for i in xrange(1, 4): name = 'foo{}.test'.format(i) res = testlib.blockstack_cli_whois(name) if 'error' in res: print res return False if not res.has_key('zonefile_hash') or res[ 'zonefile_hash'] != storage.get_zonefile_data_hash( zonefiles[name]): print res return False if res['owner_address'] != wallets[3].addr: print res return False # upload zonefile assert testlib.blockstack_put_zonefile(zonefiles[name]) # kick off subdomain indexing testlib.next_block(**kw) # query each subdomain proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)
def check( state_engine ): global preorder_info, register_info, update_info, balance_before, balance_after, names_owned_before, names_owned_after, whois, blockchain_record, deposit_info, price_info global blockchain_history, zonefile_info, all_names_info, namespace_names_info, wallet_info, lookup_info, update_history, zonefile_history, names_info # not revealed, but ready ns = state_engine.get_namespace_reveal( "test" ) if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace( "test" ) if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name( "foo.test" ) if name_rec is None: print "name does not exist" return False # owned by the right address owner_address = wallets[3].addr if name_rec['address'] != owner_address or name_rec['sender'] != pybitcoin.make_pay_to_address_script(owner_address): print "sender is wrong" return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps(queue_info, indent=4, sort_keys=True) return False # have an update hash if 'value_hash' not in name_rec or name_rec.get('value_hash', None) is None: print "No value hash" return False # have a zonefile zonefile = testlib.blockstack_get_zonefile( name_rec['value_hash'] ) if zonefile is None or 'error' in zonefile: if zonefile is not None: print "zonefile lookup error: %s" % zonefile['error'] else: print "no zonefile returned" return False # hashes to this zonefile if blockstack_client.hash_zonefile( zonefile ) != name_rec['value_hash']: print "wrong zonefile: %s != %s" % (blockstack_client.hash_zonefile(zonefile), name_rec['value_hash']) return False # verify that the profile is there profile = testlib.blockstack_get_profile( "foo.test" ) if profile is None or 'error' in profile: if profile is None: print "no profile returned" else: print "profile lookup error: %s" % profile['error'] return False # check queue operations for queue_type, queue_state in [("preorder", preorder_info), ("register", register_info), ("update", update_info)]: if not queue_state.has_key('queues'): print "missing queues:\n%s" % json.dumps(queue_state, indent=4, sort_keys=True) return False for k in ['name', 'confirmations', 'tx_hash']: for q in queue_state['queues'][queue_type]: if not q.has_key(k): print "missing key %s\n%s" % (k, json.dumps(queue_state, indent=4, sort_keys=True)) return False if q['name'] != 'foo.test': print "wrong name: %s" % queue_state['name'] return False # check price for k in ['preorder_tx_fee', 'register_tx_fee', 'update_tx_fee', 'total_estimated_cost', 'name_price']: if not price_info.has_key(k): print "bad price info (missing %s):\n%s" % (k, json.dumps(price_info, indent=4, sort_keys=True)) return False # deposit info if not deposit_info.has_key('address') or deposit_info['address'] != wallets[2].addr: print "bad deposit info:\n%s" % json.dumps(deposit_info, indent=4, sort_keys=True) return False # whois info for k in ['block_preordered_at', 'block_renewed_at', 'last_transaction_id', 'owner_address', 'owner_script', 'expire_block', 'has_zonefile', 'zonefile_hash']: if not whois.has_key(k): print "bad whois: missing %s\n%s" % (k, json.dumps(whois, indent=4, sort_keys=True)) return False # balance for balance_info in [balance_before, balance_after]: for k in ['total_balance', 'addresses']: if not balance_info.has_key(k): print "missing '%s'\n%s" % (k, json.dumps(balance_info, indent=4, sort_keys=True)) return False # name listing if len(names_owned_before) != 0: print "owned before: %s" % names_owned_before return False if len(names_owned_after) != 1 or names_owned_after[0] != 'foo.test': print "owned after: %s" % names_owned_after return False # blockchain record for k in ['name', 'op', 'op_fee', 'opcode', 'vtxindex', 'txid', 'value_hash', 'sender', 'address', 'history']: if not blockchain_record.has_key(k): print "missing %s\n%s" % (k, json.dumps(blockchain_record, indent=4, sort_keys=True)) return False # blockchain history (should have a preorder, register, and 2 updates) if len(blockchain_history) != 4: print "invalid history\n%s\n" % json.dumps(blockchain_history, indent=4, sort_keys=True) return False block_heights = blockchain_history.keys() block_heights.sort() expected_opcodes = ['NAME_PREORDER', 'NAME_REGISTRATION', 'NAME_UPDATE', 'NAME_UPDATE'] for bh, opcode in zip(block_heights, expected_opcodes): if len(blockchain_history[bh]) != 1: print "invalid history: multiple ops at %s\n%s" % (bh, json.dumps(blockchain_history, indent=4, sort_keys=True)) return False if blockchain_history[bh][0]['opcode'] != opcode: print "invalid history: expected %s at %s\n%s" % (opcode, bh, json.dumps(blockchain_history, indent=4, sort_keys=True)) return False # zonefile info if zonefile_info is None or type(zonefile_info) != str: print "invalid zonefile\n%s\n" % zonefile_info return False # name query if type(all_names_info) == dict and 'error' in all_names_info: print "error in all_names: %s" % all_names_info return False all_names = all_names_info if len(all_names) != 1 or all_names != ['foo.test']: print "all names: %s" % all_names return False # namespace query if type(namespace_names_info) == dict and 'error' in namespace_names_info: print "error in namesace_names: %s" % namespace_names_info return False namespace_names = namespace_names_info if len(namespace_names) != 1 or namespace_names != ['foo.test']: print "all namespace names: %s" % namespace_names return False # wallet info for k in ['payment_privkey', 'owner_privkey', 'data_privkey', 'payment_address', 'owner_address', 'data_pubkey']: if not wallet_info.has_key(k): print "missing %s\n%s" % (k, json.dumps(wallet_info, indent=4, sort_keys=True)) return False # profile info for k in ['profile', 'zonefile']: if not lookup_info.has_key(k): print "missing '%s'\n%s" % (k, json.dumps(lookup_info, indent=4, sort_keys=True)) return False if lookup_info['zonefile'] != zonefile_info: print "unequal zonefiles:\n%s\n%s" % (json.dumps(lookup_info['zonefile'], indent=4, sort_keys=True), json.dumps(zonefile_info, indent=4, sort_keys=True)) return False # update history (2 items) if len(update_history) != 2 or update_history[1] != blockchain_record['value_hash']: print "invalid update history\n%s" % json.dumps(update_history, indent=4, sort_keys=True) return False # zonefile history (expect 2 items) if len(zonefile_history) != 2 or zonefile_history[1] != zonefile_info: print "invalid zonefile history\n%s" % json.dumps(zonefile_history, indent=4, sort_keys=True) print "zonefile current:\n%s" % json.dumps(zonefile_info, indent=4, sort_keys=True) return False # names info if type(names_info) != dict: print "invalid names info: %s" % names_info return False for k in ['names_owned', 'addresses']: if not names_info.has_key(k): print "invalid names info (missing %s): %s" % (k, names_info) return False if len(names_info['addresses']) != 1: print "invalid names info (addresses): %s" % names_info return False if names_info['addresses'][0]['names_owned'] != ['foo.test']: print "invalid names info (names_owned): %s" % names_info return False if names_info['addresses'][0]['address'] != wallets[3].addr: print "invalid names info (addresses.address): %s" % names_info return False # immutable data immutable_data = testlib.blockstack_cli_get_immutable( "foo.test", "hello_world" ) if 'error' in immutable_data: print "Failed to get immutable data 'hello_world'" print json.dumps(immutable_data, indent=4, sort_keys=True) return False if 'data' not in immutable_data: print "invalid immutable_data: %s" % immutable_data return False if json.loads(immutable_data['data']) != {'hello': 'world'}: print "failed to get immutable data" print 'exected %s, got %s' % ({'hello': 'world'}, immutable_data['data']) return False return True
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) testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' zf_default_url_initial = zf_default_url zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } initial_zonefiles = zonefiles testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://invalid.com"' zf_default_url_invalid = zf_default_url zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } # send updates for invalid initial subdomain records testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # kick off subdomain indexing. testlib.next_block(**kw) # must all be pending proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if not res['pending']: print 'not pending: {}'.format(fqn) print res return False # broadcast initial zonefiles and re-do subdomain indexing assert testlib.blockstack_put_zonefile(initial_zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(initial_zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(initial_zonefiles['foo3.test']) testlib.next_block(**kw) proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False # right subdomain zonefile expected_zonefile = zf_template.format(fqn, zf_default_url_initial) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)
def check( state_engine ): global zonefile_hash, new_expire_block # not revealed, but ready ns = state_engine.get_namespace_reveal( "test" ) if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace( "test" ) if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name( "foo.test" ) if name_rec is None: print "name does not exist" return False # owned by owner_address = wallets[3].addr if name_rec['address'] != owner_address or name_rec['sender'] != virtualchain.make_payment_script(owner_address): print "sender is wrong" return False # value hash if name_rec['value_hash'] != zonefile_hash: print "wrong zonefile hash: %s != %s" % (name_rec['value_hash'], zonefile_hash) return False # replicated? zonefile = testlib.blockstack_get_zonefile( zonefile_hash ) if 'error' in zonefile: print "zonefile error: %s" % zonefile['error'] return False # right hash? if blockstack_client.hash_zonefile( zonefile ) != zonefile_hash: print "wrong zonefile: %s != %s" % (blockstack_client.hash_zonefile(zonefile), zonefile_hash) return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps(queue_info, indent=4, sort_keys=True) return False # final balance is correct? name_fee = blockstack_server.price_name( "foo", ns, new_expire_block ) preorder_dust_fees = 3 * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE register_dust_fees = 4 * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE renewal_dust_fees = 3 * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE total_fee = name_fee * 2 + preorder_dust_fees + register_dust_fees + renewal_dust_fees payment_address = wallets[2].addr # TODO: check return True
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) testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo4.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo5.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo6.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo7.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } # send initial subdomains testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.blockstack_name_register("foo4.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register("foo5.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register("foo6.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register("foo7.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.next_block(**kw) # will send these later initial_zonefiles = zonefiles # send updates too, but all on the same name for i in range(0, 3): zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format( i + 1) name = 'foo{}.test'.format(i + 4) zonefiles = { 'foo1.test': zf_template.format( name, subdomains.make_subdomain_txt( 'bar.foo1.test', name, wallets[4].addr, i + 1, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( name, subdomains.make_subdomain_txt( 'bar.foo2.test', name, wallets[4].addr, i + 1, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( name, subdomains.make_subdomain_txt( 'bar.foo3.test', name, wallets[4].addr, i + 1, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_update( name, storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( name, storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( name, storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) # kick off subdomain indexing (nothing should happen) testlib.next_block(**kw) # send initial zonefiles assert testlib.blockstack_put_zonefile(initial_zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(initial_zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(initial_zonefiles['foo3.test']) # now kick it off again testlib.next_block(**kw) # query each subdomain proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)
def scenario(wallets, **kw): zonefile_batches = [] 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("foo1.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url_0 = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody0/content/profile.md"' zf_default_url_1 = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody1/content/profile.md"' zf_default_url_2 = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody2/content/profile.md"' # initialize with sequence=1 zonefiles_1 = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 1, zf_template.format('bar.foo1.test', zf_default_url_1), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 1, zf_template.format('bar.foo2.test', zf_default_url_1), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 1, zf_template.format('bar.foo3.test', zf_default_url_1), wallets[4].privkey)), } zonefile_batches.append(zonefiles_1) testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles_1['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles_1['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles_1['foo3.test'])) testlib.next_block(**kw) for name in zonefiles_1: assert testlib.blockstack_put_zonefile(zonefiles_1[name]) testlib.next_block(**kw) # send sequence=0 zonefiles_0 = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url_0), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url_0), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url_0), wallets[4].privkey)), } zonefile_batches.append(zonefiles_0) testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles_0['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles_0['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles_0['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) for name in zonefiles_0: assert testlib.blockstack_put_zonefile(zonefiles_0[name]) testlib.next_block(**kw) # all names should now be at sequence 0 # query each subdomain for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, hostport='http://localhost:16264') if 'error' in res: print res return False expected_zonefile = zf_template.format(fqn, zf_default_url_0) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # send sequence=1 hashes again testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles_1['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles_1['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles_1['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) # all names should now be at sequence 1, even though we didn't re-send the zone file # query each subdomain for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, hostport='http://localhost:16264') if 'error' in res: print res return False expected_zonefile = zf_template.format(fqn, zf_default_url_1) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # send sequence=2 zonefiles_2 = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 2, zf_template.format('bar.foo1.test', zf_default_url_2), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 2, zf_template.format('bar.foo2.test', zf_default_url_2), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 2, zf_template.format('bar.foo3.test', zf_default_url_2), wallets[4].privkey)), } zonefile_batches.append(zonefiles_2) testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles_2['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles_2['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles_2['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) for name in zonefiles_2: assert testlib.blockstack_put_zonefile(zonefiles_2[name]) testlib.next_block(**kw) # all names should now be at sequence 2 # query each subdomain for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, hostport='http://localhost:16264') if 'error' in res: print res return False expected_zonefile = zf_template.format(fqn, zf_default_url_2) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)
def scenario( wallets, **kw ): zonefile_batches = [] 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( "foo1.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo2.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo3.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo4.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo5.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo6.test", wallets[2].privkey, wallets[3].addr ) testlib.blockstack_name_preorder( "foo7.test", wallets[2].privkey, wallets[3].addr ) testlib.next_block( **kw ) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' # send initial subdomain zone files zonefiles = { 'foo1.test': zf_template.format('foo1.test', subdomains.make_subdomain_txt('bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format('foo2.test', subdomains.make_subdomain_txt('bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format('foo3.test', subdomains.make_subdomain_txt('bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } zonefile_batches.append(zonefiles) testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.blockstack_name_register( "foo4.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register( "foo5.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register( "foo6.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.blockstack_name_register( "foo7.test", wallets[2].privkey, wallets[3].addr, zonefile_hash='11' * 20) testlib.next_block( **kw ) # send updates too, but via a different name each time for i in range(0, 3): zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format(i+1) name = 'foo{}.test'.format(i + 4) zonefiles = { 'foo1.test': zf_template.format(name, subdomains.make_subdomain_txt('bar.foo1.test', name, wallets[4].addr, i+1, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format(name, subdomains.make_subdomain_txt('bar.foo2.test', name, wallets[4].addr, i+1, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format(name, subdomains.make_subdomain_txt('bar.foo3.test', name, wallets[4].addr, i+1, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } zonefile_batches.append(zonefiles) testlib.blockstack_name_update(name, storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update(name, storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update(name, storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) # send all zonefiles at once for zfbatch in zonefile_batches: for name in zfbatch: assert testlib.blockstack_put_zonefile(zfbatch[name]) # kick off subdomain indexing testlib.next_block(**kw) # query each subdomain for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, hostport='http://localhost:16264') if 'error' in res: print res return False # should all have domain foo6.test at this time if res['domain'] != 'foo6.test': print 'wrong domain' print res return False expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)
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) testlib.blockstack_name_preorder("foo1.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' zf_default_url_original = zf_default_url zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.next_block(**kw) # send these initial ones out assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) missing_zonefiles = [] # send updates too for i in range(0, 3): zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format( i + 1) zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, i + 1, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, i + 1, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, i + 1, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) if i % 2 == 0: # withhold for now missing_zonefiles.append(zonefiles) else: # send these out assert testlib.blockstack_put_zonefile(zonefiles['foo1.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo2.test']) assert testlib.blockstack_put_zonefile(zonefiles['foo3.test']) assert len(missing_zonefiles) == 2 # verify that initial subdomains are present proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False if res['sequence'] != 0: print 'wrong sequence: expected 0' print res return False expected_zonefile = zf_template.format(fqn, zf_default_url_original) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # send first batch of withheld zonefiles assert testlib.blockstack_put_zonefile(missing_zonefiles[0]['foo1.test']) assert testlib.blockstack_put_zonefile(missing_zonefiles[0]['foo2.test']) assert testlib.blockstack_put_zonefile(missing_zonefiles[0]['foo3.test']) # kick off subdomain indexing testlib.next_block(**kw) # verify that we're now up to sequence=2 proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False if res['sequence'] != 2: print 'wrong sequence: expected 2' print res return False zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index=2"' expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # send second batch of withheld zonefiles assert testlib.blockstack_put_zonefile(missing_zonefiles[1]['foo1.test']) assert testlib.blockstack_put_zonefile(missing_zonefiles[1]['foo2.test']) assert testlib.blockstack_put_zonefile(missing_zonefiles[1]['foo3.test']) # kick off subdomain indexing testlib.next_block(**kw) # query each subdomain (should all be at sequence 3) proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False if res['sequence'] != 3: print 'wrong sequence: expected 3' print res return False zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index=3"' expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)
def check( state_engine ): global zonefile_hash, error if error: print "exiting with error" return False # not revealed, but ready ns = state_engine.get_namespace_reveal( "test" ) if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace( "test" ) if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name( "foo.test" ) if name_rec is None: print "name does not exist" return False # owned by owner_address = wallets[3].addr if name_rec['address'] != owner_address or name_rec['sender'] != virtualchain.make_payment_script(owner_address): print "sender is wrong" return False # value hash if name_rec['value_hash'] != zonefile_hash: print "wrong zonefile hash: %s != %s" % (name_rec['value_hash'], zonefile_hash) return False # replicated? zonefile = testlib.blockstack_get_zonefile( zonefile_hash ) if 'error' in zonefile: print "zonefile error: %s" % zonefile['error'] return False # right hash? if blockstack_client.hash_zonefile( zonefile ) != zonefile_hash: print "wrong zonefile: %s != %s" % (blockstack_client.hash_zonefile(zonefile), zonefile_hash) return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps(queue_info, indent=4, sort_keys=True) return False # renewed? # final balance is correct? name_fee = blockstack_server.price_name( "foo", ns, new_expire_block ) preorder_dust_fees = 3 * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE register_dust_fees = 4 * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE renewal_dust_fees = 3 * DEFAULT_DUST_FEE + DEFAULT_OP_RETURN_FEE total_fee = name_fee * 2 + preorder_dust_fees + register_dust_fees + renewal_dust_fees payment_address = wallets[2].addr # TODO: check return True
def check(state_engine): # not revealed, but ready ns = state_engine.get_namespace_reveal("test") if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace("test") if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name("foo.test") if name_rec is None: print "name does not exist" return False # owned by the right address owner_address = wallets[4].addr if name_rec['address'] != owner_address or name_rec[ 'sender'] != virtualchain.make_payment_script(owner_address): print "sender is wrong" return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps( queue_info, indent=4, sort_keys=True) return False # have an update hash if 'value_hash' not in name_rec or name_rec.get('value_hash', None) is None: print "No value hash" return False # have a zonefile zonefile = testlib.blockstack_get_zonefile(name_rec['value_hash']) if zonefile is None or 'error' in zonefile: if zonefile is not None: print "zonefile lookup error: %s" % zonefile['error'] else: print "no zonefile returned" return False # hashes to this zonefile if blockstack_client.hash_zonefile(zonefile) != name_rec['value_hash']: print "wrong zonefile: %s != %s" % ( blockstack_client.hash_zonefile(zonefile), name_rec['value_hash']) return False # zonefile has the right data public key zonefile_pubk = blockstack_client.user.user_zonefile_data_pubkey(zonefile) if keylib.key_formatting.compress( zonefile_pubk) != keylib.key_formatting.compress( wallets[4].pubkey_hex) or zonefile_pubk is None: print 'pubkey mismatch: {} != {}'.format(zonefile_pubk, wallets[4].pubkey_hex) return False # zonefile has the right drivers zonefile_urls = blockstack_client.user.user_zonefile_urls(zonefile) driver_urls = blockstack_client.storage.make_mutable_data_urls( 'foo.test', use_only=['dht', 'disk']) if driver_urls != zonefile_urls: print 'url mismatch: {} != {}'.format(driver_urls, zonefile_urls) return False # verify that the profile is NOT there profile = testlib.blockstack_get_profile("foo.test") if profile is not None and 'error' not in profile: print 'make a profile by mistake: {}'.format(profile) return False return True
def check(state_engine): global zonefile_hash # not revealed, but ready ns = state_engine.get_namespace_reveal("test") if ns is not None: print "namespace reveal exists" return False ns = state_engine.get_namespace("test") if ns is None: print "no namespace" return False if ns['namespace_id'] != 'test': print "wrong namespace" return False # registered name_rec = state_engine.get_name("foo.test") if name_rec is None: print "name does not exist" return False # owned by owner_address = wallets[4].addr if name_rec['address'] != owner_address or name_rec[ 'sender'] != virtualchain.make_payment_script(owner_address): print "sender is wrong" return False # value hash if name_rec['value_hash'] != zonefile_hash: print "wrong zonefile hash: %s != %s" % (name_rec['value_hash'], zonefile_hash) return False # replicated? zonefile = testlib.blockstack_get_zonefile(zonefile_hash) if 'error' in zonefile: print "zonefile error: %s" % zonefile['error'] return False # right hash? if blockstack_client.hash_zonefile(zonefile) != zonefile_hash: print "wrong zonefile: %s != %s" % ( blockstack_client.hash_zonefile(zonefile), zonefile_hash) return False # latest key? if not zonefile.has_key("txt"): print "no txt:\n%s" % json.dumps(zonefile, indent=4, sort_keys=True) return False if len(zonefile['txt']) != 2: print "wrong number of txt records:\n%s" % json.dumps( zonefile, indent=4, sort_keys=True) return False for txtrec in zonefile['txt']: if txtrec['name'] == 'pubkey': if new_data_pubkey not in txtrec['txt']: print "wrong pubkey:\n%s" % json.dumps( zonefile, indent=4, sort_keys=True) print "missing %s" % new_data_pubkey return False names_owned = testlib.blockstack_cli_names() if 'error' in names_owned: print "rpc names: %s" % names_owned['error'] return False # we still own the name if len(names_owned['names_owned']) != 1: print "owned: %s" % names_owned['names_owned'] return False # all queues are drained queue_info = testlib.blockstack_client_queue_state() if len(queue_info) > 0: print "Still in queue:\n%s" % json.dumps( queue_info, indent=4, sort_keys=True) return False return True
def scenario(wallets, **kw): wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[2].privkey, wallets[3].privkey, wallets[4].privkey) test_proxy = testlib.TestAPIProxy() blockstack_client.set_default_proxy(test_proxy) zonefile_batches = [] 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("foo1.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo2.test", wallets[2].privkey, wallets[3].addr) testlib.blockstack_name_preorder("foo3.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://raw.githubusercontent.com/nobody/content/profile.md"' zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, 0, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, 0, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, 0, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } zonefile_batches.append(zonefiles) testlib.blockstack_name_register( "foo1.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo1.test'])) testlib.blockstack_name_register( "foo2.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo2.test'])) testlib.blockstack_name_register( "foo3.test", wallets[2].privkey, wallets[3].addr, zonefile_hash=storage.get_zonefile_data_hash(zonefiles['foo3.test'])) testlib.next_block(**kw) # send updates too for i in range(0, 3): zf_template = "$ORIGIN {}\n$TTL 3600\n{}" zf_default_url = '_https._tcp URI 10 1 "https://test.com/?index={}"'.format( i + 1) zonefiles = { 'foo1.test': zf_template.format( 'foo1.test', subdomains.make_subdomain_txt( 'bar.foo1.test', 'foo1.test', wallets[4].addr, i + 1, zf_template.format('bar.foo1.test', zf_default_url), wallets[4].privkey)), 'foo2.test': zf_template.format( 'foo2.test', subdomains.make_subdomain_txt( 'bar.foo2.test', 'foo2.test', wallets[4].addr, i + 1, zf_template.format('bar.foo2.test', zf_default_url), wallets[4].privkey)), 'foo3.test': zf_template.format( 'foo3.test', subdomains.make_subdomain_txt( 'bar.foo3.test', 'foo3.test', wallets[4].addr, i + 1, zf_template.format('bar.foo3.test', zf_default_url), wallets[4].privkey)), } zonefile_batches.append(zonefiles) testlib.blockstack_name_update( 'foo1.test', storage.get_zonefile_data_hash(zonefiles['foo1.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo2.test', storage.get_zonefile_data_hash(zonefiles['foo2.test']), wallets[3].privkey) testlib.blockstack_name_update( 'foo3.test', storage.get_zonefile_data_hash(zonefiles['foo3.test']), wallets[3].privkey) testlib.next_block(**kw) # send all zonefiles at once for zfbatch in zonefile_batches: for name in zfbatch: assert testlib.blockstack_put_zonefile(zfbatch[name]) # kick off subdomain indexing testlib.next_block(**kw) # query each subdomain proxy = testlib.make_proxy() for i in xrange(1, 4): fqn = 'bar.foo{}.test'.format(i) res = client.get_name_record(fqn, proxy=proxy) if 'error' in res: print res return False expected_zonefile = zf_template.format(fqn, zf_default_url) if base64.b64decode(res['zonefile']) != expected_zonefile: print 'zonefile mismatch' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # should be in atlas as well zf = testlib.blockstack_get_zonefile(res['value_hash'], parse=False) if not zf: print 'no zone file {} in atlas'.format(res['value_hash']) return False if zf != expected_zonefile: print 'zonefile mismatch in atlas' print 'expected\n{}'.format(expected_zonefile) print 'got\n{}'.format(base64.b64decode(res['zonefile'])) return False # reindex assert testlib.check_subdomain_db(**kw)