Esempio n. 1
0
    def _on_transaction(self, tac_msg: TacMessage,
                        tac_dialogue: TacDialogue) -> None:
        """
        Handle a transaction TacMessage message.

        If the transaction is invalid (e.g. because the state of the game are not consistent), reply with an error.

        :param tac_msg: the tac message
        :param tac_dialogue: the tac dialogue
        :return: None
        """
        game = cast(Game, self.context.game)
        if not game.phase == Phase.GAME:
            self.context.logger.warning(
                "received transaction outside of game phase: '{}'".format(
                    tac_msg))
            return

        transaction = Transaction.from_message(tac_msg)
        self.context.logger.debug(
            "handling transaction: {}".format(transaction))

        game = cast(Game, self.context.game)
        if game.is_transaction_valid(transaction):
            self._handle_valid_transaction(tac_msg, tac_dialogue, transaction)
        else:
            self._handle_invalid_transaction(tac_msg, tac_dialogue)
Esempio n. 2
0
    def _on_transaction(self, message: TACMessage) -> None:
        """
        Handle a transaction TACMessage message.

        If the transaction is invalid (e.g. because the state of the game are not consistent), reply with an error.

        :param message: the 'get agent state' TACMessage.
        :return: None
        """
        transaction = Transaction.from_message(message)
        self.context.logger.debug("[{}]: Handling transaction: {}".format(
            self.context.agent_name, transaction))

        game = cast(Game, self.context.game)
        if game.is_transaction_valid(transaction):
            self._handle_valid_transaction(message, transaction)
        else:
            self._handle_invalid_transaction(message)
Esempio n. 3
0
    def test_on_transaction_invalid(self):
        """Test the _on_transaction method of the tac handler where the transaction is invalid."""
        # setup
        self.game._phase = Phase.GAME

        tac_participant_sender = COUNTERPARTY_ADDRESS
        tac_participant_counterparty = "counterparties_counterparty"

        self_dialogue = self.prepare_skill_dialogue(
            self.tac_dialogues,
            self.list_of_messages[:2],
        )

        ledger_id = "some_ledger"
        good_ids = ["G1"]
        nonce = "some_nonce"
        amount_by_currency_id = {"FET": 1}
        quantities_by_good_id = {"G1": 1}
        tx_id = Transaction.get_hash(
            ledger_id=ledger_id,
            sender_address=tac_participant_sender,
            counterparty_address=tac_participant_counterparty,
            good_ids=good_ids,
            sender_supplied_quantities=[1],
            counterparty_supplied_quantities=[0],
            sender_payable_amount=0,
            counterparty_payable_amount=1,
            nonce=nonce,
        )
        incoming_message = cast(
            TacMessage,
            self.build_incoming_message_for_skill_dialogue(
                dialogue=self_dialogue,
                performative=TacMessage.Performative.TRANSACTION,
                transaction_id=tx_id,
                ledger_id=ledger_id,
                sender_address=tac_participant_sender,
                counterparty_address=tac_participant_counterparty,
                amount_by_currency_id=amount_by_currency_id,
                fee_by_currency_id={"FET": 2},
                quantities_by_good_id=quantities_by_good_id,
                nonce=nonce,
                sender_signature="some_signature",
                counterparty_signature="some_other_signature",
            ),
        )
        tx = Transaction.from_message(incoming_message)

        # operation
        with patch.object(self.game,
                          "is_transaction_valid",
                          return_value=False):
            with patch.object(self.tac_handler.context.logger,
                              "log") as mock_logger:
                self.tac_handler.handle(incoming_message)

        # after
        self.assert_quantity_in_outbox(1)

        # _on_transaction
        mock_logger.assert_any_call(logging.DEBUG,
                                    f"handling transaction: {tx}")

        # _handle_invalid_transaction
        mock_logger.assert_any_call(
            logging.INFO,
            f"handling invalid transaction: {tx_id}, tac_msg={incoming_message}",
        )

        has_attributes, error_str = self.message_has_attributes(
            actual_message=self.get_message_from_outbox(),
            message_type=TacMessage,
            performative=TacMessage.Performative.TAC_ERROR,
            to=tac_participant_sender,
            sender=self.skill.skill_context.agent_address,
            target=incoming_message.message_id,
            error_code=TacMessage.ErrorCode.TRANSACTION_NOT_VALID,
            info={"transaction_id": tx_id},
        )
        assert has_attributes, error_str
Esempio n. 4
0
    def test_handle_valid_transaction_no_last_message(self):
        """Test the _handle_valid_transaction method of the tac handler where the recovered dialogue is empty."""
        # setup
        self.game._phase = Phase.GAME

        tac_participant_sender = COUNTERPARTY_ADDRESS
        tac_participant_counterparty = "counterparties_counterparty"

        counterparty_dialogue = self.prepare_skill_dialogue(
            self.tac_dialogues, self.list_of_messages[:2],
            tac_participant_counterparty)
        self_dialogue = self.prepare_skill_dialogue(
            self.tac_dialogues,
            self.list_of_messages[:2],
        )
        counterparty_dialogue._incoming_messages = []
        counterparty_dialogue._outgoing_messages = []

        ledger_id = "some_ledger"
        good_ids = ["G1"]
        nonce = "some_nonce"
        amount_by_currency_id = {"FET": 1}
        quantities_by_good_id = {"G1": 1}
        tx_id = Transaction.get_hash(
            ledger_id=ledger_id,
            sender_address=tac_participant_sender,
            counterparty_address=tac_participant_counterparty,
            good_ids=good_ids,
            sender_supplied_quantities=[1],
            counterparty_supplied_quantities=[0],
            sender_payable_amount=0,
            counterparty_payable_amount=1,
            nonce=nonce,
        )
        incoming_message = cast(
            TacMessage,
            self.build_incoming_message_for_skill_dialogue(
                dialogue=self_dialogue,
                performative=TacMessage.Performative.TRANSACTION,
                transaction_id=tx_id,
                ledger_id=ledger_id,
                sender_address=tac_participant_sender,
                counterparty_address=tac_participant_counterparty,
                amount_by_currency_id=amount_by_currency_id,
                fee_by_currency_id={"FET": 2},
                quantities_by_good_id=quantities_by_good_id,
                nonce=nonce,
                sender_signature="some_signature",
                counterparty_signature="some_other_signature",
            ),
        )
        tx = Transaction.from_message(incoming_message)

        mocked_holdings_summary = "some_holdings_summary"

        # operation
        with patch.object(
                type(self.game),
                "holdings_summary",
                new_callable=PropertyMock,
                return_value=mocked_holdings_summary,
        ):
            with patch.object(self.game,
                              "is_transaction_valid",
                              return_value=True):
                with patch.object(self.game, "settle_transaction"):
                    with patch.object(self.tac_handler.context.logger,
                                      "log") as mock_logger:
                        with pytest.raises(
                                ValueError,
                                match="Error when retrieving last message."):
                            self.tac_handler.handle(incoming_message)

        # after
        self.assert_quantity_in_outbox(1)

        # _on_transaction
        mock_logger.assert_any_call(logging.DEBUG,
                                    f"handling transaction: {tx}")

        # _handle_valid_transaction
        mock_logger.assert_any_call(
            logging.INFO, f"handling valid transaction: {tx_id[-10:]}")
        has_attributes, error_str = self.message_has_attributes(
            actual_message=self.get_message_from_outbox(),
            message_type=TacMessage,
            performative=TacMessage.Performative.TRANSACTION_CONFIRMATION,
            to=tac_participant_sender,
            sender=self.skill.skill_context.agent_address,
            target=incoming_message.message_id,
            transaction_id=tx_id,
            amount_by_currency_id=amount_by_currency_id,
            quantities_by_good_id=quantities_by_good_id,
        )
        assert has_attributes, error_str