Skip to content

Commit

Permalink
revert uploaded state for IssuerRevRegRecord; fix interaction with tr…
Browse files Browse the repository at this point in the history
…ansaction endorsement

Signed-off-by: Andrew Whitehead <[email protected]>
  • Loading branch information
andrewwhitehead committed Jun 18, 2022
1 parent 4e4143e commit 4dc3188
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 66 deletions.
22 changes: 5 additions & 17 deletions aries_cloudagent/protocols/endorse_transaction/v1_0/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
from ....messaging.credential_definitions.util import notify_cred_def_event
from ....messaging.schemas.util import notify_schema_event
from ....revocation.util import (
notify_revocation_entry_event,
notify_revocation_reg_endorsed_event,
notify_revocation_entry_endorsed_event,
)
from ....storage.error import StorageError, StorageNotFoundError
from ....transport.inbound.receipt import MessageReceipt
Expand Down Expand Up @@ -777,30 +777,18 @@ async def endorsed_txn_post_processing(
# revocation registry transaction
rev_reg_id = ledger_response["result"]["txnMetadata"]["txnId"]
meta_data["context"]["rev_reg_id"] = rev_reg_id
auto_create_rev_reg = meta_data["processing"].get(
"auto_create_rev_reg", False
await notify_revocation_reg_endorsed_event(
self._profile, rev_reg_id, meta_data
)

# If "auto_processing" is enabled, also create the revocation entry record
if auto_create_rev_reg:
await notify_revocation_entry_event(
self._profile, rev_reg_id, meta_data
)

elif ledger_response["result"]["txn"]["type"] == "114":
# revocation entry transaction
rev_reg_id = ledger_response["result"]["txn"]["data"]["revocRegDefId"]
meta_data["context"]["rev_reg_id"] = rev_reg_id
auto_create_rev_reg = meta_data["processing"].get(
"auto_create_rev_reg", False
await notify_revocation_entry_endorsed_event(
self._profile, rev_reg_id, meta_data
)

# If "auto_processing" is enabled, also upload tails file for this registry
if auto_create_rev_reg:
await notify_revocation_reg_endorsed_event(
self._profile, rev_reg_id, meta_data
)

elif ledger_response["result"]["txn"]["type"] == "1":
# write DID to ledger
did = ledger_response["result"]["txn"]["data"]["dest"]
Expand Down
14 changes: 8 additions & 6 deletions aries_cloudagent/revocation/indy.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ async def init_issuer_registry(
tag: str = None,
create_pending_rev_reg: bool = False,
endorser_connection_id: str = None,
notify: bool = True,
) -> "IssuerRevRegRecord":
"""Create a new revocation registry record for a credential definition."""
multitenant_mgr = self._profile.inject_or(BaseMultitenantManager)
Expand Down Expand Up @@ -86,12 +87,13 @@ async def init_issuer_registry(
if not endorser_connection_id:
raise RevocationError(reason="Endorser connection not found")

await notify_revocation_reg_init_event(
self._profile,
record.record_id,
create_pending_rev_reg=create_pending_rev_reg,
endorser_connection_id=endorser_connection_id,
)
if notify:
await notify_revocation_reg_init_event(
self._profile,
record.record_id,
create_pending_rev_reg=create_pending_rev_reg,
endorser_connection_id=endorser_connection_id,
)

return record

Expand Down
14 changes: 5 additions & 9 deletions aries_cloudagent/revocation/models/issuer_rev_reg_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ class Meta:
STATE_INIT = "init"
STATE_GENERATED = "generated"
STATE_POSTED = "posted" # definition published
STATE_UPLOADED = "uploaded" # tails file uploaded
STATE_ACTIVE = "active" # initial entry published, possibly subsequent entries
STATE_FULL = "full" # includes corrupt

Expand Down Expand Up @@ -279,7 +278,7 @@ async def send_entry(
self._check_url(self.tails_public_uri)

if self.state not in (
IssuerRevRegRecord.STATE_UPLOADED,
IssuerRevRegRecord.STATE_POSTED,
IssuerRevRegRecord.STATE_ACTIVE,
IssuerRevRegRecord.STATE_FULL, # can still publish revocation deltas
):
Expand All @@ -299,7 +298,7 @@ async def send_entry(
write_ledger=write_ledger,
endorser_did=endorser_did,
)
if self.state == IssuerRevRegRecord.STATE_UPLOADED:
if self.state == IssuerRevRegRecord.STATE_POSTED:
self.state = IssuerRevRegRecord.STATE_ACTIVE # initial entry activates
async with profile.session() as session:
await self.save(
Expand All @@ -321,7 +320,7 @@ async def upload_tails_file(self, profile: Profile):
if not self.has_local_tails_file:
raise RevocationError("Local tails file not found")

(upload_success, reason) = await tails_server.upload_tails_file(
(upload_success, result) = await tails_server.upload_tails_file(
profile.context,
self.revoc_reg_id,
self.tails_local_path,
Expand All @@ -331,12 +330,9 @@ async def upload_tails_file(self, profile: Profile):
)
if not upload_success:
raise RevocationError(
f"Tails file for rev reg {self.revoc_reg_id} failed to upload: {reason}"
f"Tails file for rev reg {self.revoc_reg_id} failed to upload: {result}"
)

self.state = IssuerRevRegRecord.STATE_UPLOADED
async with profile.session() as session:
await self.save(session, reason="Uploaded tails file")
await self.set_tails_file_public_uri(profile, result)

async def mark_pending(self, session: ProfileSession, cred_rev_id: str) -> None:
"""Mark a credential revocation id as revoked pending publication to ledger.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async def setUp(self):
TailsServer = async_mock.MagicMock(BaseTailsServer, autospec=True)
self.tails_server = TailsServer()
self.tails_server.upload_tails_file = async_mock.CoroutineMock(
return_value=(True, None)
return_value=(True, "http://1.2.3.4:8088/rev-reg-id")
)
self.profile.context.injector.bind_instance(BaseTailsServer, self.tails_server)

Expand Down Expand Up @@ -126,7 +126,10 @@ async def test_generate_registry_etc(self):

with async_mock.patch.object(test_module.Path, "is_file", lambda _: True):
await rec.upload_tails_file(self.profile)
assert rec.state == IssuerRevRegRecord.STATE_UPLOADED
assert (
rec.tails_public_uri
and rec.revoc_reg_def.value.tails_location == rec.tails_public_uri
)
self.tails_server.upload_tails_file.assert_called_once()

await rec.send_entry(self.profile)
Expand Down
42 changes: 25 additions & 17 deletions aries_cloudagent/revocation/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ async def create_rev_reg(request: web.BaseRequest):
issuer_rev_reg_rec = await revoc.init_issuer_registry(
credential_definition_id,
max_cred_num=max_cred_num,
notify=False,
)
except RevocationNotSupportedError as e:
raise web.HTTPBadRequest(reason=e.message) from e
Expand Down Expand Up @@ -1128,17 +1129,16 @@ async def send_rev_reg_entry(request: web.BaseRequest):
raise web.HTTPBadRequest(reason="No endorser connection found")

if not write_ledger:
try:
async with profile.session() as session:
async with profile.session() as session:
try:
connection_record = await ConnRecord.retrieve_by_id(
session, connection_id
)
except StorageNotFoundError as err:
raise web.HTTPNotFound(reason=err.roll_up) from err
except BaseModelError as err:
raise web.HTTPBadRequest(reason=err.roll_up) from err
except StorageNotFoundError as err:
raise web.HTTPNotFound(reason=err.roll_up) from err
except BaseModelError as err:
raise web.HTTPBadRequest(reason=err.roll_up) from err

async with profile.session() as session:
endorser_info = await connection_record.metadata_get(
session, "endorser_info"
)
Expand Down Expand Up @@ -1295,14 +1295,16 @@ async def on_revocation_registry_init_event(profile: Profile, event: Event):
meta_data = event.payload
if "endorser" in meta_data:
# TODO error handling - for now just let exceptions get raised
endorser_connection_id = meta_data["endorser"]["connection_id"]
async with profile.session() as session:
connection = await ConnRecord.retrieve_by_id(
session, meta_data["endorser"]["connection_id"]
session, endorser_connection_id
)
endorser_info = await connection.metadata_get(session, "endorser_info")
endorser_did = endorser_info["endorser_did"]
write_ledger = False
else:
endorser_connection_id = None
endorser_did = None
write_ledger = True

Expand All @@ -1313,10 +1315,8 @@ async def on_revocation_registry_init_event(profile: Profile, event: Event):
# Generate the registry and upload the tails file
async def generate(rr_record: IssuerRevRegRecord) -> dict:
await rr_record.generate_registry(profile)
await rr_record.set_tails_file_public_uri(
profile,
f"{tails_base_url}/{registry_record.revoc_reg_id}",
)
public_uri = tails_base_url.rstrip("/") + f"/{registry_record.revoc_reg_id}"
await rr_record.set_tails_file_public_uri(profile, public_uri)
rev_reg_resp = await rr_record.send_def(
profile,
write_ledger=write_ledger,
Expand Down Expand Up @@ -1381,6 +1381,7 @@ async def generate(rr_record: IssuerRevRegRecord) -> dict:
registry_record.cred_def_id,
registry_record.max_cred_num,
registry_record.revoc_def_type,
endorser_connection_id=endorser_connection_id,
)


Expand Down Expand Up @@ -1450,18 +1451,25 @@ async def on_revocation_entry_event(profile: Profile, event: Event):


async def on_revocation_registry_endorsed_event(profile: Profile, event: Event):
"""Handle revocation tails file event."""
"""Handle revocation registry endorsement event."""
meta_data = event.payload
rev_reg_id = meta_data["context"]["rev_reg_id"]
revoc = IndyRevocation(profile)
registry_record = await revoc.get_issuer_rev_reg_record(rev_reg_id)
# NOTE: if there are multiple pods, then the one processing this
# event may not be the one that generated the tails file.
await registry_record.upload_tails_file(profile)

if profile.settings.get_value("endorser.auto_request"):
# NOTE: if there are multiple pods, then the one processing this
# event may not be the one that generated the tails file.
await registry_record.upload_tails_file(profile)

# Post the initial revocation entry
await notify_revocation_entry_event(
profile, registry_record.record_id, meta_data
)

# create a "pending" registry if one is requested
# (this is done automatically when creating a credential definition, so that when a
# revocation registry fills up, we ca continue to issue credentials without a
# revocation registry fills up, we can continue to issue credentials without a
# delay)
create_pending_rev_reg = meta_data["processing"].get(
"create_pending_rev_reg", False
Expand Down
11 changes: 10 additions & 1 deletion aries_cloudagent/revocation/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
EVENT_LISTENER_PATTERN = re.compile(f"^{REVOCATION_EVENT_PREFIX}(.*)?$")
REVOCATION_REG_INIT_EVENT = "REGISTRY_INIT"
REVOCATION_REG_ENDORSED_EVENT = "REGISTRY_ENDORSED"
REVOCATION_ENTRY_EVENT = "ENTRY"
REVOCATION_ENTRY_ENDORSED_EVENT = "ENTRY_ENDORSED"
REVOCATION_ENTRY_EVENT = "SEND_ENTRY"
REVOCATION_PUBLISHED_EVENT = "published"
REVOCATION_CLEAR_PENDING_EVENT = "clear-pending"

Expand Down Expand Up @@ -50,6 +51,14 @@ async def notify_revocation_reg_endorsed_event(
await profile.notify(topic, meta_data)


async def notify_revocation_entry_endorsed_event(
profile: Profile, rev_reg_id: str, meta_data: dict
):
"""Send notification for a revocation registry entry endorsement event."""
topic = f"{REVOCATION_EVENT_PREFIX}{REVOCATION_ENTRY_ENDORSED_EVENT}::{rev_reg_id}"
await profile.notify(topic, meta_data)


async def notify_revocation_published_event(
profile: Profile,
rev_reg_id: str,
Expand Down
24 changes: 13 additions & 11 deletions aries_cloudagent/tails/indy_tails_server.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Indy tails server interface class."""

from typing import Tuple
import logging

from typing import Tuple

from ..config.injection_context import InjectionContext
from ..ledger.multiple_ledger.base_manager import BaseMultipleLedgerManager
from ..utils.http import put_file, PutError
Expand Down Expand Up @@ -58,17 +59,18 @@ async def upload_tails_file(
"tails_server_upload_url setting is not set"
)

upload_url = tails_server_upload_url.rstrip("/") + f"/{rev_reg_id}"

try:
return (
True,
await put_file(
f"{tails_server_upload_url}/{rev_reg_id}",
{"tails": tails_file_path},
{"genesis": genesis_transactions},
interval=interval,
backoff=backoff,
max_attempts=max_attempts,
),
await put_file(
upload_url,
{"tails": tails_file_path},
{"genesis": genesis_transactions},
interval=interval,
backoff=backoff,
max_attempts=max_attempts,
)
except PutError as x_put:
return (False, x_put.message)

return True, upload_url
12 changes: 9 additions & 3 deletions aries_cloudagent/tails/tests/test_indy.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ async def test_upload(self):
"/tmp/dummy/path",
)
assert ok
assert text == "tails-hash"
assert (
text == context.settings["tails_server_upload_url"] + "/" + REV_REG_ID
)

async def test_upload_indy_sdk(self):
profile = InMemoryProfile.test_profile()
Expand Down Expand Up @@ -68,7 +70,9 @@ async def test_upload_indy_sdk(self):
"/tmp/dummy/path",
)
assert ok
assert text == "tails-hash"
assert (
text == profile.settings["tails_server_upload_url"] + "/" + REV_REG_ID
)

async def test_upload_indy_vdr(self):
profile = InMemoryProfile.test_profile()
Expand Down Expand Up @@ -98,7 +102,9 @@ async def test_upload_indy_vdr(self):
"/tmp/dummy/path",
)
assert ok
assert text == "tails-hash"
assert (
text == profile.settings["tails_server_upload_url"] + "/" + REV_REG_ID
)

async def test_upload_x(self):
context = InjectionContext(
Expand Down

0 comments on commit 4dc3188

Please sign in to comment.