Skip to content

Commit 0dc5408

Browse files
Add present-proof protcol for patching
Signed-off-by: George J Padayatti <[email protected]>
1 parent 7165bb0 commit 0dc5408

40 files changed

+9378
-0
lines changed

mydata_did/patched_protocols/present_proof/__init__.py

Whitespace-only changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""Version definitions for this protocol."""
2+
3+
versions = [
4+
{
5+
"major_version": 1,
6+
"minimum_minor_version": 0,
7+
"current_minor_version": 0,
8+
"path": "v1_0",
9+
}
10+
]

mydata_did/patched_protocols/present_proof/v1_0/__init__.py

Whitespace-only changes.

mydata_did/patched_protocols/present_proof/v1_0/handlers/__init__.py

Whitespace-only changes.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""Presentation ack message handler."""
2+
3+
from .....messaging.base_handler import (
4+
BaseHandler,
5+
BaseResponder,
6+
HandlerException,
7+
RequestContext,
8+
)
9+
10+
from ..manager import PresentationManager
11+
from ..messages.presentation_ack import PresentationAck
12+
13+
from .....utils.tracing import trace_event, get_timer
14+
15+
16+
class PresentationAckHandler(BaseHandler):
17+
"""Message handler class for presentation acks."""
18+
19+
async def handle(self, context: RequestContext, responder: BaseResponder):
20+
"""
21+
Message handler logic for presentation acks.
22+
23+
Args:
24+
context: request context
25+
responder: responder callback
26+
"""
27+
r_time = get_timer()
28+
29+
self._logger.debug("PresentationAckHandler called with context %s", context)
30+
assert isinstance(context.message, PresentationAck)
31+
self._logger.info(
32+
"Received presentation ack message: %s",
33+
context.message.serialize(as_string=True),
34+
)
35+
36+
if not context.connection_ready:
37+
raise HandlerException("No connection established for presentation ack")
38+
39+
presentation_manager = PresentationManager(context)
40+
await presentation_manager.receive_presentation_ack()
41+
42+
trace_event(
43+
context.settings,
44+
context.message,
45+
outcome="PresentationAckHandler.handle.END",
46+
perf_counter=r_time,
47+
)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""Presentation message handler."""
2+
3+
from .....messaging.base_handler import (
4+
BaseHandler,
5+
BaseResponder,
6+
RequestContext,
7+
)
8+
9+
from ..manager import PresentationManager
10+
from ..messages.presentation import Presentation
11+
12+
from .....utils.tracing import trace_event, get_timer
13+
14+
15+
class PresentationHandler(BaseHandler):
16+
"""Message handler class for presentations."""
17+
18+
async def handle(self, context: RequestContext, responder: BaseResponder):
19+
"""
20+
Message handler logic for presentations.
21+
22+
Args:
23+
context: request context
24+
responder: responder callback
25+
26+
"""
27+
r_time = get_timer()
28+
29+
self._logger.debug("PresentationHandler called with context %s", context)
30+
assert isinstance(context.message, Presentation)
31+
self._logger.info(
32+
"Received presentation message: %s",
33+
context.message.serialize(as_string=True),
34+
)
35+
36+
presentation_manager = PresentationManager(context)
37+
38+
presentation_exchange_record = await presentation_manager.receive_presentation()
39+
40+
r_time = trace_event(
41+
context.settings,
42+
context.message,
43+
outcome="PresentationHandler.handle.END",
44+
perf_counter=r_time,
45+
)
46+
47+
if context.settings.get("debug.auto_verify_presentation"):
48+
await presentation_manager.verify_presentation(presentation_exchange_record)
49+
50+
trace_event(
51+
context.settings,
52+
presentation_exchange_record,
53+
outcome="PresentationHandler.handle.VERIFY",
54+
perf_counter=r_time,
55+
)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""Presentation proposal message handler."""
2+
3+
from .....messaging.base_handler import (
4+
BaseHandler,
5+
BaseResponder,
6+
HandlerException,
7+
RequestContext,
8+
)
9+
10+
from ..manager import PresentationManager
11+
from ..messages.presentation_proposal import PresentationProposal
12+
13+
from .....utils.tracing import trace_event, get_timer
14+
15+
16+
class PresentationProposalHandler(BaseHandler):
17+
"""Message handler class for presentation proposals."""
18+
19+
async def handle(self, context: RequestContext, responder: BaseResponder):
20+
"""
21+
Message handler logic for presentation proposals.
22+
23+
Args:
24+
context: proposal context
25+
responder: responder callback
26+
27+
"""
28+
r_time = get_timer()
29+
30+
self._logger.debug(
31+
"PresentationProposalHandler called with context %s", context
32+
)
33+
assert isinstance(context.message, PresentationProposal)
34+
self._logger.info(
35+
"Received presentation proposal message: %s",
36+
context.message.serialize(as_string=True),
37+
)
38+
39+
if not context.connection_ready:
40+
raise HandlerException(
41+
"No connection established for presentation proposal"
42+
)
43+
44+
presentation_manager = PresentationManager(context)
45+
presentation_exchange_record = await presentation_manager.receive_proposal()
46+
47+
r_time = trace_event(
48+
context.settings,
49+
context.message,
50+
outcome="PresentationProposalHandler.handle.END",
51+
perf_counter=r_time,
52+
)
53+
54+
# If auto_respond_presentation_proposal is set, reply with proof req
55+
if context.settings.get("debug.auto_respond_presentation_proposal"):
56+
(
57+
presentation_exchange_record,
58+
presentation_request_message,
59+
) = await presentation_manager.create_bound_request(
60+
presentation_exchange_record=presentation_exchange_record,
61+
comment=context.message.comment,
62+
)
63+
64+
await responder.send_reply(presentation_request_message)
65+
66+
trace_event(
67+
context.settings,
68+
presentation_request_message,
69+
outcome="PresentationProposalHandler.handle.PRESENT",
70+
perf_counter=r_time,
71+
)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
"""Presentation request message handler."""
2+
3+
from .....messaging.base_handler import (
4+
BaseHandler,
5+
BaseResponder,
6+
HandlerException,
7+
RequestContext,
8+
)
9+
from .....holder.base import BaseHolder
10+
from .....storage.error import StorageNotFoundError
11+
12+
from ..manager import PresentationManager
13+
from ..messages.presentation_proposal import PresentationProposal
14+
from ..messages.presentation_request import PresentationRequest
15+
from ..models.presentation_exchange import V10PresentationExchange
16+
from ..util.indy import indy_proof_req_preview2indy_requested_creds
17+
18+
from .....utils.tracing import trace_event, get_timer
19+
20+
21+
class PresentationRequestHandler(BaseHandler):
22+
"""Message handler class for Aries#0037 v1.0 presentation requests."""
23+
24+
async def handle(self, context: RequestContext, responder: BaseResponder):
25+
"""
26+
Message handler logic for Aries#0037 v1.0 presentation requests.
27+
28+
Args:
29+
context: request context
30+
responder: responder callback
31+
32+
"""
33+
r_time = get_timer()
34+
35+
self._logger.debug("PresentationRequestHandler called with context %s", context)
36+
assert isinstance(context.message, PresentationRequest)
37+
self._logger.info(
38+
"Received presentation request message: %s",
39+
context.message.serialize(as_string=True),
40+
)
41+
42+
if not context.connection_ready:
43+
raise HandlerException("No connection established for presentation request")
44+
45+
presentation_manager = PresentationManager(context)
46+
47+
indy_proof_request = context.message.indy_proof_request(0)
48+
49+
# Get presentation exchange record (holder initiated via proposal)
50+
# or create it (verifier sent request first)
51+
try:
52+
(
53+
presentation_exchange_record
54+
) = await V10PresentationExchange.retrieve_by_tag_filter(
55+
context,
56+
{"thread_id": context.message._thread_id},
57+
{"connection_id": context.connection_record.connection_id},
58+
) # holder initiated via proposal
59+
except StorageNotFoundError: # verifier sent this request free of any proposal
60+
presentation_exchange_record = V10PresentationExchange(
61+
connection_id=context.connection_record.connection_id,
62+
thread_id=context.message._thread_id,
63+
initiator=V10PresentationExchange.INITIATOR_EXTERNAL,
64+
role=V10PresentationExchange.ROLE_PROVER,
65+
presentation_request=indy_proof_request,
66+
auto_present=context.settings.get(
67+
"debug.auto_respond_presentation_request"
68+
),
69+
trace=(context.message._trace is not None),
70+
)
71+
72+
presentation_exchange_record.presentation_request = indy_proof_request
73+
presentation_exchange_record = await presentation_manager.receive_request(
74+
presentation_exchange_record
75+
)
76+
77+
r_time = trace_event(
78+
context.settings,
79+
context.message,
80+
outcome="PresentationRequestHandler.handle.END",
81+
perf_counter=r_time,
82+
)
83+
84+
# If auto_present is enabled, respond immediately with presentation
85+
if presentation_exchange_record.auto_present:
86+
presentation_preview = None
87+
if presentation_exchange_record.presentation_proposal_dict:
88+
exchange_pres_proposal = PresentationProposal.deserialize(
89+
presentation_exchange_record.presentation_proposal_dict
90+
)
91+
presentation_preview = exchange_pres_proposal.presentation_proposal
92+
93+
try:
94+
req_creds = await indy_proof_req_preview2indy_requested_creds(
95+
indy_proof_request,
96+
presentation_preview,
97+
holder=await context.inject(BaseHolder),
98+
)
99+
except ValueError as err:
100+
self._logger.warning(f"{err}")
101+
return
102+
103+
(
104+
presentation_exchange_record,
105+
presentation_message,
106+
) = await presentation_manager.create_presentation(
107+
presentation_exchange_record=presentation_exchange_record,
108+
requested_credentials=req_creds,
109+
comment="auto-presented for proof request nonce={}".format(
110+
indy_proof_request["nonce"]
111+
),
112+
)
113+
114+
await responder.send_reply(presentation_message)
115+
116+
trace_event(
117+
context.settings,
118+
presentation_message,
119+
outcome="PresentationRequestHandler.handle.PRESENT",
120+
perf_counter=r_time,
121+
)

mydata_did/patched_protocols/present_proof/v1_0/handlers/tests/__init__.py

Whitespace-only changes.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import pytest
2+
from asynctest import (
3+
mock as async_mock,
4+
TestCase as AsyncTestCase,
5+
)
6+
7+
from ......messaging.request_context import RequestContext
8+
from ......messaging.responder import MockResponder
9+
from ......transport.inbound.receipt import MessageReceipt
10+
11+
from ...messages.presentation_ack import PresentationAck
12+
from .. import presentation_ack_handler as handler
13+
14+
15+
class TestPresentationAckHandler(AsyncTestCase):
16+
async def test_called(self):
17+
request_context = RequestContext()
18+
request_context.message_receipt = MessageReceipt()
19+
20+
with async_mock.patch.object(
21+
handler, "PresentationManager", autospec=True
22+
) as mock_pres_mgr:
23+
mock_pres_mgr.return_value.receive_presentation_ack = (
24+
async_mock.CoroutineMock()
25+
)
26+
request_context.message = PresentationAck()
27+
request_context.connection_ready = True
28+
handler_inst = handler.PresentationAckHandler()
29+
responder = MockResponder()
30+
await handler_inst.handle(request_context, responder)
31+
32+
mock_pres_mgr.assert_called_once_with(request_context)
33+
mock_pres_mgr.return_value.receive_presentation_ack.assert_called_once_with()
34+
assert not responder.messages
35+
36+
async def test_called_not_ready(self):
37+
request_context = RequestContext()
38+
request_context.message_receipt = MessageReceipt()
39+
40+
with async_mock.patch.object(
41+
handler, "PresentationManager", autospec=True
42+
) as mock_pres_mgr:
43+
mock_pres_mgr.return_value.receive_presentation_ack = (
44+
async_mock.CoroutineMock()
45+
)
46+
request_context.message = PresentationAck()
47+
request_context.connection_ready = False
48+
handler_inst = handler.PresentationAckHandler()
49+
responder = MockResponder()
50+
with self.assertRaises(handler.HandlerException):
51+
await handler_inst.handle(request_context, responder)
52+
53+
assert not responder.messages

0 commit comments

Comments
 (0)