Exemple #1
0
def test_performative_match_accept_with_inform():
    """Test the serialization - deserialization of the match_accept_with_address performative."""
    msg = FipaMessage(
        message_id=1,
        dialogue_reference=(str(0), ""),
        target=0,
        performative=FipaMessage.Performative.MATCH_ACCEPT_W_INFORM,
        info={
            "address": "dummy_address",
            "signature": "my_signature"
        },
    )

    msg_bytes = FipaSerializer().encode(msg)
    envelope = Envelope(
        to="receiver",
        sender="sender",
        protocol_id=FipaMessage.protocol_id,
        message=msg_bytes,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope == actual_envelope
    deserialised_msg = FipaSerializer().decode(envelope.message)
    assert msg.get("performative") == deserialised_msg.get("performative")
Exemple #2
0
def test_fipa_cfp_serialization():
    """Test that the serialization for the 'fipa' protocol works."""
    query = Query([Constraint("something", ConstraintType(">", 1))])

    msg = FipaMessage(
        message_id=1,
        dialogue_reference=(str(0), ""),
        target=0,
        performative=FipaMessage.Performative.CFP,
        query=query,
    )
    msg_bytes = FipaSerializer().encode(msg)
    envelope = Envelope(
        to="receiver",
        sender="sender",
        protocol_id=FipaMessage.protocol_id,
        message=msg_bytes,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope == actual_envelope

    actual_msg = FipaSerializer().decode(actual_envelope.message)
    expected_msg = msg
    assert expected_msg == actual_msg
Exemple #3
0
    def _handle_propose(self, msg: FipaMessage, dialogue: Dialogue) -> None:
        """
        Handle the propose.

        :param msg: the message
        :param dialogue: the dialogue object
        :return: None
        """
        new_message_id = msg.message_id + 1
        new_target = msg.message_id
        proposal = msg.proposal
        self.context.logger.info(
            "[{}]: received proposal={} from sender={}".format(
                self.context.agent_name, proposal.values, msg.counterparty[-5:]
            )
        )
        strategy = cast(Strategy, self.context.strategy)
        acceptable = strategy.is_acceptable_proposal(proposal)
        affordable = strategy.is_affordable_proposal(proposal)
        if acceptable and affordable:
            self.context.logger.info(
                "[{}]: accepting the proposal from sender={}".format(
                    self.context.agent_name, msg.counterparty[-5:]
                )
            )
            dialogue.proposal = proposal
            accept_msg = FipaMessage(
                message_id=new_message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=new_target,
                performative=FipaMessage.Performative.ACCEPT,
            )
            accept_msg.counterparty = msg.counterparty
            dialogue.update(accept_msg)
            self.context.outbox.put_message(
                to=msg.counterparty,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(accept_msg),
            )
        else:
            self.context.logger.info(
                "[{}]: declining the proposal from sender={}".format(
                    self.context.agent_name, msg.counterparty[-5:]
                )
            )
            decline_msg = FipaMessage(
                message_id=new_message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=new_target,
                performative=FipaMessage.Performative.DECLINE,
            )
            decline_msg.counterparty = msg.counterparty
            dialogue.update(decline_msg)
            self.context.outbox.put_message(
                to=msg.counterparty,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(decline_msg),
            )
Exemple #4
0
def test_fipa_accept_serialization():
    """Test that the serialization for the 'fipa' protocol works."""
    msg = FipaMessage(
        message_id=1,
        dialogue_reference=(str(0), ""),
        target=0,
        performative=FipaMessage.Performative.ACCEPT,
    )
    msg.counterparty = "sender"
    msg_bytes = FipaSerializer().encode(msg)
    envelope = Envelope(
        to="receiver",
        sender="sender",
        protocol_id=FipaMessage.protocol_id,
        message=msg_bytes,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope == actual_envelope

    actual_msg = FipaSerializer().decode(actual_envelope.message)
    actual_msg.counterparty = "sender"
    expected_msg = msg
    assert expected_msg == actual_msg
Exemple #5
0
def test_fipa_propose_serialization():
    """Test that the serialization for the 'fipa' protocol works."""
    proposal = Description({"foo1": 1, "bar1": 2})
    msg = FipaMessage(
        message_id=1,
        dialogue_reference=(str(0), ""),
        target=0,
        performative=FipaMessage.Performative.PROPOSE,
        proposal=proposal,
    )
    msg_bytes = FipaSerializer().encode(msg)
    envelope = Envelope(
        to="receiver",
        sender="sender",
        protocol_id=FipaMessage.protocol_id,
        message=msg_bytes,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope == actual_envelope

    actual_msg = FipaSerializer().decode(actual_envelope.message)
    expected_msg = msg

    p1 = actual_msg.get("proposal")
    p2 = expected_msg.get("proposal")
    assert p1.values == p2.values
    def test_serialisation_fipa(self):
        """Tests a Value Error flag for wrong CFP query."""
        with pytest.raises(ValueError):
            msg = FipaMessage(
                performative=FipaMessage.Performative.CFP,
                message_id=1,
                dialogue_reference=(str(0), ""),
                target=0,
                query=Query([Constraint("something", ConstraintType(">", 1))]),
            )
            with mock.patch(
                "packages.fetchai.protocols.fipa.message.FipaMessage.Performative"
            ) as mock_performative_enum:
                mock_performative_enum.CFP.value = "unknown"
                FipaSerializer().encode(msg), "Raises Value Error"
        with pytest.raises(EOFError):
            cfp_msg = FipaMessage(
                message_id=1,
                dialogue_reference=(str(0), ""),
                target=0,
                performative=FipaMessage.Performative.CFP,
                query=Query([Constraint("something", ConstraintType(">", 1))]),
            )
            cfp_msg.set("query", "hello")
            fipa_msg = fipa_pb2.FipaMessage()
            fipa_msg.message_id = cfp_msg.message_id
            dialogue_reference = cast(Dict[str, str], cfp_msg.dialogue_reference)
            fipa_msg.dialogue_starter_reference = dialogue_reference[0]
            fipa_msg.dialogue_responder_reference = dialogue_reference[1]
            fipa_msg.target = cfp_msg.target
            performative = fipa_pb2.FipaMessage.Cfp_Performative()
            fipa_msg.cfp.CopyFrom(performative)
            fipa_bytes = fipa_msg.SerializeToString()

            # The encoded message is not a valid FIPA message.
            FipaSerializer().decode(fipa_bytes)
        with pytest.raises(ValueError):
            cfp_msg = FipaMessage(
                message_id=1,
                dialogue_reference=(str(0), ""),
                target=0,
                performative=FipaMessage.Performative.CFP,
                query=Query([Constraint("something", ConstraintType(">", 1))]),
            )
            with mock.patch(
                "packages.fetchai.protocols.fipa.message.FipaMessage.Performative"
            ) as mock_performative_enum:
                mock_performative_enum.CFP.value = "unknown"
                fipa_msg = fipa_pb2.FipaMessage()
                fipa_msg.message_id = cfp_msg.message_id
                dialogue_reference = cast(Dict[str, str], cfp_msg.dialogue_reference)
                fipa_msg.dialogue_starter_reference = dialogue_reference[0]
                fipa_msg.dialogue_responder_reference = dialogue_reference[1]
                fipa_msg.target = cfp_msg.target
                performative = fipa_pb2.FipaMessage.Cfp_Performative()
                fipa_msg.cfp.CopyFrom(performative)
                fipa_bytes = fipa_msg.SerializeToString()

                # The encoded message is not a FIPA message
                FipaSerializer().decode(fipa_bytes)
Exemple #7
0
    def _handle_cfp(self, msg: FipaMessage, dialogue: Dialogue) -> None:
        """
        Handle the CFP.

        If the CFP matches the supplied services then send a PROPOSE, otherwise send a DECLINE.

        :param msg: the message
        :param dialogue: the dialogue object
        :return: None
        """
        new_message_id = msg.message_id + 1
        new_target = msg.message_id
        self.context.logger.info("[{}]: received CFP from sender={}".format(
            self.context.agent_name, msg.counterparty[-5:]))
        query = cast(Query, msg.query)
        strategy = cast(Strategy, self.context.strategy)

        if strategy.is_matching_supply(query):
            proposal, temp_data = strategy.generate_proposal_and_data(
                query, msg.counterparty)
            dialogue.temp_data = temp_data
            dialogue.proposal = proposal
            self.context.logger.info(
                "[{}]: sending a PROPOSE with proposal={} to sender={}".format(
                    self.context.agent_name, proposal.values,
                    msg.counterparty[-5:]))
            proposal_msg = FipaMessage(
                message_id=new_message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=new_target,
                performative=FipaMessage.Performative.PROPOSE,
                proposal=proposal,
            )
            proposal_msg.counterparty = msg.counterparty
            dialogue.update(proposal_msg)
            self.context.outbox.put_message(
                to=msg.counterparty,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(proposal_msg),
            )
        else:
            self.context.logger.info(
                "[{}]: declined the CFP from sender={}".format(
                    self.context.agent_name, msg.counterparty[-5:]))
            decline_msg = FipaMessage(
                message_id=new_message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=new_target,
                performative=FipaMessage.Performative.DECLINE,
            )
            decline_msg.counterparty = msg.counterparty
            dialogue.update(decline_msg)
            self.context.outbox.put_message(
                to=msg.counterparty,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(decline_msg),
            )
Exemple #8
0
def test_fipa_decoding_unknown_performative():
    """Test that we raise an exception when the performative is unknown during decoding."""
    msg = FipaMessage(
        message_id=1,
        dialogue_reference=(str(0), ""),
        target=0,
        performative=FipaMessage.Performative.ACCEPT,
    )

    encoded_msg = FipaSerializer().encode(msg)
    with pytest.raises(ValueError, match="Performative not valid:"):
        with mock.patch.object(FipaMessage.Performative,
                               "__eq__",
                               return_value=False):
            FipaSerializer().decode(encoded_msg)
Exemple #9
0
    def _handle_accept(self, msg: FipaMessage, dialogue: Dialogue) -> None:
        """
        Handle the ACCEPT.

        Respond with a MATCH_ACCEPT_W_INFORM which contains the address to send the funds to.

        :param msg: the message
        :param dialogue: the dialogue object
        :return: None
        """
        new_message_id = msg.message_id + 1
        new_target = msg.message_id
        self.context.logger.info("[{}]: received ACCEPT from sender={}".format(
            self.context.agent_name, msg.counterparty[-5:]))
        self.context.logger.info(
            "[{}]: sending MATCH_ACCEPT_W_INFORM to sender={}".format(
                self.context.agent_name, msg.counterparty[-5:]))
        proposal = cast(Description, dialogue.proposal)
        identifier = cast(str, proposal.values.get("ledger_id"))
        match_accept_msg = FipaMessage(
            message_id=new_message_id,
            dialogue_reference=dialogue.dialogue_label.dialogue_reference,
            target=new_target,
            performative=FipaMessage.Performative.MATCH_ACCEPT_W_INFORM,
            info={"address": self.context.agent_addresses[identifier]},
        )
        dialogue.outgoing_extend(match_accept_msg)
        self.context.outbox.put_message(
            to=msg.counterparty,
            sender=self.context.agent_address,
            protocol_id=FipaMessage.protocol_id,
            message=FipaSerializer().encode(match_accept_msg),
        )
Exemple #10
0
    def _handle_match_accept(self, msg: FipaMessage,
                             dialogue: Dialogue) -> None:
        """
        Handle the match accept.

        :param msg: the message
        :param dialogue: the dialogue object
        :return: None
        """
        strategy = cast(Strategy, self.context.strategy)
        if strategy.is_ledger_tx:
            self.context.logger.info(
                "[{}]: received MATCH_ACCEPT_W_INFORM from sender={}".format(
                    self.context.agent_name, msg.counterparty[-5:]))
            info = msg.info
            address = cast(str, info.get("address"))
            proposal = cast(Description, dialogue.proposal)
            strategy = cast(Strategy, self.context.strategy)
            tx_msg = TransactionMessage(
                performative=TransactionMessage.Performative.
                PROPOSE_FOR_SETTLEMENT,
                skill_callback_ids=[
                    PublicId("fetchai", "carpark_client", "0.1.0")
                ],
                tx_id="transaction0",
                tx_sender_addr=self.context.agent_addresses["fetchai"],
                tx_counterparty_addr=address,
                tx_amount_by_currency_id={
                    proposal.values["currency_id"]: -proposal.values["price"]
                },
                tx_sender_fee=strategy.max_buyer_tx_fee,
                tx_counterparty_fee=proposal.values["seller_tx_fee"],
                tx_quantities_by_good_id={},
                ledger_id=proposal.values["ledger_id"],
                info={"dialogue_label": dialogue.dialogue_label.json},
            )
            self.context.decision_maker_message_queue.put_nowait(tx_msg)
            self.context.logger.info(
                "[{}]: proposing the transaction to the decision maker. Waiting for confirmation ..."
                .format(self.context.agent_name))
        else:
            new_message_id = msg.message_id + 1
            new_target = msg.message_id
            inform_msg = FipaMessage(
                message_id=new_message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=new_target,
                performative=FipaMessage.Performative.INFORM,
                info={"Done": "Sending payment via bank transfer"},
            )
            dialogue.outgoing_extend(inform_msg)
            self.context.outbox.put_message(
                to=msg.counterparty,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(inform_msg),
            )
            self.context.logger.info(
                "[{}]: informing counterparty={} of payment.".format(
                    self.context.agent_name, msg.counterparty[-5:]))
Exemple #11
0
    def _handle_unidentified_dialogue(self, msg: FipaMessage) -> None:
        """
        Handle an unidentified dialogue.

        Respond to the sender with a default message containing the appropriate error information.

        :param msg: the message
        :return: None
        """
        self.context.logger.info("[{}]: unidentified dialogue.".format(
            self.context.agent_name))
        default_msg = DefaultMessage(
            dialogue_reference=("", ""),
            message_id=1,
            target=0,
            performative=DefaultMessage.Performative.ERROR,
            error_code=DefaultMessage.ErrorCode.INVALID_DIALOGUE,
            error_msg="Invalid dialogue.",
            error_data={"fipa_message": FipaSerializer().encode(msg)},
        )
        self.context.outbox.put_message(
            to=msg.counterparty,
            sender=self.context.agent_address,
            protocol_id=DefaultMessage.protocol_id,
            message=DefaultSerializer().encode(default_msg),
        )
Exemple #12
0
    def _on_propose(self, propose: FipaMessage, dialogue: Dialogue) -> None:
        """
        Handle a Propose.

        :param propose: the message containing the Propose
        :param dialogue: the dialogue
        :return: None
        """
        new_msg_id = propose.message_id + 1
        strategy = cast(Strategy, self.context.strategy)
        proposal_description = propose.proposal
        self.context.logger.debug("[{}]: on Propose as {}.".format(
            self.context.agent_name, dialogue.role))
        transactions = cast(Transactions, self.context.transactions)
        transaction_msg = transactions.generate_transaction_message(
            TransactionMessage.Performative.PROPOSE_FOR_SIGNING,
            proposal_description,
            dialogue.dialogue_label,
            cast(Dialogue.AgentRole, dialogue.role),
            self.context.agent_address,
        )

        if strategy.is_profitable_transaction(transaction_msg,
                                              role=cast(
                                                  Dialogue.AgentRole,
                                                  dialogue.role)):
            self.context.logger.info("[{}]: Accepting propose (as {}).".format(
                self.context.agent_name, dialogue.role))
            transactions.add_locked_tx(transaction_msg,
                                       role=cast(Dialogue.AgentRole,
                                                 dialogue.role))
            transactions.add_pending_initial_acceptance(
                dialogue.dialogue_label, new_msg_id, transaction_msg)
            fipa_msg = FipaMessage(
                performative=FipaMessage.Performative.ACCEPT,
                message_id=new_msg_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=propose.message_id,
            )
        else:
            self.context.logger.info("[{}]: Declining propose (as {})".format(
                self.context.agent_name, dialogue.role))
            fipa_msg = FipaMessage(
                performative=FipaMessage.Performative.DECLINE,
                message_id=new_msg_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=propose.message_id,
            )
            dialogues = cast(Dialogues, self.context.dialogues)
            dialogues.dialogue_stats.add_dialogue_endstate(
                Dialogue.EndState.DECLINED_PROPOSE, dialogue.is_self_initiated)
        fipa_msg.counterparty = propose.counterparty
        dialogue.update(fipa_msg)
        self.context.outbox.put_message(
            to=dialogue.dialogue_label.dialogue_opponent_addr,
            sender=self.context.agent_address,
            protocol_id=FipaMessage.protocol_id,
            message=FipaSerializer().encode(fipa_msg),
        )
Exemple #13
0
    async def test_messages(self):
        """Test that at the beginning, the search request returns an empty search result."""
        msg = FipaMessage(
            performative=FipaMessage.Performative.CFP,
            dialogue_reference=(str(0), ""),
            message_id=1,
            target=0,
            query=Query([Constraint("something", ConstraintType(">", 1))]),
        )
        msg_bytes = FipaSerializer().encode(msg)
        envelope = Envelope(
            to=DEFAULT_OEF,
            sender=self.address_1,
            protocol_id=FipaMessage.protocol_id,
            message=msg_bytes,
        )
        with pytest.raises(AEAConnectionError):
            await _make_local_connection(
                self.address_1,
                self.node,
            ).send(envelope)

        self.multiplexer1.connect()
        msg = FipaMessage(
            performative=FipaMessage.Performative.CFP,
            dialogue_reference=(str(0), str(1)),
            message_id=1,
            target=0,
            query=Query([Constraint("something", ConstraintType(">", 1))]),
        )
        msg_bytes = FipaSerializer().encode(msg)
        envelope = Envelope(
            to="this_address_does_not_exist",
            sender=self.address_1,
            protocol_id=FipaMessage.protocol_id,
            message=msg_bytes,
        )
        self.multiplexer1.put(envelope)

        # check the result
        response_envelope = self.multiplexer1.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == DefaultMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        result = DefaultSerializer().decode(response_envelope.message)
        assert result.performative == DefaultMessage.Performative.ERROR
Exemple #14
0
    def _on_accept(self, accept: FipaMessage, dialogue: Dialogue) -> None:
        """
        Handle an Accept.

        :param accept: the Accept message
        :param dialogue: the dialogue
        :return: None
        """
        self.context.logger.debug(
            "[{}]: on_accept: msg_id={}, dialogue_reference={}, origin={}, target={}"
            .format(
                self.context.agent_name,
                accept.message_id,
                accept.dialogue_reference,
                dialogue.dialogue_label.dialogue_opponent_addr,
                accept.target,
            ))
        new_msg_id = accept.message_id + 1
        transactions = cast(Transactions, self.context.transactions)
        transaction_msg = transactions.pop_pending_proposal(
            dialogue.dialogue_label, accept.target)
        strategy = cast(Strategy, self.context.strategy)

        if strategy.is_profitable_transaction(transaction_msg,
                                              role=cast(
                                                  Dialogue.AgentRole,
                                                  dialogue.role)):
            self.context.logger.info(
                "[{}]: locking the current state (as {}).".format(
                    self.context.agent_name, dialogue.role))
            transactions.add_locked_tx(transaction_msg,
                                       role=cast(Dialogue.AgentRole,
                                                 dialogue.role))
            self.context.decision_maker_message_queue.put(transaction_msg)
        else:
            self.context.logger.debug(
                "[{}]: decline the Accept (as {}).".format(
                    self.context.agent_name, dialogue.role))
            fipa_msg = FipaMessage(
                performative=FipaMessage.Performative.DECLINE,
                message_id=new_msg_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=accept.message_id,
            )
            fipa_msg.counterparty = accept.counterparty
            dialogue.update(fipa_msg)
            dialogues = cast(Dialogues, self.context.dialogues)
            dialogues.dialogue_stats.add_dialogue_endstate(
                Dialogue.EndState.DECLINED_ACCEPT, dialogue.is_self_initiated)
            self.context.outbox.put_message(
                to=dialogue.dialogue_label.dialogue_opponent_addr,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(fipa_msg),
            )
Exemple #15
0
    def _handle_cfp(self, msg: FipaMessage, dialogue: Dialogue) -> None:
        """
        Handle the CFP.

        If the CFP matches the supplied services then send a PROPOSE, otherwise send a DECLINE.

        :param msg: the message
        :param dialogue: the dialogue object
        :return: None
        """
        new_message_id = msg.message_id + 1
        new_target = msg.message_id
        self.context.logger.info(
            "[{}]: received CFP from sender={}".format(
                self.context.agent_name, msg.counterparty[-5:]
            )
        )
        if self.context.behaviours.service_registration.is_items_minted:
            # simply send the same proposal, independent of the query
            strategy = cast(Strategy, self.context.strategy)
            contract = cast(ERC1155Contract, self.context.contracts.erc1155)
            trade_nonce = contract.generate_trade_nonce(self.context.agent_address)
            token_id = self.context.behaviours.service_registration.token_ids[0]
            proposal = Description(
                {
                    "contract_address": contract.instance.address,
                    "token_id": str(token_id),
                    "trade_nonce": str(trade_nonce),
                    "from_supply": str(strategy.from_supply),
                    "to_supply": str(strategy.to_supply),
                    "value": str(strategy.value),
                }
            )
            dialogue.proposal = proposal
            proposal_msg = FipaMessage(
                message_id=new_message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=new_target,
                performative=FipaMessage.Performative.PROPOSE,
                proposal=proposal,
            )
            dialogue.outgoing_extend(proposal_msg)
            self.context.logger.info(
                "[{}]: Sending PROPOSE to agent={}: proposal={}".format(
                    self.context.agent_name, msg.counterparty[-5:], proposal.values
                )
            )
            self.context.outbox.put_message(
                to=msg.counterparty,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(proposal_msg),
            )
        else:
            self.context.logger.info("Contract items not minted yet. Try again later.")
Exemple #16
0
    def handle(self, message: Message) -> None:
        """
        Dispatch message to relevant handler and respond.

        :param message: the message
        :return: None
        """
        tx_message = cast(TransactionMessage, message)
        if (tx_message.performative ==
                TransactionMessage.Performative.SUCCESSFUL_SIGNING):
            self.context.logger.info(
                "[{}]: transaction confirmed by decision maker".format(
                    self.context.agent_name))
            info = tx_message.info
            dialogue_label = DialogueLabel.from_json(
                cast(Dict[str, str], info.get("dialogue_label")))
            dialogues = cast(Dialogues, self.context.dialogues)
            dialogue = dialogues.dialogues[dialogue_label]
            fipa_message = cast(FipaMessage, dialogue.last_incoming_message)
            if (fipa_message is not None and fipa_message.performative
                    == FipaMessage.Performative.ACCEPT):
                self.context.logger.info(
                    "[{}]: sending match accept to {}.".format(
                        self.context.agent_name,
                        dialogue.dialogue_label.dialogue_opponent_addr[-5:],
                    ))
                fipa_msg = FipaMessage(
                    performative=FipaMessage.Performative.
                    MATCH_ACCEPT_W_INFORM,
                    message_id=fipa_message.message_id + 1,
                    dialogue_reference=dialogue.dialogue_label.
                    dialogue_reference,
                    target=fipa_message.message_id,
                    info={
                        "tx_signature":
                        tx_message.signed_payload.get("tx_signature"),
                        "tx_id":
                        tx_message.tx_id,
                    },
                )
                dialogue.outgoing_extend(fipa_msg)
                self.context.outbox.put_message(
                    to=dialogue.dialogue_label.dialogue_opponent_addr,
                    sender=self.context.agent_address,
                    protocol_id=FipaMessage.protocol_id,
                    message=FipaSerializer().encode(fipa_msg),
                )
            else:
                self.context.logger.warning(
                    "[{}]: last message should be of performative accept.".
                    format(self.context.agent_name))
        else:
            self.context.logger.info(
                "[{}]: transaction was not successful.".format(
                    self.context.agent_name))
Exemple #17
0
 def test_accept(self):
     """Test that an Accept can be sent correctly."""
     accept = FipaMessage(
         message_id=1,
         dialogue_reference=(str(0), ""),
         target=0,
         performative=FipaMessage.Performative.ACCEPT,
     )
     accept.counterparty = FETCHAI_ADDRESS_TWO
     self.multiplexer1.put(
         Envelope(
             to=FETCHAI_ADDRESS_TWO,
             sender=FETCHAI_ADDRESS_ONE,
             protocol_id=FipaMessage.protocol_id,
             message=FipaSerializer().encode(accept),
         ))
     envelope = self.multiplexer2.get(block=True, timeout=2.0)
     expected_accept = FipaSerializer().decode(envelope.message)
     expected_accept.counterparty = FETCHAI_ADDRESS_TWO
     assert expected_accept == accept
Exemple #18
0
 def test_decline(self):
     """Test that a Decline can be sent correctly."""
     decline = FipaMessage(
         message_id=1,
         dialogue_reference=(str(0), ""),
         target=0,
         performative=FipaMessage.Performative.DECLINE,
     )
     decline.counterparty = FETCHAI_ADDRESS_TWO
     self.multiplexer1.put(
         Envelope(
             to=FETCHAI_ADDRESS_TWO,
             sender=FETCHAI_ADDRESS_ONE,
             protocol_id=FipaMessage.protocol_id,
             message=FipaSerializer().encode(decline),
         ))
     envelope = self.multiplexer2.get(block=True, timeout=2.0)
     expected_decline = FipaSerializer().decode(envelope.message)
     expected_decline.counterparty = FETCHAI_ADDRESS_TWO
     assert expected_decline == decline
Exemple #19
0
 def test_match_accept(self):
     """Test that a match accept can be sent correctly."""
     # NOTE since the OEF SDK doesn't support the match accept, we have to use a fixed message id!
     match_accept = FipaMessage(
         message_id=4,
         dialogue_reference=(str(0), ""),
         target=3,
         performative=FipaMessage.Performative.MATCH_ACCEPT,
     )
     match_accept.counterparty = FETCHAI_ADDRESS_TWO
     self.multiplexer1.put(
         Envelope(
             to=FETCHAI_ADDRESS_TWO,
             sender=FETCHAI_ADDRESS_ONE,
             protocol_id=FipaMessage.protocol_id,
             message=FipaSerializer().encode(match_accept),
         ))
     envelope = self.multiplexer2.get(block=True, timeout=2.0)
     expected_match_accept = FipaSerializer().decode(envelope.message)
     expected_match_accept.counterparty = FETCHAI_ADDRESS_TWO
     assert expected_match_accept == match_accept
Exemple #20
0
 def test_accept_w_inform(self):
     """Test that an accept with address can be sent correctly."""
     accept_w_inform = FipaMessage(
         message_id=1,
         dialogue_reference=(str(0), ""),
         target=0,
         performative=FipaMessage.Performative.ACCEPT_W_INFORM,
         info={"address": "my_address"},
     )
     accept_w_inform.counterparty = FETCHAI_ADDRESS_TWO
     self.multiplexer1.put(
         Envelope(
             to=FETCHAI_ADDRESS_TWO,
             sender=FETCHAI_ADDRESS_ONE,
             protocol_id=FipaMessage.protocol_id,
             message=FipaSerializer().encode(accept_w_inform),
         ))
     envelope = self.multiplexer2.get(block=True, timeout=2.0)
     returned_accept_w_inform = FipaSerializer().decode(envelope.message)
     returned_accept_w_inform.counterparty = FETCHAI_ADDRESS_TWO
     assert returned_accept_w_inform == accept_w_inform
Exemple #21
0
 def test_inform(self):
     """Test that an inform can be sent correctly."""
     payload = {"foo": "bar"}
     inform = FipaMessage(
         message_id=1,
         dialogue_reference=(str(0), ""),
         target=0,
         performative=FipaMessage.Performative.INFORM,
         info=payload,
     )
     inform.counterparty = FETCHAI_ADDRESS_TWO
     self.multiplexer1.put(
         Envelope(
             to=FETCHAI_ADDRESS_TWO,
             sender=FETCHAI_ADDRESS_ONE,
             protocol_id=FipaMessage.protocol_id,
             message=FipaSerializer().encode(inform),
         ))
     envelope = self.multiplexer2.get(block=True, timeout=2.0)
     returned_inform = FipaSerializer().decode(envelope.message)
     returned_inform.counterparty = FETCHAI_ADDRESS_TWO
     assert returned_inform == inform
 def test_match_accept_w_inform(self):
     """Test that a match accept with inform can be sent correctly."""
     match_accept_w_inform = FipaMessage(
         message_id=1,
         dialogue_reference=(str(0), ""),
         target=0,
         performative=FipaMessage.Performative.MATCH_ACCEPT_W_INFORM,
         info={"address": "my_address"},
     )
     match_accept_w_inform.counterparty = self.crypto2.address
     self.multiplexer1.put(
         Envelope(
             to=self.crypto2.address,
             sender=self.crypto1.address,
             protocol_id=FipaMessage.protocol_id,
             message=FipaSerializer().encode(match_accept_w_inform),
         )
     )
     envelope = self.multiplexer2.get(block=True, timeout=2.0)
     returned_match_accept_w_inform = FipaSerializer().decode(envelope.message)
     returned_match_accept_w_inform.counterparty = self.crypto2.address
     assert returned_match_accept_w_inform == match_accept_w_inform
Exemple #23
0
    def handle(self, message: Message) -> None:
        """
        Implement the reaction to a message.

        :param message: the message
        :return: None
        """
        tx_msg_response = cast(TransactionMessage, message)
        if (
            tx_msg_response is not None
            and tx_msg_response.performative
            == TransactionMessage.Performative.SUCCESSFUL_SETTLEMENT
        ):
            self.context.logger.info(
                "[{}]: transaction was successful.".format(self.context.agent_name)
            )
            json_data = {"transaction_digest": tx_msg_response.tx_digest}
            info = tx_msg_response.info
            dialogue_label = DialogueLabel.from_json(
                cast(Dict[str, str], info.get("dialogue_label"))
            )
            dialogues = cast(Dialogues, self.context.dialogues)
            dialogue = dialogues.dialogues[dialogue_label]
            fipa_msg = cast(FipaMessage, dialogue.last_incoming_message)
            new_message_id = fipa_msg.message_id + 1
            new_target_id = fipa_msg.message_id
            counterparty_id = dialogue.dialogue_label.dialogue_opponent_addr
            inform_msg = FipaMessage(
                message_id=new_message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=new_target_id,
                performative=FipaMessage.Performative.INFORM,
                info=json_data,
            )
            dialogue.outgoing_extend(inform_msg)
            self.context.outbox.put_message(
                to=counterparty_id,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(inform_msg),
            )
            self.context.logger.info(
                "[{}]: informing counterparty={} of transaction digest.".format(
                    self.context.agent_name, counterparty_id[-5:]
                )
            )
            self._received_tx_message = True
        else:
            self.context.logger.info(
                "[{}]: transaction was not successful.".format(self.context.agent_name)
            )
Exemple #24
0
    def _handle_search(self, agents: Tuple[str, ...], search_id: int,
                       is_searching_for_sellers: bool) -> None:
        """
        Handle the search response.

        :param agents: the agents returned by the search
        :param is_searching_for_sellers: whether the agent is searching for sellers
        :return: None
        """
        searched_for = "sellers" if is_searching_for_sellers else "buyers"
        if len(agents) > 0:
            self.context.logger.info(
                "[{}]: found potential {} agents={} on search_id={}.".format(
                    self.context.agent_name,
                    searched_for,
                    list(map(lambda x: x[-5:], agents)),
                    search_id,
                ))
            strategy = cast(Strategy, self.context.strategy)
            dialogues = cast(Dialogues, self.context.dialogues)
            query = strategy.get_own_services_query(is_searching_for_sellers)

            for opponent_addr in agents:
                dialogue = dialogues.create_self_initiated(
                    opponent_addr,
                    self.context.agent_address,
                    not is_searching_for_sellers,
                )
                self.context.logger.info(
                    "[{}]: sending CFP to agent={}".format(
                        self.context.agent_name, opponent_addr[-5:]))
                fipa_msg = FipaMessage(
                    message_id=Dialogue.STARTING_MESSAGE_ID,
                    dialogue_reference=dialogue.dialogue_label.
                    dialogue_reference,
                    performative=FipaMessage.Performative.CFP,
                    target=Dialogue.STARTING_TARGET,
                    query=query,
                )
                dialogue.outgoing_extend(fipa_msg)
                self.context.outbox.put_message(
                    to=opponent_addr,
                    sender=self.context.agent_address,
                    protocol_id=FipaMessage.protocol_id,
                    message=FipaSerializer().encode(fipa_msg),
                )
        else:
            self.context.logger.info(
                "[{}]: found no {} agents on search_id={}, continue searching."
                .format(self.context.agent_name, searched_for, search_id))
Exemple #25
0
def test_performative_match_accept():
    """Test the serialization - deserialization of the match_accept performative."""
    msg = FipaMessage(
        message_id=1,
        dialogue_reference=(str(0), ""),
        target=0,
        performative=FipaMessage.Performative.MATCH_ACCEPT,
    )
    msg_bytes = FipaSerializer().encode(msg)
    envelope = Envelope(
        to="receiver",
        sender="sender",
        protocol_id=FipaMessage.protocol_id,
        message=msg_bytes,
    )
    msg.counterparty = "sender"
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope == actual_envelope
    deserialised_msg = FipaSerializer().decode(envelope.message)
    assert msg.get("performative") == deserialised_msg.get("performative")
Exemple #26
0
    def handle(self, message: Message) -> None:
        """
        Implement the reaction to a message.

        :param message: the message
        :return: None
        """
        tx_msg_response = cast(TransactionMessage, message)
        if (
            tx_msg_response.performative
            == TransactionMessage.Performative.SUCCESSFUL_SIGNING
            and (
                tx_msg_response.tx_id
                == ERC1155Contract.Performative.CONTRACT_SIGN_HASH_SINGLE.value
            )
        ):
            tx_signature = tx_msg_response.signed_payload.get("tx_signature")
            dialogue_label = DialogueLabel.from_json(
                cast(Dict[str, str], tx_msg_response.info.get("dialogue_label"))
            )
            dialogues = cast(Dialogues, self.context.dialogues)
            dialogue = dialogues.dialogues[dialogue_label]
            fipa_msg = cast(FipaMessage, dialogue.last_incoming_message)
            new_message_id = fipa_msg.message_id + 1
            new_target = fipa_msg.message_id
            counterparty_addr = dialogue.dialogue_label.dialogue_opponent_addr
            inform_msg = FipaMessage(
                message_id=new_message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                target=new_target,
                performative=FipaMessage.Performative.ACCEPT_W_INFORM,
                info={"tx_signature": tx_signature},
            )
            self.context.logger.info(
                "[{}]: sending ACCEPT_W_INFORM to agent={}: tx_signature={}".format(
                    self.context.agent_name, counterparty_addr[-5:], tx_signature
                )
            )
            self.context.outbox.put_message(
                to=counterparty_addr,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(inform_msg),
            )
        else:
            self.context.logger.info(
                "[{}]: signing failed: tx_msg_response={}".format(
                    self.context.agent_name, tx_msg_response
                )
            )
Exemple #27
0
    def on_cfp(
        self,
        msg_id: int,
        dialogue_id: int,
        origin: Address,
        target: int,
        query: CFP_TYPES,
    ) -> None:
        """
        On cfp event handler.

        :param msg_id: the message id.
        :param dialogue_id: the dialogue id.
        :param origin: the address of the sender.
        :param target: the message target.
        :param query: the query.
        :return: None
        """
        assert self.in_queue is not None
        assert self.loop is not None
        logger.warning(
            "Accepting on_cfp from deprecated API: msg_id={}, dialogue_id={}, origin={}, target={}. Continuing dialogue via envelopes!".format(
                msg_id, dialogue_id, origin, target
            )
        )
        try:
            query = pickle.loads(query)  # nosec
        except Exception as e:
            logger.debug(
                "When trying to unpickle the query the following exception occured: {}".format(
                    e
                )
            )
        msg = FipaMessage(
            message_id=msg_id,
            dialogue_reference=(str(dialogue_id), ""),
            target=target,
            performative=FipaMessage.Performative.CFP,
            query=query if query != b"" else None,
        )
        msg_bytes = FipaSerializer().encode(msg)
        envelope = Envelope(
            to=self.address,
            sender=origin,
            protocol_id=FipaMessage.protocol_id,
            message=msg_bytes,
        )
        asyncio.run_coroutine_threadsafe(
            self.in_queue.put(envelope), self.loop
        ).result()
Exemple #28
0
def test_performative_inform():
    """Test the serialization-deserialization of the inform performative."""
    msg = FipaMessage(
        message_id=1,
        dialogue_reference=(str(0), ""),
        target=0,
        performative=FipaMessage.Performative.INFORM,
        info={"foo": "bar"},
    )

    msg_bytes = FipaSerializer().encode(msg)
    envelope = Envelope(
        to="receiver",
        sender="sender",
        protocol_id=FipaMessage.protocol_id,
        message=msg_bytes,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope == actual_envelope
    deserialised_msg = FipaSerializer().decode(envelope.message)
    assert msg.get("performative") == deserialised_msg.get("performative")
    def test_propose(self):
        """Test that a Propose can be sent correctly."""
        propose_empty = FipaMessage(
            message_id=1,
            dialogue_reference=(str(0), ""),
            target=0,
            performative=FipaMessage.Performative.PROPOSE,
            proposal=Description({"foo": "bar"}),
        )
        propose_empty.counterparty = self.crypto2.address
        self.multiplexer1.put(
            Envelope(
                to=self.crypto2.address,
                sender=self.crypto1.address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(propose_empty),
            )
        )
        envelope = self.multiplexer2.get(block=True, timeout=2.0)
        expected_propose_empty = FipaSerializer().decode(envelope.message)
        expected_propose_empty.counterparty = self.crypto2.address
        assert expected_propose_empty == propose_empty

        propose_descriptions = FipaMessage(
            message_id=1,
            dialogue_reference=(str(0), ""),
            target=0,
            performative=FipaMessage.Performative.PROPOSE,
            proposal=Description(
                {"foo": "bar"}, DataModel("foobar", [Attribute("foo", str, True)])
            ),
        )

        propose_descriptions.counterparty = self.crypto2.address
        self.multiplexer1.put(
            Envelope(
                to=self.crypto2.address,
                sender=self.crypto1.address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(propose_descriptions),
            )
        )
        envelope = self.multiplexer2.get(block=True, timeout=2.0)
        expected_propose_descriptions = FipaSerializer().decode(envelope.message)
        expected_propose_descriptions.counterparty = self.crypto2.address
        assert expected_propose_descriptions == propose_descriptions
Exemple #30
0
    def _handle_search(self, agents: Tuple[str, ...]) -> None:
        """
        Handle the search response.

        :param agents: the agents returned by the search
        :return: None
        """
        if len(agents) > 0:
            self.context.logger.info(
                "[{}]: found agents={}, stopping search.".format(
                    self.context.agent_name, list(map(lambda x: x[-5:], agents))
                )
            )
            strategy = cast(Strategy, self.context.strategy)
            # stopping search
            strategy.is_searching = False
            # pick first agent found
            opponent_addr = agents[0]
            dialogues = cast(Dialogues, self.context.dialogues)
            dialogue = dialogues.create_self_initiated(
                opponent_addr, self.context.agent_address, is_seller=False
            )
            query = strategy.get_service_query()
            self.context.logger.info(
                "[{}]: sending CFP to agent={}".format(
                    self.context.agent_name, opponent_addr[-5:]
                )
            )
            cfp_msg = FipaMessage(
                message_id=Dialogue.STARTING_MESSAGE_ID,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                performative=FipaMessage.Performative.CFP,
                target=Dialogue.STARTING_TARGET,
                query=query,
            )
            dialogue.outgoing_extend(cfp_msg)
            self.context.outbox.put_message(
                to=opponent_addr,
                sender=self.context.agent_address,
                protocol_id=FipaMessage.protocol_id,
                message=FipaSerializer().encode(cfp_msg),
            )
        else:
            self.context.logger.info(
                "[{}]: found no agents, continue searching.".format(
                    self.context.agent_name
                )
            )