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 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 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 scenario( wallets, **kw ): global GAIA_READ_URL global GAIA_READ_PORT global GAIA_WRITE_PORT global GAIA_WRITE_URL global owner_privkey global owner_address # get gaia hub info with open(os.path.join(os.environ['BLOCKSTACK_WORKING_DIR'], 'gaia.conf'), 'r') as f: GAIA_CONF = json.loads(f.read().strip()) try: GAIA_READ_PORT = urlparse.urlparse(GAIA_CONF['readURL']).netloc.split(':')[-1] GAIA_READ_PORT = int(GAIA_READ_PORT) except: GAIA_READ_PORT = 80 if os.environ.get('BLOCKSTACK_PUBLIC_TESTNET_GAIA_READ_PORT'): GAIA_READ_PORT = int(os.environ['BLOCKSTACK_PUBLIC_TESTNET_GAIA_READ_PORT']) read_urlinfo = urlparse.urlparse(GAIA_CONF['readURL']) GAIA_READ_URL = 'http://{}:{}'.format(read_urlinfo.netloc.split(':')[0], GAIA_READ_PORT) GAIA_WRITE_PORT = GAIA_CONF['port'] if os.environ.get('BLOCKSTACK_PUBLIC_TESTNET_GAIA_WRITE_PORT'): GAIA_WRITE_PORT = int(os.environ['BLOCKSTACK_PUBLIC_TESTNET_GAIA_WRITE_PORT']) GAIA_WRITE_URL = 'http://{}:{}'.format(GAIA_CONF['servername'], GAIA_WRITE_PORT) testlib.blockstack_namespace_preorder( "test", wallets[1].addr, wallets[0].privkey ) testlib.next_block( **kw ) testlib.blockstack_namespace_reveal( "test", wallets[1].addr, -1, 250, 4, [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 10, 10, wallets[0].privkey, version_bits=1) testlib.next_block( **kw ) testlib.blockstack_namespace_ready( "test", wallets[1].privkey ) testlib.next_block( **kw ) # register this user under a keychain res = testlib.nodejs_cli('make_keychain') res = json.loads(res) mnemonic = res['mnemonic'] owner_privkey = res['ownerKeyInfo']['privateKey'] owner_address = res['ownerKeyInfo']['idAddress'][3:] profile = { 'type': '@Person', 'account': [], 'name': 'Testy McTestface', } testlib.blockstack_register_user('foo.test', wallets[3].privkey, owner_privkey, profile=profile, profile_name='0/profile.json', **kw) # verify that we can look up this profile res = testlib.blockstack_get_profile('foo.test') if res['profile'] != profile: print 'wrong profile' print profile print res['profile'] return False # patch the profile to insert an app URL res = testlib.nodejs_cli('gaia_sethub', 'foo.test', GAIA_WRITE_URL, 'http://www.testapp.com', GAIA_WRITE_URL, mnemonic) res = testlib.blockstack_get_profile('foo.test') updated_profile = {} updated_profile.update(res['profile']) apps = updated_profile['apps'] del updated_profile['apps'] if updated_profile != profile: print 'wrong profile after sethub' print expected_profile print res['profile'] return False if not apps['http://www.testapp.com'].startswith(GAIA_READ_URL): print 'wrong app entry for testapp.com' print apps print GAIA_WRITE_URL return False print "" print "mnemnic: {}".format(mnemonic) print "hub url: {}".format(GAIA_WRITE_URL) print ""
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 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