Esempio n. 1
0
    async def _build_rr_state_json(self, rr_id: str,
                                   timestamp: int) -> (str, int):
        """
        Build rev reg state json at a given requested timestamp.

        Return rev reg state json and its transaction time on the distributed ledger,
        with upper bound at input timestamp of interest.

        Raise AbsentRevReg if no revocation registry exists on input rev reg id,
        or BadRevStateTime if requested timestamp predates revocation registry creation.

        :param rr_id: rev reg id
        :param timestamp: timestamp of interest (epoch seconds)
        :return: rev reg state json and ledger timestamp (epoch seconds)
        """

        LOGGER.debug(
            '_Verifier._build_rr_state_json >>> rr_id: %s, timestamp: %s',
            rr_id, timestamp)

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

        rr_json = None
        ledger_timestamp = None

        get_rr_req_json = await ledger.build_get_revoc_reg_request(
            self.did, rr_id, timestamp)
        resp_json = await self._submit(get_rr_req_json)
        resp = json.loads(resp_json)
        if resp.get('result', {}).get(
                'data', None) and resp['result']['data'].get('value', None):
            # timestamp at or beyond rev reg creation, carry on
            try:
                (_, rr_json, ledger_timestamp
                 ) = await ledger.parse_get_revoc_reg_response(resp_json)
            except IndyError:  # ledger replied, but there is no such rev reg available
                LOGGER.debug(
                    'Verifier._build_rr_state_json <!< no rev reg exists on %s',
                    rr_id)
                raise AbsentRevReg('No rev reg exists on {}'.format(rr_id))
        else:
            LOGGER.debug(
                '_Verifier._build_rr_state_json <!< Rev reg %s created after asked-for time %s',
                rr_id, timestamp)
            raise BadRevStateTime(
                'Rev reg {} created after asked-for time {}'.format(
                    rr_id, timestamp))

        rv = (rr_json, ledger_timestamp)
        LOGGER.debug('_Verifier._build_rr_state_json <<< %s', rv)
        return rv
Esempio n. 2
0
    async def _get_rev_reg_def(self, rr_id: str) -> str:
        """
        Get revocation registry definition from ledger by its identifier. Raise AbsentRevReg
        for no such revocation registry, logging any error condition and raising BadLedgerTxn
        on bad request.

        Retrieve the revocation registry definition from the anchor's revocation cache if it has it;
        cache it en passant if it does not (and such a revocation registry definition exists on the ledger).

        :param rr_id: (revocation registry) identifier string, of the format
            '<issuer-did>:4:<issuer-did>:3:CL:<schema-seq-no>:<tag>:CL_ACCUM:<tag>'
        :return: revocation registry definition json as retrieved from ledger
        """

        LOGGER.debug('_BaseAnchor._get_rev_reg_def >>> rr_id: %s', rr_id)

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

        rv_json = json.dumps({})

        with REVO_CACHE.lock:
            revo_cache_entry = REVO_CACHE.get(rr_id, None)
            rr_def = revo_cache_entry.rev_reg_def if revo_cache_entry else None
            if rr_def:
                LOGGER.info(
                    '_BaseAnchor._get_rev_reg_def: rev reg def for %s from cache',
                    rr_id)
                rv_json = json.dumps(rr_def)
            else:
                get_rrd_req_json = await ledger.build_get_revoc_reg_def_request(
                    self.did, rr_id)
                resp_json = await self._submit(get_rrd_req_json)
                try:
                    (_,
                     rv_json) = await ledger.parse_get_revoc_reg_def_response(
                         resp_json)
                    rr_def = json.loads(rv_json)
                except IndyError:  # ledger replied, but there is no such rev reg
                    LOGGER.debug(
                        '_BaseAnchor._get_rev_reg_def: <!< no rev reg exists on %s',
                        rr_id)
                    raise AbsentRevReg('No rev reg exists on {}'.format(rr_id))

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

        LOGGER.debug('_BaseAnchor._get_rev_reg_def <<< %s', rv_json)
        return rv_json
Esempio n. 3
0
    async def _send_rev_reg_def(self, rr_id: str) -> None:
        """
        Move tails file from hopper; deserialize revocation registry definition and initial entry;
        send to ledger and cache revocation registry definition.

        Operation serializes to subdirectory within tails hopper directory; symbolic
        link presence signals completion.

        Raise AbsentRevReg if revocation registry is not ready in hopper, or AbsentTails if
        tails file is not yet linked by its revocation registry identifier.

        :param rr_id: revocation registry identifier
        """

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

        dir_tails_rr_id = self.rrb.dir_tails_top(rr_id)
        dir_target = self.rrb.dir_tails_target(rr_id)

        if not Tails.linked(dir_tails_rr_id, rr_id):
            LOGGER.debug(
                'Issuer._send_rev_reg_def <!< Tails file for rev reg %s not ready in dir %s',
                rr_id, dir_target)
            raise AbsentRevReg(
                'Tails file for rev reg {} not ready in dir {}'.format(
                    rr_id, dir_target))

        file_rr_def = join(dir_target, 'rr_def.json')
        if not isfile(file_rr_def):
            LOGGER.debug(
                'Issuer._send_rev_reg_def <!< Rev reg def file %s not present',
                file_rr_def)
            raise AbsentRevReg(
                'Rev reg def file {} not present'.format(file_rr_def))
        with open(file_rr_def, 'r') as fh_rr_def:
            rr_def_json = fh_rr_def.read()

        file_rr_ent = join(dir_target, 'rr_ent.json')
        if not isfile(file_rr_ent):
            LOGGER.debug(
                'Issuer._send_rev_reg_def <!< Rev reg entry file %s not present',
                file_rr_ent)
            raise AbsentRevReg(
                'Rev reg entry file {} not present'.format(file_rr_ent))
        with open(file_rr_ent, 'r') as fh_rr_ent:
            rr_ent_json = fh_rr_ent.read()

        file_tails = Tails.linked(dir_tails_rr_id, rr_id)
        if not file_tails:
            LOGGER.debug(
                'Issuer._send_rev_reg_def <!< Tails link %s not present in dir %s',
                rr_id, dir_target)
            raise AbsentTails('Tails link {} not present in dir {}'.format(
                rr_id, dir_target))

        if self.rrbx:
            dir_cd_id = join(self.dir_tails, rev_reg_id2cred_def_id(rr_id))
            makedirs(dir_cd_id, exist_ok=True)
            rename(file_tails, join(dir_cd_id, basename(file_tails)))

        with REVO_CACHE.lock:
            rr_def_req_json = await ledger.build_revoc_reg_def_request(
                self.did, rr_def_json)
            await self._sign_submit(rr_def_req_json)
            await self.get_rev_reg_def(rr_id)  # add to cache en passant

        rr_ent_req_json = await ledger.build_revoc_reg_entry_request(
            self.did, rr_id, 'CL_ACCUM', rr_ent_json)
        await self._sign_submit(rr_ent_req_json)

        if self.rrbx:
            Tails.associate(self.dir_tails, rr_id, basename(file_tails))
            rmtree(dir_tails_rr_id)
        else:
            remove(file_rr_def)
            remove(file_rr_ent)

        LOGGER.debug('Issuer._send_rev_reg_def <<<')