예제 #1
0
def proof_req_pred_referents(proof_req: dict) -> dict:
    """
    Given a proof request with all requested predicates having cred def id restrictions,
    return its predicate referents by cred def id and attribute, mapping a predicate and a limit.

    The returned structure can be useful in downstream processing to filter cred-infos for predicates.

    :param proof_req: proof request with all requested predicate specifications having cred def id restriction; e.g.,

    ::

        {
            'name': 'proof_req',
            'version': '0.0',
            'requested_attributes': {
                ...
            }
            'requested_predicates': {
                '194_highscore_GE_uuid': {
                    'name': 'highscore',
                    'p_type': '>=',
                    'p_value': '100000',
                    'restrictions': {
                        'cred_def_id': 'WgWxqztrNooG92RXvxSTWv:3:CL:194:tag'
                    },
                    'non_revoked': {
                        ...
                    }
                },
                '194_level_GE_uuid': {
                    'name': 'level',
                    'p_type': '>=',
                    'p_value': '10',
                    'restrictions': {
                        'cred_def_id': 'WgWxqztrNooG92RXvxSTWv:3:CL:194:tag'
                    },
                    'non_revoked': {
                        ...
                    }
                },
                '194_attempts_LE_uuid': {
                    'name': 'attempts',
                    'p_type': '<=',
                    'p_value': '3',
                    'restrictions': {
                        'cred_def_id': 'WgWxqztrNooG92RXvxSTWv:3:CL:194:tag'
                    },
                    'non_revoked': {
                        ...
                    }
                },
                '198_employees_LT_uuid': {
                    'name': 'employees',
                    'p_type': '<',
                    'p_value': '100',
                    'restrictions': {
                        'cred_def_id': 'WgWxqztrNooG92RXvxSTWv:3:CL:198:tag'
                    },
                    'non_revoked': {
                        ...
                    }
                },
                '198_employees_GE_uuid': {
                    'name': 'employees',
                    'p_type': '>=',
                    'p_value': '50',
                    'restrictions': {
                        'cred_def_id': 'WgWxqztrNooG92RXvxSTWv:3:CL:198:tag'
                    },
                    'non_revoked': {
                        ...
                    }
                },
            }
        }

    :return: nested dict mapping cred def id to name to proof request referent to predicate and limit; e.g.,

    ::

        {
            'WgWxqztrNooG92RXvxSTWv:3:CL:194:tag': {
                'highscore': {
                    '194_level_GE_uuid': ['>=', 100000]
                },
                'level': {
                    '194_level_GE_uuid': ['>=', 10]
                },
                'attempts': {
                    '194_attempts_LE_uuid': ['<=', 3]
                }
            },
            'WgWxqztrNooG92RXvxSTWv:3:CL:198:tag': {
                'employees': {  # may have many preds per attr, but always 1 uuid and 1 relation per pred
                    '198_LT_employees_uuid': ['<=', 100]
                    '198_GE_employees_uuid': ['>=', 50]
                }
            }
        }

    """

    rv = {}
    for uuid, spec in proof_req['requested_predicates'].items():
        cd_id = None
        for restriction in spec.get('restrictions', []):
            cd_id = restriction.get('cred_def_id', None)
            if cd_id:
                break
        if not cd_id:
            continue
        if cd_id not in rv:  # cd_id of None is not OK
            rv[cd_id] = {}
        if spec['name'] not in rv[cd_id]:
            rv[cd_id][spec['name']] = {}
        rv[cd_id][spec['name']][uuid] = [spec['p_type'], Predicate.to_int(spec['p_value'])]

    return rv
예제 #2
0
    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)