Skip to content

Commit

Permalink
⬆️ Upgrade ACA-Py version to 0.12.1 (#758)
Browse files Browse the repository at this point in the history
* 🎨 set default project version to 0.12.0

* ⬆️ Use 0.12.0 ACA-Py base image

* 🚧 test 0.12.0 redis plugin

* 🚧 test 0.12.0 groups plugin

* 🚧 test 0.12 cloudcontroller

* 🎨 update to new method operation id

* 🎨 update models

* 🚧 test on nightly aca-py build

* ✅ fix required fields in models

* 🚧 Test fix on ff137:fix/find_oob_target

* 🚧 Use aries-acapy-plugins@v1-2024-04-23

* ⬆️ use latest 0.12.1rc0 image

* ⏪ revert testing with forked aca-py

* ⬆️ Use acapy-wallet-groups-plugin with 0.12.1rc0

* ⬆️ use latest acapy-wallet-groups-plugin

* ⬆️ use latest cloudcontroller

* ⏪ Revert git install

* ⬆️ Upgrade to 0.12.1

* 🎨 deduplicate project version

* ⬆️ Use latest redis-events plugin for 0.12.1

* ✨ publishing pending revocations should wait and assert transaction has been acked

* 🎨

* 🎨 optionally return the transaction id for a publish revocations request

* 🎨 only wait if transaction id returned

* 🚧 test with forked acapy

* 🎨 publish-revocations only needs to be called once

* ✨ the beginnings of asserting that auto_publish revocation request is indeed revoked

* ✅ use empty non_revoked request to check if cred is revoked at time of proof, instead of time of acme creating proof request

* 🎨 modify `non_revoked` requests to be empty

* 👷 use default docker image again

* 🐛 wait for 2 registries again

* 🎨

* 🐛 non_revoked must be specified to avoid bug in acapy (openwallet-foundation/acapy/issues/3018)

* 🚧 test with acapy nightly build

* 🚧 fix test and leave todo

* Update aries-acapy-plugins tag

* Update acapy-wallet-groups-plugin tag

* ⬆️ use latest acapy image

* ⬆️ use acapy-wallet-groups-plugin tagged release

* add sleep to work around acapy issue

* ✨ `assert_both_webhooks_received`: use asyncio.gather to simultaneous await two webhooks

* 🎨 remove unneeded look_back

* 🎨

* 🎨 fix

* ⏪ revert from nightly build back to 0.12.1 release
  • Loading branch information
ff137 authored Jun 12, 2024
1 parent 98d2cf0 commit f02e963
Show file tree
Hide file tree
Showing 39 changed files with 407 additions and 360 deletions.
2 changes: 1 addition & 1 deletion app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@
from app.routes.wallet import sd_jws as wallet_sd_jws
from app.services.event_handling.websocket_manager import WebsocketManager
from app.util.extract_validation_error import extract_validation_error_msg
from shared.constants import PROJECT_VERSION
from shared.exceptions import CloudApiValueError
from shared.log_config import get_logger

OPENAPI_NAME = os.getenv("OPENAPI_NAME", "OpenAPI")
PROJECT_VERSION = os.getenv("PROJECT_VERSION", "0.11.0")
ROLE = os.getenv("ROLE", "*")
ROOT_PATH = os.getenv("ROOT_PATH", "")

Expand Down
2 changes: 1 addition & 1 deletion app/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
aiohttp~=3.9.2
aries-cloudcontroller==0.11.0.post5
aries-cloudcontroller==0.12.1
base58~=2.1.1
fastapi~=0.111.0
fastapi_websocket_pubsub~=0.3.8
Expand Down
26 changes: 25 additions & 1 deletion app/routes/issuer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
from typing import List, Optional
from uuid import UUID

Expand Down Expand Up @@ -26,6 +27,7 @@
issuer_from_protocol_version,
)
from app.util.did import did_from_credential_definition_id, qualified_did_sov
from app.util.retry_method import coroutine_with_retry_until_value
from shared.log_config import get_logger
from shared.models.credential_exchange import (
CredentialExchange,
Expand Down Expand Up @@ -661,11 +663,33 @@ async def publish_revocations(

async with client_from_auth(auth) as aries_controller:
bound_logger.debug("Publishing revocations")
await revocation_registry.publish_pending_revocations(
endorser_transaction_id = await revocation_registry.publish_pending_revocations(
controller=aries_controller,
revocation_registry_credential_map=publish_request.revocation_registry_credential_map,
)

if endorser_transaction_id:
bound_logger.debug(
"Wait for publish complete on transaction id: {}",
endorser_transaction_id,
)
try:
# Wait for transaction to be acknowledged and written to the ledger
await coroutine_with_retry_until_value(
coroutine_func=aries_controller.endorse_transaction.get_transaction,
args=(endorser_transaction_id,),
field_name="state",
expected_value="transaction_acked",
logger=bound_logger,
max_attempts=10,
retry_delay=2,
)
except asyncio.TimeoutError as e:
raise CloudApiException(
"Timeout waiting for endorser to accept the revocations request.",
504,
) from e

bound_logger.info("Successfully published revocations.")


Expand Down
4 changes: 2 additions & 2 deletions app/routes/wallet/jws.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ async def sign_jws(
async with client_from_auth(auth) as aries_controller:
jws = await handle_acapy_call(
logger=bound_logger,
acapy_call=aries_controller.wallet.wallet_jwt_sign_post,
acapy_call=aries_controller.wallet.sign_jwt,
body=sign_request,
)

Expand Down Expand Up @@ -90,7 +90,7 @@ async def verify_jws(
async with client_from_auth(auth) as aries_controller:
verify_result = await handle_acapy_call(
logger=bound_logger,
acapy_call=aries_controller.wallet.wallet_jwt_verify_post,
acapy_call=aries_controller.wallet.verify_jwt,
body=verify_request,
)

Expand Down
4 changes: 2 additions & 2 deletions app/routes/wallet/sd_jws.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async def sign_sd_jws(
async with client_from_auth(auth) as aries_controller:
sd_jws = await handle_acapy_call(
logger=bound_logger,
acapy_call=aries_controller.wallet.wallet_sd_jwt_sign_post,
acapy_call=aries_controller.wallet.sign_sd_jwt,
body=sign_request,
)

Expand Down Expand Up @@ -92,7 +92,7 @@ async def verify_sd_jws(
async with client_from_auth(auth) as aries_controller:
verify_result = await handle_acapy_call(
logger=bound_logger,
acapy_call=aries_controller.wallet.wallet_sd_jwt_verify_post,
acapy_call=aries_controller.wallet.verify_sd_jwt,
body=verify_request,
)

Expand Down
2 changes: 1 addition & 1 deletion app/services/issuer/acapy_issuer_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async def create_offer(
)
record = await handle_acapy_call(
logger=bound_logger,
acapy_call=controller.issue_credential_v2_0.issue_credential20_create_offer_post,
acapy_call=controller.issue_credential_v2_0.create_offer,
body=request_body,
)

Expand Down
60 changes: 52 additions & 8 deletions app/services/revocation_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
)
from app.models.issuer import ClearPendingRevocationsResult
from app.util.credentials import strip_protocol_prefix
from app.util.retry_method import coroutine_with_retry
from shared.log_config import get_logger

logger = get_logger(__name__)
Expand Down Expand Up @@ -112,12 +113,43 @@ async def revoke_credential(
f"Failed to revoke credential: {e.detail}", e.status_code
) from e

if auto_publish_to_ledger:
bound_logger.debug("Wait for publish complete")

revoked = False
max_tries = 5
retry_delay = 1
n_try = 0
while not revoked and n_try < max_tries:
n_try += 1
# Safely fetch revocation record and check if change reflected
record = await coroutine_with_retry(
coroutine_func=controller.revocation.get_revocation_status,
args=(strip_protocol_prefix(credential_exchange_id),),
logger=bound_logger,
max_attempts=5,
retry_delay=0.5,
)
# Todo: this record state can be "revoked" before it's been endorsed
if record.result:
revoked = record.result.state == "revoked"

if not revoked and n_try < max_tries:
bound_logger.debug("Not yet revoked, waiting ...")
await asyncio.sleep(retry_delay)

if not revoked:
raise CloudApiException(
"Could not assert that revocation was published within timeout. "
"Please check the revocation record state and retry if not revoked."
)

bound_logger.info("Successfully revoked credential.")


async def publish_pending_revocations(
controller: AcaPyClient, revocation_registry_credential_map: Dict[str, List[str]]
) -> None:
) -> Optional[str]:
"""
Publish pending revocations
Expand All @@ -130,18 +162,16 @@ async def publish_pending_revocations(
Exception: When the pending revocations could not be published
Returns:
result (None): Successful execution returns None.
result (str): Successful execution returns the endorser transaction id.
"""
bound_logger = logger.bind(body=revocation_registry_credential_map)

bound_logger.info("Validating revocation registry ids")
await validate_rev_reg_ids(
controller=controller,
revocation_registry_credential_map=revocation_registry_credential_map,
)

try:
await handle_acapy_call(
result = await handle_acapy_call(
logger=bound_logger,
acapy_call=controller.revocation.publish_revocations,
body=PublishRevocations(rrid2crid=revocation_registry_credential_map),
Expand All @@ -151,7 +181,19 @@ async def publish_pending_revocations(
f"Failed to publish pending revocations: {e.detail}", e.status_code
) from e

bound_logger.info("Successfully published pending revocations.")
if not result.txn or not result.txn.transaction_id:
bound_logger.warning(
"Published pending revocations but received no endorser transaction id. Got result: {}",
result,
)
return

endorse_transaction_id = result.txn.transaction_id
bound_logger.info(
"Successfully published pending revocations. Endorser transaction id: {}.",
endorse_transaction_id,
)
return endorse_transaction_id


async def clear_pending_revocations(
Expand Down Expand Up @@ -339,12 +381,13 @@ async def validate_rev_reg_ids(
"""
bound_logger = logger.bind(body=revocation_registry_credential_map)
bound_logger.info("Validating revocation registry ids")
rev_reg_id_list = list(revocation_registry_credential_map.keys())

if not rev_reg_id_list:
return

bound_logger.info("Validating revocation registry ids")

for rev_reg_id in rev_reg_id_list:
try:
rev_reg_result = await handle_acapy_call(
Expand Down Expand Up @@ -437,7 +480,8 @@ async def wait_for_active_registry(
active_registries = []
sleep_duration = 0 # First sleep should be 0

while len(active_registries) < 1: # We need one of the two registries to be ready
# we want both active registries ready before trying to publish revocations to it
while len(active_registries) < 2:
await asyncio.sleep(sleep_duration)
active_registries = await get_created_active_registries(controller, cred_def_id)
sleep_duration = 0.5 # Following sleeps should wait 0.5s before retry
Expand Down
Loading

0 comments on commit f02e963

Please sign in to comment.