def revoc_info(creds: dict, filt: dict = None) -> dict:
    """
    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
    """

    rv = {}
    for uuid2creds in (creds.get('attrs', {}), creds.get('predicates', {})):
        for inner_creds in uuid2creds.values():
            for cred in inner_creds:
                cred_info = cred['cred_info']
                (rr_id, cr_id) = (cred_info['rev_reg_id'], cred_info['cred_rev_id'])
                if (rr_id, cr_id) in rv or rr_id is None or cr_id is None:
                    continue
                if not filt:
                    rv[(rr_id, cr_id)] = cred_info['attrs']
                    continue
                if ({attr: str(filt[attr]) for attr in filt}.items() <= cred_info['attrs'].items()):
                    rv[(rr_id, cr_id)] = cred_info['attrs']
    return rv