<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 async def get_creds(self, proof_req_json: str, filt: dict = None, filt_dflt_incl: bool = False) -> (Set[str], str):
 """ Get credentials from HolderProver wallet corresponding to proof request and filter criteria; return credential identifiers from wallet and credentials json. Return empty set and empty production for no such credentials. :param proof_req_json: proof request json as Verifier creates; has entries for proof request's nonce, name, and version; plus credential's requested attributes, requested predicates. I.e., :: { 'nonce': string, # indy-sdk makes no semantic specification on this value 'name': string, # indy-sdk makes no semantic specification on this value 'version': numeric-string, # indy-sdk makes no semantic specification on this value 'requested_attributes': { '<attr_uuid>': { # aka attr_referent, a proof-request local identifier 'name': string, # attribute name (matches case- and space-insensitively) 'restrictions' [ # optional { "schema_id": string, # optional "schema_issuer_did": string, # optional "schema_name": string, # optional "schema_version": string, # optional "issuer_did": string, # optional "cred_def_id": string # optional }, { } ], 'non_revoked': { # optional - indy-sdk ignores when getting creds from wallet 'from': int, # optional, epoch seconds 'to': int # optional, epoch seconds } }, }, 'requested_predicates': { '<pred_uuid>': { # aka predicate_referent, a proof-request local predicate identifier 'name': string, # attribute name (matches case- and space-insensitively) 'p_type': '>=', 'p_value': int, # predicate value 'restrictions': [ # optional { "schema_id": string, # optional "schema_issuer_did": string, # optional "schema_name": string, # optional "schema_version": string, # optional "issuer_did": string, # optional "cred_def_id": string # optional }, { } ], 'non_revoked': { # optional - indy-sdk ignores when getting creds from wallet 'from': int, # optional, epoch seconds 'to': int # optional, epoch seconds } }, }, 'non_revoked': { # optional - indy-sdk ignores when getting creds from wallet 'from': Optional<int>, 'to': Optional<int> } } :param filt: filter for matching attribute-value pairs and predicates; dict mapping each cred def id to dict (specify empty dict or none for no filter, matching all) mapping attributes to values to match or compare. E.g., :: { 'attr-match': { 'name': 'Alex', 'sex': 'M', 'favouriteDrink': None }, 'minima': { # if both attr-match and minima present, combined conjunctively (i.e., via AND) 'favouriteNumber' : 10, 'score': '100' # nicety: implementation converts to int for caller }, }, 'attr-match': { 'height': 175, 'birthdate': '1975-11-15' # combined conjunctively (i.e., via AND) } }, 'attr-match': {} # match all attributes on this cred def } } :param filt_dflt_incl: whether to include (True) all credentials from wallet that filter does not identify by cred def, or to exclude (False) all such credentials :return: tuple with (set of referents, creds json for input proof request); empty set and empty production for no such credential """


        LOGGER.debug('HolderProver.get_creds >>> proof_req_json: %s, filt: %s', proof_req_json, filt)

        if filt is None:
            filt = {}
        rv = None
        creds_json = await anoncreds.prover_get_credentials_for_proof_req(self.wallet.handle, proof_req_json)
        creds = json.loads(creds_json)
        cred_ids = set()

        if filt:
            for cd_id in filt:
                try:
                    json.loads(await self.get_cred_def(cd_id))
                except AbsentCredDef:
                    LOGGER.warning('HolderProver.get_creds: ignoring filter criterion, no cred def on %s', cd_id)
                    filt.pop(cd_id)

        for inner_creds in {**creds['attrs'], **creds['predicates']}.values():
            for cred in inner_creds:  # cred is a dict in a list of dicts
                cred_info = cred['cred_info']
                if filt:
                    cred_cd_id = cred_info['cred_def_id']
                    if cred_cd_id not in filt:
                        if filt_dflt_incl:
                            cred_ids.add(cred_info['referent'])
                        continue
                    if 'attr-match' in (filt[cred_cd_id] or {}):  # maybe filt[cred_cd_id]: None
                        if not {k: str(filt[cred_cd_id].get('attr-match', {})[k])
                                for k in filt[cred_cd_id].get('attr-match', {})}.items() <= cred_info['attrs'].items():
                            continue
                    if 'minima' in (filt[cred_cd_id] or {}):  # maybe filt[cred_cd_id]: None
                        minima = filt[cred_cd_id].get('minima', {})
                        try:
                            if any((attr not in cred_info['attrs'])
                                or (int(cred_info['attrs'][attr]) < int(minima[attr]))
                                    for attr in minima):
                                continue
                        except ValueError:
                            continue  # int conversion failed - reject candidate
                    cred_ids.add(cred_info['referent'])
                else:
                    cred_ids.add(cred_info['referent'])

        if filt:
            creds = json.loads(prune_creds_json(creds, cred_ids))

        rv = (cred_ids, json.dumps(creds))
        LOGGER.debug('HolderProver.get_creds <<< %s', rv)
        return rv