示例#1
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)
示例#2
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)
示例#3
0
def test_register_serialization():
    """Test the serialization for 'register' speech-act works."""
    msg = TacMessage(
        performative=TacMessage.Performative.REGISTER,
        agent_name="some_agent_name",
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        message=msg,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope.to == actual_envelope.to
    assert expected_envelope.sender == actual_envelope.sender
    assert (expected_envelope.protocol_specification_id ==
            actual_envelope.protocol_specification_id)
    assert expected_envelope.message != actual_envelope.message

    actual_msg = TacMessage.serializer.decode(actual_envelope.message)
    actual_msg.to = actual_envelope.to
    actual_msg.sender = actual_envelope.sender
    expected_msg = msg
    assert expected_msg == actual_msg
示例#4
0
def test_transaction_confirmation_serialization():
    """Test the serialization for 'transaction_confirmation' speech-act works."""
    msg = TacMessage(
        performative=TacMessage.Performative.TRANSACTION_CONFIRMATION,
        transaction_id="some_transaction_id",
        amount_by_currency_id={
            "key_1": 1,
            "key_2": 2
        },
        quantities_by_good_id={
            "key_1": 1,
            "key_2": 2
        },
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        protocol_id=TacMessage.protocol_id,
        message=msg,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope.to == actual_envelope.to
    assert expected_envelope.sender == actual_envelope.sender
    assert expected_envelope.protocol_id == actual_envelope.protocol_id
    assert expected_envelope.message != actual_envelope.message

    actual_msg = TacMessage.serializer.decode(actual_envelope.message)
    actual_msg.to = actual_envelope.to
    actual_msg.sender = actual_envelope.sender
    expected_msg = msg
    assert expected_msg == actual_msg
示例#5
0
def test_unregister_serialization():
    """Test the serialization for 'unregister' speech-act works."""
    msg = TacMessage(
        message_id=2,
        target=1,
        performative=TacMessage.Performative.UNREGISTER,
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        protocol_id=TacMessage.protocol_id,
        message=msg,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope.to == actual_envelope.to
    assert expected_envelope.sender == actual_envelope.sender
    assert expected_envelope.protocol_id == actual_envelope.protocol_id
    assert expected_envelope.message != actual_envelope.message

    actual_msg = TacMessage.serializer.decode(actual_envelope.message)
    actual_msg.to = actual_envelope.to
    actual_msg.sender = actual_envelope.sender
    expected_msg = msg
    assert expected_msg == actual_msg
示例#6
0
def test_tac_error_serialization():
    """Test the serialization for 'tac_error' speech-act works."""
    msg = TacMessage(
        performative=TacMessage.Performative.TAC_ERROR,
        error_code=TacMessage.ErrorCode.GENERIC_ERROR,
        info={
            "key_1": "value_1",
            "key_2": "value_2"
        },
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        protocol_id=TacMessage.protocol_id,
        message=msg,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope.to == actual_envelope.to
    assert expected_envelope.sender == actual_envelope.sender
    assert expected_envelope.protocol_id == actual_envelope.protocol_id
    assert expected_envelope.message != actual_envelope.message

    actual_msg = TacMessage.serializer.decode(actual_envelope.message)
    actual_msg.to = actual_envelope.to
    actual_msg.sender = actual_envelope.sender
    expected_msg = msg
    assert expected_msg == actual_msg
示例#7
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)
示例#8
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
示例#9
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
示例#10
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)
示例#11
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)
示例#12
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,
        )
        self.context.outbox.put_message(
            to=transaction.sender_addr,
            sender=self.context.agent_address,
            protocol_id=TacMessage.protocol_id,
            message=TacSerializer().encode(sender_tac_msg),
        )
        self.context.outbox.put_message(
            to=transaction.counterparty_addr,
            sender=self.context.agent_address,
            protocol_id=TacMessage.protocol_id,
            message=TacSerializer().encode(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))
示例#13
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.error(
                "[{}]: Agent not registered: '{}'".format(
                    self.context.agent_name, message.counterparty))
            tac_msg = TacMessage(
                performative=TacMessage.Performative.TAC_ERROR,
                error_code=TacMessage.ErrorCode.AGENT_NOT_REGISTERED,
            )
            self.context.outbox.put_message(
                to=message.counterparty,
                sender=self.context.agent_address,
                protocol_id=TacMessage.protocol_id,
                message=TacSerializer().encode(tac_msg),
            )
        else:
            self.context.logger.debug("[{}]: Agent unregistered: '{}'".format(
                self.context.agent_name,
                game.configuration.agent_addr_to_name[message.counterparty],
            ))
            game.registration.unregister_agent(message.counterparty)
示例#14
0
    def handle(self, message: Message) -> None:
        """
        Dispatch message to relevant handler and respond.

        :param message: the message
        :return: None
        """
        tx_message = cast(TransactionMessage, message)
        if (
            tx_message.performative
            == TransactionMessage.Performative.SUCCESSFUL_SIGNING
        ):

            # 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(
                bytes, tx_message.info.get("tx_counterparty_signature")
            )
            tx_counterparty_id = cast(str, tx_message.info.get("tx_counterparty_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=tx_message.tx_sender_addr,
                    tx_counterparty_addr=tx_message.tx_counterparty_addr,
                    amount_by_currency_id=tx_message.tx_amount_by_currency_id,
                    tx_sender_fee=tx_message.tx_sender_fee,
                    tx_counterparty_fee=tx_message.tx_counterparty_fee,
                    quantities_by_good_id=tx_message.tx_quantities_by_good_id,
                    tx_sender_signature=tx_message.signed_payload.get("tx_signature"),
                    tx_counterparty_signature=tx_message.info.get(
                        "tx_counterparty_signature"
                    ),
                    tx_nonce=tx_message.info.get("tx_nonce"),
                )
                self.context.outbox.put_message(
                    to=game.configuration.controller_addr,
                    sender=self.context.agent_address,
                    protocol_id=TacMessage.protocol_id,
                    message=TacSerializer().encode(msg),
                )
            else:
                self.context.logger.warning(
                    "[{}]: transaction has no counterparty id or signature!".format(
                        self.context.agent_name
                    )
                )
        else:
            self.context.logger.info(
                "[{}]: transaction was not successful.".format(self.context.agent_name)
            )
示例#15
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.Type.CANCELLED)
            self.context.outbox.put_message(
                to=agent_addr,
                sender=self.context.agent_address,
                protocol_id=TacMessage.protocol_id,
                message=TacSerializer().encode(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
示例#16
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.configuration.agent_addr_to_name.keys():
            agent_state = game.current_agent_states[agent_address]
            tac_msg = TacMessage(
                type=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.configuration.tx_fee,
                agent_addr_to_name=game.configuration.agent_addr_to_name,
                good_id_to_name=game.configuration.good_id_to_name,
                version_id=game.configuration.version_id,
                contract_address=self.context.contracts.erc1155.instance.
                address,
            )
            self.context.logger.debug(
                "[{}]: sending game data to '{}': {}".format(
                    self.context.agent_name, agent_address, str(tac_msg)))
            self.context.outbox.put_message(
                to=agent_address,
                sender=self.context.agent_address,
                protocol_id=TacMessage.protocol_id,
                message=TacSerializer().encode(tac_msg),
            )
示例#17
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))
示例#18
0
def test_transaction_serialization():
    """Test the serialization for 'transaction' speech-act works."""
    msg = TacMessage(
        performative=TacMessage.Performative.TRANSACTION,
        transaction_id="some_transaction_id",
        ledger_id="some_ledger_id",
        sender_address="some_sender_address",
        counterparty_address="some_counterparty_address",
        amount_by_currency_id={
            "key_1": 1,
            "key_2": 2
        },
        fee_by_currency_id={
            "key_1": 1,
            "key_2": 2
        },
        quantities_by_good_id={
            "key_1": 1,
            "key_2": 2
        },
        nonce="some_nonce",
        sender_signature="some_sender_signature",
        counterparty_signature="some_counterparty_signature",
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        message=msg,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope.to == actual_envelope.to
    assert expected_envelope.sender == actual_envelope.sender
    assert (expected_envelope.protocol_specification_id ==
            actual_envelope.protocol_specification_id)
    assert expected_envelope.message != actual_envelope.message

    actual_msg = TacMessage.serializer.decode(actual_envelope.message)
    actual_msg.to = actual_envelope.to
    actual_msg.sender = actual_envelope.sender
    expected_msg = msg
    assert expected_msg == actual_msg
示例#19
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
示例#20
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)
示例#21
0
def test_encoding_unknown_performative():
    """Test that we raise an exception when the performative is unknown during encoding."""
    msg = TacMessage(performative=TacMessage.Performative.CANCELLED, )

    with pytest.raises(ValueError, match="Performative not valid:"):
        with mock.patch.object(TacMessage.Performative,
                               "__eq__",
                               return_value=False):
            TacMessage.serializer.encode(msg)
示例#22
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)
示例#23
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))
示例#24
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)
示例#25
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))
示例#26
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)))
示例#27
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
示例#28
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(
             self.context.agent_name, reason
         )
     )
     for agent_addr in game.registration.agent_addr_to_name.keys():
         tac_msg = TacMessage(performative=TacMessage.Performative.CANCELLED)
         self.context.outbox.put_message(
             to=agent_addr,
             sender=self.context.agent_address,
             protocol_id=TacMessage.protocol_id,
             message=TacSerializer().encode(tac_msg),
         )
示例#29
0
def test_cancelled_serialization():
    """Test the serialization for 'cancelled' speech-act works."""
    msg = TacMessage(performative=TacMessage.Performative.CANCELLED, )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        protocol_id=TacMessage.protocol_id,
        message=msg,
    )
    envelope_bytes = envelope.encode()

    actual_envelope = Envelope.decode(envelope_bytes)
    expected_envelope = envelope
    assert expected_envelope.to == actual_envelope.to
    assert expected_envelope.sender == actual_envelope.sender
    assert expected_envelope.protocol_id == actual_envelope.protocol_id
    assert expected_envelope.message != actual_envelope.message

    actual_msg = TacMessage.serializer.decode(actual_envelope.message)
    actual_msg.to = actual_envelope.to
    actual_msg.sender = actual_envelope.sender
    expected_msg = msg
    assert expected_msg == actual_msg
示例#30
0
def test_tac_message_instantiation():
    """Test instantiation of the tac message."""
    assert TacMessage(
        performative=TacMessage.Performative.REGISTER, agent_name="some_name"
    )
    assert TacMessage(performative=TacMessage.Performative.UNREGISTER)
    assert TacMessage(
        performative=TacMessage.Performative.TRANSACTION,
        tx_id="some_id",
        tx_sender_addr="some_address",
        tx_counterparty_addr="some_other_address",
        amount_by_currency_id={"FET": 10},
        tx_sender_fee=10,
        tx_counterparty_fee=10,
        quantities_by_good_id={"123": 0, "1234": 10},
        tx_nonce=1,
        tx_sender_signature=b"some_signature",
        tx_counterparty_signature=b"some_other_signature",
    )
    assert TacMessage(performative=TacMessage.Performative.GET_STATE_UPDATE)
    assert TacMessage(performative=TacMessage.Performative.CANCELLED)
    assert TacMessage(
        performative=TacMessage.Performative.GAME_DATA,
        amount_by_currency_id={"FET": 10},
        exchange_params_by_currency_id={"FET": 10.0},
        quantities_by_good_id={"123": 20, "1234": 15},
        utility_params_by_good_id={"123": 30.0, "1234": 50.0},
        tx_fee=20,
        agent_addr_to_name={"agent_1": "Agent one", "agent_2": "Agent two"},
        currency_id_to_name={"FET": "currency_name"},
        good_id_to_name={"123": "First good", "1234": "Second good"},
        version_id="game_version_1",
    )
    assert TacMessage(
        performative=TacMessage.Performative.TRANSACTION_CONFIRMATION,
        tx_id="some_id",
        amount_by_currency_id={"FET": 10},
        quantities_by_good_id={"123": 20, "1234": 15},
    )
    assert TacMessage(
        performative=TacMessage.Performative.TAC_ERROR,
        error_code=TacMessage.ErrorCode.GENERIC_ERROR,
        info={"msg": "This is info msg."},
    )
    assert str(TacMessage.Performative.REGISTER) == "register"