async def handle(self, content_type, data): try: if content_type == DIDExchange.MESSAGE_CONTENT_TYPE: kwargs = json.loads(data) msg = Message(**kwargs) elif content_type in WIRED_CONTENT_TYPES: msg = await DIDExchange.unpack_agent_message(data, self.get_wallet()) else: raise RuntimeError('Unknown content_type "%s"' % content_type) await self.__log('Receive', msg.to_dict()) if msg.type == DIDExchange.INVITE: await self.__receive_invitation(msg) elif msg.type == DIDExchange.RESPONSE: await self.__receive_connection_response(msg) elif msg.type == DIDExchange.PROBLEM_REPORT: if self.status == DIDExchangeStatus.Requested: # Stay in same state - retryable pass else: raise ImpossibleStatus() else: logging.error('Unexpected message type: %s' % msg.type) except Exception as e: if not isinstance(e, MachineIsDone): logging.exception('Base machine terminated with exception') await self.done()
async def handle(cls, agent_name: str, wire_message: bytes, my_label: str = None, my_endpoint: str = None) -> bool: unpacked = await WalletAgent.unpack_message(agent_name, wire_message) kwargs = json.loads(unpacked['message']) message = Message(**kwargs) print('***** feature 0037 handle message *****') if 'sender_verkey' in unpacked: sender_verkey = unpacked['sender_verkey'] else: sender_verkey = None if 'recipient_verkey' in unpacked: recipient_verkey = unpacked['recipient_verkey'] else: recipient_verkey = None print('sender_verkey: ' + sender_verkey) print('recipient_verkey: ' + recipient_verkey) print(json.dumps(message.to_dict(), indent=2, sort_keys=True)) print('***************************************') if message.get('@type', None) is None: return False if not cls.endorsement(message): return False state_machine_id = cls.get_state_machine_id(unpacked['sender_verkey']) if message.type in [ PresentProofProtocol.REQUEST_PRESENTATION, AckMessage.ACK ]: if message.type == PresentProofProtocol.REQUEST_PRESENTATION: machine_class = PresentProofProtocol.ProverStateMachine await WalletAgent.start_state_machine( status=PresentProofStatus.Null, ttl=PresentProofProtocol.STATE_MACHINE_TTL, agent_name=agent_name, machine_class=machine_class, machine_id=state_machine_id) await WalletAgent.invoke_state_machine( agent_name=agent_name, id_=state_machine_id, content_type=cls.WIRED_CONTENT_TYPE, data=wire_message) return True elif message.type in [PresentProofProtocol.PRESENTATION]: await WalletAgent.invoke_state_machine( agent_name=agent_name, id_=state_machine_id, content_type=cls.WIRED_CONTENT_TYPE, data=wire_message) return True elif message.type == PresentProofProtocol.PROBLEM_REPORT: await WalletAgent.invoke_state_machine( agent_name=agent_name, id_=state_machine_id, content_type=cls.WIRED_CONTENT_TYPE, data=wire_message) return True else: return False
async def handle(cls, agent_name: str, wire_message: bytes, my_label: str=None, my_endpoint: str=None) -> bool: unpacked = await WalletAgent.unpack_message(agent_name, wire_message) kwargs = json.loads(unpacked['message']) message = Message(**kwargs) if message.get('@type', None) is None: return False if message.type == cls.REQUEST: state_machine_id = unpacked['sender_verkey'] machine_class = DIDExchange.DIDExchangeInviterStateMachine await WalletAgent.start_state_machine( agent_name=agent_name, machine_class=machine_class, machine_id=state_machine_id, endpoint=my_endpoint, label=my_label, status=DIDExchangeStatus.Invited ) await WalletAgent.invoke_state_machine( agent_name=agent_name, id_=state_machine_id, content_type=cls.WIRED_CONTENT_TYPE, data=wire_message ) return True elif message.type == DIDExchange.RESPONSE: state_machine_id = message['connection~sig']['signer'] await WalletAgent.invoke_state_machine( agent_name=agent_name, id_=state_machine_id, content_type=cls.WIRED_CONTENT_TYPE, data=wire_message ) return True elif message.type in [TrustPing.PING, TrustPing.PING_RESPONSE]: state_machine_id = unpacked['sender_verkey'] await WalletAgent.invoke_state_machine( agent_name=agent_name, id_=state_machine_id, content_type=cls.WIRED_CONTENT_TYPE, data=wire_message ) return True elif message.type == DIDExchange.PROBLEM_REPORT: state_machine_id = message.to_dict().get('connection~sig', {}).get('signer') if state_machine_id: await WalletAgent.invoke_state_machine( agent_name=agent_name, id_=state_machine_id, content_type=cls.WIRED_CONTENT_TYPE, data=wire_message ) return True else: logging.error('Problem report', message.as_json()) return True else: return False
async def __validate_cred_offer(self, msg: Message, context: Context): offer_attaches = msg.to_dict().get('offers~attach', None) if isinstance(offer_attaches, dict): offer_attaches = [offer_attaches] if (not type(offer_attaches) is list) or ( type(offer_attaches) is list and len(offer_attaches) == 0): await self.__send_problem_report( problem_code=IssueCredentialProtocol. OFFER_PROCESSING_ERROR, problem_str= 'Expected offer~attach must contains credOffer and credDef', context=context, thread_id=msg.id) await self.done() offer = offer_attaches[0] offer_body = None cred_def_body = None for attach in offer_attaches: raw_base64 = attach.get('data', {}).get('base64', None) if raw_base64: payload = json.loads(base64.b64decode(raw_base64).decode()) offer_fields = [ 'key_correctness_proof', 'nonce', 'schema_id', 'cred_def_id' ] cred_def_fields = [ 'value', 'type', 'ver', 'schemaId', 'id', 'tag' ] if all([field in payload.keys() for field in offer_fields ]): # check if cred offer content offer_body = { attr: val for attr, val in payload.items() if attr in offer_fields } if all( [field in payload.keys() for field in cred_def_fields ]): # check if cred def content cred_def_body = { attr: val for attr, val in payload.items() if attr in cred_def_fields } if not offer_body: await self.__send_problem_report( problem_code=IssueCredentialProtocol. OFFER_PROCESSING_ERROR, problem_str= 'Expected offer~attach must contains Payload with offer', context=context, thread_id=msg.id) await self.done() if cred_def_body: cred_def_id = cred_def_body['id'] await indy_sdk_utils.store_cred_def(self.get_wallet(), cred_def_id, cred_def_body) else: await self.__send_problem_report( problem_code=IssueCredentialProtocol. OFFER_PROCESSING_ERROR, problem_str= 'Expected offer~attach must contains Payload with cred_def data', context=context, thread_id=msg.id) await self.done() attaches = msg.to_dict().get('~attach', None) if attaches: if isinstance(attaches, dict): attaches = [attaches] for attach in attaches: if attach.get( '@type', None ) == IssueCredentialProtocol.ISSUER_SCHEMA_TYPE: issuer_schema_body = attach['data']['json'] issuer_schema_id = issuer_schema_body['id'] await indy_sdk_utils.store_issuer_schema( self.get_wallet(), issuer_schema_id, issuer_schema_body) return offer, offer_body, cred_def_body
async def handle(self, content_type, data): try: msg_type_offer_credential = IssueCredentialProtocol.set_protocol_version( IssueCredentialProtocol.OFFER_CREDENTIAL, self.protocol_version or IssueCredentialProtocol.VERSION) msg_type_issue_credential = IssueCredentialProtocol.set_protocol_version( IssueCredentialProtocol.ISSUE_CREDENTIAL, self.protocol_version or IssueCredentialProtocol.VERSION) if content_type in WIRED_CONTENT_TYPES: msg, context = await IssueCredentialProtocol.unpack_agent_message( data, self.get_wallet()) self.to = context.their_did success, err_msg = await IssueCredentialProtocol.validate_common_message_blocks( msg, IssueCredentialProtocol.REQUEST_NOT_ACCEPTED, context) if not success: if err_msg: await IssueCredentialProtocol.send_message_to_agent( context.their_did, err_msg, self.get_wallet()) else: raise RuntimeError('Unsupported content_type "%s"' % content_type) if msg.type == msg_type_offer_credential: if self.status == IssueCredentialStatus.Null: await self.__log('Received credential offer', msg.to_dict()) offer, offer_body, cred_def_body = await self.__validate_cred_offer( msg, context) self.cred_def_id = offer_body['cred_def_id'] link_secret_name = settings.INDY['WALLET_SETTINGS'][ 'PROVER_MASTER_SECRET_NAME'] try: await self.get_wallet( ).prover_create_master_secret(link_secret_name) except WalletOperationError as e: if 'duplicate' in e.error_message.lower(): # nothing to do pass else: raise e # Create Credential request self.cred_def_buffer = json.dumps(cred_def_body) cred_request, metadata = await self.get_wallet( ).prover_create_credential_req( prover_did=context.my_did, cred_offer=offer_body, cred_def=cred_def_body, master_secret_id=link_secret_name) await self.__log( 'Cred request artifacts', dict(cred_request=cred_request, metadata=metadata)) self.cred_metadata = json.dumps(metadata) # Build request data = { "@type": IssueCredentialProtocol.REQUEST_CREDENTIAL, "~thread": { Message.THREAD_ID: msg.id, Message.SENDER_ORDER: 0 }, "requests~attach": [ { "@id": uuid.uuid4().hex, "mime-type": "application/json", "data": { "base64": base64.b64encode( json.dumps(cred_request).encode()). decode() } }, ] } if self.comment: data['comment'] = self.comment message_request = Message(data) await IssueCredentialProtocol.send_message_to_agent( self.to, message_request, self.get_wallet()) await self.__log('Send credential request', message_request.to_dict()) self.status = IssueCredentialStatus.RequestCredential else: await self.__send_problem_report( problem_code=IssueCredentialProtocol. OFFER_PROCESSING_ERROR, problem_str='Impossible state machine state', context=context, thread_id=msg.id) raise ImpossibleStatus elif msg.type == msg_type_issue_credential: if self.status == IssueCredentialStatus.RequestCredential: await self.__log('Received Issue credential', msg.to_dict()) cred_attaches = msg.to_dict().get( 'credentials~attach', None) if isinstance(cred_attaches, dict): cred_attaches = [cred_attaches] for cred_attach in cred_attaches: cred_body = cred_attach.get('data').get('base64') cred_body = base64.b64decode(cred_body) cred_body = json.loads(cred_body.decode()) cred_def = json.loads(self.cred_def_buffer) cred_id = cred_attach.get('@id', None) # Store credential cred_older = await self.get_wallet( ).prover_get_credential(cred_id) if cred_older: # Delete older credential await self.get_wallet( ).prover_delete_credential(cred_id) cred_id = await self.get_wallet( ).prover_store_credential( cred_req_metadata=json.loads( self.cred_metadata), cred=cred_body, cred_def=cred_def, rev_reg_def=self.rev_reg_def, cred_id=cred_id) await self.__log( 'Store credential with id: %s' % str(cred_id), cred_body) ack_message_id = msg.to_dict().get( '~please_ack', {}).get('message_id', None) if not ack_message_id: ack_message_id = msg.id ack = AckMessage.build(ack_message_id) await IssueCredentialProtocol.send_message_to_agent( self.to, ack, self.get_wallet()) await self.__log('Send ACK', ack.to_dict()) await self.done() else: await self.__send_problem_report( problem_code=IssueCredentialProtocol. ISSUE_PROCESSING_ERROR, problem_str='Impossible state machine state', context=context, thread_id=msg.id) raise ImpossibleStatus elif msg.type == IssueCredentialProtocol.PROBLEM_REPORT: await self.__log('Received problem report', msg.to_dict()) await self.done() else: await self.__send_problem_report( problem_code=IssueCredentialProtocol. RESPONSE_FOR_UNKNOWN_REQUEST, problem_str='Unknown message type', context=context, thread_id=msg.id) except Exception as e: if not isinstance(e, MachineIsDone): logging.exception('Base machine terminated with exception') await self.done()