def test_handle_message_signing_ethereum_deprecated(self): """Test message signing for ethereum deprecated.""" message = b"0x11f3f9487724404e3a1fb7252a3226" signing_dialogues = SigningDialogues("agent5") signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_MESSAGE, dialogue_reference=signing_dialogues.new_self_initiated_dialogue_reference(), skill_callback_ids=(str(PublicId("author", "a_skill", "0.1.0")),), skill_callback_info={}, terms=Terms( ledger_id=ETHEREUM, sender_address="pk1", counterparty_address="pk2", amount_by_currency_id={"FET": -1}, is_sender_payable_tx_fee=True, quantities_by_good_id={"good_id": 10}, nonce="transaction nonce", ), raw_message=RawMessage(ETHEREUM, message, is_deprecated_mode=True), ) signing_msg.counterparty = "decision_maker" self.decision_maker.message_in_queue.put_nowait(signing_msg) signing_msg_response = self.decision_maker.message_out_queue.get(timeout=2) assert ( signing_msg_response.performative == SigningMessage.Performative.SIGNED_MESSAGE ) assert signing_msg_response.skill_callback_ids == signing_msg.skill_callback_ids assert type(signing_msg_response.signed_message) == SignedMessage assert signing_msg_response.signed_message.is_deprecated_mode
def _handle_raw_transaction( self, ledger_api_msg: LedgerApiMessage, ledger_api_dialogue: LedgerApiDialogue) -> None: """ Handle a message of raw_transaction performative. :param ledger_api_message: the ledger api message :param ledger_api_dialogue: the ledger api dialogue """ self.context.logger.info( "received raw transaction={}".format(ledger_api_msg)) signing_dialogues = cast(SigningDialogues, self.context.signing_dialogues) signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_TRANSACTION, dialogue_reference=signing_dialogues. new_self_initiated_dialogue_reference(), skill_callback_ids=(str(self.context.skill_id), ), raw_transaction=ledger_api_msg.raw_transaction, terms=ledger_api_dialogue.associated_fipa_dialogue.terms, skill_callback_info={}, ) signing_msg.counterparty = "decision_maker" signing_dialogue = cast(Optional[SigningDialogue], signing_dialogues.update(signing_msg)) assert signing_dialogue is not None, "Error when creating signing dialogue" signing_dialogue.associated_fipa_dialogue = ( ledger_api_dialogue.associated_fipa_dialogue) self.context.decision_maker_message_queue.put_nowait(signing_msg) self.context.logger.info( "proposing the transaction to the decision maker. Waiting for confirmation ..." )
def test_handle_tx_signing_fetchai(self): """Test tx signing for fetchai.""" tx = TokenTxFactory.transfer( FetchaiAddress("v3sZs7gKKz9xmoTo9yzRkfHkjYuX42MzXaq4eVjGHxrX9qu3U"), FetchaiAddress("2bzQNV4TTjMAiKZe85EyLUttoFpHHuksRzUUBYB1brt98pMXKK"), 1, 1, [], ) signing_dialogues = SigningDialogues("agent1") signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_TRANSACTION, dialogue_reference=signing_dialogues.new_self_initiated_dialogue_reference(), skill_callback_ids=(str(PublicId("author", "a_skill", "0.1.0")),), skill_callback_info={}, terms=Terms( ledger_id=FETCHAI, sender_address="pk1", counterparty_address="pk2", amount_by_currency_id={"FET": -1}, is_sender_payable_tx_fee=True, quantities_by_good_id={"good_id": 10}, nonce="transaction nonce", ), raw_transaction=RawTransaction(FETCHAI, tx), ) signing_msg.counterparty = "decision_maker" self.decision_maker.message_in_queue.put_nowait(signing_msg) signing_msg_response = self.decision_maker.message_out_queue.get(timeout=2) assert ( signing_msg_response.performative == SigningMessage.Performative.SIGNED_TRANSACTION ) assert signing_msg_response.skill_callback_ids == signing_msg.skill_callback_ids assert type(signing_msg_response.signed_transaction.body) == FetchaiTransaction
def test_handle_tx_signing_ethereum(self): """Test tx signing for ethereum.""" tx = {"gasPrice": 30, "nonce": 1, "gas": 20000} signing_dialogues = SigningDialogues("agent2") signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_TRANSACTION, dialogue_reference=signing_dialogues.new_self_initiated_dialogue_reference(), skill_callback_ids=(str(PublicId("author", "a_skill", "0.1.0")),), skill_callback_info={}, terms=Terms( ledger_id=ETHEREUM, sender_address="pk1", counterparty_address="pk2", amount_by_currency_id={"FET": -1}, is_sender_payable_tx_fee=True, quantities_by_good_id={"good_id": 10}, nonce="transaction nonce", ), raw_transaction=RawTransaction(ETHEREUM, tx), ) signing_msg.counterparty = "decision_maker" self.decision_maker.message_in_queue.put_nowait(signing_msg) signing_msg_response = self.decision_maker.message_out_queue.get(timeout=2) assert ( signing_msg_response.performative == SigningMessage.Performative.SIGNED_TRANSACTION ) assert signing_msg_response.skill_callback_ids == signing_msg.skill_callback_ids assert ( type(signing_msg_response.signed_transaction.body) == eth_account.datastructures.AttributeDict )
def test_handle_tx_signing_unknown(self): """Test tx signing for unknown.""" tx = {} signing_dialogues = SigningDialogues("agent") signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_TRANSACTION, dialogue_reference=signing_dialogues.new_self_initiated_dialogue_reference(), skill_callback_ids=(str(PublicId("author", "a_skill", "0.1.0")),), skill_callback_info={}, terms=Terms( ledger_id="unknown", sender_address="pk1", counterparty_address="pk2", amount_by_currency_id={"FET": -1}, is_sender_payable_tx_fee=True, quantities_by_good_id={"good_id": 10}, nonce="transaction nonce", ), raw_transaction=RawTransaction("unknown", tx), ) signing_msg.counterparty = "decision_maker" signing_dialogue = signing_dialogues.update(signing_msg) assert signing_dialogue is not None self.decision_maker.message_in_queue.put_nowait(signing_msg) signing_msg_response = self.decision_maker.message_out_queue.get(timeout=2) signing_msg_response.counterparty = signing_msg.counterparty signing_msg_response.is_incoming = True recovered_dialogue = signing_dialogues.update(signing_msg_response) assert recovered_dialogue is not None and recovered_dialogue == signing_dialogue assert signing_msg_response.performative == SigningMessage.Performative.ERROR assert signing_msg_response.skill_callback_ids == signing_msg.skill_callback_ids assert ( signing_msg_response.error_code == SigningMessage.ErrorCode.UNSUCCESSFUL_TRANSACTION_SIGNING )
def test_handle_message_signing_unknown_and_two_dialogues(self): """Test message signing for unknown.""" message = b"0x11f3f9487724404e3a1fb7252a322656b90ba0455a2ca5fcdcbe6eeee5f8126d" signing_dialogues = SigningDialogues("agent") signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_MESSAGE, dialogue_reference=signing_dialogues.new_self_initiated_dialogue_reference(), skill_callback_ids=(str(PublicId("author", "a_skill", "0.1.0")),), skill_callback_info={}, terms=Terms( ledger_id="unknown", sender_address="pk1", counterparty_address="pk2", amount_by_currency_id={"FET": -1}, is_sender_payable_tx_fee=True, quantities_by_good_id={"good_id": 10}, nonce="transaction nonce", ), raw_message=RawMessage("unknown", message), ) signing_msg.counterparty = "decision_maker" signing_dialogue = signing_dialogues.update(signing_msg) assert signing_dialogue is not None self.decision_maker.message_in_queue.put_nowait(signing_msg) signing_msg_response = self.decision_maker.message_out_queue.get(timeout=2) signing_msg_response.counterparty = signing_msg.counterparty signing_msg_response.is_incoming = True recovered_dialogue = signing_dialogues.update(signing_msg_response) assert recovered_dialogue is not None and recovered_dialogue == signing_dialogue assert signing_msg_response.performative == SigningMessage.Performative.ERROR assert signing_msg_response.skill_callback_ids == signing_msg.skill_callback_ids assert ( signing_msg_response.error_code == SigningMessage.ErrorCode.UNSUCCESSFUL_MESSAGE_SIGNING )
def test_sign_message(self): """Test for an error for a sign transaction message.""" tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_MESSAGE, skill_callback_ids=self.skill_callback_ids, skill_callback_info=self.skill_callback_info, terms=self.terms, raw_message=RawMessage(self.ledger_id, "message"), ) assert tx_msg._is_consistent() encoded_tx_msg = tx_msg.encode() decoded_tx_msg = tx_msg.serializer.decode(encoded_tx_msg) assert tx_msg == decoded_tx_msg
def test_signed_message(self): """Test for an error for a signed message.""" tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGNED_MESSAGE, message_id=2, target=1, skill_callback_ids=self.skill_callback_ids, skill_callback_info=self.skill_callback_info, signed_message=SignedMessage(self.ledger_id, "message"), ) assert tx_msg._is_consistent() encoded_tx_msg = tx_msg.encode() decoded_tx_msg = tx_msg.serializer.decode(encoded_tx_msg) assert tx_msg == decoded_tx_msg
def test_signed_transaction(self): """Test for an error for a signed transaction.""" tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGNED_TRANSACTION, message_id=2, target=1, skill_callback_ids=self.skill_callback_ids, skill_callback_info=self.skill_callback_info, signed_transaction=SignedTransaction(self.ledger_id, "signature"), ) assert tx_msg._is_consistent() encoded_tx_msg = tx_msg.encode() decoded_tx_msg = tx_msg.serializer.decode(encoded_tx_msg) assert tx_msg == decoded_tx_msg
def test_serialization_negative(): """Test serialization when performative is not recognized.""" skill_callback_ids = (str(PublicId("author", "a_skill", "0.1.0")), ) skill_callback_info = {"some_string": "some_string"} tx_msg = SigningMessage( performative=SigningMessage.Performative.ERROR, message_id=2, target=1, skill_callback_ids=skill_callback_ids, skill_callback_info=skill_callback_info, error_code=SigningMessage.ErrorCode.UNSUCCESSFUL_MESSAGE_SIGNING, ) with patch.object(SigningMessage.Performative, "__eq__", return_value=False): with pytest.raises( ValueError, match=f"Performative not valid: {tx_msg.performative}"): tx_msg.serializer.encode(tx_msg) encoded_tx_bytes = tx_msg.serializer.encode(tx_msg) with patch.object(SigningMessage.Performative, "__eq__", return_value=False): with pytest.raises( ValueError, match=f"Performative not valid: {tx_msg.performative}"): tx_msg.serializer.decode(encoded_tx_bytes)
def test_error_message(self): """Test for an error for an error message.""" tx_msg = SigningMessage( performative=SigningMessage.Performative.ERROR, message_id=2, target=1, skill_callback_ids=self.skill_callback_ids, skill_callback_info=self.skill_callback_info, error_code=SigningMessage.ErrorCode.UNSUCCESSFUL_MESSAGE_SIGNING, ) assert tx_msg._is_consistent() encoded_tx_msg = tx_msg.encode() decoded_tx_msg = tx_msg.serializer.decode(encoded_tx_msg) assert tx_msg == decoded_tx_msg assert str(tx_msg.performative) == "error" assert len(tx_msg.valid_performatives) == 5
def _handle_signing_message(self, signing_message: SigningMessage): """Handle transaction message from the Decision Maker.""" skill_callback_ids = [ PublicId.from_str(skill_id) for skill_id in signing_message.skill_callback_ids ] for skill_id in skill_callback_ids: handler = self.resources.handler_registry.fetch_by_protocol_and_skill( signing_message.protocol_id, skill_id) if handler is not None: logger.debug("Calling handler {} of skill {}".format( type(handler), skill_id)) signing_message.counterparty = "decision_maker" # TODO: temp fix signing_message.is_incoming = True handler.handle(cast(Message, signing_message)) else: logger.warning( "No internal handler fetched for skill_id={}".format( skill_id))
def _handle_message_signing(self, signing_msg: SigningMessage, signing_dialogue: SigningDialogue) -> None: """ Handle a message for signing. :param signing_msg: the signing message :param signing_dialogue: the signing dialogue :return: None """ signing_msg_response = SigningMessage( performative=SigningMessage.Performative.ERROR, dialogue_reference=signing_dialogue.dialogue_label. dialogue_reference, target=signing_msg.message_id, message_id=signing_msg.message_id + 1, skill_callback_ids=signing_msg.skill_callback_ids, skill_callback_info=signing_msg.skill_callback_info, error_code=SigningMessage.ErrorCode.UNSUCCESSFUL_MESSAGE_SIGNING, ) if self._is_acceptable_for_signing(signing_msg): signed_message = self.wallet.sign_message( signing_msg.raw_message.ledger_id, signing_msg.raw_message.body, signing_msg.raw_message.is_deprecated_mode, ) if signed_message is not None: signing_msg_response = SigningMessage( performative=SigningMessage.Performative.SIGNED_MESSAGE, dialogue_reference=signing_dialogue.dialogue_label. dialogue_reference, target=signing_msg.message_id, message_id=signing_msg.message_id + 1, skill_callback_ids=signing_msg.skill_callback_ids, skill_callback_info=signing_msg.skill_callback_info, signed_message=SignedMessage( signing_msg.raw_message.ledger_id, signed_message, signing_msg.raw_message.is_deprecated_mode, ), ) signing_msg_response.counterparty = signing_msg.counterparty signing_dialogue.update(signing_msg_response) self.message_out_queue.put(signing_msg_response)
def test_handle_internal_messages(self): """Test that the internal messages are handled.""" t = SigningMessage( performative=SigningMessage.Performative.SIGNED_TRANSACTION, skill_callback_ids=(str(PublicId("dummy_author", "dummy", "0.1.0")), ), skill_callback_info={}, # crypto_id="ledger_id", signed_transaction=SignedTransaction("ledger_id", "tx"), ) t.counterparty = "skill" t.sender = "decision_maker" self.aea.decision_maker.message_out_queue.put(t) self.aea._filter.handle_internal_messages() internal_handlers_list = self.aea.resources.get_handlers(t.protocol_id) assert len(internal_handlers_list) == 1 internal_handler = internal_handlers_list[0] assert len(internal_handler.handled_internal_messages) == 1 self.aea.teardown()
def _handle_transaction_signing(self, signing_msg: SigningMessage, signing_dialogue: SigningDialogue) -> None: """ Handle a transaction for signing. :param signing_msg: the signing message :param signing_dialogue: the signing dialogue :return: None """ signing_msg_response = SigningMessage( performative=SigningMessage.Performative.ERROR, dialogue_reference=signing_dialogue.dialogue_label. dialogue_reference, target=signing_msg.message_id, message_id=signing_msg.message_id + 1, skill_callback_ids=signing_msg.skill_callback_ids, skill_callback_info=signing_msg.skill_callback_info, error_code=SigningMessage.ErrorCode. UNSUCCESSFUL_TRANSACTION_SIGNING, ) if self._is_acceptable_for_signing(signing_msg): signed_tx = self.wallet.sign_transaction( signing_msg.raw_transaction.ledger_id, signing_msg.raw_transaction.body) if signed_tx is not None: signing_msg_response = SigningMessage( performative=SigningMessage.Performative. SIGNED_TRANSACTION, dialogue_reference=signing_dialogue.dialogue_label. dialogue_reference, target=signing_msg.message_id, message_id=signing_msg.message_id + 1, skill_callback_ids=signing_msg.skill_callback_ids, skill_callback_info=signing_msg.skill_callback_info, signed_transaction=SignedTransaction( signing_msg.raw_transaction.ledger_id, signed_tx), ) signing_msg_response.counterparty = signing_msg.counterparty signing_dialogue.update(signing_msg_response) self.message_out_queue.put(signing_msg_response)
def _handle_raw_message( self, contract_api_msg: ContractApiMessage, contract_api_dialogue: ContractApiDialogue, ) -> None: """ Handle a message of raw_message performative. :param contract_api_message: the ledger api message :param contract_api_dialogue: the ledger api dialogue """ self.context.logger.info("[{}]: received raw message={}".format( self.context.agent_name, contract_api_msg)) signing_dialogues = cast(SigningDialogues, self.context.signing_dialogues) signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_MESSAGE, dialogue_reference=signing_dialogues. new_self_initiated_dialogue_reference(), skill_callback_ids=(str(self.context.skill_id), ), raw_message=RawMessage( contract_api_msg.raw_message.ledger_id, contract_api_msg.raw_message.body, is_deprecated_mode=True, ), terms=contract_api_dialogue.terms, skill_callback_info={}, ) signing_msg.counterparty = "decision_maker" signing_dialogue = cast(Optional[SigningDialogue], signing_dialogues.update(signing_msg)) assert signing_dialogue is not None, "Error when creating signing dialogue." signing_dialogue.associated_contract_api_dialogue = contract_api_dialogue self.context.decision_maker_message_queue.put_nowait(signing_msg) self.context.logger.info( "[{}]: proposing the transaction to the decision maker. Waiting for confirmation ..." .format(self.context.agent_name))
def test_message_inconsistency(self): """Test for an error in consistency of a message.""" tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_TRANSACTION, skill_callback_ids=self.skill_callback_ids, terms=self.terms, ) assert not tx_msg._is_consistent() tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_MESSAGE, skill_callback_ids=self.skill_callback_ids, terms=self.terms, ) assert not tx_msg._is_consistent()
def generate_signing_message( self, performative: SigningMessage.Performative, proposal_description: Description, dialogue_label: DialogueLabel, role: FipaDialogue.Role, agent_addr: Address, ) -> SigningMessage: """ Generate the transaction message from the description and the dialogue. :param proposal_description: the description of the proposal :param dialogue_label: the dialogue label :param role: the role of the agent (seller or buyer) :param agent_addr: the address of the agent :return: a transaction message """ is_seller = role == FipaDialogue.Role.SELLER goods_component = copy.copy(proposal_description.values) [ # pylint: disable=expression-not-assigned goods_component.pop(key) for key in ["fee", "price", "currency_id", "nonce", "ledger_id"] ] # switch signs based on whether seller or buyer role amount = (proposal_description.values["price"] if is_seller else -proposal_description.values["price"]) fee = proposal_description.values["fee"] if is_seller: for good_id in goods_component.keys(): goods_component[good_id] = goods_component[good_id] * (-1) amount_by_currency_id = { proposal_description.values["currency_id"]: amount } fee_by_currency_id = {proposal_description.values["currency_id"]: fee} nonce = proposal_description.values["nonce"] ledger_id = proposal_description.values["ledger_id"] terms = Terms( ledger_id=ledger_id, sender_address=agent_addr, counterparty_address=dialogue_label.dialogue_opponent_addr, amount_by_currency_id=amount_by_currency_id, is_sender_payable_tx_fee=not is_seller, quantities_by_good_id=goods_component, nonce=nonce, fee_by_currency_id=fee_by_currency_id, ) skill_callback_ids = (str(self.context.skill_id), ) signing_dialogues = cast(SigningDialogues, self.context.signing_dialogues) skill_callback_info = {"dialogue_label": str(dialogue_label)} raw_message = RawMessage(ledger_id=ledger_id, body=terms.sender_hash.encode("utf-8")) signing_msg = SigningMessage( performative=performative, dialogue_reference=signing_dialogues. new_self_initiated_dialogue_reference(), skill_callback_ids=skill_callback_ids, terms=terms, skill_callback_info=skill_callback_info, raw_message=raw_message, ) signing_msg.counterparty = "decision_maker" return signing_msg
def test_consistency_check_negative(): """Test the consistency check, negative case.""" tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_TRANSACTION, ) assert not tx_msg._is_consistent()
def test_message_consistency(self): """Test for an error in consistency of a message.""" tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_TRANSACTION, skill_callback_ids=self.skill_callback_ids, skill_callback_info=self.skill_callback_info, terms=self.terms, raw_transaction=RawTransaction(self.ledger_id, "transaction"), ) assert tx_msg._is_consistent() tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_MESSAGE, skill_callback_ids=self.skill_callback_ids, skill_callback_info=self.skill_callback_info, terms=self.terms, raw_message=RawMessage(self.ledger_id, "message"), ) assert tx_msg._is_consistent() tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGNED_TRANSACTION, message_id=2, target=1, skill_callback_ids=self.skill_callback_ids, skill_callback_info=self.skill_callback_info, signed_transaction=SignedTransaction(self.ledger_id, "signature"), ) assert tx_msg._is_consistent() tx_msg = SigningMessage( performative=SigningMessage.Performative.SIGNED_MESSAGE, message_id=2, target=1, skill_callback_ids=self.skill_callback_ids, skill_callback_info=self.skill_callback_info, signed_message=SignedMessage(self.ledger_id, "message"), ) assert tx_msg._is_consistent() tx_msg = SigningMessage( performative=SigningMessage.Performative.ERROR, message_id=2, target=1, skill_callback_ids=self.skill_callback_ids, skill_callback_info=self.skill_callback_info, error_code=SigningMessage.ErrorCode.UNSUCCESSFUL_MESSAGE_SIGNING, ) assert tx_msg._is_consistent() assert str(tx_msg.performative) == "error" assert len(tx_msg.valid_performatives) == 5
def generate_transaction_message( # pylint: disable=no-self-use self, performative: SigningMessage.Performative, proposal_description: Description, dialogue_label: DialogueLabel, role: Dialogue.Role, agent_addr: Address, ) -> SigningMessage: """ Generate the transaction message from the description and the dialogue. :param proposal_description: the description of the proposal :param dialogue_label: the dialogue label :param role: the role of the agent (seller or buyer) :param agent_addr: the address of the agent :return: a transaction message """ is_seller = role == Dialogue.Role.SELLER # sender_tx_fee = ( # proposal_description.values["seller_tx_fee"] # if is_seller # else proposal_description.values["buyer_tx_fee"] # ) # counterparty_tx_fee = ( # proposal_description.values["buyer_tx_fee"] # if is_seller # else proposal_description.values["seller_tx_fee"] # ) goods_component = copy.copy(proposal_description.values) [ # pylint: disable=expression-not-assigned goods_component.pop(key) for key in [ "seller_tx_fee", "buyer_tx_fee", "price", "currency_id", "tx_nonce", ] ] # switch signs based on whether seller or buyer role amount = ( proposal_description.values["price"] if is_seller else -proposal_description.values["price"] ) if is_seller: for good_id in goods_component.keys(): goods_component[good_id] = goods_component[good_id] * (-1) tx_amount_by_currency_id = {proposal_description.values["currency_id"]: amount} tx_fee_by_currency_id = {proposal_description.values["currency_id"]: 1} tx_nonce = proposal_description.values["tx_nonce"] # need to hash positive.negative side separately tx_hash = tx_hash_from_values( tx_sender_addr=agent_addr, tx_counterparty_addr=dialogue_label.dialogue_opponent_addr, tx_quantities_by_good_id=goods_component, tx_amount_by_currency_id=tx_amount_by_currency_id, tx_nonce=tx_nonce, ) skill_callback_ids = ( (PublicId.from_str("fetchai/tac_participation:0.4.0"),) if performative == SigningMessage.Performative.SIGN_MESSAGE else (PublicId.from_str("fetchai/tac_negotiation:0.5.0"),) ) transaction_msg = SigningMessage( performative=performative, skill_callback_ids=skill_callback_ids, # tx_id=self.get_internal_tx_id(), terms=Terms( ledger_id="ethereum", sender_address=agent_addr, counterparty_address=dialogue_label.dialogue_opponent_addr, amount_by_currency_id=tx_amount_by_currency_id, is_sender_payable_tx_fee=True, # TODO: check! quantities_by_good_id=goods_component, nonce=tx_nonce, fee_by_currency_id=tx_fee_by_currency_id, ), skill_callback_info={"dialogue_label": dialogue_label.json}, message=tx_hash, ) return transaction_msg
def test_handle_messages_from_two_dialogues_same_agent(self): """Test message signing for unknown.""" message = b"0x11f3f9487724404e3a1fb7252a322656b90ba0455a2ca5fcdcbe6eeee5f8126d" signing_dialogues = SigningDialogues("agent") dialogue_reference = signing_dialogues.new_self_initiated_dialogue_reference() signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_MESSAGE, dialogue_reference=dialogue_reference, skill_callback_ids=(str(PublicId("author", "a_skill", "0.1.0")),), skill_callback_info={}, terms=Terms( ledger_id="unknown", sender_address="pk1", counterparty_address="pk2", amount_by_currency_id={"FET": -1}, is_sender_payable_tx_fee=True, quantities_by_good_id={"good_id": 10}, nonce="transaction nonce", ), raw_message=RawMessage("unknown", message), ) signing_msg.counterparty = "decision_maker" signing_dialogue = signing_dialogues.update(signing_msg) assert signing_dialogue is not None self.decision_maker.message_in_queue.put_nowait(signing_msg) signing_msg_response = self.decision_maker.message_out_queue.get(timeout=2) assert signing_msg_response is not None signing_dialogues = SigningDialogues("agent") signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_MESSAGE, dialogue_reference=dialogue_reference, skill_callback_ids=(str(PublicId("author", "a_skill", "0.1.0")),), skill_callback_info={}, terms=Terms( ledger_id="unknown", sender_address="pk1", counterparty_address="pk2", amount_by_currency_id={"FET": -1}, is_sender_payable_tx_fee=True, quantities_by_good_id={"good_id": 10}, nonce="transaction nonce", ), raw_message=RawMessage("unknown", message), ) signing_msg.counterparty = "decision_maker" signing_dialogue = signing_dialogues.update(signing_msg) assert signing_dialogue is not None with pytest.raises(Exception): # Exception occurs because the same counterparty sends two identical dialogue references self.decision_maker.message_out_queue.get(timeout=1) # test twice; should work again even from same agent signing_dialogues = SigningDialogues("agent") signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_MESSAGE, dialogue_reference=signing_dialogues.new_self_initiated_dialogue_reference(), skill_callback_ids=(str(PublicId("author", "a_skill", "0.1.0")),), skill_callback_info={}, terms=Terms( ledger_id="unknown", sender_address="pk1", counterparty_address="pk2", amount_by_currency_id={"FET": -1}, is_sender_payable_tx_fee=True, quantities_by_good_id={"good_id": 10}, nonce="transaction nonce", ), raw_message=RawMessage("unknown", message), ) signing_msg.counterparty = "decision_maker" signing_dialogue = signing_dialogues.update(signing_msg) assert signing_dialogue is not None self.decision_maker.message_in_queue.put_nowait(signing_msg) signing_msg_response = self.decision_maker.message_out_queue.get(timeout=2) assert signing_msg_response is not None
def run(): # Create a private key create_private_key(CosmosCrypto.identifier, private_key_file=COSMOS_PRIVATE_KEY_FILE_1) # Instantiate the builder and build the AEA # By default, the default protocol, error skill and stub connection are added builder = AEABuilder() builder.set_name("my_aea") builder.add_private_key(CosmosCrypto.identifier, COSMOS_PRIVATE_KEY_FILE_1) # Create our AEA my_aea = builder.build() # add a simple skill with handler skill_context = SkillContext(my_aea.context) skill_config = SkillConfig(name="simple_skill", author="fetchai", version="0.1.0") signing_handler = SigningHandler(skill_context=skill_context, name="signing_handler") signing_dialogues_model = SigningDialogues(skill_context=skill_context, name="signing_dialogues") simple_skill = Skill( skill_config, skill_context, handlers={signing_handler.name: signing_handler}, models={signing_dialogues_model.name: signing_dialogues_model}, ) my_aea.resources.add_skill(simple_skill) # create a second identity create_private_key(CosmosCrypto.identifier, private_key_file=COSMOS_PRIVATE_KEY_FILE_2) counterparty_wallet = Wallet( {CosmosCrypto.identifier: COSMOS_PRIVATE_KEY_FILE_2}) counterparty_identity = Identity( name="counterparty_aea", addresses=counterparty_wallet.addresses, default_address_key=CosmosCrypto.identifier, ) # create signing message for decision maker to sign terms = Terms( ledger_id=CosmosCrypto.identifier, sender_address=my_aea.identity.address, counterparty_address=counterparty_identity.address, amount_by_currency_id={"FET": -1}, quantities_by_good_id={"some_service": 1}, nonce="some_nonce", fee_by_currency_id={"FET": 0}, ) signing_dialogues = cast(SigningDialogues, skill_context.signing_dialogues) stub_transaction = LedgerApis.get_transfer_transaction( terms.ledger_id, terms.sender_address, terms.counterparty_address, terms.sender_payable_amount, terms.sender_fee, terms.nonce, ) signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_TRANSACTION, dialogue_reference=signing_dialogues. new_self_initiated_dialogue_reference(), skill_callback_ids=(str(skill_context.skill_id), ), raw_transaction=RawTransaction(CosmosCrypto.identifier, stub_transaction), terms=terms, skill_callback_info={"some_info_key": "some_info_value"}, ) signing_msg.counterparty = "decision_maker" signing_dialogue = cast(Optional[SigningDialogue], signing_dialogues.update(signing_msg)) assert signing_dialogue is not None my_aea.context.decision_maker_message_queue.put_nowait(signing_msg) # Set the AEA running in a different thread try: logger.info("STARTING AEA NOW!") t = Thread(target=my_aea.start) t.start() # Let it run long enough to interact with the decision maker time.sleep(1) finally: # Shut down the AEA logger.info("STOPPING AEA NOW!") my_aea.stop() t.join()
def decode(obj: bytes) -> Message: """ Decode bytes into a 'Signing' message. :param obj: the bytes object. :return: the 'Signing' message. """ signing_pb = signing_pb2.SigningMessage() signing_pb.ParseFromString(obj) message_id = signing_pb.message_id dialogue_reference = ( signing_pb.dialogue_starter_reference, signing_pb.dialogue_responder_reference, ) target = signing_pb.target performative = signing_pb.WhichOneof("performative") performative_id = SigningMessage.Performative(str(performative)) performative_content = dict() # type: Dict[str, Any] if performative_id == SigningMessage.Performative.SIGN_TRANSACTION: skill_callback_ids = signing_pb.sign_transaction.skill_callback_ids skill_callback_ids_tuple = tuple(skill_callback_ids) performative_content[ "skill_callback_ids"] = skill_callback_ids_tuple skill_callback_info = signing_pb.sign_transaction.skill_callback_info skill_callback_info_dict = dict(skill_callback_info) performative_content[ "skill_callback_info"] = skill_callback_info_dict pb2_terms = signing_pb.sign_transaction.terms terms = Terms.decode(pb2_terms) performative_content["terms"] = terms pb2_raw_transaction = signing_pb.sign_transaction.raw_transaction raw_transaction = RawTransaction.decode(pb2_raw_transaction) performative_content["raw_transaction"] = raw_transaction elif performative_id == SigningMessage.Performative.SIGN_MESSAGE: skill_callback_ids = signing_pb.sign_message.skill_callback_ids skill_callback_ids_tuple = tuple(skill_callback_ids) performative_content[ "skill_callback_ids"] = skill_callback_ids_tuple skill_callback_info = signing_pb.sign_message.skill_callback_info skill_callback_info_dict = dict(skill_callback_info) performative_content[ "skill_callback_info"] = skill_callback_info_dict pb2_terms = signing_pb.sign_message.terms terms = Terms.decode(pb2_terms) performative_content["terms"] = terms pb2_raw_message = signing_pb.sign_message.raw_message raw_message = RawMessage.decode(pb2_raw_message) performative_content["raw_message"] = raw_message elif performative_id == SigningMessage.Performative.SIGNED_TRANSACTION: skill_callback_ids = signing_pb.signed_transaction.skill_callback_ids skill_callback_ids_tuple = tuple(skill_callback_ids) performative_content[ "skill_callback_ids"] = skill_callback_ids_tuple skill_callback_info = signing_pb.signed_transaction.skill_callback_info skill_callback_info_dict = dict(skill_callback_info) performative_content[ "skill_callback_info"] = skill_callback_info_dict pb2_signed_transaction = signing_pb.signed_transaction.signed_transaction signed_transaction = SignedTransaction.decode( pb2_signed_transaction) performative_content["signed_transaction"] = signed_transaction elif performative_id == SigningMessage.Performative.SIGNED_MESSAGE: skill_callback_ids = signing_pb.signed_message.skill_callback_ids skill_callback_ids_tuple = tuple(skill_callback_ids) performative_content[ "skill_callback_ids"] = skill_callback_ids_tuple skill_callback_info = signing_pb.signed_message.skill_callback_info skill_callback_info_dict = dict(skill_callback_info) performative_content[ "skill_callback_info"] = skill_callback_info_dict pb2_signed_message = signing_pb.signed_message.signed_message signed_message = SignedMessage.decode(pb2_signed_message) performative_content["signed_message"] = signed_message elif performative_id == SigningMessage.Performative.ERROR: skill_callback_ids = signing_pb.error.skill_callback_ids skill_callback_ids_tuple = tuple(skill_callback_ids) performative_content[ "skill_callback_ids"] = skill_callback_ids_tuple skill_callback_info = signing_pb.error.skill_callback_info skill_callback_info_dict = dict(skill_callback_info) performative_content[ "skill_callback_info"] = skill_callback_info_dict pb2_error_code = signing_pb.error.error_code error_code = ErrorCode.decode(pb2_error_code) performative_content["error_code"] = error_code else: raise ValueError( "Performative not valid: {}.".format(performative_id)) return SigningMessage(message_id=message_id, dialogue_reference=dialogue_reference, target=target, performative=performative, **performative_content)