예제 #1
0
    async def _create_rev_reg(self, rr_id: str, rr_size: int = None) -> None:
        """
        Create revocation registry and new tails file (and association to
        corresponding revocation registry definition via symbolic link) for input
        revocation registry identifier.

        :param rr_id: revocation registry identifier
        :param rr_size: revocation registry size (defaults to 256)
        """

        LOGGER.debug('Issuer._create_rev_reg >>> rr_id: %s, rr_size: %s',
                     rr_id, rr_size)

        if not ok_rev_reg_id(rr_id):
            LOGGER.debug('Issuer._create_rev_reg <!< Bad rev reg id %s', rr_id)
            raise BadIdentifier('Bad rev reg id {}'.format(rr_id))

        rr_size = rr_size or 256
        (cd_id, tag) = rev_reg_id2cred_def_id_tag(rr_id)

        LOGGER.info(
            'Creating revocation registry (capacity %s) for rev reg id %s',
            rr_size, rr_id)
        tails_writer_handle = await blob_storage.open_writer(
            'default',
            json.dumps({
                'base_dir': Tails.dir(self._dir_tails, rr_id),
                'uri_pattern': ''
            }))
        apriori = Tails.unlinked(self._dir_tails)
        (rr_id, rrd_json,
         rre_json) = await anoncreds.issuer_create_and_store_revoc_reg(
             self.wallet.handle, self.did, 'CL_ACCUM', tag, cd_id,
             json.dumps({
                 'max_cred_num': rr_size,
                 'issuance_type': 'ISSUANCE_ON_DEMAND'
             }), tails_writer_handle)
        delta = Tails.unlinked(self._dir_tails) - apriori
        if len(delta) != 1:
            LOGGER.debug(
                'Issuer._create_rev_reg: <!< Could not create tails file for rev reg id: %s',
                rr_id)
            raise CorruptTails(
                'Could not create tails file for rev reg id {}'.format(rr_id))
        tails_hash = basename(delta.pop())
        Tails.associate(self._dir_tails, rr_id, tails_hash)

        with REVO_CACHE.lock:
            rrd_req_json = await ledger.build_revoc_reg_def_request(
                self.did, rrd_json)
            await self._sign_submit(rrd_req_json)
            await self._get_rev_reg_def(rr_id)  # add to cache en passant

        rre_req_json = await ledger.build_revoc_reg_entry_request(
            self.did, rr_id, 'CL_ACCUM', rre_json)
        await self._sign_submit(rre_req_json)

        LOGGER.debug('Issuer._create_rev_reg <<<')
예제 #2
0
    async def revoke_cred(self, rr_id: str, cr_id) -> int:
        """
        Revoke credential that input revocation registry identifier and
        credential revocation identifier specify.

        Return (epoch seconds) time of revocation.

        Raise AbsentTails if no tails file is available for input revocation registry identifier.
        Raise WalletState for closed wallet.
        Raise BadRevocation if issuer cannot revoke specified credential for any other reason
        (e.g., did not issue it, already revoked it).

        :param rr_id: revocation registry identifier
        :param cr_id: credential revocation identifier
        :return: time of revocation, in epoch seconds
        """

        LOGGER.debug('Issuer.revoke_cred >>> rr_id: %s, cr_id: %s', rr_id, cr_id)

        if not self.wallet.handle:
            LOGGER.debug('Issuer.revoke_cred <!< Wallet %s is closed', self.wallet.name)
            raise WalletState('Wallet {} is closed'.format(self.wallet.name))

        if not ok_rev_reg_id(rr_id):
            LOGGER.debug('Issuer.revoke_cred <!< Bad rev reg id %s', rr_id)
            raise BadIdentifier('Bad rev reg id {}'.format(rr_id))

        tails_reader_handle = (await Tails(
            self._dir_tails,
            *rev_reg_id2cred_def_id_tag(rr_id)).open()).reader_handle
        try:
            rrdelta_json = await anoncreds.issuer_revoke_credential(
                self.wallet.handle,
                tails_reader_handle,
                rr_id,
                cr_id)
        except IndyError as x_indy:
            LOGGER.debug(
                'Issuer.revoke_cred <!< Could not revoke revoc reg id %s, cred rev id %s: indy error code %s',
                rr_id,
                cr_id,
                x_indy.error_code)
            raise BadRevocation(
                'Could not revoke revoc reg id {}, cred rev id {}: indy error code {}'.format(
                    rr_id,
                    cr_id,
                    x_indy.error_code))

        rr_ent_req_json = await ledger.build_revoc_reg_entry_request(self.did, rr_id, 'CL_ACCUM', rrdelta_json)
        resp_json = await self._sign_submit(rr_ent_req_json)  # raises AbsentPool or ClosedPool if applicable
        resp = json.loads(resp_json)

        rv = self.pool.protocol.txn2epoch(resp)
        LOGGER.debug('Issuer.revoke_cred <<< %s', rv)
        return rv
예제 #3
0
    async def _sync_revoc_for_issue(self,
                                    rr_id: str,
                                    rr_size: int = None) -> None:
        """
        Create revocation registry if need be for input revocation registry identifier;
        open and cache tails file reader.

        :param rr_id: revocation registry identifier
        :param rr_size: if new revocation registry necessary, its size (default as per RevRegBuilder.create_rev_reg())
        """

        LOGGER.debug('Issuer._sync_revoc_for_issue >>> rr_id: %s, rr_size: %s',
                     rr_id, rr_size)

        if not ok_rev_reg_id(rr_id):
            LOGGER.debug('Issuer._sync_revoc_for_issue <!< Bad rev reg id %s',
                         rr_id)
            raise BadIdentifier('Bad rev reg id {}'.format(rr_id))

        (cd_id, tag) = rev_reg_id2cred_def_id_tag(rr_id)

        try:
            await self.get_cred_def(cd_id)
        except AbsentCredDef:
            LOGGER.debug(
                'Issuer._sync_revoc_for_issue <!< tails tree %s may be for another ledger; no cred def found on %s',
                self.dir_tails, cd_id)
            raise AbsentCredDef(
                'Tails tree {} may be for another ledger; no cred def found on {}'
                .format(self.dir_tails, cd_id))

        with REVO_CACHE.lock:
            revo_cache_entry = REVO_CACHE.get(rr_id, None)
            tails = None if revo_cache_entry is None else revo_cache_entry.tails
            if tails is None:  #  it's a new revocation registry, or not yet set in cache
                try:
                    tails = await Tails(self.dir_tails, cd_id, tag).open()
                except AbsentTails:  # it's a new revocation registry
                    if self.rrbx:
                        await self._set_rev_reg(rr_id, rr_size)
                    else:
                        await self.rrb.create_rev_reg(rr_id, rr_size)
                        await self._send_rev_reg_def(rr_id)
                    tails = await Tails(self.dir_tails, cd_id,
                                        tag).open()  # symlink should exist now

                if revo_cache_entry is None:
                    REVO_CACHE[rr_id] = RevoCacheEntry(None, tails)
                else:
                    REVO_CACHE[rr_id].tails = tails

        LOGGER.debug('Issuer._sync_revoc_for_issue <<<')
예제 #4
0
    async def create_rev_reg(self, rr_id: str, rr_size: int = None) -> None:
        """
        Create revocation registry artifacts and new tails file (with association to
        corresponding revocation registry identifier via symbolic link name)
        for input revocation registry identifier. Symbolic link presence signals completion.
        If revocation registry builder operates in a process external to its Issuer's,
        target directory is hopper directory.

        Raise WalletState for closed wallet.

        :param rr_id: revocation registry identifier
        :param rr_size: revocation registry size (defaults to 64)
        """

        LOGGER.debug('RevRegBuilder.create_rev_reg >>> rr_id: %s, rr_size: %s',
                     rr_id, rr_size)

        if not self.wallet.handle:
            LOGGER.debug(
                'RevRegBuilder.create_rev_reg <!< Wallet %s is closed',
                self.name)
            raise WalletState('Wallet {} is closed'.format(self.name))

        if not ok_rev_reg_id(rr_id):
            LOGGER.debug('RevRegBuilder.create_rev_reg <!< Bad rev reg id %s',
                         rr_id)
            raise BadIdentifier('Bad rev reg id {}'.format(rr_id))

        rr_size = rr_size or 64

        (cd_id, tag) = rev_reg_id2cred_def_id_tag(rr_id)

        dir_tails = self.dir_tails_top(rr_id)
        dir_target = self.dir_tails_target(rr_id)
        if self.external:
            try:
                makedirs(dir_target, exist_ok=False)
            except FileExistsError:
                LOGGER.warning(
                    'RevRegBuilder.create_rev_reg found dir %s, but task not in progress: rebuilding rev reg %s',
                    dir_target, rr_id)
                rmtree(dir_target)
                makedirs(dir_target, exist_ok=False)

        LOGGER.info(
            'Creating revocation registry (capacity %s) for rev reg id %s',
            rr_size, rr_id)
        tails_writer_handle = await blob_storage.open_writer(
            'default', json.dumps({
                'base_dir': dir_target,
                'uri_pattern': ''
            }))

        (created_rr_id, rr_def_json,
         rr_ent_json) = await anoncreds.issuer_create_and_store_revoc_reg(
             self.wallet.handle, self.did, 'CL_ACCUM', tag, cd_id,
             json.dumps({
                 'max_cred_num': rr_size,
                 'issuance_type': 'ISSUANCE_BY_DEFAULT'
             }), tails_writer_handle)

        tails_hash = basename(Tails.unlinked(dir_target).pop())
        with open(join(dir_target, 'rr_def.json'), 'w') as rr_def_fh:
            print(rr_def_json, file=rr_def_fh)
        with open(join(dir_target, 'rr_ent.json'), 'w') as rr_ent_fh:
            print(rr_ent_json, file=rr_ent_fh)
        Tails.associate(
            dir_tails, created_rr_id,
            tails_hash)  # associate last: symlink signals completion

        LOGGER.debug('RevRegBuilder.create_rev_reg <<<')