def load_user(record_hash): """ Load a user record from the storage implementation with the given hex string hash, The user record hash should have been loaded from the blockchain, and thereby be the authentic hash. Return the user record on success Return None on error """ user_json = storage.get_immutable_data(record_hash) if user_json is None: log.error("Failed to load user record '%s'" % record_hash) return None # verify integrity user_record_hash = storage.get_data_hash(user_json) if user_record_hash != record_hash: log.error( "Profile hash mismatch: expected '%s', got '%s'" % record_hash, user_record_hash) return None user = user_db.parse_user(user_json) return user
def load_name_zonefile(name, expected_zonefile_hash, storage_drivers=None, raw_zonefile=False, allow_legacy=False, proxy=None ): """ Fetch and load a user zonefile from the storage implementation with the given hex string hash, The user zonefile hash should have been loaded from the blockchain, and thereby be the authentic hash. If raw_zonefile is True, then return the raw zonefile data. Don't parse it. If however, raw_zonefile is False, the zonefile will be parsed. If name is given, the $ORIGIN will be checked. Return the user zonefile (as a dict) on success Return None on error """ proxy = get_default_proxy() if proxy is None else proxy conf = proxy.conf assert 'server' in conf, json.dumps(conf, indent=4, sort_keys=True) assert 'port' in conf, json.dumps(conf, indent=4, sort_keys=True) atlas_host = conf['server'] atlas_port = conf['port'] hostport = '{}:{}'.format( atlas_host, atlas_port ) zonefile_txt = None expected_zonefile_hash = str(expected_zonefile_hash) # try atlas node first res = get_zonefiles( hostport, [expected_zonefile_hash], proxy=proxy ) if 'error' in res or expected_zonefile_hash not in res['zonefiles'].keys(): # fall back to storage drivers if atlas node didn't have it zonefile_txt = storage.get_immutable_data( expected_zonefile_hash, hash_func=storage.get_zonefile_data_hash, fqu=name, zonefile=True, drivers=storage_drivers ) if zonefile_txt is None: log.error('Failed to load user zonefile "{}"'.format(expected_zonefile_hash)) return None else: # extract log.debug('Fetched {} from Atlas peer {}'.format(expected_zonefile_hash, hostport)) zonefile_txt = res['zonefiles'][expected_zonefile_hash] if raw_zonefile: msg = 'Driver did not return a serialized zonefile' try: assert isinstance(zonefile_txt, (str, unicode)), msg except AssertionError as ae: if BLOCKSTACK_TEST is not None: log.exception(ae) log.error(msg) return None return zonefile_txt parsed_zonefile = decode_name_zonefile(name, zonefile_txt, allow_legacy=allow_legacy) return parsed_zonefile
def get_immutable(name, data_hash, data_id=None, proxy=None): """ get_immutable Fetch a piece of immutable data. Use @data_hash to look it up in the user's zonefile, and then fetch and verify the data itself from the configured storage providers. Return {'data': the data, 'hash': hash} on success Return {'error': ...} on failure """ if proxy is None: proxy = get_default_proxy() user_zonefile = get_name_zonefile(name, proxy=proxy) if user_zonefile is None: return {'error': 'No user zonefile defined'} if 'error' in user_zonefile: return user_zonefile if blockstack_profiles.is_profile_in_legacy_format( user_zonefile ) or not user_db.is_user_zonefile( user_zonefile ): # zonefile is really a legacy profile return {'error': 'Profile is in a legacy format that does not support immutable data.'} if data_id is not None: # look up hash by name h = user_db.get_immutable_data_hash( user_zonefile, data_id ) if h is None: return {'error': 'No such immutable datum'} if type(h) == list: # this tool doesn't allow this to happen (one ID matches one hash), # but that doesn't preclude the user from doing this with other tools. if data_hash is not None and data_hash not in h: return {'error': 'Data ID/hash mismatch'} else: return {'error': "Multiple matches for '%s': %s" % (data_id, ",".join(h))} if data_hash is not None: if h != data_hash: return {'error': 'Data ID/hash mismatch'} else: data_hash = h elif not user_db.has_immutable_data( user_zonefile, data_hash ): return {'error': 'No such immutable datum'} data_url_hint = user_db.get_immutable_data_url( user_zonefile, data_hash ) data = storage.get_immutable_data( data_hash, fqu=name, data_id=data_id, data_url=data_url_hint ) if data is None: return {'error': 'No immutable data returned'} return {'data': data, 'hash': data_hash}
def load_user(record_hash): """ Load a user record from the storage implementation with the given hex string hash, The user record hash should have been loaded from the blockchain, and thereby be the authentic hash. Return the user record on success Return None on error """ user_json = storage.get_immutable_data(record_hash) if user_json is None: log.error("Failed to load user record '%s'" % record_hash) return None # verify integrity user_record_hash = storage.get_data_hash(user_json) if user_record_hash != record_hash: log.error("Profile hash mismatch: expected '%s', got '%s'" % record_hash, user_record_hash) return None user = user_db.parse_user(user_json) return user
def get_immutable(name, data_key): """ get_immutable """ user = get_name_record(name) if 'error' in user: # no user data return {'error': "Unable to load user record: %s" % user['error']} if not user_db.has_immutable_data(user, data_key): # no data return {'error': 'Profile has no such immutable data'} data = storage.get_immutable_data(data_key) if data is None: # no data return {'error': 'No immutable data found'} return {'data': data}