Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

admin api for generic tails file upload #125

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions anoncreds_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ async def main():
"maxCredNum": 10,
},
)
rev_reg_def_id = rev_reg_def["revocation_registry_definition_state"][
"revocation_registry_definition_id"
]
tails = await alice.put(
f"/anoncreds/registry/{rev_reg_def_id}/tails-file",
)
rev_status_list = await alice.post(
"/anoncreds/revocation-list",
json={
Expand Down
4 changes: 2 additions & 2 deletions aries_cloudagent/anoncreds/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
)
from .models.anoncreds_revocation import (
GetRevListResult,
AnonCredsRegistryGetRevocationRegistryDefinition,
GetRevRegDefResult,
RevRegDef,
RevRegDefResult,
RevList,
Expand Down Expand Up @@ -115,7 +115,7 @@ async def get_credential_definition(
@abstractmethod
async def get_revocation_registry_definition(
self, profile: Profile, revocation_registry_id: str
) -> AnonCredsRegistryGetRevocationRegistryDefinition:
) -> GetRevRegDefResult:
"""Get a revocation registry definition from the registry."""

@abstractmethod
Expand Down
4 changes: 2 additions & 2 deletions aries_cloudagent/anoncreds/default/did_indy/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
)
from ...models.anoncreds_revocation import (
GetRevListResult,
AnonCredsRegistryGetRevocationRegistryDefinition,
GetRevRegDefResult,
RevRegDef,
RevRegDefResult,
RevList,
Expand Down Expand Up @@ -70,7 +70,7 @@ async def register_credential_definition(

async def get_revocation_registry_definition(
self, profile: Profile, revocation_registry_id: str
) -> AnonCredsRegistryGetRevocationRegistryDefinition:
) -> GetRevRegDefResult:
"""Get a revocation registry definition from the registry."""
raise NotImplementedError()

Expand Down
19 changes: 4 additions & 15 deletions aries_cloudagent/anoncreds/default/did_web/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,15 @@

from ....config.injection_context import InjectionContext
from ....core.profile import Profile
from ...models.anoncreds_cred_def import (
GetCredDefResult,
)
from ...models.anoncreds_revocation import (
GetRevListResult,
AnonCredsRegistryGetRevocationRegistryDefinition,
RevRegDef,
RevList,
RevListResult,
)
from ...models.anoncreds_schema import GetSchemaResult
from ...base import BaseAnonCredsRegistrar, BaseAnonCredsResolver
from ...models.anoncreds_cred_def import CredDef, CredDefResult, GetCredDefResult
from ...models.anoncreds_revocation import (
AnonCredsRegistryGetRevocationRegistryDefinition,
GetRevListResult,
RevRegDef,
RevRegDefResult,
GetRevRegDefResult,
RevList,
RevListResult,
RevRegDef,
RevRegDefResult,
)
from ...models.anoncreds_schema import AnonCredsSchema, GetSchemaResult, SchemaResult

Expand Down Expand Up @@ -76,7 +65,7 @@ async def register_credential_definition(

async def get_revocation_registry_definition(
self, profile: Profile, revocation_registry_id: str
) -> AnonCredsRegistryGetRevocationRegistryDefinition:
) -> GetRevRegDefResult:
"""Get a revocation registry definition from the registry."""
raise NotImplementedError()

Expand Down
55 changes: 44 additions & 11 deletions aries_cloudagent/anoncreds/default/legacy_indy/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@
IndyLedgerRequestsExecutor,
)
from ....multitenant.base import BaseMultitenantManager
from ....revocation.anoncreds import AnonCredsRevocation
from ....revocation.models.issuer_cred_rev_record import IssuerCredRevRecord
from ....revocation.recover import generate_ledger_rrrecovery_txn
from ....storage.error import StorageNotFoundError
from ...base import (
AnonCredsObjectAlreadyExists,
AnonCredsObjectNotFound,
Expand All @@ -41,14 +39,15 @@
GetCredDefResult,
)
from ...models.anoncreds_revocation import (
AnonCredsRegistryGetRevocationRegistryDefinition,
GetRevRegDefResult,
GetRevListResult,
RevRegDef,
RevRegDefResult,
RevRegDefState,
RevList,
RevListResult,
RevListState,
RevRegDefValue,
)
from ...models.anoncreds_schema import (
AnonCredsSchema,
Expand Down Expand Up @@ -357,17 +356,51 @@ async def register_credential_definition(

async def get_revocation_registry_definition(
self, profile: Profile, rev_reg_def_id: str
) -> AnonCredsRegistryGetRevocationRegistryDefinition:
) -> GetRevRegDefResult:
"""Get a revocation registry definition from the registry."""
async with profile.session() as session:
multitenant_mgr = session.inject_or(BaseMultitenantManager)
if multitenant_mgr:
ledger_exec_inst = IndyLedgerRequestsExecutor(profile)
else:
ledger_exec_inst = session.inject(IndyLedgerRequestsExecutor)

try:
revoc = AnonCredsRevocation(profile)
rev_reg = await revoc.get_issuer_rev_reg_record(rev_reg_def_id)
except StorageNotFoundError as err:
raise AnonCredsResolutionError(err)
ledger_id, ledger = await ledger_exec_inst.get_ledger_for_identifier(
rev_reg_def_id,
txn_record_type=GET_CRED_DEF,
)
if not ledger:
reason = "No ledger available"
if not profile.settings.get_value("wallet.type"):
reason += ": missing wallet-type?"
raise AnonCredsResolutionError(reason)

async with ledger:
rev_reg_def = await ledger.get_revoc_reg_def(rev_reg_def_id)

return rev_reg.serialize
# use AnonCredsRevocationRegistryDefinition object
if rev_reg_def is None:
raise AnonCredsObjectNotFound(
f"Revocation registry definition not found: {rev_reg_def_id}",
{"ledger_id": ledger_id},
)

LOGGER.debug("Retrieved revocation registry definition: %s", rev_reg_def)
rev_reg_def_value = RevRegDefValue.deserialize(rev_reg_def["value"])
anoncreds_rev_reg_def = RevRegDef(
issuer_id=rev_reg_def["id"].split(":")[0],
cred_def_id=rev_reg_def["credDefId"],
type=rev_reg_def["revocDefType"],
value=rev_reg_def_value,
tag=rev_reg_def["tag"],
)
result = GetRevRegDefResult(
revocation_registry=anoncreds_rev_reg_def,
revocation_registry_id=rev_reg_def["id"],
resolution_metadata={},
revocation_registry_metadata={},
)

return result

async def get_revocation_registry_definitions(self, profile: Profile, filter: str):
"""Get credential definition ids filtered by filter"""
Expand Down
25 changes: 22 additions & 3 deletions aries_cloudagent/anoncreds/issuer.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,6 @@ async def create_and_register_revocation_registry_definition(
except AnoncredsError as err:
raise AnonCredsIssuerError("Error creating revocation registry") from err

rev_reg_def_json = rev_reg_def.to_json()
rev_reg_def = RevRegDef.from_native(rev_reg_def)

public_tails_uri = self.get_public_tails_uri(rev_reg_def)
Expand All @@ -572,6 +571,7 @@ async def create_and_register_revocation_registry_definition(
)

rev_reg_def_id = result.rev_reg_def_id
rev_reg_def_json = rev_reg_def.to_json()

try:
async with self._profile.transaction() as txn:
Expand Down Expand Up @@ -639,13 +639,16 @@ async def upload_tails_file(self, rev_reg_def: RevRegDef):
if not upload_success:
raise AnonCredsIssuerError(
f"Tails file for rev reg for {rev_reg_def.cred_def_id} "
"failed to upload: {result}"
f"failed to upload: {result}"
)
if rev_reg_def.value.tails_location != result:
raise AnonCredsIssuerError(
f"Tails file for rev reg for {rev_reg_def.cred_def_id} "
"uploaded to wrong location: {result}"
f"uploaded to wrong location: {result} "
f"(should have been {rev_reg_def.value.tails_location})"
)
# TODO: do we need to set uri? something like..
# await self.set_tails_file_public_uri(profile, result)

async def update_revocation_registry_definition_state(
self, rev_reg_def_id: str, state: str
Expand Down Expand Up @@ -681,6 +684,22 @@ async def get_created_revocation_registry_definitions(
# entry.name was stored as the credential_definition's ID
return [entry.name for entry in rev_reg_defs]

async def get_created_revocation_registry_definition(
self,
rev_reg_def_id: str,
) -> Optional[RevRegDef]:
"""Retrieve rev reg def by ID from rev reg defs previously created."""
async with self._profile.session() as session:
rev_reg_def_entry = await session.handle.fetch(
CATEGORY_REV_REG_DEF,
name=rev_reg_def_id,
)

if rev_reg_def_entry:
return RevRegDef.deserialize(rev_reg_def_entry.value_json)

return None

async def create_and_register_revocation_list(
self, rev_reg_def_id: str, options: Optional[dict] = None
):
Expand Down
14 changes: 7 additions & 7 deletions aries_cloudagent/anoncreds/models/anoncreds_revocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,13 @@ class Meta:
revocation_registry_definition_metadata = fields.Dict()


class AnonCredsRegistryGetRevocationRegistryDefinition(BaseModel):
"""AnonCredsRegistryGetRevocationRegistryDefinition"""
class GetRevRegDefResult(BaseModel):
"""GetRevRegDefResult"""

class Meta:
"""AnonCredsRegistryGetRevocationRegistryDefinition metadata."""
"""GetRevRegDefResult metadata."""

schema_class = "AnonCredsRegistryGetRevocationRegistryDefinitionSchema"
schema_class = "GetRevRegDefResultSchema"

def __init__(
self,
Expand All @@ -228,11 +228,11 @@ def __init__(
self.revocation_registry_metadata = revocation_registry_metadata


class AnonCredsRegistryGetRevocationRegistryDefinitionSchema(BaseModelSchema):
class GetRevRegDefResultSchema(BaseModelSchema):
class Meta:
"""AnonCredsRegistryGetRevocationRegistryDefinitionSchema metadata."""
"""GetRevRegDefResultSchema metadata."""

model_class = AnonCredsRegistryGetRevocationRegistryDefinition
model_class = GetRevRegDefResult
unknown = EXCLUDE

revocation_registry = fields.Nested(RevRegDefSchema())
Expand Down
4 changes: 2 additions & 2 deletions aries_cloudagent/anoncreds/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
)
from .models.anoncreds_revocation import (
GetRevListResult,
AnonCredsRegistryGetRevocationRegistryDefinition,
GetRevRegDefResult,
RevRegDef,
RevRegDefResult,
RevList,
Expand Down Expand Up @@ -119,7 +119,7 @@ async def register_credential_definition(

async def get_revocation_registry_definition(
self, profile: Profile, revocation_registry_id: str
) -> AnonCredsRegistryGetRevocationRegistryDefinition:
) -> GetRevRegDefResult:
"""Get a revocation registry definition from the registry."""
resolver = await self._resolver_for_identifier(revocation_registry_id)
return await resolver.get_revocation_registry_definition(
Expand Down
57 changes: 49 additions & 8 deletions aries_cloudagent/anoncreds/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
response_schema,
)
from marshmallow import fields
from aries_cloudagent.askar.profile import AskarProfile

from aries_cloudagent.revocation.routes import (
RevRegIdMatchInfoSchema,
RevocationModuleResponseSchema,
)

from ..admin.request_context import AdminRequestContext
from ..messaging.models.openapi import OpenAPISchema
Expand Down Expand Up @@ -371,17 +377,18 @@ async def rev_reg_def_post(request: web.BaseRequest):
)

try:
revoc = AnonCredsRevocation(context.profile)
issuer_rev_reg_rec = await revoc.init_issuer_registry(
issuer_id,
cred_def_id,
max_cred_num=max_cred_num,
options=options,
notify=False,
result = await shield(
issuer.create_and_register_revocation_registry_definition(
issuer_id,
cred_def_id,
registry_type="CL_ACCUM",
max_cred_num=max_cred_num,
tag="default",
options=options,
)
)
except RevocationNotSupportedError as e:
raise web.HTTPBadRequest(reason=e.message) from e
result = await shield(issuer_rev_reg_rec.create_and_register_def(context.profile))

return web.json_response(result.serialize())

Expand Down Expand Up @@ -439,6 +446,39 @@ async def rev_list_post(request: web.BaseRequest):
return web.json_response(result.serialize())


@docs(
tags=["revocation"],
summary="Upload local tails file to server",
)
@match_info_schema(RevRegIdMatchInfoSchema())
@response_schema(RevocationModuleResponseSchema(), description="")
async def upload_tails_file(request: web.BaseRequest):
"""
Request handler to upload local tails file for revocation registry.

Args:
request: aiohttp request object

"""
context: AdminRequestContext = request["context"]
profile: AskarProfile = context.profile
rev_reg_id = request.match_info["rev_reg_id"]
try:
issuer = AnonCredsIssuer(profile)
rev_reg_def = await issuer.get_created_revocation_registry_definition(
rev_reg_id
)
if rev_reg_def is None:
raise web.HTTPNotFound(reason="No rev reg def found")

await issuer.upload_tails_file(rev_reg_def)

except AnonCredsIssuerError as e:
raise web.HTTPInternalServerError(reason=str(e)) from e

return web.json_response({})


async def register(app: web.Application):
"""Register routes."""

Expand All @@ -460,6 +500,7 @@ async def register(app: web.Application):
),
web.post("/anoncreds/revocation-registry-definition", rev_reg_def_post),
web.post("/anoncreds/revocation-list", rev_list_post),
web.put("/anoncreds/registry/{rev_reg_id}/tails-file", upload_tails_file),
]
)

Expand Down
Loading