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

Reuse credential offers and requests when possible #242

Merged
merged 7 commits into from
Oct 30, 2019
62 changes: 46 additions & 16 deletions aries_cloudagent/messaging/credentials/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,18 @@ async def create_offer(

"""

issuer: BaseIssuer = await self.context.inject(BaseIssuer)
credential_offer = await issuer.create_credential_offer(
credential_definition_id
)
cache_key = f"credential_offer::{credential_definition_id}"
cached = await CredentialExchange.get_cached_key(self.context, cache_key)
if cached:
credential_offer = cached["offer"]
else:
issuer: BaseIssuer = await self.context.inject(BaseIssuer)
credential_offer = await issuer.create_credential_offer(
credential_definition_id
)
await CredentialExchange.set_cached_key(
self.context, cache_key, {"offer": credential_offer}, 3600
)

credential_offer_message = CredentialOffer(
offer_json=json.dumps(credential_offer)
Expand Down Expand Up @@ -146,19 +154,41 @@ async def create_request(
credential_exchange_record.credential_exchange_id,
)
else:
ledger: BaseLedger = await self.context.inject(BaseLedger)
async with ledger:
credential_definition = await ledger.get_credential_definition(
credential_definition_id
)

holder: BaseHolder = await self.context.inject(BaseHolder)
(
credential_exchange_record.credential_request,
credential_exchange_record.credential_request_metadata,
) = await holder.create_credential_request(
credential_offer, credential_definition, did
nonce = credential_offer["nonce"]
cache_key = (
f"credential_request::{credential_definition_id}::{did}::{nonce}"
)
cached = await CredentialExchange.get_cached_key(self.context, cache_key)
if cached:
(
credential_exchange_record.credential_request,
credential_exchange_record.credential_request_metadata,
) = (cached["request"], cached["metadata"])
else:
ledger: BaseLedger = await self.context.inject(BaseLedger)
async with ledger:
credential_definition = await ledger.get_credential_definition(
credential_definition_id
)

holder: BaseHolder = await self.context.inject(BaseHolder)
(
credential_exchange_record.credential_request,
credential_exchange_record.credential_request_metadata,
) = await holder.create_credential_request(
credential_offer, credential_definition, did
)
await CredentialExchange.set_cached_key(
self.context,
cache_key,
{
"request": credential_exchange_record.credential_request,
"metadata": (
credential_exchange_record.credential_request_metadata
),
},
7200,
)

credential_request_message = CredentialRequest(
request=json.dumps(credential_exchange_record.credential_request)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""Basic message handler."""


from .....storage.error import StorageNotFoundError
from ....base_handler import (
BaseHandler,
BaseResponder,
Expand All @@ -10,8 +8,6 @@
)
from ..manager import CredentialManager
from ..messages.credential_offer import CredentialOffer
from ..messages.credential_proposal import CredentialProposal
from ..models.credential_exchange import V10CredentialExchange


class CredentialOfferHandler(BaseHandler):
Expand All @@ -38,43 +34,7 @@ async def handle(self, context: RequestContext, responder: BaseResponder):

credential_manager = CredentialManager(context)

indy_offer = context.message.indy_offer(0)
credential_proposal_dict = CredentialProposal(
comment=context.message.comment,
credential_proposal=context.message.credential_preview,
cred_def_id=indy_offer["cred_def_id"],
schema_id=indy_offer["schema_id"],
).serialize()

# Get credential exchange record (holder sent proposal first)
# or create it (issuer sent offer first)
try:
(
credential_exchange_record
) = await V10CredentialExchange.retrieve_by_tag_filter(
context,
{"thread_id": context.message._thread_id},
{"connection_id": context.connection_record.connection_id},
)
credential_exchange_record.credential_proposal_dict = (
credential_proposal_dict
)
except StorageNotFoundError: # issuer sent this offer free of any proposal
credential_exchange_record = V10CredentialExchange(
connection_id=context.connection_record.connection_id,
thread_id=context.message._thread_id,
initiator=V10CredentialExchange.INITIATOR_EXTERNAL,
role=V10CredentialExchange.ROLE_HOLDER,
credential_definition_id=indy_offer["cred_def_id"],
schema_id=indy_offer["schema_id"],
credential_proposal_dict=credential_proposal_dict,
)

credential_exchange_record.credential_offer = indy_offer

credential_exchange_record = await credential_manager.receive_offer(
credential_exchange_record
)
credential_exchange_record = await credential_manager.receive_offer()

# If auto respond is turned on, automatically reply with credential request
if context.settings.get("debug.auto_respond_credential_offer"):
Expand Down