def revoc_info(creds: dict, filt: dict = None) -> dict:
rv = {}<EOL>for uuid2creds in (creds.get('<STR_LIT>', {}), creds.get('<STR_LIT>', {})):<EOL><INDENT>for inner_creds in uuid2creds.values():<EOL><INDENT>for cred in inner_creds:<EOL><INDENT>cred_info = cred['<STR_LIT>']<EOL>(rr_id, cr_id) = (cred_info['<STR_LIT>'], cred_info['<STR_LIT>'])<EOL>if (rr_id, cr_id) in rv or rr_id is None or cr_id is None:<EOL><INDENT>continue<EOL><DEDENT>if not filt:<EOL><INDENT>rv[(rr_id, cr_id)] = cred_info['<STR_LIT>']<EOL>continue<EOL><DEDENT>if ({attr: str(filt[attr]) for attr in filt}.items() <= cred_info['<STR_LIT>'].items()):<EOL><INDENT>rv[(rr_id, cr_id)] = cred_info['<STR_LIT>']<EOL><DEDENT><DEDENT><DEDENT><DEDENT>return rv<EOL>
Given a creds structure, return a dict mapping pairs
(revocation registry identifier, credential revocation identifier)
to (decoded) attribute name:value dicts.

If the caller includes a filter of attribute:value pairs, retain only matching attributes.

:param creds: creds structure returned by HolderProver.get_creds() as above
:param filt: dict mapping attributes to values of interest; e.g.,

::

    {
        'legalName': 'Flan Nebula',
        'effectiveDate': '2018-01-01',
        'endDate': None
    }

:return: dict mapping (rev_reg_id, cred_rev_id) pairs to decoded attributes