From 7f5eae76b108a113be55d2a5da8032ebf2775d5d Mon Sep 17 00:00:00 2001 From: Daniel Bluhm Date: Thu, 4 Apr 2024 15:11:06 -0400 Subject: [PATCH] fix: oob manager test failures Corrected serialization, service decorator should be base58 raw keys Signed-off-by: Daniel Bluhm --- .../protocols/out_of_band/v1_0/manager.py | 23 ++++++++++---- .../out_of_band/v1_0/models/oob_record.py | 28 ++++++++++++----- .../out_of_band/v1_0/tests/test_manager.py | 31 +++++++++++++------ 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/aries_cloudagent/protocols/out_of_band/v1_0/manager.py b/aries_cloudagent/protocols/out_of_band/v1_0/manager.py index d8c015fa6a..590a4a70b0 100644 --- a/aries_cloudagent/protocols/out_of_band/v1_0/manager.py +++ b/aries_cloudagent/protocols/out_of_band/v1_0/manager.py @@ -235,7 +235,7 @@ async def create_attachment( else: raise OutOfBandManagerError(f"Unknown attachment type: {a_type}") - message.assign_thread_id(thid=message._thread_id, pthid=pthid) + message.assign_thread_id(pthid=pthid) return InvitationMessage.wrap_message(message.serialize()) async def create_attachments( @@ -328,6 +328,16 @@ async def handle_handshake_protos( return conn_rec + def did_key_to_key(self, did_key: str) -> str: + """Convert a DID key to a key.""" + if did_key.startswith("did:key:"): + return DIDKey.from_did(did_key).public_key_b58 + return did_key + + def did_keys_to_keys(self, did_keys: Sequence[str]) -> List[str]: + """Convert DID keys to keys.""" + return [self.did_key_to_key(did_key) for did_key in did_keys] + async def handle_did( self, did_info: DIDInfo, @@ -361,9 +371,9 @@ async def handle_did( self.profile, did_info.verkey, mediation_record ) our_service = ServiceDecorator( - recipient_keys=recipient_keys, + recipient_keys=self.did_keys_to_keys(recipient_keys), endpoint=self.my_endpoint, - routing_keys=routing_keys, + routing_keys=self.did_keys_to_keys(routing_keys), ) return self.CreateResult( @@ -523,9 +533,9 @@ async def handle_legacy_invite_key( ) conn_rec = None our_service = ServiceDecorator( - recipient_keys=recipient_keys, + recipient_keys=self.did_keys_to_keys(recipient_keys), endpoint=my_endpoint, - routing_keys=routing_keys, + routing_keys=self.did_keys_to_keys(routing_keys), ) return self.CreateResult( @@ -1082,10 +1092,11 @@ async def _perform_handshake( service.routing_keys = [ DIDKey.from_did(key).public_key_b58 for key in service.routing_keys ] or [] + msg_type = DIDCommPrefix.qualify_current(protocol.name) + "/invitation" connection_invitation = ConnectionInvitation.deserialize( { "@id": invitation._id, - "@type": DIDCommPrefix.qualify_current(protocol.name), + "@type": msg_type, "label": invitation.label, "recipientKeys": service.recipient_keys, "serviceEndpoint": service.service_endpoint, diff --git a/aries_cloudagent/protocols/out_of_band/v1_0/models/oob_record.py b/aries_cloudagent/protocols/out_of_band/v1_0/models/oob_record.py index 830c523c79..e99201bd4f 100644 --- a/aries_cloudagent/protocols/out_of_band/v1_0/models/oob_record.py +++ b/aries_cloudagent/protocols/out_of_band/v1_0/models/oob_record.py @@ -56,13 +56,13 @@ def __init__( invi_msg_id: str, role: str, invitation: Union[InvitationMessage, Mapping[str, Any]], - their_service: Optional[ServiceDecorator] = None, + their_service: Optional[Union[ServiceDecorator, Mapping[str, Any]]] = None, connection_id: Optional[str] = None, reuse_msg_id: Optional[str] = None, oob_id: Optional[str] = None, attach_thread_id: Optional[str] = None, our_recipient_key: Optional[str] = None, - our_service: Optional[ServiceDecorator] = None, + our_service: Optional[Union[ServiceDecorator, Mapping[str, Any]]] = None, multi_use: bool = False, trace: bool = False, **kwargs, @@ -76,8 +76,8 @@ def __init__( self._invitation = InvitationMessage.serde(invitation) self.connection_id = connection_id self.reuse_msg_id = reuse_msg_id - self.their_service = their_service - self.our_service = our_service + self._their_service = ServiceDecorator.serde(their_service) + self._our_service = ServiceDecorator.serde(our_service) self.attach_thread_id = attach_thread_id self.our_recipient_key = our_recipient_key self.multi_use = multi_use @@ -89,7 +89,7 @@ def oob_id(self) -> str: return self._id @property - def invitation(self) -> InvitationMessage: + def invitation(self) -> Optional[InvitationMessage]: """Accessor; get deserialized view.""" return None if self._invitation is None else self._invitation.de @@ -98,6 +98,21 @@ def invitation(self, value): """Setter; store de/serialized views.""" self._invitation = InvitationMessage.serde(value) + @property + def our_service(self) -> Optional[ServiceDecorator]: + """Accessor; get deserialized view.""" + return None if self._our_service is None else self._our_service.de + + @our_service.setter + def our_service(self, value: Union[ServiceDecorator, Mapping[str, Any]]): + """Setter; store de/serialized views.""" + self._our_service = ServiceDecorator.serde(value) + + @property + def their_service(self) -> Optional[ServiceDecorator]: + """Accessor; get deserialized view.""" + return None if self._their_service is None else self._their_service.de + @property def record_value(self) -> dict: """Accessor for the JSON record value generated for this invitation.""" @@ -109,14 +124,13 @@ def record_value(self) -> dict: "their_service", "connection_id", "role", - "our_service", "invi_msg_id", "multi_use", ) }, **{ prop: getattr(self, f"_{prop}").ser - for prop in ("invitation",) + for prop in ("invitation", "our_service", "their_service") if getattr(self, prop) is not None }, } diff --git a/aries_cloudagent/protocols/out_of_band/v1_0/tests/test_manager.py b/aries_cloudagent/protocols/out_of_band/v1_0/tests/test_manager.py index 05034e9685..3b8d33a51c 100644 --- a/aries_cloudagent/protocols/out_of_band/v1_0/tests/test_manager.py +++ b/aries_cloudagent/protocols/out_of_band/v1_0/tests/test_manager.py @@ -591,9 +591,7 @@ async def test_create_invitation_attachment_v2_0_cred_offer(self): ) mock_retrieve_cxid_v1.side_effect = test_module.StorageNotFoundError() mock_retrieve_cxid_v2.return_value = mock.MagicMock( - cred_offer=mock.MagicMock( - serialize=mock.MagicMock(return_value={"cred": "offer"}) - ) + cred_offer=V20CredOffer() ) invi_rec = await self.manager.create_invitation( my_endpoint=TestConfig.test_endpoint, @@ -606,10 +604,10 @@ async def test_create_invitation_attachment_v2_0_cred_offer(self): mock_retrieve_cxid_v2.assert_called_once_with(ANY, "dummy-id") assert isinstance(invi_rec, InvitationRecord) assert not invi_rec.invitation.handshake_protocols - assert invi_rec.invitation.requests_attach[0].content == { - "cred": "offer", - "~thread": {"pthid": invi_rec.invi_msg_id}, - } + attach = invi_rec.invitation.requests_attach[0].content + assert isinstance(attach, dict) + assert "~thread" in attach and "pthid" in attach["~thread"] + assert attach["~thread"]["pthid"] == invi_rec.invi_msg_id async def test_create_invitation_attachment_present_proof_v1_0(self): self.profile.context.update_settings({"public_invites": True}) @@ -759,7 +757,15 @@ async def test_create_invitation_attachment_x(self): public=False, hs_protos=[test_module.HSProto.RFC23], multi_use=False, - attachments=[{"having": "attachment", "is": "no", "good": "here"}], + attachments=[ + { + "type": "asdf", + "id": "asdf", + "having": "attachment", + "is": "no", + "good": "here", + } + ], ) assert "Unknown attachment type" in str(context.exception) @@ -1613,7 +1619,9 @@ async def test_request_attach_oob_message_processor_connectionless(self): mock.CoroutineMock(), ) as mock_service_decorator_from_service: mock_create_signing_key.return_value = KeyInfo( - verkey="a-verkey", metadata={}, key_type=ED25519 + verkey="H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV", + metadata={}, + key_type=ED25519, ) mock_service_decorator_from_service.return_value = mock_service_decorator oob_invitation = InvitationMessage( @@ -1626,7 +1634,10 @@ async def test_request_attach_oob_message_processor_connectionless(self): oob_invitation, use_existing_connection=True ) - assert oob_record.our_recipient_key == "a-verkey" + assert ( + oob_record.our_recipient_key + == "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + ) assert oob_record.our_service assert oob_record.state == OobRecord.STATE_PREPARE_RESPONSE