Ejemplo n.º 1
0
class MyScaffoldMessage(Message):
    """The scaffold message class."""

    protocol_id = ProtocolId.from_str("fetchai/scaffold:0.1.0")
    serializer = MyScaffoldSerializer

    class Performative(Enum):
        """Scaffold Message types."""
        def __str__(self):
            """Get string representation."""
            return str(self.value)  # pragma: no cover

    def __init__(self, performative: Performative, **kwargs):
        """
        Initialize.

        :param performative: the type of message.
        """
        super().__init__(performative=performative, **kwargs)
        assert (
            self._is_consistent()
        ), "MyScaffoldMessage initialization inconsistent."  # pragma: no cover

    def _is_consistent(self) -> bool:
        """Check that the data is consistent."""
        try:
            raise NotImplementedError
        except (AssertionError, ValueError):
            return False  # pragma: no cover

        return True  # pragma: no cover
Ejemplo n.º 2
0
async def test_unsupported_protocol(ledger_apis_connection: LedgerConnection):
    """Test fail on protocol not supported."""
    envelope = Envelope(
        to=str(ledger_apis_connection.connection_id),
        sender="test",
        protocol_id=ProtocolId.from_str("author/package_name:0.1.0"),
        message=b"message",
    )
    with pytest.raises(ValueError):
        ledger_apis_connection._schedule_request(envelope)
Ejemplo n.º 3
0
    async def _handle_envelope(self, envelope: Envelope) -> None:
        """Handle an envelope.

        :param envelope: the envelope
        :return: None
        """
        if envelope.protocol_id == ProtocolId.from_str("fetchai/oef:0.1.0"):
            await self._handle_oef_message(envelope)
        else:
            await self._handle_agent_message(envelope)
Ejemplo n.º 4
0
class TProtocolNoCtMessage(Message):
    """A protocol for testing purposes."""

    protocol_id = ProtocolId.from_str("fetchai/t_protocol_no_ct:0.1.0")

    class Performative(Enum):
        """Performatives for the t_protocol_no_ct protocol."""

        PERFORMATIVE_EMPTY_CONTENTS = "performative_empty_contents"
        PERFORMATIVE_MT = "performative_mt"
        PERFORMATIVE_O = "performative_o"
        PERFORMATIVE_PCT = "performative_pct"
        PERFORMATIVE_PMT = "performative_pmt"
        PERFORMATIVE_PT = "performative_pt"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of TProtocolNoCtMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=TProtocolNoCtMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {
            "performative_empty_contents",
            "performative_mt",
            "performative_o",
            "performative_pct",
            "performative_pmt",
            "performative_pt",
        }

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(TProtocolNoCtMessage.Performative,
                    self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def content_bool(self) -> bool:
        """Get the 'content_bool' content from the message."""
        assert self.is_set(
            "content_bool"), "'content_bool' content is not set."
        return cast(bool, self.get("content_bool"))

    @property
    def content_bytes(self) -> bytes:
        """Get the 'content_bytes' content from the message."""
        assert self.is_set(
            "content_bytes"), "'content_bytes' content is not set."
        return cast(bytes, self.get("content_bytes"))

    @property
    def content_dict_bool_bool(self) -> Dict[bool, bool]:
        """Get the 'content_dict_bool_bool' content from the message."""
        assert self.is_set("content_dict_bool_bool"
                           ), "'content_dict_bool_bool' content is not set."
        return cast(Dict[bool, bool], self.get("content_dict_bool_bool"))

    @property
    def content_dict_bool_bytes(self) -> Dict[bool, bytes]:
        """Get the 'content_dict_bool_bytes' content from the message."""
        assert self.is_set("content_dict_bool_bytes"
                           ), "'content_dict_bool_bytes' content is not set."
        return cast(Dict[bool, bytes], self.get("content_dict_bool_bytes"))

    @property
    def content_dict_bool_float(self) -> Dict[bool, float]:
        """Get the 'content_dict_bool_float' content from the message."""
        assert self.is_set("content_dict_bool_float"
                           ), "'content_dict_bool_float' content is not set."
        return cast(Dict[bool, float], self.get("content_dict_bool_float"))

    @property
    def content_dict_bool_int(self) -> Dict[bool, int]:
        """Get the 'content_dict_bool_int' content from the message."""
        assert self.is_set("content_dict_bool_int"
                           ), "'content_dict_bool_int' content is not set."
        return cast(Dict[bool, int], self.get("content_dict_bool_int"))

    @property
    def content_dict_bool_str(self) -> Dict[bool, str]:
        """Get the 'content_dict_bool_str' content from the message."""
        assert self.is_set("content_dict_bool_str"
                           ), "'content_dict_bool_str' content is not set."
        return cast(Dict[bool, str], self.get("content_dict_bool_str"))

    @property
    def content_dict_int_bool(self) -> Dict[int, bool]:
        """Get the 'content_dict_int_bool' content from the message."""
        assert self.is_set("content_dict_int_bool"
                           ), "'content_dict_int_bool' content is not set."
        return cast(Dict[int, bool], self.get("content_dict_int_bool"))

    @property
    def content_dict_int_bytes(self) -> Dict[int, bytes]:
        """Get the 'content_dict_int_bytes' content from the message."""
        assert self.is_set("content_dict_int_bytes"
                           ), "'content_dict_int_bytes' content is not set."
        return cast(Dict[int, bytes], self.get("content_dict_int_bytes"))

    @property
    def content_dict_int_float(self) -> Dict[int, float]:
        """Get the 'content_dict_int_float' content from the message."""
        assert self.is_set("content_dict_int_float"
                           ), "'content_dict_int_float' content is not set."
        return cast(Dict[int, float], self.get("content_dict_int_float"))

    @property
    def content_dict_int_int(self) -> Dict[int, int]:
        """Get the 'content_dict_int_int' content from the message."""
        assert self.is_set("content_dict_int_int"
                           ), "'content_dict_int_int' content is not set."
        return cast(Dict[int, int], self.get("content_dict_int_int"))

    @property
    def content_dict_int_str(self) -> Dict[int, str]:
        """Get the 'content_dict_int_str' content from the message."""
        assert self.is_set("content_dict_int_str"
                           ), "'content_dict_int_str' content is not set."
        return cast(Dict[int, str], self.get("content_dict_int_str"))

    @property
    def content_dict_str_bool(self) -> Dict[str, bool]:
        """Get the 'content_dict_str_bool' content from the message."""
        assert self.is_set("content_dict_str_bool"
                           ), "'content_dict_str_bool' content is not set."
        return cast(Dict[str, bool], self.get("content_dict_str_bool"))

    @property
    def content_dict_str_bytes(self) -> Dict[str, bytes]:
        """Get the 'content_dict_str_bytes' content from the message."""
        assert self.is_set("content_dict_str_bytes"
                           ), "'content_dict_str_bytes' content is not set."
        return cast(Dict[str, bytes], self.get("content_dict_str_bytes"))

    @property
    def content_dict_str_float(self) -> Dict[str, float]:
        """Get the 'content_dict_str_float' content from the message."""
        assert self.is_set("content_dict_str_float"
                           ), "'content_dict_str_float' content is not set."
        return cast(Dict[str, float], self.get("content_dict_str_float"))

    @property
    def content_dict_str_int(self) -> Dict[str, int]:
        """Get the 'content_dict_str_int' content from the message."""
        assert self.is_set("content_dict_str_int"
                           ), "'content_dict_str_int' content is not set."
        return cast(Dict[str, int], self.get("content_dict_str_int"))

    @property
    def content_dict_str_str(self) -> Dict[str, str]:
        """Get the 'content_dict_str_str' content from the message."""
        assert self.is_set("content_dict_str_str"
                           ), "'content_dict_str_str' content is not set."
        return cast(Dict[str, str], self.get("content_dict_str_str"))

    @property
    def content_float(self) -> float:
        """Get the 'content_float' content from the message."""
        assert self.is_set(
            "content_float"), "'content_float' content is not set."
        return cast(float, self.get("content_float"))

    @property
    def content_int(self) -> int:
        """Get the 'content_int' content from the message."""
        assert self.is_set("content_int"), "'content_int' content is not set."
        return cast(int, self.get("content_int"))

    @property
    def content_list_bool(self) -> Tuple[bool, ...]:
        """Get the 'content_list_bool' content from the message."""
        assert self.is_set(
            "content_list_bool"), "'content_list_bool' content is not set."
        return cast(Tuple[bool, ...], self.get("content_list_bool"))

    @property
    def content_list_bytes(self) -> Tuple[bytes, ...]:
        """Get the 'content_list_bytes' content from the message."""
        assert self.is_set(
            "content_list_bytes"), "'content_list_bytes' content is not set."
        return cast(Tuple[bytes, ...], self.get("content_list_bytes"))

    @property
    def content_list_float(self) -> Tuple[float, ...]:
        """Get the 'content_list_float' content from the message."""
        assert self.is_set(
            "content_list_float"), "'content_list_float' content is not set."
        return cast(Tuple[float, ...], self.get("content_list_float"))

    @property
    def content_list_int(self) -> Tuple[int, ...]:
        """Get the 'content_list_int' content from the message."""
        assert self.is_set(
            "content_list_int"), "'content_list_int' content is not set."
        return cast(Tuple[int, ...], self.get("content_list_int"))

    @property
    def content_list_str(self) -> Tuple[str, ...]:
        """Get the 'content_list_str' content from the message."""
        assert self.is_set(
            "content_list_str"), "'content_list_str' content is not set."
        return cast(Tuple[str, ...], self.get("content_list_str"))

    @property
    def content_o_bool(self) -> Optional[bool]:
        """Get the 'content_o_bool' content from the message."""
        return cast(Optional[bool], self.get("content_o_bool"))

    @property
    def content_o_dict_str_int(self) -> Optional[Dict[str, int]]:
        """Get the 'content_o_dict_str_int' content from the message."""
        return cast(Optional[Dict[str, int]],
                    self.get("content_o_dict_str_int"))

    @property
    def content_o_list_bytes(self) -> Optional[Tuple[bytes, ...]]:
        """Get the 'content_o_list_bytes' content from the message."""
        return cast(Optional[Tuple[bytes, ...]],
                    self.get("content_o_list_bytes"))

    @property
    def content_o_set_int(self) -> Optional[FrozenSet[int]]:
        """Get the 'content_o_set_int' content from the message."""
        return cast(Optional[FrozenSet[int]], self.get("content_o_set_int"))

    @property
    def content_set_bool(self) -> FrozenSet[bool]:
        """Get the 'content_set_bool' content from the message."""
        assert self.is_set(
            "content_set_bool"), "'content_set_bool' content is not set."
        return cast(FrozenSet[bool], self.get("content_set_bool"))

    @property
    def content_set_bytes(self) -> FrozenSet[bytes]:
        """Get the 'content_set_bytes' content from the message."""
        assert self.is_set(
            "content_set_bytes"), "'content_set_bytes' content is not set."
        return cast(FrozenSet[bytes], self.get("content_set_bytes"))

    @property
    def content_set_float(self) -> FrozenSet[float]:
        """Get the 'content_set_float' content from the message."""
        assert self.is_set(
            "content_set_float"), "'content_set_float' content is not set."
        return cast(FrozenSet[float], self.get("content_set_float"))

    @property
    def content_set_int(self) -> FrozenSet[int]:
        """Get the 'content_set_int' content from the message."""
        assert self.is_set(
            "content_set_int"), "'content_set_int' content is not set."
        return cast(FrozenSet[int], self.get("content_set_int"))

    @property
    def content_set_str(self) -> FrozenSet[str]:
        """Get the 'content_set_str' content from the message."""
        assert self.is_set(
            "content_set_str"), "'content_set_str' content is not set."
        return cast(FrozenSet[str], self.get("content_set_str"))

    @property
    def content_str(self) -> str:
        """Get the 'content_str' content from the message."""
        assert self.is_set("content_str"), "'content_str' content is not set."
        return cast(str, self.get("content_str"))

    @property
    def content_union_1(
        self,
    ) -> Union[bytes, int, float, bool, str, FrozenSet[int], Tuple[bool, ...],
               Dict[str, int]]:
        """Get the 'content_union_1' content from the message."""
        assert self.is_set(
            "content_union_1"), "'content_union_1' content is not set."
        return cast(
            Union[bytes, int, float, bool, str, FrozenSet[int],
                  Tuple[bool, ...], Dict[str, int], ],
            self.get("content_union_1"),
        )

    @property
    def content_union_2(
        self,
    ) -> Union[FrozenSet[bytes], FrozenSet[int], FrozenSet[str], Tuple[
            float, ...], Tuple[bool, ...], Tuple[bytes, ...], Dict[str, int],
               Dict[int, float], Dict[bool, bytes], ]:
        """Get the 'content_union_2' content from the message."""
        assert self.is_set(
            "content_union_2"), "'content_union_2' content is not set."
        return cast(
            Union[FrozenSet[bytes], FrozenSet[int], FrozenSet[str],
                  Tuple[float, ...], Tuple[bool, ...], Tuple[bytes, ...],
                  Dict[str, int], Dict[int, float], Dict[bool, bytes], ],
            self.get("content_union_2"),
        )

    def _is_consistent(self) -> bool:
        """Check that the message follows the t_protocol_no_ct protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == TProtocolNoCtMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == TProtocolNoCtMessage.Performative.PERFORMATIVE_PT:
                expected_nb_of_contents = 5
                assert (
                    type(self.content_bytes) == bytes
                ), "Invalid type for content 'content_bytes'. Expected 'bytes'. Found '{}'.".format(
                    type(self.content_bytes))
                assert (
                    type(self.content_int) == int
                ), "Invalid type for content 'content_int'. Expected 'int'. Found '{}'.".format(
                    type(self.content_int))
                assert (
                    type(self.content_float) == float
                ), "Invalid type for content 'content_float'. Expected 'float'. Found '{}'.".format(
                    type(self.content_float))
                assert (
                    type(self.content_bool) == bool
                ), "Invalid type for content 'content_bool'. Expected 'bool'. Found '{}'.".format(
                    type(self.content_bool))
                assert (
                    type(self.content_str) == str
                ), "Invalid type for content 'content_str'. Expected 'str'. Found '{}'.".format(
                    type(self.content_str))
            elif (self.performative ==
                  TProtocolNoCtMessage.Performative.PERFORMATIVE_PCT):
                expected_nb_of_contents = 10
                assert (
                    type(self.content_set_bytes) == frozenset
                ), "Invalid type for content 'content_set_bytes'. Expected 'frozenset'. Found '{}'.".format(
                    type(self.content_set_bytes))
                assert all(
                    type(element) == bytes
                    for element in self.content_set_bytes
                ), "Invalid type for frozenset elements in content 'content_set_bytes'. Expected 'bytes'."
                assert (
                    type(self.content_set_int) == frozenset
                ), "Invalid type for content 'content_set_int'. Expected 'frozenset'. Found '{}'.".format(
                    type(self.content_set_int))
                assert all(
                    type(element) == int for element in self.content_set_int
                ), "Invalid type for frozenset elements in content 'content_set_int'. Expected 'int'."
                assert (
                    type(self.content_set_float) == frozenset
                ), "Invalid type for content 'content_set_float'. Expected 'frozenset'. Found '{}'.".format(
                    type(self.content_set_float))
                assert all(
                    type(element) == float
                    for element in self.content_set_float
                ), "Invalid type for frozenset elements in content 'content_set_float'. Expected 'float'."
                assert (
                    type(self.content_set_bool) == frozenset
                ), "Invalid type for content 'content_set_bool'. Expected 'frozenset'. Found '{}'.".format(
                    type(self.content_set_bool))
                assert all(
                    type(element) == bool for element in self.content_set_bool
                ), "Invalid type for frozenset elements in content 'content_set_bool'. Expected 'bool'."
                assert (
                    type(self.content_set_str) == frozenset
                ), "Invalid type for content 'content_set_str'. Expected 'frozenset'. Found '{}'.".format(
                    type(self.content_set_str))
                assert all(
                    type(element) == str for element in self.content_set_str
                ), "Invalid type for frozenset elements in content 'content_set_str'. Expected 'str'."
                assert (
                    type(self.content_list_bytes) == tuple
                ), "Invalid type for content 'content_list_bytes'. Expected 'tuple'. Found '{}'.".format(
                    type(self.content_list_bytes))
                assert all(
                    type(element) == bytes
                    for element in self.content_list_bytes
                ), "Invalid type for tuple elements in content 'content_list_bytes'. Expected 'bytes'."
                assert (
                    type(self.content_list_int) == tuple
                ), "Invalid type for content 'content_list_int'. Expected 'tuple'. Found '{}'.".format(
                    type(self.content_list_int))
                assert all(
                    type(element) == int for element in self.content_list_int
                ), "Invalid type for tuple elements in content 'content_list_int'. Expected 'int'."
                assert (
                    type(self.content_list_float) == tuple
                ), "Invalid type for content 'content_list_float'. Expected 'tuple'. Found '{}'.".format(
                    type(self.content_list_float))
                assert all(
                    type(element) == float
                    for element in self.content_list_float
                ), "Invalid type for tuple elements in content 'content_list_float'. Expected 'float'."
                assert (
                    type(self.content_list_bool) == tuple
                ), "Invalid type for content 'content_list_bool'. Expected 'tuple'. Found '{}'.".format(
                    type(self.content_list_bool))
                assert all(
                    type(element) == bool for element in self.content_list_bool
                ), "Invalid type for tuple elements in content 'content_list_bool'. Expected 'bool'."
                assert (
                    type(self.content_list_str) == tuple
                ), "Invalid type for content 'content_list_str'. Expected 'tuple'. Found '{}'.".format(
                    type(self.content_list_str))
                assert all(
                    type(element) == str for element in self.content_list_str
                ), "Invalid type for tuple elements in content 'content_list_str'. Expected 'str'."
            elif (self.performative ==
                  TProtocolNoCtMessage.Performative.PERFORMATIVE_PMT):
                expected_nb_of_contents = 15
                assert (
                    type(self.content_dict_int_bytes) == dict
                ), "Invalid type for content 'content_dict_int_bytes'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_int_bytes))
                for (
                        key_of_content_dict_int_bytes,
                        value_of_content_dict_int_bytes,
                ) in self.content_dict_int_bytes.items():
                    assert (
                        type(key_of_content_dict_int_bytes) == int
                    ), "Invalid type for dictionary keys in content 'content_dict_int_bytes'. Expected 'int'. Found '{}'.".format(
                        type(key_of_content_dict_int_bytes))
                    assert (
                        type(value_of_content_dict_int_bytes) == bytes
                    ), "Invalid type for dictionary values in content 'content_dict_int_bytes'. Expected 'bytes'. Found '{}'.".format(
                        type(value_of_content_dict_int_bytes))
                assert (
                    type(self.content_dict_int_int) == dict
                ), "Invalid type for content 'content_dict_int_int'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_int_int))
                for (
                        key_of_content_dict_int_int,
                        value_of_content_dict_int_int,
                ) in self.content_dict_int_int.items():
                    assert (
                        type(key_of_content_dict_int_int) == int
                    ), "Invalid type for dictionary keys in content 'content_dict_int_int'. Expected 'int'. Found '{}'.".format(
                        type(key_of_content_dict_int_int))
                    assert (
                        type(value_of_content_dict_int_int) == int
                    ), "Invalid type for dictionary values in content 'content_dict_int_int'. Expected 'int'. Found '{}'.".format(
                        type(value_of_content_dict_int_int))
                assert (
                    type(self.content_dict_int_float) == dict
                ), "Invalid type for content 'content_dict_int_float'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_int_float))
                for (
                        key_of_content_dict_int_float,
                        value_of_content_dict_int_float,
                ) in self.content_dict_int_float.items():
                    assert (
                        type(key_of_content_dict_int_float) == int
                    ), "Invalid type for dictionary keys in content 'content_dict_int_float'. Expected 'int'. Found '{}'.".format(
                        type(key_of_content_dict_int_float))
                    assert (
                        type(value_of_content_dict_int_float) == float
                    ), "Invalid type for dictionary values in content 'content_dict_int_float'. Expected 'float'. Found '{}'.".format(
                        type(value_of_content_dict_int_float))
                assert (
                    type(self.content_dict_int_bool) == dict
                ), "Invalid type for content 'content_dict_int_bool'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_int_bool))
                for (
                        key_of_content_dict_int_bool,
                        value_of_content_dict_int_bool,
                ) in self.content_dict_int_bool.items():
                    assert (
                        type(key_of_content_dict_int_bool) == int
                    ), "Invalid type for dictionary keys in content 'content_dict_int_bool'. Expected 'int'. Found '{}'.".format(
                        type(key_of_content_dict_int_bool))
                    assert (
                        type(value_of_content_dict_int_bool) == bool
                    ), "Invalid type for dictionary values in content 'content_dict_int_bool'. Expected 'bool'. Found '{}'.".format(
                        type(value_of_content_dict_int_bool))
                assert (
                    type(self.content_dict_int_str) == dict
                ), "Invalid type for content 'content_dict_int_str'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_int_str))
                for (
                        key_of_content_dict_int_str,
                        value_of_content_dict_int_str,
                ) in self.content_dict_int_str.items():
                    assert (
                        type(key_of_content_dict_int_str) == int
                    ), "Invalid type for dictionary keys in content 'content_dict_int_str'. Expected 'int'. Found '{}'.".format(
                        type(key_of_content_dict_int_str))
                    assert (
                        type(value_of_content_dict_int_str) == str
                    ), "Invalid type for dictionary values in content 'content_dict_int_str'. Expected 'str'. Found '{}'.".format(
                        type(value_of_content_dict_int_str))
                assert (
                    type(self.content_dict_bool_bytes) == dict
                ), "Invalid type for content 'content_dict_bool_bytes'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_bool_bytes))
                for (
                        key_of_content_dict_bool_bytes,
                        value_of_content_dict_bool_bytes,
                ) in self.content_dict_bool_bytes.items():
                    assert (
                        type(key_of_content_dict_bool_bytes) == bool
                    ), "Invalid type for dictionary keys in content 'content_dict_bool_bytes'. Expected 'bool'. Found '{}'.".format(
                        type(key_of_content_dict_bool_bytes))
                    assert (
                        type(value_of_content_dict_bool_bytes) == bytes
                    ), "Invalid type for dictionary values in content 'content_dict_bool_bytes'. Expected 'bytes'. Found '{}'.".format(
                        type(value_of_content_dict_bool_bytes))
                assert (
                    type(self.content_dict_bool_int) == dict
                ), "Invalid type for content 'content_dict_bool_int'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_bool_int))
                for (
                        key_of_content_dict_bool_int,
                        value_of_content_dict_bool_int,
                ) in self.content_dict_bool_int.items():
                    assert (
                        type(key_of_content_dict_bool_int) == bool
                    ), "Invalid type for dictionary keys in content 'content_dict_bool_int'. Expected 'bool'. Found '{}'.".format(
                        type(key_of_content_dict_bool_int))
                    assert (
                        type(value_of_content_dict_bool_int) == int
                    ), "Invalid type for dictionary values in content 'content_dict_bool_int'. Expected 'int'. Found '{}'.".format(
                        type(value_of_content_dict_bool_int))
                assert (
                    type(self.content_dict_bool_float) == dict
                ), "Invalid type for content 'content_dict_bool_float'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_bool_float))
                for (
                        key_of_content_dict_bool_float,
                        value_of_content_dict_bool_float,
                ) in self.content_dict_bool_float.items():
                    assert (
                        type(key_of_content_dict_bool_float) == bool
                    ), "Invalid type for dictionary keys in content 'content_dict_bool_float'. Expected 'bool'. Found '{}'.".format(
                        type(key_of_content_dict_bool_float))
                    assert (
                        type(value_of_content_dict_bool_float) == float
                    ), "Invalid type for dictionary values in content 'content_dict_bool_float'. Expected 'float'. Found '{}'.".format(
                        type(value_of_content_dict_bool_float))
                assert (
                    type(self.content_dict_bool_bool) == dict
                ), "Invalid type for content 'content_dict_bool_bool'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_bool_bool))
                for (
                        key_of_content_dict_bool_bool,
                        value_of_content_dict_bool_bool,
                ) in self.content_dict_bool_bool.items():
                    assert (
                        type(key_of_content_dict_bool_bool) == bool
                    ), "Invalid type for dictionary keys in content 'content_dict_bool_bool'. Expected 'bool'. Found '{}'.".format(
                        type(key_of_content_dict_bool_bool))
                    assert (
                        type(value_of_content_dict_bool_bool) == bool
                    ), "Invalid type for dictionary values in content 'content_dict_bool_bool'. Expected 'bool'. Found '{}'.".format(
                        type(value_of_content_dict_bool_bool))
                assert (
                    type(self.content_dict_bool_str) == dict
                ), "Invalid type for content 'content_dict_bool_str'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_bool_str))
                for (
                        key_of_content_dict_bool_str,
                        value_of_content_dict_bool_str,
                ) in self.content_dict_bool_str.items():
                    assert (
                        type(key_of_content_dict_bool_str) == bool
                    ), "Invalid type for dictionary keys in content 'content_dict_bool_str'. Expected 'bool'. Found '{}'.".format(
                        type(key_of_content_dict_bool_str))
                    assert (
                        type(value_of_content_dict_bool_str) == str
                    ), "Invalid type for dictionary values in content 'content_dict_bool_str'. Expected 'str'. Found '{}'.".format(
                        type(value_of_content_dict_bool_str))
                assert (
                    type(self.content_dict_str_bytes) == dict
                ), "Invalid type for content 'content_dict_str_bytes'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_str_bytes))
                for (
                        key_of_content_dict_str_bytes,
                        value_of_content_dict_str_bytes,
                ) in self.content_dict_str_bytes.items():
                    assert (
                        type(key_of_content_dict_str_bytes) == str
                    ), "Invalid type for dictionary keys in content 'content_dict_str_bytes'. Expected 'str'. Found '{}'.".format(
                        type(key_of_content_dict_str_bytes))
                    assert (
                        type(value_of_content_dict_str_bytes) == bytes
                    ), "Invalid type for dictionary values in content 'content_dict_str_bytes'. Expected 'bytes'. Found '{}'.".format(
                        type(value_of_content_dict_str_bytes))
                assert (
                    type(self.content_dict_str_int) == dict
                ), "Invalid type for content 'content_dict_str_int'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_str_int))
                for (
                        key_of_content_dict_str_int,
                        value_of_content_dict_str_int,
                ) in self.content_dict_str_int.items():
                    assert (
                        type(key_of_content_dict_str_int) == str
                    ), "Invalid type for dictionary keys in content 'content_dict_str_int'. Expected 'str'. Found '{}'.".format(
                        type(key_of_content_dict_str_int))
                    assert (
                        type(value_of_content_dict_str_int) == int
                    ), "Invalid type for dictionary values in content 'content_dict_str_int'. Expected 'int'. Found '{}'.".format(
                        type(value_of_content_dict_str_int))
                assert (
                    type(self.content_dict_str_float) == dict
                ), "Invalid type for content 'content_dict_str_float'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_str_float))
                for (
                        key_of_content_dict_str_float,
                        value_of_content_dict_str_float,
                ) in self.content_dict_str_float.items():
                    assert (
                        type(key_of_content_dict_str_float) == str
                    ), "Invalid type for dictionary keys in content 'content_dict_str_float'. Expected 'str'. Found '{}'.".format(
                        type(key_of_content_dict_str_float))
                    assert (
                        type(value_of_content_dict_str_float) == float
                    ), "Invalid type for dictionary values in content 'content_dict_str_float'. Expected 'float'. Found '{}'.".format(
                        type(value_of_content_dict_str_float))
                assert (
                    type(self.content_dict_str_bool) == dict
                ), "Invalid type for content 'content_dict_str_bool'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_str_bool))
                for (
                        key_of_content_dict_str_bool,
                        value_of_content_dict_str_bool,
                ) in self.content_dict_str_bool.items():
                    assert (
                        type(key_of_content_dict_str_bool) == str
                    ), "Invalid type for dictionary keys in content 'content_dict_str_bool'. Expected 'str'. Found '{}'.".format(
                        type(key_of_content_dict_str_bool))
                    assert (
                        type(value_of_content_dict_str_bool) == bool
                    ), "Invalid type for dictionary values in content 'content_dict_str_bool'. Expected 'bool'. Found '{}'.".format(
                        type(value_of_content_dict_str_bool))
                assert (
                    type(self.content_dict_str_str) == dict
                ), "Invalid type for content 'content_dict_str_str'. Expected 'dict'. Found '{}'.".format(
                    type(self.content_dict_str_str))
                for (
                        key_of_content_dict_str_str,
                        value_of_content_dict_str_str,
                ) in self.content_dict_str_str.items():
                    assert (
                        type(key_of_content_dict_str_str) == str
                    ), "Invalid type for dictionary keys in content 'content_dict_str_str'. Expected 'str'. Found '{}'.".format(
                        type(key_of_content_dict_str_str))
                    assert (
                        type(value_of_content_dict_str_str) == str
                    ), "Invalid type for dictionary values in content 'content_dict_str_str'. Expected 'str'. Found '{}'.".format(
                        type(value_of_content_dict_str_str))
            elif self.performative == TProtocolNoCtMessage.Performative.PERFORMATIVE_MT:
                expected_nb_of_contents = 2
                assert (
                    type(self.content_union_1) == bool
                    or type(self.content_union_1) == bytes
                    or type(self.content_union_1) == dict
                    or type(self.content_union_1) == float
                    or type(self.content_union_1) == frozenset
                    or type(self.content_union_1) == int
                    or type(self.content_union_1) == str
                    or type(self.content_union_1) == tuple
                ), "Invalid type for content 'content_union_1'. Expected either of '['bool', 'bytes', 'dict', 'float', 'frozenset', 'int', 'str', 'tuple']'. Found '{}'.".format(
                    type(self.content_union_1))
                if type(self.content_union_1) == frozenset:
                    assert all(
                        type(element) == int
                        for element in self.content_union_1
                    ), "Invalid type for elements of content 'content_union_1'. Expected 'int'."
                if type(self.content_union_1) == tuple:
                    assert all(
                        type(element) == bool
                        for element in self.content_union_1
                    ), "Invalid type for tuple elements in content 'content_union_1'. Expected 'bool'."
                if type(self.content_union_1) == dict:
                    for (
                            key_of_content_union_1,
                            value_of_content_union_1,
                    ) in self.content_union_1.items():
                        assert (
                            type(key_of_content_union_1) == str
                            and type(value_of_content_union_1) == int
                        ), "Invalid type for dictionary key, value in content 'content_union_1'. Expected 'str', 'int'."
                assert (
                    type(self.content_union_2) == dict
                    or type(self.content_union_2) == frozenset
                    or type(self.content_union_2) == tuple
                ), "Invalid type for content 'content_union_2'. Expected either of '['dict', 'frozenset', 'tuple']'. Found '{}'.".format(
                    type(self.content_union_2))
                if type(self.content_union_2) == frozenset:
                    assert (
                        all(
                            type(element) == bytes
                            for element in self.content_union_2) or all(
                                type(element) == int
                                for element in self.content_union_2) or all(
                                    type(element) == str
                                    for element in self.content_union_2)
                    ), "Invalid type for frozenset elements in content 'content_union_2'. Expected either 'bytes' or 'int' or 'str'."
                if type(self.content_union_2) == tuple:
                    assert (
                        all(
                            type(element) == bool
                            for element in self.content_union_2) or all(
                                type(element) == bytes
                                for element in self.content_union_2) or all(
                                    type(element) == float
                                    for element in self.content_union_2)
                    ), "Invalid type for tuple elements in content 'content_union_2'. Expected either 'bool' or 'bytes' or 'float'."
                if type(self.content_union_2) == dict:
                    for (
                            key_of_content_union_2,
                            value_of_content_union_2,
                    ) in self.content_union_2.items():
                        assert (
                            (type(key_of_content_union_2) == bool
                             and type(value_of_content_union_2) == bytes)
                            or (type(key_of_content_union_2) == int
                                and type(value_of_content_union_2) == float)
                            or (type(key_of_content_union_2) == str
                                and type(value_of_content_union_2) == int)
                        ), "Invalid type for dictionary key, value in content 'content_union_2'. Expected 'bool','bytes' or 'int','float' or 'str','int'."
            elif self.performative == TProtocolNoCtMessage.Performative.PERFORMATIVE_O:
                expected_nb_of_contents = 0
                if self.is_set("content_o_bool"):
                    expected_nb_of_contents += 1
                    content_o_bool = cast(bool, self.content_o_bool)
                    assert (
                        type(content_o_bool) == bool
                    ), "Invalid type for content 'content_o_bool'. Expected 'bool'. Found '{}'.".format(
                        type(content_o_bool))
                if self.is_set("content_o_set_int"):
                    expected_nb_of_contents += 1
                    content_o_set_int = cast(FrozenSet[int],
                                             self.content_o_set_int)
                    assert (
                        type(content_o_set_int) == frozenset
                    ), "Invalid type for content 'content_o_set_int'. Expected 'frozenset'. Found '{}'.".format(
                        type(content_o_set_int))
                    assert all(
                        type(element) == int for element in content_o_set_int
                    ), "Invalid type for frozenset elements in content 'content_o_set_int'. Expected 'int'."
                if self.is_set("content_o_list_bytes"):
                    expected_nb_of_contents += 1
                    content_o_list_bytes = cast(Tuple[bytes, ...],
                                                self.content_o_list_bytes)
                    assert (
                        type(content_o_list_bytes) == tuple
                    ), "Invalid type for content 'content_o_list_bytes'. Expected 'tuple'. Found '{}'.".format(
                        type(content_o_list_bytes))
                    assert all(
                        type(element) == bytes
                        for element in content_o_list_bytes
                    ), "Invalid type for tuple elements in content 'content_o_list_bytes'. Expected 'bytes'."
                if self.is_set("content_o_dict_str_int"):
                    expected_nb_of_contents += 1
                    content_o_dict_str_int = cast(Dict[str, int],
                                                  self.content_o_dict_str_int)
                    assert (
                        type(content_o_dict_str_int) == dict
                    ), "Invalid type for content 'content_o_dict_str_int'. Expected 'dict'. Found '{}'.".format(
                        type(content_o_dict_str_int))
                    for (
                            key_of_content_o_dict_str_int,
                            value_of_content_o_dict_str_int,
                    ) in content_o_dict_str_int.items():
                        assert (
                            type(key_of_content_o_dict_str_int) == str
                        ), "Invalid type for dictionary keys in content 'content_o_dict_str_int'. Expected 'str'. Found '{}'.".format(
                            type(key_of_content_o_dict_str_int))
                        assert (
                            type(value_of_content_o_dict_str_int) == int
                        ), "Invalid type for dictionary values in content 'content_o_dict_str_int'. Expected 'int'. Found '{}'.".format(
                            type(value_of_content_o_dict_str_int))
            elif (self.performative == TProtocolNoCtMessage.Performative.
                  PERFORMATIVE_EMPTY_CONTENTS):
                expected_nb_of_contents = 0

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 5
0
class GymMessage(Message):
    """A protocol for interacting with a gym connection."""

    protocol_id = ProtocolId.from_str("fetchai/gym:0.4.0")

    AnyObject = CustomAnyObject

    class Performative(Enum):
        """Performatives for the gym protocol."""

        ACT = "act"
        CLOSE = "close"
        PERCEPT = "percept"
        RESET = "reset"
        STATUS = "status"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of GymMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=GymMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {"act", "close", "percept", "reset", "status"}

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(GymMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def action(self) -> CustomAnyObject:
        """Get the 'action' content from the message."""
        assert self.is_set("action"), "'action' content is not set."
        return cast(CustomAnyObject, self.get("action"))

    @property
    def content(self) -> Dict[str, str]:
        """Get the 'content' content from the message."""
        assert self.is_set("content"), "'content' content is not set."
        return cast(Dict[str, str], self.get("content"))

    @property
    def done(self) -> bool:
        """Get the 'done' content from the message."""
        assert self.is_set("done"), "'done' content is not set."
        return cast(bool, self.get("done"))

    @property
    def info(self) -> CustomAnyObject:
        """Get the 'info' content from the message."""
        assert self.is_set("info"), "'info' content is not set."
        return cast(CustomAnyObject, self.get("info"))

    @property
    def observation(self) -> CustomAnyObject:
        """Get the 'observation' content from the message."""
        assert self.is_set("observation"), "'observation' content is not set."
        return cast(CustomAnyObject, self.get("observation"))

    @property
    def reward(self) -> float:
        """Get the 'reward' content from the message."""
        assert self.is_set("reward"), "'reward' content is not set."
        return cast(float, self.get("reward"))

    @property
    def step_id(self) -> int:
        """Get the 'step_id' content from the message."""
        assert self.is_set("step_id"), "'step_id' content is not set."
        return cast(int, self.get("step_id"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the gym protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == GymMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == GymMessage.Performative.ACT:
                expected_nb_of_contents = 2
                assert (
                    type(self.action) == CustomAnyObject
                ), "Invalid type for content 'action'. Expected 'AnyObject'. Found '{}'.".format(
                    type(self.action))
                assert (
                    type(self.step_id) == int
                ), "Invalid type for content 'step_id'. Expected 'int'. Found '{}'.".format(
                    type(self.step_id))
            elif self.performative == GymMessage.Performative.PERCEPT:
                expected_nb_of_contents = 5
                assert (
                    type(self.step_id) == int
                ), "Invalid type for content 'step_id'. Expected 'int'. Found '{}'.".format(
                    type(self.step_id))
                assert (
                    type(self.observation) == CustomAnyObject
                ), "Invalid type for content 'observation'. Expected 'AnyObject'. Found '{}'.".format(
                    type(self.observation))
                assert (
                    type(self.reward) == float
                ), "Invalid type for content 'reward'. Expected 'float'. Found '{}'.".format(
                    type(self.reward))
                assert (
                    type(self.done) == bool
                ), "Invalid type for content 'done'. Expected 'bool'. Found '{}'.".format(
                    type(self.done))
                assert (
                    type(self.info) == CustomAnyObject
                ), "Invalid type for content 'info'. Expected 'AnyObject'. Found '{}'.".format(
                    type(self.info))
            elif self.performative == GymMessage.Performative.STATUS:
                expected_nb_of_contents = 1
                assert (
                    type(self.content) == dict
                ), "Invalid type for content 'content'. Expected 'dict'. Found '{}'.".format(
                    type(self.content))
                for key_of_content, value_of_content in self.content.items():
                    assert (
                        type(key_of_content) == str
                    ), "Invalid type for dictionary keys in content 'content'. Expected 'str'. Found '{}'.".format(
                        type(key_of_content))
                    assert (
                        type(value_of_content) == str
                    ), "Invalid type for dictionary values in content 'content'. Expected 'str'. Found '{}'.".format(
                        type(value_of_content))
            elif self.performative == GymMessage.Performative.RESET:
                expected_nb_of_contents = 0
            elif self.performative == GymMessage.Performative.CLOSE:
                expected_nb_of_contents = 0

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 6
0
class MlTradeMessage(Message):
    """A protocol for trading data for training and prediction purposes."""

    protocol_id = ProtocolId.from_str("fetchai/ml_trade:0.4.0")

    Description = CustomDescription

    Query = CustomQuery

    class Performative(Enum):
        """Performatives for the ml_trade protocol."""

        ACCEPT = "accept"
        CFP = "cfp"
        DATA = "data"
        TERMS = "terms"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of MlTradeMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=MlTradeMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {"accept", "cfp", "data", "terms"}

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(MlTradeMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def payload(self) -> bytes:
        """Get the 'payload' content from the message."""
        assert self.is_set("payload"), "'payload' content is not set."
        return cast(bytes, self.get("payload"))

    @property
    def query(self) -> CustomQuery:
        """Get the 'query' content from the message."""
        assert self.is_set("query"), "'query' content is not set."
        return cast(CustomQuery, self.get("query"))

    @property
    def terms(self) -> CustomDescription:
        """Get the 'terms' content from the message."""
        assert self.is_set("terms"), "'terms' content is not set."
        return cast(CustomDescription, self.get("terms"))

    @property
    def tx_digest(self) -> str:
        """Get the 'tx_digest' content from the message."""
        assert self.is_set("tx_digest"), "'tx_digest' content is not set."
        return cast(str, self.get("tx_digest"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the ml_trade protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == MlTradeMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == MlTradeMessage.Performative.CFP:
                expected_nb_of_contents = 1
                assert (
                    type(self.query) == CustomQuery
                ), "Invalid type for content 'query'. Expected 'Query'. Found '{}'.".format(
                    type(self.query))
            elif self.performative == MlTradeMessage.Performative.TERMS:
                expected_nb_of_contents = 1
                assert (
                    type(self.terms) == CustomDescription
                ), "Invalid type for content 'terms'. Expected 'Description'. Found '{}'.".format(
                    type(self.terms))
            elif self.performative == MlTradeMessage.Performative.ACCEPT:
                expected_nb_of_contents = 2
                assert (
                    type(self.terms) == CustomDescription
                ), "Invalid type for content 'terms'. Expected 'Description'. Found '{}'.".format(
                    type(self.terms))
                assert (
                    type(self.tx_digest) == str
                ), "Invalid type for content 'tx_digest'. Expected 'str'. Found '{}'.".format(
                    type(self.tx_digest))
            elif self.performative == MlTradeMessage.Performative.DATA:
                expected_nb_of_contents = 2
                assert (
                    type(self.terms) == CustomDescription
                ), "Invalid type for content 'terms'. Expected 'Description'. Found '{}'.".format(
                    type(self.terms))
                assert (
                    type(self.payload) == bytes
                ), "Invalid type for content 'payload'. Expected 'bytes'. Found '{}'.".format(
                    type(self.payload))

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 7
0
class TacMessage(Message):
    """The tac protocol implements the messages an AEA needs to participate in the TAC."""

    protocol_id = ProtocolId.from_str("fetchai/tac:0.5.0")

    ErrorCode = CustomErrorCode

    class Performative(Enum):
        """Performatives for the tac protocol."""

        CANCELLED = "cancelled"
        GAME_DATA = "game_data"
        REGISTER = "register"
        TAC_ERROR = "tac_error"
        TRANSACTION = "transaction"
        TRANSACTION_CONFIRMATION = "transaction_confirmation"
        UNREGISTER = "unregister"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of TacMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=TacMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {
            "cancelled",
            "game_data",
            "register",
            "tac_error",
            "transaction",
            "transaction_confirmation",
            "unregister",
        }

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(TacMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def agent_addr_to_name(self) -> Dict[str, str]:
        """Get the 'agent_addr_to_name' content from the message."""
        assert self.is_set(
            "agent_addr_to_name"), "'agent_addr_to_name' content is not set."
        return cast(Dict[str, str], self.get("agent_addr_to_name"))

    @property
    def agent_name(self) -> str:
        """Get the 'agent_name' content from the message."""
        assert self.is_set("agent_name"), "'agent_name' content is not set."
        return cast(str, self.get("agent_name"))

    @property
    def amount_by_currency_id(self) -> Dict[str, int]:
        """Get the 'amount_by_currency_id' content from the message."""
        assert self.is_set("amount_by_currency_id"
                           ), "'amount_by_currency_id' content is not set."
        return cast(Dict[str, int], self.get("amount_by_currency_id"))

    @property
    def counterparty_address(self) -> str:
        """Get the 'counterparty_address' content from the message."""
        assert self.is_set("counterparty_address"
                           ), "'counterparty_address' content is not set."
        return cast(str, self.get("counterparty_address"))

    @property
    def counterparty_signature(self) -> str:
        """Get the 'counterparty_signature' content from the message."""
        assert self.is_set("counterparty_signature"
                           ), "'counterparty_signature' content is not set."
        return cast(str, self.get("counterparty_signature"))

    @property
    def currency_id_to_name(self) -> Dict[str, str]:
        """Get the 'currency_id_to_name' content from the message."""
        assert self.is_set(
            "currency_id_to_name"), "'currency_id_to_name' content is not set."
        return cast(Dict[str, str], self.get("currency_id_to_name"))

    @property
    def error_code(self) -> CustomErrorCode:
        """Get the 'error_code' content from the message."""
        assert self.is_set("error_code"), "'error_code' content is not set."
        return cast(CustomErrorCode, self.get("error_code"))

    @property
    def exchange_params_by_currency_id(self) -> Dict[str, float]:
        """Get the 'exchange_params_by_currency_id' content from the message."""
        assert self.is_set(
            "exchange_params_by_currency_id"
        ), "'exchange_params_by_currency_id' content is not set."
        return cast(Dict[str, float],
                    self.get("exchange_params_by_currency_id"))

    @property
    def fee_by_currency_id(self) -> Dict[str, int]:
        """Get the 'fee_by_currency_id' content from the message."""
        assert self.is_set(
            "fee_by_currency_id"), "'fee_by_currency_id' content is not set."
        return cast(Dict[str, int], self.get("fee_by_currency_id"))

    @property
    def good_id_to_name(self) -> Dict[str, str]:
        """Get the 'good_id_to_name' content from the message."""
        assert self.is_set(
            "good_id_to_name"), "'good_id_to_name' content is not set."
        return cast(Dict[str, str], self.get("good_id_to_name"))

    @property
    def info(self) -> Optional[Dict[str, str]]:
        """Get the 'info' content from the message."""
        return cast(Optional[Dict[str, str]], self.get("info"))

    @property
    def ledger_id(self) -> str:
        """Get the 'ledger_id' content from the message."""
        assert self.is_set("ledger_id"), "'ledger_id' content is not set."
        return cast(str, self.get("ledger_id"))

    @property
    def nonce(self) -> str:
        """Get the 'nonce' content from the message."""
        assert self.is_set("nonce"), "'nonce' content is not set."
        return cast(str, self.get("nonce"))

    @property
    def quantities_by_good_id(self) -> Dict[str, int]:
        """Get the 'quantities_by_good_id' content from the message."""
        assert self.is_set("quantities_by_good_id"
                           ), "'quantities_by_good_id' content is not set."
        return cast(Dict[str, int], self.get("quantities_by_good_id"))

    @property
    def sender_address(self) -> str:
        """Get the 'sender_address' content from the message."""
        assert self.is_set(
            "sender_address"), "'sender_address' content is not set."
        return cast(str, self.get("sender_address"))

    @property
    def sender_signature(self) -> str:
        """Get the 'sender_signature' content from the message."""
        assert self.is_set(
            "sender_signature"), "'sender_signature' content is not set."
        return cast(str, self.get("sender_signature"))

    @property
    def transaction_id(self) -> str:
        """Get the 'transaction_id' content from the message."""
        assert self.is_set(
            "transaction_id"), "'transaction_id' content is not set."
        return cast(str, self.get("transaction_id"))

    @property
    def utility_params_by_good_id(self) -> Dict[str, float]:
        """Get the 'utility_params_by_good_id' content from the message."""
        assert self.is_set("utility_params_by_good_id"
                           ), "'utility_params_by_good_id' content is not set."
        return cast(Dict[str, float], self.get("utility_params_by_good_id"))

    @property
    def version_id(self) -> str:
        """Get the 'version_id' content from the message."""
        assert self.is_set("version_id"), "'version_id' content is not set."
        return cast(str, self.get("version_id"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the tac protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == TacMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == TacMessage.Performative.REGISTER:
                expected_nb_of_contents = 1
                assert (
                    type(self.agent_name) == str
                ), "Invalid type for content 'agent_name'. Expected 'str'. Found '{}'.".format(
                    type(self.agent_name))
            elif self.performative == TacMessage.Performative.UNREGISTER:
                expected_nb_of_contents = 0
            elif self.performative == TacMessage.Performative.TRANSACTION:
                expected_nb_of_contents = 10
                assert (
                    type(self.transaction_id) == str
                ), "Invalid type for content 'transaction_id'. Expected 'str'. Found '{}'.".format(
                    type(self.transaction_id))
                assert (
                    type(self.ledger_id) == str
                ), "Invalid type for content 'ledger_id'. Expected 'str'. Found '{}'.".format(
                    type(self.ledger_id))
                assert (
                    type(self.sender_address) == str
                ), "Invalid type for content 'sender_address'. Expected 'str'. Found '{}'.".format(
                    type(self.sender_address))
                assert (
                    type(self.counterparty_address) == str
                ), "Invalid type for content 'counterparty_address'. Expected 'str'. Found '{}'.".format(
                    type(self.counterparty_address))
                assert (
                    type(self.amount_by_currency_id) == dict
                ), "Invalid type for content 'amount_by_currency_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.amount_by_currency_id))
                for (
                        key_of_amount_by_currency_id,
                        value_of_amount_by_currency_id,
                ) in self.amount_by_currency_id.items():
                    assert (
                        type(key_of_amount_by_currency_id) == str
                    ), "Invalid type for dictionary keys in content 'amount_by_currency_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_amount_by_currency_id))
                    assert (
                        type(value_of_amount_by_currency_id) == int
                    ), "Invalid type for dictionary values in content 'amount_by_currency_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_amount_by_currency_id))
                assert (
                    type(self.fee_by_currency_id) == dict
                ), "Invalid type for content 'fee_by_currency_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.fee_by_currency_id))
                for (
                        key_of_fee_by_currency_id,
                        value_of_fee_by_currency_id,
                ) in self.fee_by_currency_id.items():
                    assert (
                        type(key_of_fee_by_currency_id) == str
                    ), "Invalid type for dictionary keys in content 'fee_by_currency_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_fee_by_currency_id))
                    assert (
                        type(value_of_fee_by_currency_id) == int
                    ), "Invalid type for dictionary values in content 'fee_by_currency_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_fee_by_currency_id))
                assert (
                    type(self.quantities_by_good_id) == dict
                ), "Invalid type for content 'quantities_by_good_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.quantities_by_good_id))
                for (
                        key_of_quantities_by_good_id,
                        value_of_quantities_by_good_id,
                ) in self.quantities_by_good_id.items():
                    assert (
                        type(key_of_quantities_by_good_id) == str
                    ), "Invalid type for dictionary keys in content 'quantities_by_good_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_quantities_by_good_id))
                    assert (
                        type(value_of_quantities_by_good_id) == int
                    ), "Invalid type for dictionary values in content 'quantities_by_good_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_quantities_by_good_id))
                assert (
                    type(self.nonce) == str
                ), "Invalid type for content 'nonce'. Expected 'str'. Found '{}'.".format(
                    type(self.nonce))
                assert (
                    type(self.sender_signature) == str
                ), "Invalid type for content 'sender_signature'. Expected 'str'. Found '{}'.".format(
                    type(self.sender_signature))
                assert (
                    type(self.counterparty_signature) == str
                ), "Invalid type for content 'counterparty_signature'. Expected 'str'. Found '{}'.".format(
                    type(self.counterparty_signature))
            elif self.performative == TacMessage.Performative.CANCELLED:
                expected_nb_of_contents = 0
            elif self.performative == TacMessage.Performative.GAME_DATA:
                expected_nb_of_contents = 9
                assert (
                    type(self.amount_by_currency_id) == dict
                ), "Invalid type for content 'amount_by_currency_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.amount_by_currency_id))
                for (
                        key_of_amount_by_currency_id,
                        value_of_amount_by_currency_id,
                ) in self.amount_by_currency_id.items():
                    assert (
                        type(key_of_amount_by_currency_id) == str
                    ), "Invalid type for dictionary keys in content 'amount_by_currency_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_amount_by_currency_id))
                    assert (
                        type(value_of_amount_by_currency_id) == int
                    ), "Invalid type for dictionary values in content 'amount_by_currency_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_amount_by_currency_id))
                assert (
                    type(self.exchange_params_by_currency_id) == dict
                ), "Invalid type for content 'exchange_params_by_currency_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.exchange_params_by_currency_id))
                for (
                        key_of_exchange_params_by_currency_id,
                        value_of_exchange_params_by_currency_id,
                ) in self.exchange_params_by_currency_id.items():
                    assert (
                        type(key_of_exchange_params_by_currency_id) == str
                    ), "Invalid type for dictionary keys in content 'exchange_params_by_currency_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_exchange_params_by_currency_id))
                    assert (
                        type(value_of_exchange_params_by_currency_id) == float
                    ), "Invalid type for dictionary values in content 'exchange_params_by_currency_id'. Expected 'float'. Found '{}'.".format(
                        type(value_of_exchange_params_by_currency_id))
                assert (
                    type(self.quantities_by_good_id) == dict
                ), "Invalid type for content 'quantities_by_good_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.quantities_by_good_id))
                for (
                        key_of_quantities_by_good_id,
                        value_of_quantities_by_good_id,
                ) in self.quantities_by_good_id.items():
                    assert (
                        type(key_of_quantities_by_good_id) == str
                    ), "Invalid type for dictionary keys in content 'quantities_by_good_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_quantities_by_good_id))
                    assert (
                        type(value_of_quantities_by_good_id) == int
                    ), "Invalid type for dictionary values in content 'quantities_by_good_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_quantities_by_good_id))
                assert (
                    type(self.utility_params_by_good_id) == dict
                ), "Invalid type for content 'utility_params_by_good_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.utility_params_by_good_id))
                for (
                        key_of_utility_params_by_good_id,
                        value_of_utility_params_by_good_id,
                ) in self.utility_params_by_good_id.items():
                    assert (
                        type(key_of_utility_params_by_good_id) == str
                    ), "Invalid type for dictionary keys in content 'utility_params_by_good_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_utility_params_by_good_id))
                    assert (
                        type(value_of_utility_params_by_good_id) == float
                    ), "Invalid type for dictionary values in content 'utility_params_by_good_id'. Expected 'float'. Found '{}'.".format(
                        type(value_of_utility_params_by_good_id))
                assert (
                    type(self.fee_by_currency_id) == dict
                ), "Invalid type for content 'fee_by_currency_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.fee_by_currency_id))
                for (
                        key_of_fee_by_currency_id,
                        value_of_fee_by_currency_id,
                ) in self.fee_by_currency_id.items():
                    assert (
                        type(key_of_fee_by_currency_id) == str
                    ), "Invalid type for dictionary keys in content 'fee_by_currency_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_fee_by_currency_id))
                    assert (
                        type(value_of_fee_by_currency_id) == int
                    ), "Invalid type for dictionary values in content 'fee_by_currency_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_fee_by_currency_id))
                assert (
                    type(self.agent_addr_to_name) == dict
                ), "Invalid type for content 'agent_addr_to_name'. Expected 'dict'. Found '{}'.".format(
                    type(self.agent_addr_to_name))
                for (
                        key_of_agent_addr_to_name,
                        value_of_agent_addr_to_name,
                ) in self.agent_addr_to_name.items():
                    assert (
                        type(key_of_agent_addr_to_name) == str
                    ), "Invalid type for dictionary keys in content 'agent_addr_to_name'. Expected 'str'. Found '{}'.".format(
                        type(key_of_agent_addr_to_name))
                    assert (
                        type(value_of_agent_addr_to_name) == str
                    ), "Invalid type for dictionary values in content 'agent_addr_to_name'. Expected 'str'. Found '{}'.".format(
                        type(value_of_agent_addr_to_name))
                assert (
                    type(self.currency_id_to_name) == dict
                ), "Invalid type for content 'currency_id_to_name'. Expected 'dict'. Found '{}'.".format(
                    type(self.currency_id_to_name))
                for (
                        key_of_currency_id_to_name,
                        value_of_currency_id_to_name,
                ) in self.currency_id_to_name.items():
                    assert (
                        type(key_of_currency_id_to_name) == str
                    ), "Invalid type for dictionary keys in content 'currency_id_to_name'. Expected 'str'. Found '{}'.".format(
                        type(key_of_currency_id_to_name))
                    assert (
                        type(value_of_currency_id_to_name) == str
                    ), "Invalid type for dictionary values in content 'currency_id_to_name'. Expected 'str'. Found '{}'.".format(
                        type(value_of_currency_id_to_name))
                assert (
                    type(self.good_id_to_name) == dict
                ), "Invalid type for content 'good_id_to_name'. Expected 'dict'. Found '{}'.".format(
                    type(self.good_id_to_name))
                for (
                        key_of_good_id_to_name,
                        value_of_good_id_to_name,
                ) in self.good_id_to_name.items():
                    assert (
                        type(key_of_good_id_to_name) == str
                    ), "Invalid type for dictionary keys in content 'good_id_to_name'. Expected 'str'. Found '{}'.".format(
                        type(key_of_good_id_to_name))
                    assert (
                        type(value_of_good_id_to_name) == str
                    ), "Invalid type for dictionary values in content 'good_id_to_name'. Expected 'str'. Found '{}'.".format(
                        type(value_of_good_id_to_name))
                assert (
                    type(self.version_id) == str
                ), "Invalid type for content 'version_id'. Expected 'str'. Found '{}'.".format(
                    type(self.version_id))
                if self.is_set("info"):
                    expected_nb_of_contents += 1
                    info = cast(Dict[str, str], self.info)
                    assert (
                        type(info) == dict
                    ), "Invalid type for content 'info'. Expected 'dict'. Found '{}'.".format(
                        type(info))
                    for key_of_info, value_of_info in info.items():
                        assert (
                            type(key_of_info) == str
                        ), "Invalid type for dictionary keys in content 'info'. Expected 'str'. Found '{}'.".format(
                            type(key_of_info))
                        assert (
                            type(value_of_info) == str
                        ), "Invalid type for dictionary values in content 'info'. Expected 'str'. Found '{}'.".format(
                            type(value_of_info))
            elif self.performative == TacMessage.Performative.TRANSACTION_CONFIRMATION:
                expected_nb_of_contents = 3
                assert (
                    type(self.transaction_id) == str
                ), "Invalid type for content 'transaction_id'. Expected 'str'. Found '{}'.".format(
                    type(self.transaction_id))
                assert (
                    type(self.amount_by_currency_id) == dict
                ), "Invalid type for content 'amount_by_currency_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.amount_by_currency_id))
                for (
                        key_of_amount_by_currency_id,
                        value_of_amount_by_currency_id,
                ) in self.amount_by_currency_id.items():
                    assert (
                        type(key_of_amount_by_currency_id) == str
                    ), "Invalid type for dictionary keys in content 'amount_by_currency_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_amount_by_currency_id))
                    assert (
                        type(value_of_amount_by_currency_id) == int
                    ), "Invalid type for dictionary values in content 'amount_by_currency_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_amount_by_currency_id))
                assert (
                    type(self.quantities_by_good_id) == dict
                ), "Invalid type for content 'quantities_by_good_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.quantities_by_good_id))
                for (
                        key_of_quantities_by_good_id,
                        value_of_quantities_by_good_id,
                ) in self.quantities_by_good_id.items():
                    assert (
                        type(key_of_quantities_by_good_id) == str
                    ), "Invalid type for dictionary keys in content 'quantities_by_good_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_quantities_by_good_id))
                    assert (
                        type(value_of_quantities_by_good_id) == int
                    ), "Invalid type for dictionary values in content 'quantities_by_good_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_quantities_by_good_id))
            elif self.performative == TacMessage.Performative.TAC_ERROR:
                expected_nb_of_contents = 1
                assert (
                    type(self.error_code) == CustomErrorCode
                ), "Invalid type for content 'error_code'. Expected 'ErrorCode'. Found '{}'.".format(
                    type(self.error_code))
                if self.is_set("info"):
                    expected_nb_of_contents += 1
                    info = cast(Dict[str, str], self.info)
                    assert (
                        type(info) == dict
                    ), "Invalid type for content 'info'. Expected 'dict'. Found '{}'.".format(
                        type(info))
                    for key_of_info, value_of_info in info.items():
                        assert (
                            type(key_of_info) == str
                        ), "Invalid type for dictionary keys in content 'info'. Expected 'str'. Found '{}'.".format(
                            type(key_of_info))
                        assert (
                            type(value_of_info) == str
                        ), "Invalid type for dictionary values in content 'info'. Expected 'str'. Found '{}'.".format(
                            type(value_of_info))

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 8
0
def test_soef():

    # First run OEF in a separate terminal: python scripts/oef/launch.py -c ./scripts/oef/launch_config.json
    crypto = FetchAICrypto()

    # create the connection and multiplexer objects
    soef_connection = SOEFConnection(
        api_key="TwiCIriSl0mLahw17pyqoA",
        soef_addr="soef.fetch.ai",
        soef_port=9002,
        address=crypto.address,
    )
    multiplexer = Multiplexer([soef_connection])
    try:
        # Set the multiplexer running in a different thread
        t = Thread(target=multiplexer.connect)
        t.start()

        time.sleep(3.0)

        # register a service with location
        attr_service_name = Attribute("service_name", str, True,
                                      "The name of the service.")
        attr_location = Attribute(
            "location", Location, True,
            "The location where the service is provided.")
        service_location_model = DataModel(
            "location_service",
            [attr_service_name, attr_location],
            "A data model to describe location of a service.",
        )
        service_name = "train"
        service_location = Location(52.2057092, 2.1183431)
        service_instance = {
            "service_name": service_name,
            "location": service_location
        }
        service_description = Description(service_instance,
                                          data_model=service_location_model)
        message = OefSearchMessage(
            performative=OefSearchMessage.Performative.REGISTER_SERVICE,
            service_description=service_description,
        )
        message_b = OefSearchSerializer().encode(message)
        envelope = Envelope(
            to="soef",
            sender=crypto.address,
            protocol_id=ProtocolId.from_str("fetchai/oef_search:0.1.0"),
            message=message_b,
        )
        logger.info(
            "Registering service={} at location=({},{}) by agent={}".format(
                service_name,
                service_location.latitude,
                service_location.longitude,
                crypto.address,
            ))
        multiplexer.put(envelope)

        # find agents near the previously registered service
        radius = 0.1
        matches_my_service_name = Constraint(
            "service_name", ConstraintType("==", service_name))
        close_to_my_service = Constraint(
            "location", ConstraintType("distance", (service_location, radius)))
        closeness_query = Query([matches_my_service_name, close_to_my_service],
                                model=service_location_model)
        message = OefSearchMessage(
            performative=OefSearchMessage.Performative.SEARCH_SERVICES,
            query=closeness_query,
        )
        message_b = OefSearchSerializer().encode(message)
        envelope = Envelope(
            to="soef",
            sender=crypto.address,
            protocol_id=ProtocolId.from_str("fetchai/oef_search:0.1.0"),
            message=message_b,
        )
        logger.info(
            "Searching for agents in radius={} of service={} at location=({},{})"
            .format(
                radius,
                service_name,
                service_location.latitude,
                service_location.longitude,
            ))
        multiplexer.put(envelope)
        time.sleep(4.0)

        # check for search results
        envelope = multiplexer.get()
        message = OefSearchSerializer().decode(envelope.message)
        assert len(message.agents) >= 0

    finally:
        # Shut down the multiplexer
        multiplexer.disconnect()
        t.join()
Ejemplo n.º 9
0
class SigningMessage(Message):
    """A protocol for communication between skills and decision maker."""

    protocol_id = ProtocolId.from_str("fetchai/signing:0.2.0")

    ErrorCode = CustomErrorCode

    RawMessage = CustomRawMessage

    RawTransaction = CustomRawTransaction

    SignedMessage = CustomSignedMessage

    SignedTransaction = CustomSignedTransaction

    Terms = CustomTerms

    class Performative(Enum):
        """Performatives for the signing protocol."""

        ERROR = "error"
        SIGN_MESSAGE = "sign_message"
        SIGN_TRANSACTION = "sign_transaction"
        SIGNED_MESSAGE = "signed_message"
        SIGNED_TRANSACTION = "signed_transaction"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of SigningMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=SigningMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {
            "error",
            "sign_message",
            "sign_transaction",
            "signed_message",
            "signed_transaction",
        }

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(SigningMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def error_code(self) -> CustomErrorCode:
        """Get the 'error_code' content from the message."""
        assert self.is_set("error_code"), "'error_code' content is not set."
        return cast(CustomErrorCode, self.get("error_code"))

    @property
    def raw_message(self) -> CustomRawMessage:
        """Get the 'raw_message' content from the message."""
        assert self.is_set("raw_message"), "'raw_message' content is not set."
        return cast(CustomRawMessage, self.get("raw_message"))

    @property
    def raw_transaction(self) -> CustomRawTransaction:
        """Get the 'raw_transaction' content from the message."""
        assert self.is_set(
            "raw_transaction"), "'raw_transaction' content is not set."
        return cast(CustomRawTransaction, self.get("raw_transaction"))

    @property
    def signed_message(self) -> CustomSignedMessage:
        """Get the 'signed_message' content from the message."""
        assert self.is_set(
            "signed_message"), "'signed_message' content is not set."
        return cast(CustomSignedMessage, self.get("signed_message"))

    @property
    def signed_transaction(self) -> CustomSignedTransaction:
        """Get the 'signed_transaction' content from the message."""
        assert self.is_set(
            "signed_transaction"), "'signed_transaction' content is not set."
        return cast(CustomSignedTransaction, self.get("signed_transaction"))

    @property
    def skill_callback_ids(self) -> Tuple[str, ...]:
        """Get the 'skill_callback_ids' content from the message."""
        assert self.is_set(
            "skill_callback_ids"), "'skill_callback_ids' content is not set."
        return cast(Tuple[str, ...], self.get("skill_callback_ids"))

    @property
    def skill_callback_info(self) -> Dict[str, str]:
        """Get the 'skill_callback_info' content from the message."""
        assert self.is_set(
            "skill_callback_info"), "'skill_callback_info' content is not set."
        return cast(Dict[str, str], self.get("skill_callback_info"))

    @property
    def terms(self) -> CustomTerms:
        """Get the 'terms' content from the message."""
        assert self.is_set("terms"), "'terms' content is not set."
        return cast(CustomTerms, self.get("terms"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the signing protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == SigningMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == SigningMessage.Performative.SIGN_TRANSACTION:
                expected_nb_of_contents = 4
                assert (
                    type(self.skill_callback_ids) == tuple
                ), "Invalid type for content 'skill_callback_ids'. Expected 'tuple'. Found '{}'.".format(
                    type(self.skill_callback_ids))
                assert all(
                    type(element) == str for element in self.skill_callback_ids
                ), "Invalid type for tuple elements in content 'skill_callback_ids'. Expected 'str'."
                assert (
                    type(self.skill_callback_info) == dict
                ), "Invalid type for content 'skill_callback_info'. Expected 'dict'. Found '{}'.".format(
                    type(self.skill_callback_info))
                for (
                        key_of_skill_callback_info,
                        value_of_skill_callback_info,
                ) in self.skill_callback_info.items():
                    assert (
                        type(key_of_skill_callback_info) == str
                    ), "Invalid type for dictionary keys in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(key_of_skill_callback_info))
                    assert (
                        type(value_of_skill_callback_info) == str
                    ), "Invalid type for dictionary values in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(value_of_skill_callback_info))
                assert (
                    type(self.terms) == CustomTerms
                ), "Invalid type for content 'terms'. Expected 'Terms'. Found '{}'.".format(
                    type(self.terms))
                assert (
                    type(self.raw_transaction) == CustomRawTransaction
                ), "Invalid type for content 'raw_transaction'. Expected 'RawTransaction'. Found '{}'.".format(
                    type(self.raw_transaction))
            elif self.performative == SigningMessage.Performative.SIGN_MESSAGE:
                expected_nb_of_contents = 4
                assert (
                    type(self.skill_callback_ids) == tuple
                ), "Invalid type for content 'skill_callback_ids'. Expected 'tuple'. Found '{}'.".format(
                    type(self.skill_callback_ids))
                assert all(
                    type(element) == str for element in self.skill_callback_ids
                ), "Invalid type for tuple elements in content 'skill_callback_ids'. Expected 'str'."
                assert (
                    type(self.skill_callback_info) == dict
                ), "Invalid type for content 'skill_callback_info'. Expected 'dict'. Found '{}'.".format(
                    type(self.skill_callback_info))
                for (
                        key_of_skill_callback_info,
                        value_of_skill_callback_info,
                ) in self.skill_callback_info.items():
                    assert (
                        type(key_of_skill_callback_info) == str
                    ), "Invalid type for dictionary keys in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(key_of_skill_callback_info))
                    assert (
                        type(value_of_skill_callback_info) == str
                    ), "Invalid type for dictionary values in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(value_of_skill_callback_info))
                assert (
                    type(self.terms) == CustomTerms
                ), "Invalid type for content 'terms'. Expected 'Terms'. Found '{}'.".format(
                    type(self.terms))
                assert (
                    type(self.raw_message) == CustomRawMessage
                ), "Invalid type for content 'raw_message'. Expected 'RawMessage'. Found '{}'.".format(
                    type(self.raw_message))
            elif self.performative == SigningMessage.Performative.SIGNED_TRANSACTION:
                expected_nb_of_contents = 3
                assert (
                    type(self.skill_callback_ids) == tuple
                ), "Invalid type for content 'skill_callback_ids'. Expected 'tuple'. Found '{}'.".format(
                    type(self.skill_callback_ids))
                assert all(
                    type(element) == str for element in self.skill_callback_ids
                ), "Invalid type for tuple elements in content 'skill_callback_ids'. Expected 'str'."
                assert (
                    type(self.skill_callback_info) == dict
                ), "Invalid type for content 'skill_callback_info'. Expected 'dict'. Found '{}'.".format(
                    type(self.skill_callback_info))
                for (
                        key_of_skill_callback_info,
                        value_of_skill_callback_info,
                ) in self.skill_callback_info.items():
                    assert (
                        type(key_of_skill_callback_info) == str
                    ), "Invalid type for dictionary keys in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(key_of_skill_callback_info))
                    assert (
                        type(value_of_skill_callback_info) == str
                    ), "Invalid type for dictionary values in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(value_of_skill_callback_info))
                assert (
                    type(self.signed_transaction) == CustomSignedTransaction
                ), "Invalid type for content 'signed_transaction'. Expected 'SignedTransaction'. Found '{}'.".format(
                    type(self.signed_transaction))
            elif self.performative == SigningMessage.Performative.SIGNED_MESSAGE:
                expected_nb_of_contents = 3
                assert (
                    type(self.skill_callback_ids) == tuple
                ), "Invalid type for content 'skill_callback_ids'. Expected 'tuple'. Found '{}'.".format(
                    type(self.skill_callback_ids))
                assert all(
                    type(element) == str for element in self.skill_callback_ids
                ), "Invalid type for tuple elements in content 'skill_callback_ids'. Expected 'str'."
                assert (
                    type(self.skill_callback_info) == dict
                ), "Invalid type for content 'skill_callback_info'. Expected 'dict'. Found '{}'.".format(
                    type(self.skill_callback_info))
                for (
                        key_of_skill_callback_info,
                        value_of_skill_callback_info,
                ) in self.skill_callback_info.items():
                    assert (
                        type(key_of_skill_callback_info) == str
                    ), "Invalid type for dictionary keys in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(key_of_skill_callback_info))
                    assert (
                        type(value_of_skill_callback_info) == str
                    ), "Invalid type for dictionary values in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(value_of_skill_callback_info))
                assert (
                    type(self.signed_message) == CustomSignedMessage
                ), "Invalid type for content 'signed_message'. Expected 'SignedMessage'. Found '{}'.".format(
                    type(self.signed_message))
            elif self.performative == SigningMessage.Performative.ERROR:
                expected_nb_of_contents = 3
                assert (
                    type(self.skill_callback_ids) == tuple
                ), "Invalid type for content 'skill_callback_ids'. Expected 'tuple'. Found '{}'.".format(
                    type(self.skill_callback_ids))
                assert all(
                    type(element) == str for element in self.skill_callback_ids
                ), "Invalid type for tuple elements in content 'skill_callback_ids'. Expected 'str'."
                assert (
                    type(self.skill_callback_info) == dict
                ), "Invalid type for content 'skill_callback_info'. Expected 'dict'. Found '{}'.".format(
                    type(self.skill_callback_info))
                for (
                        key_of_skill_callback_info,
                        value_of_skill_callback_info,
                ) in self.skill_callback_info.items():
                    assert (
                        type(key_of_skill_callback_info) == str
                    ), "Invalid type for dictionary keys in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(key_of_skill_callback_info))
                    assert (
                        type(value_of_skill_callback_info) == str
                    ), "Invalid type for dictionary values in content 'skill_callback_info'. Expected 'str'. Found '{}'.".format(
                        type(value_of_skill_callback_info))
                assert (
                    type(self.error_code) == CustomErrorCode
                ), "Invalid type for content 'error_code'. Expected 'ErrorCode'. Found '{}'.".format(
                    type(self.error_code))

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 10
0
class FipaMessage(Message):
    """A protocol for FIPA ACL."""

    protocol_id = ProtocolId.from_str("fetchai/fipa:0.5.0")

    Description = CustomDescription

    Query = CustomQuery

    class Performative(Enum):
        """Performatives for the fipa protocol."""

        ACCEPT = "accept"
        ACCEPT_W_INFORM = "accept_w_inform"
        CFP = "cfp"
        DECLINE = "decline"
        INFORM = "inform"
        MATCH_ACCEPT = "match_accept"
        MATCH_ACCEPT_W_INFORM = "match_accept_w_inform"
        PROPOSE = "propose"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of FipaMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=FipaMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {
            "accept",
            "accept_w_inform",
            "cfp",
            "decline",
            "inform",
            "match_accept",
            "match_accept_w_inform",
            "propose",
        }

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(FipaMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def info(self) -> Dict[str, str]:
        """Get the 'info' content from the message."""
        assert self.is_set("info"), "'info' content is not set."
        return cast(Dict[str, str], self.get("info"))

    @property
    def proposal(self) -> CustomDescription:
        """Get the 'proposal' content from the message."""
        assert self.is_set("proposal"), "'proposal' content is not set."
        return cast(CustomDescription, self.get("proposal"))

    @property
    def query(self) -> CustomQuery:
        """Get the 'query' content from the message."""
        assert self.is_set("query"), "'query' content is not set."
        return cast(CustomQuery, self.get("query"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the fipa protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == FipaMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == FipaMessage.Performative.CFP:
                expected_nb_of_contents = 1
                assert (
                    type(self.query) == CustomQuery
                ), "Invalid type for content 'query'. Expected 'Query'. Found '{}'.".format(
                    type(self.query))
            elif self.performative == FipaMessage.Performative.PROPOSE:
                expected_nb_of_contents = 1
                assert (
                    type(self.proposal) == CustomDescription
                ), "Invalid type for content 'proposal'. Expected 'Description'. Found '{}'.".format(
                    type(self.proposal))
            elif self.performative == FipaMessage.Performative.ACCEPT_W_INFORM:
                expected_nb_of_contents = 1
                assert (
                    type(self.info) == dict
                ), "Invalid type for content 'info'. Expected 'dict'. Found '{}'.".format(
                    type(self.info))
                for key_of_info, value_of_info in self.info.items():
                    assert (
                        type(key_of_info) == str
                    ), "Invalid type for dictionary keys in content 'info'. Expected 'str'. Found '{}'.".format(
                        type(key_of_info))
                    assert (
                        type(value_of_info) == str
                    ), "Invalid type for dictionary values in content 'info'. Expected 'str'. Found '{}'.".format(
                        type(value_of_info))
            elif self.performative == FipaMessage.Performative.MATCH_ACCEPT_W_INFORM:
                expected_nb_of_contents = 1
                assert (
                    type(self.info) == dict
                ), "Invalid type for content 'info'. Expected 'dict'. Found '{}'.".format(
                    type(self.info))
                for key_of_info, value_of_info in self.info.items():
                    assert (
                        type(key_of_info) == str
                    ), "Invalid type for dictionary keys in content 'info'. Expected 'str'. Found '{}'.".format(
                        type(key_of_info))
                    assert (
                        type(value_of_info) == str
                    ), "Invalid type for dictionary values in content 'info'. Expected 'str'. Found '{}'.".format(
                        type(value_of_info))
            elif self.performative == FipaMessage.Performative.INFORM:
                expected_nb_of_contents = 1
                assert (
                    type(self.info) == dict
                ), "Invalid type for content 'info'. Expected 'dict'. Found '{}'.".format(
                    type(self.info))
                for key_of_info, value_of_info in self.info.items():
                    assert (
                        type(key_of_info) == str
                    ), "Invalid type for dictionary keys in content 'info'. Expected 'str'. Found '{}'.".format(
                        type(key_of_info))
                    assert (
                        type(value_of_info) == str
                    ), "Invalid type for dictionary values in content 'info'. Expected 'str'. Found '{}'.".format(
                        type(value_of_info))
            elif self.performative == FipaMessage.Performative.ACCEPT:
                expected_nb_of_contents = 0
            elif self.performative == FipaMessage.Performative.DECLINE:
                expected_nb_of_contents = 0
            elif self.performative == FipaMessage.Performative.MATCH_ACCEPT:
                expected_nb_of_contents = 0

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 11
0
class HttpMessage(Message):
    """A protocol for HTTP requests and responses."""

    protocol_id = ProtocolId.from_str("fetchai/http:0.4.0")

    class Performative(Enum):
        """Performatives for the http protocol."""

        REQUEST = "request"
        RESPONSE = "response"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of HttpMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=HttpMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {"request", "response"}

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(HttpMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def bodyy(self) -> bytes:
        """Get the 'bodyy' content from the message."""
        assert self.is_set("bodyy"), "'bodyy' content is not set."
        return cast(bytes, self.get("bodyy"))

    @property
    def headers(self) -> str:
        """Get the 'headers' content from the message."""
        assert self.is_set("headers"), "'headers' content is not set."
        return cast(str, self.get("headers"))

    @property
    def method(self) -> str:
        """Get the 'method' content from the message."""
        assert self.is_set("method"), "'method' content is not set."
        return cast(str, self.get("method"))

    @property
    def status_code(self) -> int:
        """Get the 'status_code' content from the message."""
        assert self.is_set("status_code"), "'status_code' content is not set."
        return cast(int, self.get("status_code"))

    @property
    def status_text(self) -> str:
        """Get the 'status_text' content from the message."""
        assert self.is_set("status_text"), "'status_text' content is not set."
        return cast(str, self.get("status_text"))

    @property
    def url(self) -> str:
        """Get the 'url' content from the message."""
        assert self.is_set("url"), "'url' content is not set."
        return cast(str, self.get("url"))

    @property
    def version(self) -> str:
        """Get the 'version' content from the message."""
        assert self.is_set("version"), "'version' content is not set."
        return cast(str, self.get("version"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the http protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == HttpMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == HttpMessage.Performative.REQUEST:
                expected_nb_of_contents = 5
                assert (
                    type(self.method) == str
                ), "Invalid type for content 'method'. Expected 'str'. Found '{}'.".format(
                    type(self.method))
                assert (
                    type(self.url) == str
                ), "Invalid type for content 'url'. Expected 'str'. Found '{}'.".format(
                    type(self.url))
                assert (
                    type(self.version) == str
                ), "Invalid type for content 'version'. Expected 'str'. Found '{}'.".format(
                    type(self.version))
                assert (
                    type(self.headers) == str
                ), "Invalid type for content 'headers'. Expected 'str'. Found '{}'.".format(
                    type(self.headers))
                assert (
                    type(self.bodyy) == bytes
                ), "Invalid type for content 'bodyy'. Expected 'bytes'. Found '{}'.".format(
                    type(self.bodyy))
            elif self.performative == HttpMessage.Performative.RESPONSE:
                expected_nb_of_contents = 5
                assert (
                    type(self.version) == str
                ), "Invalid type for content 'version'. Expected 'str'. Found '{}'.".format(
                    type(self.version))
                assert (
                    type(self.status_code) == int
                ), "Invalid type for content 'status_code'. Expected 'int'. Found '{}'.".format(
                    type(self.status_code))
                assert (
                    type(self.status_text) == str
                ), "Invalid type for content 'status_text'. Expected 'str'. Found '{}'.".format(
                    type(self.status_text))
                assert (
                    type(self.headers) == str
                ), "Invalid type for content 'headers'. Expected 'str'. Found '{}'.".format(
                    type(self.headers))
                assert (
                    type(self.bodyy) == bytes
                ), "Invalid type for content 'bodyy'. Expected 'bytes'. Found '{}'.".format(
                    type(self.bodyy))

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 12
0
class LedgerApiMessage(Message):
    """A protocol for ledger APIs requests and responses."""

    protocol_id = ProtocolId.from_str("fetchai/ledger_api:0.2.0")

    RawTransaction = CustomRawTransaction

    SignedTransaction = CustomSignedTransaction

    Terms = CustomTerms

    TransactionDigest = CustomTransactionDigest

    TransactionReceipt = CustomTransactionReceipt

    class Performative(Enum):
        """Performatives for the ledger_api protocol."""

        BALANCE = "balance"
        ERROR = "error"
        GET_BALANCE = "get_balance"
        GET_RAW_TRANSACTION = "get_raw_transaction"
        GET_TRANSACTION_RECEIPT = "get_transaction_receipt"
        RAW_TRANSACTION = "raw_transaction"
        SEND_SIGNED_TRANSACTION = "send_signed_transaction"
        TRANSACTION_DIGEST = "transaction_digest"
        TRANSACTION_RECEIPT = "transaction_receipt"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of LedgerApiMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=LedgerApiMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {
            "balance",
            "error",
            "get_balance",
            "get_raw_transaction",
            "get_transaction_receipt",
            "raw_transaction",
            "send_signed_transaction",
            "transaction_digest",
            "transaction_receipt",
        }

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set("dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(LedgerApiMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def address(self) -> str:
        """Get the 'address' content from the message."""
        assert self.is_set("address"), "'address' content is not set."
        return cast(str, self.get("address"))

    @property
    def balance(self) -> int:
        """Get the 'balance' content from the message."""
        assert self.is_set("balance"), "'balance' content is not set."
        return cast(int, self.get("balance"))

    @property
    def code(self) -> int:
        """Get the 'code' content from the message."""
        assert self.is_set("code"), "'code' content is not set."
        return cast(int, self.get("code"))

    @property
    def data(self) -> Optional[bytes]:
        """Get the 'data' content from the message."""
        return cast(Optional[bytes], self.get("data"))

    @property
    def ledger_id(self) -> str:
        """Get the 'ledger_id' content from the message."""
        assert self.is_set("ledger_id"), "'ledger_id' content is not set."
        return cast(str, self.get("ledger_id"))

    @property
    def message(self) -> Optional[str]:
        """Get the 'message' content from the message."""
        return cast(Optional[str], self.get("message"))

    @property
    def raw_transaction(self) -> CustomRawTransaction:
        """Get the 'raw_transaction' content from the message."""
        assert self.is_set("raw_transaction"), "'raw_transaction' content is not set."
        return cast(CustomRawTransaction, self.get("raw_transaction"))

    @property
    def signed_transaction(self) -> CustomSignedTransaction:
        """Get the 'signed_transaction' content from the message."""
        assert self.is_set(
            "signed_transaction"
        ), "'signed_transaction' content is not set."
        return cast(CustomSignedTransaction, self.get("signed_transaction"))

    @property
    def terms(self) -> CustomTerms:
        """Get the 'terms' content from the message."""
        assert self.is_set("terms"), "'terms' content is not set."
        return cast(CustomTerms, self.get("terms"))

    @property
    def transaction_digest(self) -> CustomTransactionDigest:
        """Get the 'transaction_digest' content from the message."""
        assert self.is_set(
            "transaction_digest"
        ), "'transaction_digest' content is not set."
        return cast(CustomTransactionDigest, self.get("transaction_digest"))

    @property
    def transaction_receipt(self) -> CustomTransactionReceipt:
        """Get the 'transaction_receipt' content from the message."""
        assert self.is_set(
            "transaction_receipt"
        ), "'transaction_receipt' content is not set."
        return cast(CustomTransactionReceipt, self.get("transaction_receipt"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the ledger_api protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference)
            )
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0])
            )
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1])
            )
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id)
            )
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target)
            )

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == LedgerApiMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative
            )

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == LedgerApiMessage.Performative.GET_BALANCE:
                expected_nb_of_contents = 2
                assert (
                    type(self.ledger_id) == str
                ), "Invalid type for content 'ledger_id'. Expected 'str'. Found '{}'.".format(
                    type(self.ledger_id)
                )
                assert (
                    type(self.address) == str
                ), "Invalid type for content 'address'. Expected 'str'. Found '{}'.".format(
                    type(self.address)
                )
            elif self.performative == LedgerApiMessage.Performative.GET_RAW_TRANSACTION:
                expected_nb_of_contents = 1
                assert (
                    type(self.terms) == CustomTerms
                ), "Invalid type for content 'terms'. Expected 'Terms'. Found '{}'.".format(
                    type(self.terms)
                )
            elif (
                self.performative
                == LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION
            ):
                expected_nb_of_contents = 1
                assert (
                    type(self.signed_transaction) == CustomSignedTransaction
                ), "Invalid type for content 'signed_transaction'. Expected 'SignedTransaction'. Found '{}'.".format(
                    type(self.signed_transaction)
                )
            elif (
                self.performative
                == LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT
            ):
                expected_nb_of_contents = 1
                assert (
                    type(self.transaction_digest) == CustomTransactionDigest
                ), "Invalid type for content 'transaction_digest'. Expected 'TransactionDigest'. Found '{}'.".format(
                    type(self.transaction_digest)
                )
            elif self.performative == LedgerApiMessage.Performative.BALANCE:
                expected_nb_of_contents = 2
                assert (
                    type(self.ledger_id) == str
                ), "Invalid type for content 'ledger_id'. Expected 'str'. Found '{}'.".format(
                    type(self.ledger_id)
                )
                assert (
                    type(self.balance) == int
                ), "Invalid type for content 'balance'. Expected 'int'. Found '{}'.".format(
                    type(self.balance)
                )
            elif self.performative == LedgerApiMessage.Performative.RAW_TRANSACTION:
                expected_nb_of_contents = 1
                assert (
                    type(self.raw_transaction) == CustomRawTransaction
                ), "Invalid type for content 'raw_transaction'. Expected 'RawTransaction'. Found '{}'.".format(
                    type(self.raw_transaction)
                )
            elif self.performative == LedgerApiMessage.Performative.TRANSACTION_DIGEST:
                expected_nb_of_contents = 1
                assert (
                    type(self.transaction_digest) == CustomTransactionDigest
                ), "Invalid type for content 'transaction_digest'. Expected 'TransactionDigest'. Found '{}'.".format(
                    type(self.transaction_digest)
                )
            elif self.performative == LedgerApiMessage.Performative.TRANSACTION_RECEIPT:
                expected_nb_of_contents = 1
                assert (
                    type(self.transaction_receipt) == CustomTransactionReceipt
                ), "Invalid type for content 'transaction_receipt'. Expected 'TransactionReceipt'. Found '{}'.".format(
                    type(self.transaction_receipt)
                )
            elif self.performative == LedgerApiMessage.Performative.ERROR:
                expected_nb_of_contents = 1
                assert (
                    type(self.code) == int
                ), "Invalid type for content 'code'. Expected 'int'. Found '{}'.".format(
                    type(self.code)
                )
                if self.is_set("message"):
                    expected_nb_of_contents += 1
                    message = cast(str, self.message)
                    assert (
                        type(message) == str
                    ), "Invalid type for content 'message'. Expected 'str'. Found '{}'.".format(
                        type(message)
                    )
                if self.is_set("data"):
                    expected_nb_of_contents += 1
                    data = cast(bytes, self.data)
                    assert (
                        type(data) == bytes
                    ), "Invalid type for content 'data'. Expected 'bytes'. Found '{}'.".format(
                        type(data)
                    )

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents
            )

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target
                )
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1, self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 13
0
class StateUpdateMessage(Message):
    """A protocol for state updates to the decision maker state."""

    protocol_id = ProtocolId.from_str("fetchai/state_update:0.2.0")

    class Performative(Enum):
        """Performatives for the state_update protocol."""

        APPLY = "apply"
        INITIALIZE = "initialize"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of StateUpdateMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=StateUpdateMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {"apply", "initialize"}

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(StateUpdateMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def amount_by_currency_id(self) -> Dict[str, int]:
        """Get the 'amount_by_currency_id' content from the message."""
        assert self.is_set("amount_by_currency_id"
                           ), "'amount_by_currency_id' content is not set."
        return cast(Dict[str, int], self.get("amount_by_currency_id"))

    @property
    def exchange_params_by_currency_id(self) -> Dict[str, float]:
        """Get the 'exchange_params_by_currency_id' content from the message."""
        assert self.is_set(
            "exchange_params_by_currency_id"
        ), "'exchange_params_by_currency_id' content is not set."
        return cast(Dict[str, float],
                    self.get("exchange_params_by_currency_id"))

    @property
    def quantities_by_good_id(self) -> Dict[str, int]:
        """Get the 'quantities_by_good_id' content from the message."""
        assert self.is_set("quantities_by_good_id"
                           ), "'quantities_by_good_id' content is not set."
        return cast(Dict[str, int], self.get("quantities_by_good_id"))

    @property
    def utility_params_by_good_id(self) -> Dict[str, float]:
        """Get the 'utility_params_by_good_id' content from the message."""
        assert self.is_set("utility_params_by_good_id"
                           ), "'utility_params_by_good_id' content is not set."
        return cast(Dict[str, float], self.get("utility_params_by_good_id"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the state_update protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == StateUpdateMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == StateUpdateMessage.Performative.INITIALIZE:
                expected_nb_of_contents = 4
                assert (
                    type(self.exchange_params_by_currency_id) == dict
                ), "Invalid type for content 'exchange_params_by_currency_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.exchange_params_by_currency_id))
                for (
                        key_of_exchange_params_by_currency_id,
                        value_of_exchange_params_by_currency_id,
                ) in self.exchange_params_by_currency_id.items():
                    assert (
                        type(key_of_exchange_params_by_currency_id) == str
                    ), "Invalid type for dictionary keys in content 'exchange_params_by_currency_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_exchange_params_by_currency_id))
                    assert (
                        type(value_of_exchange_params_by_currency_id) == float
                    ), "Invalid type for dictionary values in content 'exchange_params_by_currency_id'. Expected 'float'. Found '{}'.".format(
                        type(value_of_exchange_params_by_currency_id))
                assert (
                    type(self.utility_params_by_good_id) == dict
                ), "Invalid type for content 'utility_params_by_good_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.utility_params_by_good_id))
                for (
                        key_of_utility_params_by_good_id,
                        value_of_utility_params_by_good_id,
                ) in self.utility_params_by_good_id.items():
                    assert (
                        type(key_of_utility_params_by_good_id) == str
                    ), "Invalid type for dictionary keys in content 'utility_params_by_good_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_utility_params_by_good_id))
                    assert (
                        type(value_of_utility_params_by_good_id) == float
                    ), "Invalid type for dictionary values in content 'utility_params_by_good_id'. Expected 'float'. Found '{}'.".format(
                        type(value_of_utility_params_by_good_id))
                assert (
                    type(self.amount_by_currency_id) == dict
                ), "Invalid type for content 'amount_by_currency_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.amount_by_currency_id))
                for (
                        key_of_amount_by_currency_id,
                        value_of_amount_by_currency_id,
                ) in self.amount_by_currency_id.items():
                    assert (
                        type(key_of_amount_by_currency_id) == str
                    ), "Invalid type for dictionary keys in content 'amount_by_currency_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_amount_by_currency_id))
                    assert (
                        type(value_of_amount_by_currency_id) == int
                    ), "Invalid type for dictionary values in content 'amount_by_currency_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_amount_by_currency_id))
                assert (
                    type(self.quantities_by_good_id) == dict
                ), "Invalid type for content 'quantities_by_good_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.quantities_by_good_id))
                for (
                        key_of_quantities_by_good_id,
                        value_of_quantities_by_good_id,
                ) in self.quantities_by_good_id.items():
                    assert (
                        type(key_of_quantities_by_good_id) == str
                    ), "Invalid type for dictionary keys in content 'quantities_by_good_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_quantities_by_good_id))
                    assert (
                        type(value_of_quantities_by_good_id) == int
                    ), "Invalid type for dictionary values in content 'quantities_by_good_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_quantities_by_good_id))
            elif self.performative == StateUpdateMessage.Performative.APPLY:
                expected_nb_of_contents = 2
                assert (
                    type(self.amount_by_currency_id) == dict
                ), "Invalid type for content 'amount_by_currency_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.amount_by_currency_id))
                for (
                        key_of_amount_by_currency_id,
                        value_of_amount_by_currency_id,
                ) in self.amount_by_currency_id.items():
                    assert (
                        type(key_of_amount_by_currency_id) == str
                    ), "Invalid type for dictionary keys in content 'amount_by_currency_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_amount_by_currency_id))
                    assert (
                        type(value_of_amount_by_currency_id) == int
                    ), "Invalid type for dictionary values in content 'amount_by_currency_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_amount_by_currency_id))
                assert (
                    type(self.quantities_by_good_id) == dict
                ), "Invalid type for content 'quantities_by_good_id'. Expected 'dict'. Found '{}'.".format(
                    type(self.quantities_by_good_id))
                for (
                        key_of_quantities_by_good_id,
                        value_of_quantities_by_good_id,
                ) in self.quantities_by_good_id.items():
                    assert (
                        type(key_of_quantities_by_good_id) == str
                    ), "Invalid type for dictionary keys in content 'quantities_by_good_id'. Expected 'str'. Found '{}'.".format(
                        type(key_of_quantities_by_good_id))
                    assert (
                        type(value_of_quantities_by_good_id) == int
                    ), "Invalid type for dictionary values in content 'quantities_by_good_id'. Expected 'int'. Found '{}'.".format(
                        type(value_of_quantities_by_good_id))

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 14
0
class DefaultMessage(Message):
    """A protocol for exchanging any bytes message."""

    protocol_id = ProtocolId.from_str("fetchai/default:0.4.0")

    ErrorCode = CustomErrorCode

    class Performative(Enum):
        """Performatives for the default protocol."""

        BYTES = "bytes"
        ERROR = "error"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of DefaultMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=DefaultMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {"bytes", "error"}

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(DefaultMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def content(self) -> bytes:
        """Get the 'content' content from the message."""
        assert self.is_set("content"), "'content' content is not set."
        return cast(bytes, self.get("content"))

    @property
    def error_code(self) -> CustomErrorCode:
        """Get the 'error_code' content from the message."""
        assert self.is_set("error_code"), "'error_code' content is not set."
        return cast(CustomErrorCode, self.get("error_code"))

    @property
    def error_data(self) -> Dict[str, bytes]:
        """Get the 'error_data' content from the message."""
        assert self.is_set("error_data"), "'error_data' content is not set."
        return cast(Dict[str, bytes], self.get("error_data"))

    @property
    def error_msg(self) -> str:
        """Get the 'error_msg' content from the message."""
        assert self.is_set("error_msg"), "'error_msg' content is not set."
        return cast(str, self.get("error_msg"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the default protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == DefaultMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == DefaultMessage.Performative.BYTES:
                expected_nb_of_contents = 1
                assert (
                    type(self.content) == bytes
                ), "Invalid type for content 'content'. Expected 'bytes'. Found '{}'.".format(
                    type(self.content))
            elif self.performative == DefaultMessage.Performative.ERROR:
                expected_nb_of_contents = 3
                assert (
                    type(self.error_code) == CustomErrorCode
                ), "Invalid type for content 'error_code'. Expected 'ErrorCode'. Found '{}'.".format(
                    type(self.error_code))
                assert (
                    type(self.error_msg) == str
                ), "Invalid type for content 'error_msg'. Expected 'str'. Found '{}'.".format(
                    type(self.error_msg))
                assert (
                    type(self.error_data) == dict
                ), "Invalid type for content 'error_data'. Expected 'dict'. Found '{}'.".format(
                    type(self.error_data))
                for key_of_error_data, value_of_error_data in self.error_data.items(
                ):
                    assert (
                        type(key_of_error_data) == str
                    ), "Invalid type for dictionary keys in content 'error_data'. Expected 'str'. Found '{}'.".format(
                        type(key_of_error_data))
                    assert (
                        type(value_of_error_data) == bytes
                    ), "Invalid type for dictionary values in content 'error_data'. Expected 'bytes'. Found '{}'.".format(
                        type(value_of_error_data))

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 15
0
class ContractApiMessage(Message):
    """A protocol for contract APIs requests and responses."""

    protocol_id = ProtocolId.from_str("fetchai/contract_api:0.2.0")

    Kwargs = CustomKwargs

    RawMessage = CustomRawMessage

    RawTransaction = CustomRawTransaction

    State = CustomState

    class Performative(Enum):
        """Performatives for the contract_api protocol."""

        ERROR = "error"
        GET_DEPLOY_TRANSACTION = "get_deploy_transaction"
        GET_RAW_MESSAGE = "get_raw_message"
        GET_RAW_TRANSACTION = "get_raw_transaction"
        GET_STATE = "get_state"
        RAW_MESSAGE = "raw_message"
        RAW_TRANSACTION = "raw_transaction"
        STATE = "state"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of ContractApiMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=ContractApiMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {
            "error",
            "get_deploy_transaction",
            "get_raw_message",
            "get_raw_transaction",
            "get_state",
            "raw_message",
            "raw_transaction",
            "state",
        }

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set("dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(ContractApiMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def callable(self) -> str:
        """Get the 'callable' content from the message."""
        assert self.is_set("callable"), "'callable' content is not set."
        return cast(str, self.get("callable"))

    @property
    def code(self) -> Optional[int]:
        """Get the 'code' content from the message."""
        return cast(Optional[int], self.get("code"))

    @property
    def contract_address(self) -> str:
        """Get the 'contract_address' content from the message."""
        assert self.is_set("contract_address"), "'contract_address' content is not set."
        return cast(str, self.get("contract_address"))

    @property
    def contract_id(self) -> str:
        """Get the 'contract_id' content from the message."""
        assert self.is_set("contract_id"), "'contract_id' content is not set."
        return cast(str, self.get("contract_id"))

    @property
    def data(self) -> bytes:
        """Get the 'data' content from the message."""
        assert self.is_set("data"), "'data' content is not set."
        return cast(bytes, self.get("data"))

    @property
    def kwargs(self) -> CustomKwargs:
        """Get the 'kwargs' content from the message."""
        assert self.is_set("kwargs"), "'kwargs' content is not set."
        return cast(CustomKwargs, self.get("kwargs"))

    @property
    def ledger_id(self) -> str:
        """Get the 'ledger_id' content from the message."""
        assert self.is_set("ledger_id"), "'ledger_id' content is not set."
        return cast(str, self.get("ledger_id"))

    @property
    def message(self) -> Optional[str]:
        """Get the 'message' content from the message."""
        return cast(Optional[str], self.get("message"))

    @property
    def raw_message(self) -> CustomRawMessage:
        """Get the 'raw_message' content from the message."""
        assert self.is_set("raw_message"), "'raw_message' content is not set."
        return cast(CustomRawMessage, self.get("raw_message"))

    @property
    def raw_transaction(self) -> CustomRawTransaction:
        """Get the 'raw_transaction' content from the message."""
        assert self.is_set("raw_transaction"), "'raw_transaction' content is not set."
        return cast(CustomRawTransaction, self.get("raw_transaction"))

    @property
    def state(self) -> CustomState:
        """Get the 'state' content from the message."""
        assert self.is_set("state"), "'state' content is not set."
        return cast(CustomState, self.get("state"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the contract_api protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference)
            )
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0])
            )
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1])
            )
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id)
            )
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target)
            )

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == ContractApiMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative
            )

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if (
                self.performative
                == ContractApiMessage.Performative.GET_DEPLOY_TRANSACTION
            ):
                expected_nb_of_contents = 4
                assert (
                    type(self.ledger_id) == str
                ), "Invalid type for content 'ledger_id'. Expected 'str'. Found '{}'.".format(
                    type(self.ledger_id)
                )
                assert (
                    type(self.contract_id) == str
                ), "Invalid type for content 'contract_id'. Expected 'str'. Found '{}'.".format(
                    type(self.contract_id)
                )
                assert (
                    type(self.callable) == str
                ), "Invalid type for content 'callable'. Expected 'str'. Found '{}'.".format(
                    type(self.callable)
                )
                assert (
                    type(self.kwargs) == CustomKwargs
                ), "Invalid type for content 'kwargs'. Expected 'Kwargs'. Found '{}'.".format(
                    type(self.kwargs)
                )
            elif (
                self.performative == ContractApiMessage.Performative.GET_RAW_TRANSACTION
            ):
                expected_nb_of_contents = 5
                assert (
                    type(self.ledger_id) == str
                ), "Invalid type for content 'ledger_id'. Expected 'str'. Found '{}'.".format(
                    type(self.ledger_id)
                )
                assert (
                    type(self.contract_id) == str
                ), "Invalid type for content 'contract_id'. Expected 'str'. Found '{}'.".format(
                    type(self.contract_id)
                )
                assert (
                    type(self.contract_address) == str
                ), "Invalid type for content 'contract_address'. Expected 'str'. Found '{}'.".format(
                    type(self.contract_address)
                )
                assert (
                    type(self.callable) == str
                ), "Invalid type for content 'callable'. Expected 'str'. Found '{}'.".format(
                    type(self.callable)
                )
                assert (
                    type(self.kwargs) == CustomKwargs
                ), "Invalid type for content 'kwargs'. Expected 'Kwargs'. Found '{}'.".format(
                    type(self.kwargs)
                )
            elif self.performative == ContractApiMessage.Performative.GET_RAW_MESSAGE:
                expected_nb_of_contents = 5
                assert (
                    type(self.ledger_id) == str
                ), "Invalid type for content 'ledger_id'. Expected 'str'. Found '{}'.".format(
                    type(self.ledger_id)
                )
                assert (
                    type(self.contract_id) == str
                ), "Invalid type for content 'contract_id'. Expected 'str'. Found '{}'.".format(
                    type(self.contract_id)
                )
                assert (
                    type(self.contract_address) == str
                ), "Invalid type for content 'contract_address'. Expected 'str'. Found '{}'.".format(
                    type(self.contract_address)
                )
                assert (
                    type(self.callable) == str
                ), "Invalid type for content 'callable'. Expected 'str'. Found '{}'.".format(
                    type(self.callable)
                )
                assert (
                    type(self.kwargs) == CustomKwargs
                ), "Invalid type for content 'kwargs'. Expected 'Kwargs'. Found '{}'.".format(
                    type(self.kwargs)
                )
            elif self.performative == ContractApiMessage.Performative.GET_STATE:
                expected_nb_of_contents = 5
                assert (
                    type(self.ledger_id) == str
                ), "Invalid type for content 'ledger_id'. Expected 'str'. Found '{}'.".format(
                    type(self.ledger_id)
                )
                assert (
                    type(self.contract_id) == str
                ), "Invalid type for content 'contract_id'. Expected 'str'. Found '{}'.".format(
                    type(self.contract_id)
                )
                assert (
                    type(self.contract_address) == str
                ), "Invalid type for content 'contract_address'. Expected 'str'. Found '{}'.".format(
                    type(self.contract_address)
                )
                assert (
                    type(self.callable) == str
                ), "Invalid type for content 'callable'. Expected 'str'. Found '{}'.".format(
                    type(self.callable)
                )
                assert (
                    type(self.kwargs) == CustomKwargs
                ), "Invalid type for content 'kwargs'. Expected 'Kwargs'. Found '{}'.".format(
                    type(self.kwargs)
                )
            elif self.performative == ContractApiMessage.Performative.STATE:
                expected_nb_of_contents = 1
                assert (
                    type(self.state) == CustomState
                ), "Invalid type for content 'state'. Expected 'State'. Found '{}'.".format(
                    type(self.state)
                )
            elif self.performative == ContractApiMessage.Performative.RAW_TRANSACTION:
                expected_nb_of_contents = 1
                assert (
                    type(self.raw_transaction) == CustomRawTransaction
                ), "Invalid type for content 'raw_transaction'. Expected 'RawTransaction'. Found '{}'.".format(
                    type(self.raw_transaction)
                )
            elif self.performative == ContractApiMessage.Performative.RAW_MESSAGE:
                expected_nb_of_contents = 1
                assert (
                    type(self.raw_message) == CustomRawMessage
                ), "Invalid type for content 'raw_message'. Expected 'RawMessage'. Found '{}'.".format(
                    type(self.raw_message)
                )
            elif self.performative == ContractApiMessage.Performative.ERROR:
                expected_nb_of_contents = 1
                if self.is_set("code"):
                    expected_nb_of_contents += 1
                    code = cast(int, self.code)
                    assert (
                        type(code) == int
                    ), "Invalid type for content 'code'. Expected 'int'. Found '{}'.".format(
                        type(code)
                    )
                if self.is_set("message"):
                    expected_nb_of_contents += 1
                    message = cast(str, self.message)
                    assert (
                        type(message) == str
                    ), "Invalid type for content 'message'. Expected 'str'. Found '{}'.".format(
                        type(message)
                    )
                assert (
                    type(self.data) == bytes
                ), "Invalid type for content 'data'. Expected 'bytes'. Found '{}'.".format(
                    type(self.data)
                )

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents
            )

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target
                )
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1, self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True
Ejemplo n.º 16
0
class OefSearchMessage(Message):
    """A protocol for interacting with an OEF search service."""

    protocol_id = ProtocolId.from_str("fetchai/oef_search:0.4.0")

    Description = CustomDescription

    OefErrorOperation = CustomOefErrorOperation

    Query = CustomQuery

    class Performative(Enum):
        """Performatives for the oef_search protocol."""

        OEF_ERROR = "oef_error"
        REGISTER_SERVICE = "register_service"
        SEARCH_RESULT = "search_result"
        SEARCH_SERVICES = "search_services"
        UNREGISTER_SERVICE = "unregister_service"

        def __str__(self):
            """Get the string representation."""
            return str(self.value)

    def __init__(
        self,
        performative: Performative,
        dialogue_reference: Tuple[str, str] = ("", ""),
        message_id: int = 1,
        target: int = 0,
        **kwargs,
    ):
        """
        Initialise an instance of OefSearchMessage.

        :param message_id: the message id.
        :param dialogue_reference: the dialogue reference.
        :param target: the message target.
        :param performative: the message performative.
        """
        super().__init__(
            dialogue_reference=dialogue_reference,
            message_id=message_id,
            target=target,
            performative=OefSearchMessage.Performative(performative),
            **kwargs,
        )
        self._performatives = {
            "oef_error",
            "register_service",
            "search_result",
            "search_services",
            "unregister_service",
        }

    @property
    def valid_performatives(self) -> Set[str]:
        """Get valid performatives."""
        return self._performatives

    @property
    def dialogue_reference(self) -> Tuple[str, str]:
        """Get the dialogue_reference of the message."""
        assert self.is_set(
            "dialogue_reference"), "dialogue_reference is not set."
        return cast(Tuple[str, str], self.get("dialogue_reference"))

    @property
    def message_id(self) -> int:
        """Get the message_id of the message."""
        assert self.is_set("message_id"), "message_id is not set."
        return cast(int, self.get("message_id"))

    @property
    def performative(self) -> Performative:  # type: ignore # noqa: F821
        """Get the performative of the message."""
        assert self.is_set("performative"), "performative is not set."
        return cast(OefSearchMessage.Performative, self.get("performative"))

    @property
    def target(self) -> int:
        """Get the target of the message."""
        assert self.is_set("target"), "target is not set."
        return cast(int, self.get("target"))

    @property
    def agents(self) -> Tuple[str, ...]:
        """Get the 'agents' content from the message."""
        assert self.is_set("agents"), "'agents' content is not set."
        return cast(Tuple[str, ...], self.get("agents"))

    @property
    def oef_error_operation(self) -> CustomOefErrorOperation:
        """Get the 'oef_error_operation' content from the message."""
        assert self.is_set(
            "oef_error_operation"), "'oef_error_operation' content is not set."
        return cast(CustomOefErrorOperation, self.get("oef_error_operation"))

    @property
    def query(self) -> CustomQuery:
        """Get the 'query' content from the message."""
        assert self.is_set("query"), "'query' content is not set."
        return cast(CustomQuery, self.get("query"))

    @property
    def service_description(self) -> CustomDescription:
        """Get the 'service_description' content from the message."""
        assert self.is_set(
            "service_description"), "'service_description' content is not set."
        return cast(CustomDescription, self.get("service_description"))

    def _is_consistent(self) -> bool:
        """Check that the message follows the oef_search protocol."""
        try:
            assert (
                type(self.dialogue_reference) == tuple
            ), "Invalid type for 'dialogue_reference'. Expected 'tuple'. Found '{}'.".format(
                type(self.dialogue_reference))
            assert (
                type(self.dialogue_reference[0]) == str
            ), "Invalid type for 'dialogue_reference[0]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[0]))
            assert (
                type(self.dialogue_reference[1]) == str
            ), "Invalid type for 'dialogue_reference[1]'. Expected 'str'. Found '{}'.".format(
                type(self.dialogue_reference[1]))
            assert (
                type(self.message_id) == int
            ), "Invalid type for 'message_id'. Expected 'int'. Found '{}'.".format(
                type(self.message_id))
            assert (
                type(self.target) == int
            ), "Invalid type for 'target'. Expected 'int'. Found '{}'.".format(
                type(self.target))

            # Light Protocol Rule 2
            # Check correct performative
            assert (
                type(self.performative) == OefSearchMessage.Performative
            ), "Invalid 'performative'. Expected either of '{}'. Found '{}'.".format(
                self.valid_performatives, self.performative)

            # Check correct contents
            actual_nb_of_contents = len(self.body) - DEFAULT_BODY_SIZE
            expected_nb_of_contents = 0
            if self.performative == OefSearchMessage.Performative.REGISTER_SERVICE:
                expected_nb_of_contents = 1
                assert (
                    type(self.service_description) == CustomDescription
                ), "Invalid type for content 'service_description'. Expected 'Description'. Found '{}'.".format(
                    type(self.service_description))
            elif self.performative == OefSearchMessage.Performative.UNREGISTER_SERVICE:
                expected_nb_of_contents = 1
                assert (
                    type(self.service_description) == CustomDescription
                ), "Invalid type for content 'service_description'. Expected 'Description'. Found '{}'.".format(
                    type(self.service_description))
            elif self.performative == OefSearchMessage.Performative.SEARCH_SERVICES:
                expected_nb_of_contents = 1
                assert (
                    type(self.query) == CustomQuery
                ), "Invalid type for content 'query'. Expected 'Query'. Found '{}'.".format(
                    type(self.query))
            elif self.performative == OefSearchMessage.Performative.SEARCH_RESULT:
                expected_nb_of_contents = 1
                assert (
                    type(self.agents) == tuple
                ), "Invalid type for content 'agents'. Expected 'tuple'. Found '{}'.".format(
                    type(self.agents))
                assert all(
                    type(element) == str for element in self.agents
                ), "Invalid type for tuple elements in content 'agents'. Expected 'str'."
            elif self.performative == OefSearchMessage.Performative.OEF_ERROR:
                expected_nb_of_contents = 1
                assert (
                    type(self.oef_error_operation) == CustomOefErrorOperation
                ), "Invalid type for content 'oef_error_operation'. Expected 'OefErrorOperation'. Found '{}'.".format(
                    type(self.oef_error_operation))

            # Check correct content count
            assert (
                expected_nb_of_contents == actual_nb_of_contents
            ), "Incorrect number of contents. Expected {}. Found {}".format(
                expected_nb_of_contents, actual_nb_of_contents)

            # Light Protocol Rule 3
            if self.message_id == 1:
                assert (
                    self.target == 0
                ), "Invalid 'target'. Expected 0 (because 'message_id' is 1). Found {}.".format(
                    self.target)
            else:
                assert (
                    0 < self.target < self.message_id
                ), "Invalid 'target'. Expected an integer between 1 and {} inclusive. Found {}.".format(
                    self.message_id - 1,
                    self.target,
                )
        except (AssertionError, ValueError, KeyError) as e:
            logger.error(str(e))
            return False

        return True