def scenario(wallets, **kw): global wallet_keys, wallet_keys_2, error, index_file_data, resource_data wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[3].privkey) test_proxy = testlib.TestAPIProxy() blockstack_client.set_default_proxy(test_proxy) testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw) testlib.blockstack_name_preorder("foo.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) testlib.blockstack_name_register("foo.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) # migrate profiles, but no data key in the zone file res = testlib.migrate_profile("foo.test", zonefile_has_data_key=False, proxy=test_proxy, wallet_keys=wallet_keys) if 'error' in res: res['test'] = 'Failed to initialize foo.test profile' print json.dumps(res, indent=4, sort_keys=True) error = True return # tell serialization-checker that value_hash can be ignored here print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block(**kw) config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None) # make a session datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex() res = testlib.blockstack_cli_app_signin( "foo.test", datastore_pk, 'register.app', [ 'names', 'register', 'prices', 'zonefiles', 'blockchain', 'node_read', 'user_read' ]) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) error = True return ses = res['token'] # register the name bar.test. autogenerate the rest old_user_zonefile = blockstack_client.zonefile.make_empty_zonefile( 'bar.test', None) old_user_zonefile_txt = blockstack_zones.make_zone_file(old_user_zonefile) res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data={ 'name': 'bar.test', 'zonefile': old_user_zonefile_txt, 'make_profile': True }) if 'error' in res: res['test'] = 'Failed to register user' print json.dumps(res) error = True return False print res tx_hash = res['response']['transaction_hash'] # wait for preorder to get confirmed... for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(ses, 'bar.test', 'preorder', tx_hash) if not res: return False # wait for the preorder to get confirmed for i in xrange(0, 4): testlib.next_block(**kw) # wait for register to go through print 'Wait for register to be submitted' time.sleep(10) # wait for the register/update to get confirmed for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(ses, 'bar.test', 'register', None) if not res: return False for i in xrange(0, 3): testlib.next_block(**kw) # should have nine confirmations now res = testlib.get_queue(ses, 'register') if 'error' in res: print res return False if len(res) != 1: print res return False reg = res[0] confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 9: print 'wrong number of confs for {} (expected 9): {}'.format( reg['tx_hash'], confs) return False # stop the API server testlib.stop_api() # advance blockchain testlib.next_block(**kw) testlib.next_block(**kw) confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 11: print 'wrong number of confs for {} (expected 11): {}'.format( reg['tx_hash'], confs) return False # make sure the registrar does not process reg/up zonefile replication # (i.e. we want to make sure that the zonefile gets processed even if the blockchain goes too fast) os.environ[ 'BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_REGUP_REPLICATION'] = '1' testlib.start_api("0123456789abcdef") print 'Wait to verify that we do not remove the zone file just because the tx is confirmed' time.sleep(10) # verify that this is still in the queue res = testlib.get_queue(ses, 'register') if 'error' in res: print res return False if len(res) != 1: print res return False # clear the fault print 'Clearing regup replication fault' testlib.blockstack_test_setenv( "BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_REGUP_REPLICATION", "0") # wait for register to go through print 'Wait for zonefile to replicate' time.sleep(10) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False old_expire_block = res['response']['expire_block'] # get the zonefile res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/zonefile", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name zonefile' print json.dumps(res) return False # zonefile must not have a public key listed zonefile_txt = res['response']['zonefile'] print zonefile_txt parsed_zonefile = blockstack_zones.parse_zone_file(zonefile_txt) if parsed_zonefile.has_key('txt'): print 'have txt records' print parsed_zonefile return False # renew it, but put the *current* owner key as the zonefile's *new* public key new_user_zonefile = blockstack_client.zonefile.make_empty_zonefile( 'bar.test', wallets[3].pubkey_hex) new_user_zonefile_txt = blockstack_zones.make_zone_file(new_user_zonefile) res = testlib.blockstack_REST_call("POST", "/v1/names", ses, data={ 'name': 'bar.test', 'zonefile': new_user_zonefile_txt }) if 'error' in res or res['http_status'] != 202: res['test'] = 'Failed to renew name' print json.dumps(res) return False # verify in renew queue for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(ses, 'bar.test', 'renew', None) if not res: return False for i in xrange(0, 3): testlib.next_block(**kw) # should have nine confirmations now res = testlib.get_queue(ses, 'renew') if 'error' in res: print res return False if len(res) != 1: print res return False reg = res[0] confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 9: print 'wrong number of confs for {} (expected 9): {}'.format( reg['tx_hash'], confs) return False # stop the API server testlib.stop_api() # advance blockchain testlib.next_block(**kw) testlib.next_block(**kw) confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 11: print 'wrong number of confs for {} (expected 11): {}'.format( reg['tx_hash'], confs) return False # make the registrar skip the first few steps, so the only thing it does is clear out confirmed updates # (i.e. we want to make sure that the renewal's zonefile gets processed even if the blockchain goes too fast) os.environ[ 'BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_RENEWAL_REPLICATION'] = '1' testlib.start_api("0123456789abcdef") # wait a while print 'Wait to verify that clearing out confirmed transactions does NOT remove zonefiles' time.sleep(10) # verify that this is still in the queue res = testlib.get_queue(ses, 'renew') if 'error' in res: print res return False if len(res) != 1: print res return False # clear the fault print 'Clearing renewal replication fault' testlib.blockstack_test_setenv( "BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_RENEWAL_REPLICATION", "0") # now the renewal zonefile should replicate print 'Wait for renewal zonefile to replicate' time.sleep(10) # new expire block res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False new_expire_block = res['response']['expire_block'] # do we have the history for the name? res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history", ses) if 'error' in res or res['http_status'] != 200: res['test'] = "Failed to get name history for bar.test" print json.dumps(res) return False # valid history? hist = res['response'] if len(hist.keys()) != 3: res['test'] = 'Failed to get update history' res['history'] = hist print json.dumps(res, indent=4, sort_keys=True) return False # get the zonefile res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/zonefile", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name zonefile' print json.dumps(res) return False # zonefile must have old owner key zonefile_txt = res['response']['zonefile'] parsed_zonefile = blockstack_zones.parse_zone_file(zonefile_txt) if not parsed_zonefile.has_key('txt'): print 'missing txt' print parsed_zonefile return False found = False for txtrec in parsed_zonefile['txt']: if txtrec['name'] == 'pubkey' and txtrec[ 'txt'] == 'pubkey:data:{}'.format(wallets[3].pubkey_hex): found = True if not found: print 'missing public key {}'.format(wallets[3].pubkey_hex) return False # profile lookup must work res = testlib.blockstack_REST_call("GET", "/v1/users/bar.test", ses) if 'error' in res or res['http_status'] != 200: res['text'] = 'failed to get profile for bar.test' print json.dumps(res) return False print '' print json.dumps(res['response'], indent=4, sort_keys=True) print '' # verify pushed back if old_expire_block + 10 > new_expire_block: # didn't go through print >> sys.stderr, "Renewal didn't work: %s --> %s" % ( old_expire_block, new_expire_block) return False
def scenario(wallets, **kw): global wallet_keys, wallet_keys_2, error, index_file_data, resource_data wallet_keys = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[5].privkey, wallets[3].privkey, wallets[4].privkey) test_proxy = testlib.TestAPIProxy() blockstack_client.set_default_proxy(test_proxy) testlib.blockstack_namespace_preorder("test", wallets[1].addr, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, 52595, 250, 4, [6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 10, 10, wallets[0].privkey) testlib.next_block(**kw) testlib.blockstack_namespace_ready("test", wallets[1].privkey) testlib.next_block(**kw) testlib.blockstack_name_preorder("foo.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) testlib.blockstack_name_register("foo.test", wallets[2].privkey, wallets[3].addr) testlib.next_block(**kw) # migrate profiles res = testlib.migrate_profile("foo.test", proxy=test_proxy, wallet_keys=wallet_keys) if 'error' in res: res['test'] = 'Failed to initialize foo.test profile' print json.dumps(res, indent=4, sort_keys=True) error = True return # tell serialization-checker that value_hash can be ignored here print "BLOCKSTACK_SERIALIZATION_CHECK_IGNORE value_hash" sys.stdout.flush() testlib.next_block(**kw) data_pk = wallets[-1].privkey data_pub = wallets[-1].pubkey_hex config_path = os.environ.get("BLOCKSTACK_CLIENT_CONFIG", None) # make a session datastore_pk = keylib.ECPrivateKey(wallets[-1].privkey).to_hex() res = testlib.blockstack_cli_app_signin( "foo.test", datastore_pk, 'register.app', [ 'names', 'register', 'update', 'prices', 'zonefiles', 'blockchain', 'node_read' ]) if 'error' in res: print json.dumps(res, indent=4, sort_keys=True) error = True return ses = res['token'] # register the name bar.test res = testlib.blockstack_REST_call('POST', '/v1/names', ses, data={'name': 'bar.test'}) if 'error' in res: res['test'] = 'Failed to register user' print json.dumps(res) error = True return False print res tx_hash = res['response']['transaction_hash'] # wait for preorder to get confirmed... for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(ses, 'bar.test', 'preorder', tx_hash) if not res: return False # wait for the preorder to get confirmed for i in xrange(0, 4): testlib.next_block(**kw) # wait for register to go through print 'Wait for register to be submitted' time.sleep(10) # wait for the register to get confirmed for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(ses, 'bar.test', 'register', None) if not res: return False for i in xrange(0, 4): testlib.next_block(**kw) print 'Wait for update to be submitted' time.sleep(10) # wait for update to get confirmed for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(ses, 'bar.test', 'update', None) if not res: return False for i in xrange(0, 3): testlib.next_block(**kw) # should have 9 confirmations res = testlib.get_queue(ses, 'update') if 'error' in res: print res return False if len(res) != 1: print res return False reg = res[0] confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 9: print 'wrong number of confs for {} (expected 9): {}'.format( reg['tx_hash'], confs) return False # stop the API server testlib.stop_api() # advance blockchain testlib.next_block(**kw) testlib.next_block(**kw) confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 11: print 'wrong number of confs for {} (expected 11): {}'.format( reg['tx_hash'], confs) return False # make the registrar skip the first few steps, so the only thing it does is clear out confirmed updates # (i.e. we want to make sure that the renewal's zonefile gets processed even if the blockchain goes too fast) os.environ[ 'BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_UPDATE_REPLICATION'] = '1' testlib.start_api("0123456789abcdef") # wait a while print 'Wait to verify that clearing out confirmed transactions does NOT remove zonefiles' time.sleep(10) # verify that this is still in the queue res = testlib.get_queue(ses, 'update') if 'error' in res: print res return False if len(res) != 1: print res return False # clear the fault print 'Clearing update replication fault' testlib.blockstack_test_setenv( "BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_UPDATE_REPLICATION", "0") # now the renewal zonefile should replicate print 'Wait for first zonefile to replicate' time.sleep(10) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False first_zonefile_hash = res['response']['zonefile_hash'] # update res = testlib.blockstack_REST_call("PUT", "/v1/names/bar.test/zonefile", ses, data={'zonefile_hash': '11' * 20}) if 'error' in res or res['http_status'] != 202: res['test'] = 'failed to update zonefile hash' print json.dumps(res) return False # wait for update to get confirmed for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(ses, 'bar.test', 'update', None) if not res: return False for i in xrange(0, 3): testlib.next_block(**kw) # should have 9 confirmations res = testlib.get_queue(ses, 'update') if 'error' in res: print res return False if len(res) != 1: print res return False reg = res[0] confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 9: print 'wrong number of confs for {} (expected 9): {}'.format( reg['tx_hash'], confs) return False # stop the API server testlib.stop_api() # advance blockchain testlib.next_block(**kw) testlib.next_block(**kw) confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 11: print 'wrong number of confs for {} (expected 11): {}'.format( reg['tx_hash'], confs) return False # make the registrar skip the first few steps, so the only thing it does is clear out confirmed updates # (i.e. we want to make sure that the renewal's zonefile gets processed even if the blockchain goes too fast) os.environ[ 'BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_UPDATE_REPLICATION'] = '1' testlib.start_api("0123456789abcdef") # wait a while print 'Wait to verify that clearing out confirmed transactions does NOT remove zonefiles' time.sleep(10) # verify that it is NOT in the queue, since there is no zone file res = testlib.get_queue(ses, 'update') if 'error' not in res: print res return False # clear the fault print 'Clearing update replication fault' testlib.blockstack_test_setenv( "BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_UPDATE_REPLICATION", "0") res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False # update set? if res['response']['zonefile_hash'] != '11' * 20: res['test'] = 'failed to set zonefile hash' print json.dumps(res) return False # update with nonstandard zonefile res = testlib.blockstack_REST_call("PUT", "/v1/names/bar.test/zonefile", ses, data={'zonefile': 'hello world'}) if 'error' in res or res['http_status'] != 202: res['test'] = 'failed to update zonefile hash' print json.dumps(res) return False # wait for third update to get confirmed for i in xrange(0, 6): testlib.next_block(**kw) res = testlib.verify_in_queue(ses, 'bar.test', 'update', None) if not res: return False for i in xrange(0, 3): testlib.next_block(**kw) # should have 9 confirmations res = testlib.get_queue(ses, 'update') if 'error' in res: print res return False if len(res) != 1: print res return False reg = res[0] confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 9: print 'wrong number of confs for {} (expected 9): {}'.format( reg['tx_hash'], confs) return False # stop the API server testlib.stop_api() # advance blockchain testlib.next_block(**kw) testlib.next_block(**kw) confs = blockstack_client.get_tx_confirmations(reg['tx_hash']) if confs != 11: print 'wrong number of confs for {} (expected 11): {}'.format( reg['tx_hash'], confs) return False # make the registrar skip the first few steps, so the only thing it does is clear out confirmed updates # (i.e. we want to make sure that the renewal's zonefile gets processed even if the blockchain goes too fast) os.environ[ 'BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_UPDATE_REPLICATION'] = '1' testlib.start_api("0123456789abcdef") # wait a while print 'Wait to verify that clearing out confirmed transactions does NOT remove zonefiles' time.sleep(10) # verify that this is still in the queue res = testlib.get_queue(ses, 'update') if 'error' in res: print res return False if len(res) != 1: print res return False # clear the fault print 'Clearing update replication fault' testlib.blockstack_test_setenv( "BLOCKSTACK_TEST_REGISTRAR_FAULT_INJECTION_SKIP_UPDATE_REPLICATION", "0") print 'Wait for third update to be confirmed' time.sleep(10) res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test", ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get name bar.test' print json.dumps(res) return False last_zonefile_hash = res['response']['zonefile_hash'] # do we have the history for the name? res = testlib.blockstack_REST_call("GET", "/v1/names/bar.test/history", ses) if 'error' in res or res['http_status'] != 200: res['test'] = "Failed to get name history for foo.test" print json.dumps(res) return False # valid history? hist = res['response'] if len(hist.keys()) != 5: res['test'] = 'Failed to get update history' res['history'] = hist print json.dumps(res, indent=4, sort_keys=True) return False # get the historic zonefile res = testlib.blockstack_REST_call( "GET", "/v1/names/bar.test/zonefile/{}".format(first_zonefile_hash), ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get first zonefile' print json.dumps(res) return False # get the latest zonefile res = testlib.blockstack_REST_call( "GET", "/v1/names/bar.test/zonefile/{}?raw=1".format(last_zonefile_hash), ses) if 'error' in res or res['http_status'] != 200: res['test'] = 'Failed to get last zonefile' print json.dumps(res) return False if res['raw'] != 'hello world': res['test'] = 'Failed to set zonefile data' print json.dumps(res) return False