Skip to content

Commit 5923d55

Browse files
Support ADA RFC 003 Data Agreement Negotiation protocol in Aries RFC 036 Issue credential protocol.
Issue credential protocol messages are patched to support Data Agreement Context Decorator (ADA RFC 006) to carry Data Agreement Negotiation messages. Signed-off-by: George J Padayatti <[email protected]>
1 parent 887899b commit 5923d55

28 files changed

+3478
-99
lines changed

mydata_did/patched_protocols/issue_credential/v1_0/handlers/credential_offer_handler.py

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Credential offer message handler."""
2+
import json
23

34
from aries_cloudagent.messaging.base_handler import (
45
BaseHandler,
@@ -7,8 +8,20 @@
78
RequestContext,
89
)
910

11+
from aries_cloudagent.wallet.base import BaseWallet
12+
from aries_cloudagent.wallet.indy import IndyWallet
13+
1014
from ..manager import CredentialManager
1115
from ..messages.credential_offer import CredentialOffer
16+
from ..models.credential_exchange import V10CredentialExchange
17+
18+
from .....v1_0.manager import ADAManager, ADAManagerError
19+
from .....v1_0.messages.data_agreement_offer import DataAgreementNegotiationOfferMessage
20+
from .....v1_0.models.diddoc_model import MyDataDIDResponseBody
21+
from .....v1_0.utils.jsonld.data_agreement import verify_data_agreement
22+
from .....v1_0.utils.did.mydata_did import DIDMyData
23+
from .....v1_0.decorators.data_agreement_context_decorator import DataAgreementContextDecorator
24+
from .....v1_0.messages.problem_report import DataAgreementNegotiationProblemReportReason
1225

1326
from aries_cloudagent.utils.tracing import trace_event, get_timer
1427

@@ -27,20 +40,126 @@ async def handle(self, context: RequestContext, responder: BaseResponder):
2740
"""
2841
r_time = get_timer()
2942

30-
self._logger.debug("CredentialOfferHandler called with context %s", context)
43+
self._logger.debug(
44+
"CredentialOfferHandler called with context %s", context)
3145
assert isinstance(context.message, CredentialOffer)
3246
self._logger.info(
3347
"Received credential offer message: %s",
3448
context.message.serialize(as_string=True),
3549
)
3650

3751
if not context.connection_ready:
38-
raise HandlerException("No connection established for credential offer")
52+
raise HandlerException(
53+
"No connection established for credential offer")
3954

4055
credential_manager = CredentialManager(context)
4156

4257
cred_ex_record = await credential_manager.receive_offer()
4358

59+
# Wallet instance from request context
60+
wallet: IndyWallet = await context.inject(BaseWallet)
61+
62+
# Initialise ADA manager
63+
ada_manager = ADAManager(context)
64+
65+
# Process data agreement context decorator
66+
data_agreement_context_message = None
67+
try:
68+
data_agreement_context_message: DataAgreementNegotiationOfferMessage = await ada_manager.process_data_agreement_context_decorator(
69+
decorator_set=context.message._decorators
70+
)
71+
72+
if isinstance(data_agreement_context_message, DataAgreementNegotiationOfferMessage):
73+
74+
# Resolve controller DID (Organisation DID) from MyData DID registry
75+
controller_mydata_did = DIDMyData.from_did(
76+
data_agreement_context_message.body.proof.verification_method)
77+
78+
await ada_manager.resolve_remote_mydata_did(mydata_did=controller_mydata_did.did)
79+
80+
# Verify signatures on data agreement offer
81+
valid = await verify_data_agreement(
82+
data_agreement_context_message.body.serialize(),
83+
controller_mydata_did.public_key_b58,
84+
wallet
85+
)
86+
87+
if not valid:
88+
self._logger.error(
89+
"Data agreement offer verification failed"
90+
)
91+
92+
# Send problem report
93+
problem_report = await ada_manager.construct_data_agreement_negotiation_problem_report_message(
94+
connection_record=context.connection_record,
95+
data_agreement_id=data_agreement_context_message.body.data_agreement_id,
96+
problem_code=DataAgreementNegotiationProblemReportReason.SIGNATURE_VERIFICATION_FAILED.value,
97+
explain="Data agreement offer verification failed"
98+
)
99+
100+
await ada_manager.send_data_agreement_negotiation_problem_report_message(
101+
connection_record=context.connection_record,
102+
data_agreement_negotiation_problem_report_message=problem_report
103+
)
104+
105+
cred_ex_record.data_agreement_status = V10CredentialExchange.DATA_AGREEMENT_PROBLEM_REPORT
106+
cred_ex_record.data_agreement_problem_report = problem_report.serialize()
107+
await cred_ex_record.save(context)
108+
109+
raise HandlerException(
110+
"Data agreement offer signature verification failed"
111+
)
112+
113+
# Update credential exchange record with data agreement
114+
cred_ex_record.data_agreement = data_agreement_context_message.body.serialize()
115+
cred_ex_record.data_agreement_id = data_agreement_context_message.body.data_agreement_id
116+
cred_ex_record.data_agreement_template_id = data_agreement_context_message.body.data_agreement_template_id
117+
cred_ex_record.data_agreement_status = V10CredentialExchange.DATA_AGREEMENT_OFFER
118+
119+
await cred_ex_record.save(context)
120+
121+
# Save data agreement instance metadata
122+
await ada_manager.store_data_agreement_instance_metadata(
123+
data_agreement_id=data_agreement_context_message.body.data_agreement_id,
124+
data_agreement_template_id=data_agreement_context_message.body.data_agreement_template_id,
125+
data_exchange_record_id=cred_ex_record.credential_exchange_id,
126+
method_of_use=data_agreement_context_message.body.method_of_use
127+
)
128+
129+
self._logger.info(
130+
f"Data agreement offer verified and stored for credential exchange record {cred_ex_record.credential_exchange_id}"
131+
)
132+
133+
self._logger.info(
134+
f"Received data agreement offer context message: \n{json.dumps(data_agreement_context_message.serialize(), indent=4)}\n"
135+
)
136+
137+
except ADAManagerError as err:
138+
self._logger.error(
139+
"Failed to process data agreement context decorator: %s", err
140+
)
141+
142+
# Send problem report
143+
problem_report = await ada_manager.construct_data_agreement_negotiation_problem_report_message(
144+
connection_record=context.connection_record,
145+
data_agreement_id=data_agreement_context_message.body.data_agreement_id,
146+
problem_code=None,
147+
explain=str(err)
148+
)
149+
150+
await ada_manager.send_data_agreement_negotiation_problem_report_message(
151+
connection_record=context.connection_record,
152+
data_agreement_negotiation_problem_report_message=problem_report
153+
)
154+
155+
cred_ex_record.data_agreement_status = V10CredentialExchange.DATA_AGREEMENT_PROBLEM_REPORT
156+
cred_ex_record.data_agreement_problem_report = problem_report.serialize()
157+
await cred_ex_record.save(context)
158+
159+
raise HandlerException(
160+
"Failed to process data agreement context decorator: %s" % err
161+
)
162+
44163
r_time = trace_event(
45164
context.settings,
46165
context.message,
@@ -54,6 +173,43 @@ async def handle(self, context: RequestContext, responder: BaseResponder):
54173
cred_ex_record=cred_ex_record,
55174
holder_did=context.connection_record.my_did,
56175
)
176+
177+
if data_agreement_context_message:
178+
try:
179+
(data_agreement_instance, data_agreement_negotiation_accept_message) = await ada_manager.construct_data_agreement_negotiation_accept_message(
180+
data_agreement_negotiation_offer_body=data_agreement_context_message.body,
181+
connection_record=context.connection_record,
182+
)
183+
184+
# Update credential request message with data agreement context decorator
185+
credential_request_message._decorators["data-agreement-context"] = DataAgreementContextDecorator(
186+
message_type="protocol",
187+
message=data_agreement_negotiation_accept_message.serialize()
188+
)
189+
190+
# Update credential exchange record with data agreement
191+
cred_ex_record.data_agreement = data_agreement_instance.serialize()
192+
cred_ex_record.data_agreement_status = V10CredentialExchange.DATA_AGREEMENT_ACCEPT
193+
194+
await cred_ex_record.save(context)
195+
196+
self._logger.info(
197+
f"Data agreement offer accepted and stored for credential exchange record {cred_ex_record.credential_exchange_id}"
198+
)
199+
200+
self._logger.info(
201+
f"Data agreement negotiation accept context message: \n{json.dumps(data_agreement_negotiation_accept_message.serialize(), indent=4)}\n"
202+
)
203+
204+
except ADAManagerError as err:
205+
self._logger.error(
206+
"Failed to construct data agreement negotiation accept message: %s", err
207+
)
208+
209+
raise HandlerException(
210+
"Failed to construct data agreement negotiation accept message: %s" % err
211+
)
212+
57213
await responder.send_reply(credential_request_message)
58214

59215
trace_event(

0 commit comments

Comments
 (0)