Build and return indy-sdk proof request for input attributes and timestamps by cred def id.

        Raise AbsentInterval if caller specifies cache_only and default non-revocation intervals, but
        revocation cache does not have delta frames for any revocation registries on a specified cred def.

        :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) 'minima': (pred) integer lower-bounds of interest (omit, empty list, or None for none)
            - (optionally), 'interval': (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) if cache_only
                is clear, or latest values from cache if cache_only is set.
            e.g.,

        ::

            {
                'Vx4E82R17q...:3:CL:16:0': {
                    'attrs': [  # request attrs 'name' and 'favouriteDrink' from this cred def's schema
                        'name',
                        'favouriteDrink'
                    ],
                    'minima': {  # request predicate score>=80 from this cred def
                        'score': 80
                    }
                    'interval': 1528116008  # same instant for all attrs and preds of corresponding schema
                },
                'R17v42T4pk...:3:CL:19:0': None,  # request all attrs, no preds, default intervals on all attrs
                'e3vc5K168n...:3:CL:23:0': {},  # request all attrs, no preds, default intervals on all attrs
                'Z9ccax812j...:3:CL:27:0': {  # request all attrs, no preds, this interval on all attrs
                    'interval': (1528112408, 1528116008)
                },
                '9cHbp54C8n...:3:CL:37:0': {  # request no attrs, one pred, specify interval on pred
                    'attrs': [],  # or equivalently, 'attrs': None
                    'minima': {
                        'employees': '50'  # nicety: implementation converts to int for caller
                    },
                    'interval': (1528029608, 1528116008)
                },
                '6caBcmLi33...:3:CL:41:0': {  # all attrs, one pred, default intervals to now on attrs & pred
                    'minima': {
                        'regEpoch': 1514782800
                    }
                }
                ...
            }

        :param cache_only: (True) take default intervals (per cred def id) from latest cached deltas, or
            (default False) use current time
        :return: indy-sdk proof request json

async def build_proof_req_json(self, cd_id2spec: dict, cache_only: bool = False) -> str:
        """
        Build and return indy-sdk proof request for input attributes and timestamps by cred def id.

        Raise AbsentInterval if caller specifies cache_only and default non-revocation intervals, but
        revocation cache does not have delta frames for any revocation registries on a specified cred def.

        :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) 'minima': (pred) integer lower-bounds of interest (omit, empty list, or None for none)
            - (optionally), 'interval': (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) if cache_only
                is clear, or latest values from cache if cache_only is set.
            e.g.,

        ::

            {
                'Vx4E82R17q...:3:CL:16:0': {
                    'attrs': [  # request attrs 'name' and 'favouriteDrink' from this cred def's schema
                        'name',
                        'favouriteDrink'
                    ],
                    'minima': {  # request predicate score>=80 from this cred def
                        'score': 80
                    }
                    'interval': 1528116008  # same instant for all attrs and preds of corresponding schema
                },
                'R17v42T4pk...:3:CL:19:0': None,  # request all attrs, no preds, default intervals on all attrs
                'e3vc5K168n...:3:CL:23:0': {},  # request all attrs, no preds, default intervals on all attrs
                'Z9ccax812j...:3:CL:27:0': {  # request all attrs, no preds, this interval on all attrs
                    'interval': (1528112408, 1528116008)
                },
                '9cHbp54C8n...:3:CL:37:0': {  # request no attrs, one pred, specify interval on pred
                    'attrs': [],  # or equivalently, 'attrs': None
                    'minima': {
                        'employees': '50'  # nicety: implementation converts to int for caller
                    },
                    'interval': (1528029608, 1528116008)
                },
                '6caBcmLi33...:3:CL:41:0': {  # all attrs, one pred, default intervals to now on attrs & pred
                    'minima': {
                        'regEpoch': 1514782800
                    }
                }
                ...
            }

        :param cache_only: (True) take default intervals (per cred def id) from latest cached deltas, or
            (default False) use current time
        :return: indy-sdk proof request json
        """

        LOGGER.debug('HolderProver.build_proof_req_json >>> cd_id2spec: %s, cache_only: %s', cd_id2spec, cache_only)

        cd_id2schema = {}
        now = int(time())
        proof_req = {
            'nonce': str(int(time())),
            'name': 'proof_req',
            'version': '0.0',
            'requested_attributes': {},
            'requested_predicates': {}
        }

        for cd_id in cd_id2spec:
            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']:
                if cache_only and not (cd_id2spec.get(cd_id, {}) or {}).get('interval', None):
                    with REVO_CACHE.lock:
                        (fro, to) = REVO_CACHE.dflt_interval(cd_id)
                        if not (fro and to):
                            LOGGER.debug(
                                'HolderProver.build_proof_req_json: <!< no cached delta for non-revoc interval on %s',
                                cd_id)
                            raise AbsentInterval('No cached delta for non-revoc interval on {}'.format(cd_id))
                        interval = {
                            'from': fro,
                            'to': to
                        }
                else:
                    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, attr)
                proof_req['requested_attributes'][attr_uuid] = {
                    'name': attr,
                    'restrictions': [{
                        'cred_def_id': cd_id
                    }]
                }
                if interval:
                    proof_req['requested_attributes'][attr_uuid]['non_revoked'] = interval

            for attr in (cd_id2spec[cd_id].get('minima', {}) or {} if cd_id2spec[cd_id] else {}):
                pred_uuid = '{}_{}_uuid'.format(seq_no, attr)
                try:
                    proof_req['requested_predicates'][pred_uuid] = {
                        'name': attr,
                        'p_type': '>=',
                        'p_value': int(cd_id2spec[cd_id]['minima'][attr]),
                        'restrictions': [{
                            'cred_def_id': cd_id
                        }]
                    }
                except ValueError:
                    LOGGER.info(
                        'cannot build predicate on non-int minimum %s for %s',
                        cd_id2spec[cd_id]['minima'][attr],
                        attr)
                    continue  # int conversion failed - reject candidate
                if interval:
                    proof_req['requested_predicates'][pred_uuid]['non_revoked'] = interval

        rv_json = json.dumps(proof_req)
        LOGGER.debug('HolderProver.build_proof_req_json <<< %s', rv_json)
        return rv_json