async def get_box_ids_issued(self) -> str: """ Return json object on lists of all unique box identifiers (schema identifiers, credential definition identifiers, and revocation registry identifiers) for all credential definitions and credentials issued; e.g., :: { "schema_id": [ "R17v42T4pk...:2:tombstone:1.2", ... ], "cred_def_id": [ "R17v42T4pk...:3:CL:19:tag", ... ] "rev_reg_id": [ "R17v42T4pk...:4:R17v42T4pk...:3:CL:19:tag:CL_ACCUM:0", "R17v42T4pk...:4:R17v42T4pk...:3:CL:19:tag:CL_ACCUM:1", ... ] } An issuer must issue a credential definition to include its schema identifier in the returned values; the schema identifier in isolation belongs properly to an Origin, not necessarily to an Issuer. The operation may be useful for a Verifier anchor going off-line to seed its cache before doing so. :return: tuple of sets for schema ids, cred def ids, rev reg ids """ LOGGER.debug('Issuer.get_box_ids_issued >>>') cd_ids = [d for d in listdir(self._dir_tails) if isdir(join(self._dir_tails, d)) and ok_cred_def_id(d, self.did)] s_ids = [] for cd_id in cd_ids: try: s_ids.append(json.loads(await self.get_schema(cred_def_id2seq_no(cd_id)))['id']) except AbsentSchema: LOGGER.error( 'Issuer %s has issued cred def %s but no corresponding schema on ledger', self.wallet.name, cd_id) rr_ids = [basename(link) for link in Tails.links(self._dir_tails, self.did)] rv = json.dumps({ 'schema_id': s_ids, 'cred_def_id': cd_ids, 'rev_reg_id': rr_ids }) LOGGER.debug('Issuer.get_box_ids_issued <<< %s', rv) return rv
async def build_proof_req_json(self, cd_id2spec: dict) -> str: """ Build and return indy-sdk proof request for input attributes and non-revocation intervals by cred def id. :param cd_id2spec: dict mapping cred def ids to: - (optionally) 'attrs': lists of names of attributes of interest (omit for all, empty list or None for none) - (optionally) '>=': (pred) inclusive int lower-bounds of interest (omit, empty list, or None for none) - (optionally) '>': (pred) exclusive int lower-bounds of interest (omit, empty list, or None for none) - (optionally) '<=': (pred) inclusive int upper-bounds of interest (omit, empty list, or None for none) - (optionally) '<': (pred) exclusive int upper-bounds of interest (omit, empty list, or None for none) - (optionally), 'interval': either - (2-tuple) pair of epoch second counts marking 'from' and 'to' timestamps, or - | single epoch second count to set 'from' and 'to' the same; default | (now, now) for cred defs supporting revocation or None otherwise; e.g., :: { 'Vx4E82R17q...:3:CL:16:tag': { 'attrs': [ # request attrs 'name' and 'favouriteDrink' from this cred def's schema 'name', 'favouriteDrink' ], '>=': { # request predicate score>=80 from this cred def 'score': 80 } '<=': { # request ranking <=10 from this cred def 'ranking': 10 } 'interval': 1528116008 # same instant for all attrs and preds of corresponding schema }, 'R17v42T4pk...:3:CL:19:tag': None, # request all attrs, no preds, default intervals on all attrs 'e3vc5K168n...:3:CL:23:tag': {}, # request all attrs, no preds, default intervals on all attrs 'Z9ccax812j...:3:CL:27:tag': { # request all attrs, no preds, this interval on all attrs 'interval': (1528112408, 1528116008) }, '9cHbp54C8n...:3:CL:37:tag': { # request no attrs and some predicates; specify interval 'attrs': [], # or equivalently, 'attrs': None '>=': { 'employees': '50' # nicety: implementation converts to int for caller }, '>=': { 'revenue': '10000000' # nicety: implementation converts to int for caller 'ebidta': 0 } 'interval': (1528029608, 1528116008) }, '6caBcmLi33...:3:CL:41:tag': { # all attrs, one pred, default intervals to now on attrs & pred '>': { 'regEpoch': 1514782800 } }, ... } :return: indy-sdk proof request json """ LOGGER.debug('Verifier.build_proof_req_json >>> cd_id2spec: %s', cd_id2spec) cd_id2schema = {} now = int(time()) rv = { 'nonce': str(int(time())), 'name': 'proof_req', 'version': '0.0', 'requested_attributes': {}, 'requested_predicates': {} } for cd_id in cd_id2spec: if not ok_cred_def_id(cd_id): LOGGER.debug( 'Verifier.build_proof_req_json <!< Bad cred def id %s', cd_id) raise BadIdentifier('Bad cred def id {}'.format(cd_id)) interval = None cred_def = json.loads(await self.get_cred_def(cd_id)) seq_no = cred_def_id2seq_no(cd_id) cd_id2schema[cd_id] = json.loads(await self.get_schema(seq_no)) if 'revocation' in cred_def['value']: fro_to = cd_id2spec[cd_id].get( 'interval', (now, now)) if cd_id2spec[cd_id] else (now, now) interval = { 'from': fro_to if isinstance(fro_to, int) else min(fro_to), 'to': fro_to if isinstance(fro_to, int) else max(fro_to) } for attr in (cd_id2spec[cd_id].get( 'attrs', cd_id2schema[cd_id]['attrNames']) or [] if cd_id2spec[cd_id] else cd_id2schema[cd_id]['attrNames']): attr_uuid = '{}_{}_uuid'.format(seq_no, canon(attr)) rv['requested_attributes'][attr_uuid] = { 'name': attr, 'restrictions': [{ 'cred_def_id': cd_id }] } if interval: rv['requested_attributes'][attr_uuid][ 'non_revoked'] = interval for pred in Predicate: for attr in (cd_id2spec[cd_id].get(pred.value.math, {}) or {} if cd_id2spec[cd_id] else {}): pred_uuid = '{}_{}_{}_uuid'.format(seq_no, canon(attr), pred.value.fortran) try: rv['requested_predicates'][pred_uuid] = { 'name': attr, 'p_type': pred.value.math, 'p_value': Predicate.to_int( cd_id2spec[cd_id][pred.value.math][attr]), 'restrictions': [{ 'cred_def_id': cd_id }] } except ValueError: LOGGER.info( 'cannot build %s predicate on non-int bound %s for %s', pred.value.fortran, cd_id2spec[cd_id][pred.value.math][attr], attr) continue # int conversion failed - reject candidate if interval: rv['requested_predicates'][pred_uuid][ 'non_revoked'] = interval LOGGER.debug('Verifier.build_proof_req_json <<< %s', json.dumps(rv)) return json.dumps(rv)