示例#1
0
    def _handle_valid_transaction(
        self, tac_msg: TacMessage, tac_dialogue: TacDialogue, transaction: Transaction
    ) -> None:
        """
        Handle a valid transaction.

        That is:
        - update the game state
        - send a transaction confirmation both to the buyer and the seller.

        :param transaction: the transaction.
        :return: None
        """
        game = cast(Game, self.context.game)
        self.context.logger.info(
            "handling valid transaction: {}".format(transaction.id[-10:])
        )
        game.settle_transaction(transaction)

        # send the transaction confirmation.
        sender_tac_msg = TacMessage(
            performative=TacMessage.Performative.TRANSACTION_CONFIRMATION,
            dialogue_reference=tac_dialogue.dialogue_label.dialogue_reference,
            transaction_id=transaction.sender_hash,
            amount_by_currency_id=transaction.amount_by_currency_id,
            quantities_by_good_id=transaction.quantities_by_good_id,
            message_id=tac_msg.message_id + 1,
            target=tac_msg.message_id,
        )
        sender_tac_msg.counterparty = transaction.sender_address
        assert tac_dialogue.update(sender_tac_msg)
        self.context.outbox.put_message(message=sender_tac_msg)

        tac_dialogues = cast(TacDialogues, self.context.tac_dialogues)
        recovered_tac_dialogue = tac_dialogues.dialogue_by_address.get(
            transaction.counterparty_address, None
        )
        assert recovered_tac_dialogue is not None, "Error when retrieving dialogue."
        last_msg = recovered_tac_dialogue.last_message
        assert last_msg is not None, "Error when retrieving last message."
        counterparty_tac_msg = TacMessage(
            performative=TacMessage.Performative.TRANSACTION_CONFIRMATION,
            dialogue_reference=recovered_tac_dialogue.dialogue_label.dialogue_reference,
            transaction_id=transaction.counterparty_hash,
            amount_by_currency_id=transaction.amount_by_currency_id,
            quantities_by_good_id=transaction.quantities_by_good_id,
            message_id=last_msg.message_id + 1,
            target=last_msg.message_id,
        )
        counterparty_tac_msg.counterparty = transaction.counterparty_address
        assert recovered_tac_dialogue.update(counterparty_tac_msg)
        self.context.outbox.put_message(message=counterparty_tac_msg)

        # log messages
        self.context.logger.info(
            "transaction '{}' settled successfully.".format(transaction.id[-10:])
        )
        self.context.logger.info("current state:\n{}".format(game.holdings_summary))
示例#2
0
    def _on_register(self, message: TacMessage) -> None:
        """
        Handle a register message.

        If the address is not registered, answer with an error message.

        :param message: the 'get agent state' TacMessage.
        :return: None
        """
        parameters = cast(Parameters, self.context.parameters)
        agent_name = message.agent_name
        if len(parameters.whitelist
               ) != 0 and agent_name not in parameters.whitelist:
            self.context.logger.warning(
                "[{}]: Agent name not in whitelist: '{}'".format(
                    self.context.agent_name, agent_name))
            tac_msg = TacMessage(
                performative=TacMessage.Performative.TAC_ERROR,
                error_code=TacMessage.ErrorCode.AGENT_NAME_NOT_IN_WHITELIST,
            )
            tac_msg.counterparty = message.counterparty
            self.context.outbox.put_message(message=tac_msg)
            return

        game = cast(Game, self.context.game)
        if message.counterparty in game.registration.agent_addr_to_name:
            self.context.logger.warning(
                "[{}]: Agent already registered: '{}'".format(
                    self.context.agent_name,
                    game.registration.agent_addr_to_name[message.counterparty],
                ))
            tac_msg = TacMessage(
                performative=TacMessage.Performative.TAC_ERROR,
                error_code=TacMessage.ErrorCode.AGENT_ADDR_ALREADY_REGISTERED,
            )
            tac_msg.counterparty = message.counterparty
            self.context.outbox.put_message(message=tac_msg)

        if agent_name in game.registration.agent_addr_to_name.values():
            self.context.logger.warning(
                "[{}]: Agent with this name already registered: '{}'".format(
                    self.context.agent_name, agent_name))
            tac_msg = TacMessage(
                performative=TacMessage.Performative.TAC_ERROR,
                error_code=TacMessage.ErrorCode.AGENT_NAME_ALREADY_REGISTERED,
            )
            tac_msg.counterparty = message.counterparty
            self.context.outbox.put_message(message=tac_msg)

        game.registration.register_agent(message.counterparty, agent_name)
        self.context.logger.info("[{}]: Agent registered: '{}'".format(
            self.context.agent_name, agent_name))
示例#3
0
    def _cancel_tac(self):
        """Notify agents that the TAC is cancelled."""
        game = cast(Game, self.context.game)
        self.context.logger.info(
            "[{}]: Notifying agents that TAC is cancelled.".format(
                self.context.agent_name
            )
        )
        for agent_addr in game.registration.agent_addr_to_name.keys():
            tac_msg = TacMessage(performative=TacMessage.Performative.CANCELLED)
            tac_msg.counterparty = agent_addr
            self.context.outbox.put_message(message=tac_msg)
        if game.phase == Phase.GAME:
            self.context.logger.info(
                "[{}]: Finished competition:\n{}".format(
                    self.context.agent_name, game.holdings_summary
                )
            )
            self.context.logger.info(
                "[{}]: Computed equilibrium:\n{}".format(
                    self.context.agent_name, game.equilibrium_summary
                )
            )

            self.context.is_active = False
示例#4
0
    def _on_unregister(self, message: TacMessage) -> None:
        """
        Handle a unregister message.

        If the address is not registered, answer with an error message.

        :param message: the 'get agent state' TacMessage.
        :return: None
        """
        game = cast(Game, self.context.game)
        if message.counterparty not in game.registration.agent_addr_to_name:
            self.context.logger.warning(
                "agent not registered: '{}'".format(message.counterparty)
            )
            tac_msg = TacMessage(
                performative=TacMessage.Performative.TAC_ERROR,
                error_code=TacMessage.ErrorCode.AGENT_NOT_REGISTERED,
            )
            tac_msg.counterparty = message.counterparty
            self.context.outbox.put_message(message=tac_msg)
        else:
            self.context.logger.debug(
                "agent unregistered: '{}'".format(
                    game.conf.agent_addr_to_name[message.counterparty],
                )
            )
            game.registration.unregister_agent(message.counterparty)
示例#5
0
 def _start_tac(self, game: Game) -> None:
     """Create a game and send the game configuration to every registered agent."""
     self.context.logger.info(
         "starting competition with configuration:\n{}".format(
             game.holdings_summary))
     self.context.logger.info(
         "computed theoretical equilibrium:\n{}".format(
             game.equilibrium_summary))
     for agent_address in game.conf.agent_addr_to_name.keys():
         agent_state = game.current_agent_states[agent_address]
         tac_msg = TacMessage(
             performative=TacMessage.Performative.GAME_DATA,
             amount_by_currency_id=agent_state.amount_by_currency_id,
             exchange_params_by_currency_id=agent_state.
             exchange_params_by_currency_id,
             quantities_by_good_id=agent_state.quantities_by_good_id,
             utility_params_by_good_id=agent_state.
             utility_params_by_good_id,
             tx_fee=game.conf.tx_fee,
             agent_addr_to_name=game.conf.agent_addr_to_name,
             good_id_to_name=game.conf.good_id_to_name,
             currency_id_to_name=game.conf.currency_id_to_name,
             version_id=game.conf.version_id,
             info={"contract_address": game.conf.contract_address},
         )
         self.context.logger.debug(
             "sending game data to '{}'.".format(agent_address))
         self.context.logger.debug("game data={}".format(str(tac_msg)))
         tac_msg.counterparty = agent_address
         self.context.outbox.put_message(message=tac_msg)
示例#6
0
 def _cancel_tac(self, game: Game):
     """Notify agents that the TAC is cancelled."""
     self.context.logger.info("notifying agents that TAC is cancelled.")
     tac_dialogues = cast(TacDialogues, self.context.tac_dialogues)
     for agent_address in game.registration.agent_addr_to_name.keys():
         tac_dialogue = tac_dialogues.dialogue_by_address.get(
             agent_address, None)
         assert tac_dialogue is not None, "Error when retrieving dialogue."
         last_msg = tac_dialogue.last_message
         assert last_msg is not None, "Error when retrieving last message."
         tac_msg = TacMessage(
             performative=TacMessage.Performative.CANCELLED,
             dialogue_reference=tac_dialogue.dialogue_label.
             dialogue_reference,
             message_id=last_msg.message_id + 1,
             target=last_msg.message_id,
         )
         tac_msg.counterparty = agent_address
         tac_dialogues.update(tac_msg)
         self.context.outbox.put_message(message=tac_msg)
     if game.phase == Phase.GAME:
         self.context.logger.info("finished competition:\n{}".format(
             game.holdings_summary))
         self.context.logger.info("computed equilibrium:\n{}".format(
             game.equilibrium_summary))
         self.context.is_active = False
示例#7
0
 def _start_tac(self):
     """Create a game and send the game configuration to every registered agent."""
     game = cast(Game, self.context.game)
     game.create()
     self.context.logger.info(
         "[{}]: Started competition:\n{}".format(
             self.context.agent_name, game.holdings_summary
         )
     )
     self.context.logger.info(
         "[{}]: Computed equilibrium:\n{}".format(
             self.context.agent_name, game.equilibrium_summary
         )
     )
     for agent_address in game.conf.agent_addr_to_name.keys():
         agent_state = game.current_agent_states[agent_address]
         tac_msg = TacMessage(
             performative=TacMessage.Performative.GAME_DATA,
             amount_by_currency_id=agent_state.amount_by_currency_id,
             exchange_params_by_currency_id=agent_state.exchange_params_by_currency_id,
             quantities_by_good_id=agent_state.quantities_by_good_id,
             utility_params_by_good_id=agent_state.utility_params_by_good_id,
             tx_fee=game.conf.tx_fee,
             currency_id_to_name=game.conf.currency_id_to_name,
             agent_addr_to_name=game.conf.agent_addr_to_name,
             good_id_to_name=game.conf.good_id_to_name,
             version_id=game.conf.version_id,
         )
         self.context.logger.debug(
             "[{}]: sending game data to '{}': {}".format(
                 self.context.agent_name, agent_address, str(tac_msg)
             )
         )
         tac_msg.counterparty = agent_address
         self.context.outbox.put_message(message=tac_msg)
示例#8
0
 def _end_tac(self, game: Game, reason: str) -> None:
     """Notify agents that the TAC is cancelled."""
     self.context.logger.info(
         "notifying agents that TAC is {}.".format(reason))
     for agent_addr in game.registration.agent_addr_to_name.keys():
         tac_msg = TacMessage(
             performative=TacMessage.Performative.CANCELLED)
         tac_msg.counterparty = agent_addr
         self.context.outbox.put_message(message=tac_msg)
示例#9
0
    def _handle_valid_transaction(self, message: TacMessage,
                                  transaction: Transaction) -> None:
        """
        Handle a valid transaction.

        That is:
        - update the game state
        - send a transaction confirmation both to the buyer and the seller.

        :param transaction: the transaction.
        :return: None
        """
        game = cast(Game, self.context.game)
        self.context.logger.info("[{}]: Handling valid transaction: {}".format(
            self.context.agent_name, transaction.id[-10:]))
        game.settle_transaction(transaction)

        tx_sender_id, tx_counterparty_id = transaction.id.split("_")
        # send the transaction confirmation.
        sender_tac_msg = TacMessage(
            performative=TacMessage.Performative.TRANSACTION_CONFIRMATION,
            tx_id=tx_sender_id,
            amount_by_currency_id=transaction.amount_by_currency_id,
            quantities_by_good_id=transaction.quantities_by_good_id,
        )
        counterparty_tac_msg = TacMessage(
            performative=TacMessage.Performative.TRANSACTION_CONFIRMATION,
            tx_id=tx_counterparty_id,
            amount_by_currency_id=transaction.amount_by_currency_id,
            quantities_by_good_id=transaction.quantities_by_good_id,
        )
        sender_tac_msg.counterparty = transaction.sender_addr
        self.context.outbox.put_message(message=sender_tac_msg)
        counterparty_tac_msg.counterparty = transaction.counterparty_addr
        self.context.outbox.put_message(message=counterparty_tac_msg)

        # log messages
        self.context.logger.info(
            "[{}]: Transaction '{}' settled successfully.".format(
                self.context.agent_name, transaction.id[-10:]))
        self.context.logger.info("[{}]: Current state:\n{}".format(
            self.context.agent_name, game.holdings_summary))
示例#10
0
 def _handle_invalid_transaction(self, message: TacMessage) -> None:
     """Handle an invalid transaction."""
     tx_id = message.tx_id[-10:]
     self.context.logger.info(
         "[{}]: Handling invalid transaction: {}".format(
             self.context.agent_name, tx_id))
     tac_msg = TacMessage(
         performative=TacMessage.Performative.TAC_ERROR,
         error_code=TacMessage.ErrorCode.TRANSACTION_NOT_VALID,
         info={"transaction_id": message.tx_id},
     )
     tac_msg.counterparty = message.counterparty
     self.context.outbox.put_message(message=tac_msg)
示例#11
0
 def _handle_invalid_transaction(
     self, tac_msg: TacMessage, tac_dialogue: TacDialogue
 ) -> None:
     """Handle an invalid transaction."""
     self.context.logger.info(
         "handling invalid transaction: {}".format(tac_msg.transaction_id)
     )
     error_msg = TacMessage(
         performative=TacMessage.Performative.TAC_ERROR,
         dialogue_reference=tac_dialogue.dialogue_label.dialogue_reference,
         error_code=TacMessage.ErrorCode.TRANSACTION_NOT_VALID,
         info={"transaction_id": tac_msg.transaction_id},
         message_id=tac_msg.message_id + 1,
         target=tac_msg.message_id,
     )
     error_msg.counterparty = tac_msg.counterparty
     assert tac_dialogue.update(error_msg)
     self.context.outbox.put_message(message=error_msg)
示例#12
0
    def _register_to_tac(self, controller_addr: Address) -> None:
        """
        Register to active TAC Controller.

        :param controller_addr: the address of the controller.

        :return: None
        """
        game = cast(Game, self.context.game)
        game.update_expected_controller_addr(controller_addr)
        game.update_game_phase(Phase.GAME_REGISTRATION)
        tac_msg = TacMessage(
            performative=TacMessage.Performative.REGISTER,
            agent_name=self.context.agent_name,
        )
        tac_msg.counterparty = controller_addr
        self.context.outbox.put_message(message=tac_msg)
        self.context.behaviours.tac.is_active = False
示例#13
0
    def _process_transactions(self) -> None:
        """
        Process transactions.

        :return: None
        """
        game = cast(Game, self.context.game)
        tac_dialogue = game.tac_dialogue
        transactions = cast(Dict[str, Dict[str, Any]],
                            self.context.shared_state.get("transactions", {}))
        tx_ids = list(transactions.keys())
        for tx_id in tx_ids:
            self.context.logger.info(
                "sending transaction {} to controller.".format(tx_id))
            last_msg = tac_dialogue.last_message
            assert last_msg is not None, "No last message available."
            tx_content = transactions.pop(tx_id, None)
            assert tx_content is not None, "Tx for id={} not found.".format(
                tx_id)
            terms = tx_content["terms"]
            sender_signature = tx_content["sender_signature"]
            counterparty_signature = tx_content["counterparty_signature"]
            msg = TacMessage(
                performative=TacMessage.Performative.TRANSACTION,
                dialogue_reference=tac_dialogue.dialogue_label.
                dialogue_reference,
                message_id=last_msg.message_id + 1,
                target=last_msg.message_id,
                transaction_id=tx_id,
                ledger_id=terms.ledger_id,
                sender_address=terms.sender_address,
                counterparty_address=terms.counterparty_address,
                amount_by_currency_id=terms.amount_by_currency_id,
                fee_by_currency_id=terms.fee_by_currency_id,
                quantities_by_good_id=terms.quantities_by_good_id,
                sender_signature=sender_signature,
                counterparty_signature=counterparty_signature,
                nonce=terms.nonce,
            )
            msg.counterparty = game.conf.controller_addr
            tac_dialogue.update(msg)
            self.context.outbox.put_message(message=msg)
示例#14
0
    def _handle_signed_transaction(self, signing_msg: SigningMessage,
                                   signing_dialogue: SigningDialogue) -> None:
        """
        Handle an oef search message.

        :param signing_msg: the signing message
        :param signing_dialogue: the dialogue
        :return: None
        """
        # TODO: Need to modify here and add the contract option in case we are using one.
        self.context.logger.info(
            "[{}]: transaction confirmed by decision maker, sending to controller."
            .format(self.context.agent_name))
        game = cast(Game, self.context.game)
        tx_counterparty_signature = cast(
            str,
            signing_msg.skill_callback_info.get("tx_counterparty_signature"))
        tx_counterparty_id = cast(
            str, signing_msg.skill_callback_info.get("tx_counterparty_id"))
        tx_id = cast(str, signing_msg.skill_callback_info.get("tx_id"))
        if (tx_counterparty_signature is not None) and (tx_counterparty_id
                                                        is not None):
            # tx_id = tx_message.tx_id + "_" + tx_counterparty_id
            msg = TacMessage(
                performative=TacMessage.Performative.TRANSACTION,
                tx_id=tx_id,
                tx_sender_addr=signing_msg.terms.sender_address,
                tx_counterparty_addr=signing_msg.terms.counterparty_address,
                amount_by_currency_id=signing_msg.terms.amount_by_currency_id,
                is_sender_payable_tx_fee=signing_msg.terms.
                is_sender_payable_tx_fee,
                quantities_by_good_id=signing_msg.terms.quantities_by_good_id,
                tx_sender_signature=signing_msg.signed_transaction.body,
                tx_counterparty_signature=tx_counterparty_signature,
                tx_nonce=signing_msg.terms.nonce,
            )
            msg.counterparty = game.conf.controller_addr
            self.context.outbox.put_message(message=msg)
        else:
            self.context.logger.warning(
                "[{}]: transaction has no counterparty id or signature!".
                format(self.context.agent_name))
示例#15
0
    def _on_unregister(self, tac_msg: TacMessage, tac_dialogue: TacDialogue) -> None:
        """
        Handle a unregister message.

        If the address is not registered, answer with an error message.

        :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_REGISTRATION:
            self.context.logger.warning(
                "received unregister outside of game registration phase: '{}'".format(
                    tac_msg
                )
            )
            return

        if tac_msg.counterparty not in game.registration.agent_addr_to_name:
            self.context.logger.warning(
                "agent not registered: '{}'".format(tac_msg.counterparty)
            )
            error_msg = TacMessage(
                performative=TacMessage.Performative.TAC_ERROR,
                dialogue_reference=tac_dialogue.dialogue_label.dialogue_reference,
                error_code=TacMessage.ErrorCode.AGENT_NOT_REGISTERED,
                message_id=tac_msg.message_id + 1,
                target=tac_msg.message_id,
            )
            error_msg.counterparty = tac_msg.counterparty
            assert tac_dialogue.update(error_msg)
            self.context.outbox.put_message(message=error_msg)
        else:
            self.context.logger.debug(
                "agent unregistered: '{}'".format(
                    game.conf.agent_addr_to_name[tac_msg.counterparty],
                )
            )
            game.registration.unregister_agent(tac_msg.counterparty)
示例#16
0
 def _start_tac(self, game: Game):
     """Create a game and send the game configuration to every registered agent."""
     game.create()
     self.context.logger.info("started competition:\n{}".format(
         game.holdings_summary))
     self.context.logger.info("computed equilibrium:\n{}".format(
         game.equilibrium_summary))
     tac_dialogues = cast(TacDialogues, self.context.tac_dialogues)
     for agent_address in game.conf.agent_addr_to_name.keys():
         tac_dialogue = tac_dialogues.dialogue_by_address.get(
             agent_address, None)
         assert tac_dialogue is not None, "Error when retrieving dialogue."
         last_msg = tac_dialogue.last_message
         assert last_msg is not None, "Error when retrieving last message."
         agent_state = game.current_agent_states[agent_address]
         tac_msg = TacMessage(
             performative=TacMessage.Performative.GAME_DATA,
             dialogue_reference=tac_dialogue.dialogue_label.
             dialogue_reference,
             message_id=last_msg.message_id + 1,
             target=last_msg.message_id,
             amount_by_currency_id=agent_state.amount_by_currency_id,
             exchange_params_by_currency_id=agent_state.
             exchange_params_by_currency_id,
             quantities_by_good_id=agent_state.quantities_by_good_id,
             utility_params_by_good_id=agent_state.
             utility_params_by_good_id,
             fee_by_currency_id=game.conf.fee_by_currency_id,
             currency_id_to_name=game.conf.currency_id_to_name,
             agent_addr_to_name=game.conf.agent_addr_to_name,
             good_id_to_name=game.conf.good_id_to_name,
             version_id=game.conf.version_id,
         )
         tac_msg.counterparty = agent_address
         tac_dialogues.update(tac_msg)
         self.context.outbox.put_message(message=tac_msg)
         self.context.logger.debug("sending game data to '{}': {}".format(
             agent_address, str(tac_msg)))
示例#17
0
    def _register_to_tac(self, controller_addr: Address) -> None:
        """
        Register to active TAC Controller.

        :param controller_addr: the address of the controller.

        :return: None
        """
        game = cast(Game, self.context.game)
        game.update_expected_controller_addr(controller_addr)
        game.update_game_phase(Phase.GAME_REGISTRATION)
        tac_dialogues = cast(TacDialogues, self.context.tac_dialogues)
        tac_msg = TacMessage(
            performative=TacMessage.Performative.REGISTER,
            dialogue_reference=tac_dialogues.new_self_initiated_dialogue_reference(),
            agent_name=self.context.agent_name,
        )
        tac_msg.counterparty = controller_addr
        tac_dialogue = cast(Optional[TacDialogue], tac_dialogues.update(tac_msg))
        assert tac_dialogue is not None, "TacDialogue not created."
        game.tac_dialogue = tac_dialogue
        self.context.outbox.put_message(message=tac_msg)
        self.context.behaviours.tac_search.is_active = False
示例#18
0
    def _on_register(self, tac_msg: TacMessage, tac_dialogue: TacDialogue) -> None:
        """
        Handle a register message.

        If the address is not registered, answer with an error message.

        :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_REGISTRATION:
            self.context.logger.warning(
                "received registration outside of game registration phase: '{}'".format(
                    tac_msg
                )
            )
            return

        parameters = cast(Parameters, self.context.parameters)
        agent_name = tac_msg.agent_name
        if len(parameters.whitelist) != 0 and agent_name not in parameters.whitelist:
            self.context.logger.warning(
                "agent name not in whitelist: '{}'".format(agent_name)
            )
            error_msg = TacMessage(
                performative=TacMessage.Performative.TAC_ERROR,
                dialogue_reference=tac_dialogue.dialogue_label.dialogue_reference,
                error_code=TacMessage.ErrorCode.AGENT_NAME_NOT_IN_WHITELIST,
                message_id=tac_msg.message_id + 1,
                target=tac_msg.message_id,
            )
            error_msg.counterparty = tac_msg.counterparty
            assert tac_dialogue.update(error_msg)
            self.context.outbox.put_message(message=error_msg)
            return

        game = cast(Game, self.context.game)
        if tac_msg.counterparty in game.registration.agent_addr_to_name:
            self.context.logger.warning(
                "agent already registered: '{}'".format(
                    game.registration.agent_addr_to_name[tac_msg.counterparty],
                )
            )
            error_msg = TacMessage(
                performative=TacMessage.Performative.TAC_ERROR,
                dialogue_reference=tac_dialogue.dialogue_label.dialogue_reference,
                error_code=TacMessage.ErrorCode.AGENT_ADDR_ALREADY_REGISTERED,
                message_id=tac_msg.message_id + 1,
                target=tac_msg.message_id,
            )
            error_msg.counterparty = tac_msg.counterparty
            assert tac_dialogue.update(error_msg)
            self.context.outbox.put_message(message=error_msg)
            return

        if agent_name in game.registration.agent_addr_to_name.values():
            self.context.logger.warning(
                "agent with this name already registered: '{}'".format(agent_name)
            )
            error_msg = TacMessage(
                performative=TacMessage.Performative.TAC_ERROR,
                dialogue_reference=tac_dialogue.dialogue_label.dialogue_reference,
                error_code=TacMessage.ErrorCode.AGENT_NAME_ALREADY_REGISTERED,
                message_id=tac_msg.message_id + 1,
                target=tac_msg.message_id,
            )
            error_msg.counterparty = tac_msg.counterparty
            assert tac_dialogue.update(error_msg)
            self.context.outbox.put_message(message=error_msg)
            return

        game.registration.register_agent(tac_msg.counterparty, agent_name)
        self.context.logger.info("agent registered: '{}'".format(agent_name))