Ejemplo n.º 1
0
    def _handle_transaction_digest(
            self, ledger_api_msg: LedgerApiMessage,
            ledger_api_dialogue: LedgerApiDialogue) -> None:
        """
        Handle a message of transaction_digest performative.

        :param ledger_api_message: the ledger api message
        :param ledger_api_dialogue: the ledger api dialogue
        """
        self.context.logger.info(
            "[{}]: transaction was successfully submitted. Transaction digest={}"
            .format(self.context.agent_name,
                    ledger_api_msg.transaction_digest))
        msg = LedgerApiMessage(
            performative=LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT,
            message_id=ledger_api_msg.message_id + 1,
            dialogue_reference=ledger_api_dialogue.dialogue_label.
            dialogue_reference,
            target=ledger_api_msg.message_id,
            transaction_digest=ledger_api_msg.transaction_digest,
        )
        msg.counterparty = ledger_api_msg.counterparty
        ledger_api_dialogue.update(msg)
        self.context.outbox.put_message(message=msg)
        self.context.logger.info(
            "[{}]: requesting transaction receipt.".format(
                self.context.agent_name))
Ejemplo n.º 2
0
    def get_balance(
        self, api: LedgerApi, message: LedgerApiMessage, dialogue: LedgerApiDialogue,
    ) -> LedgerApiMessage:
        """
        Send the request 'get_balance'.

        :param api: the API object.
        :param message: the Ledger API message
        :return: None
        """
        balance = api.get_balance(message.address)
        if balance is None:
            response = self.get_error_message(
                ValueError("No balance returned"), api, message, dialogue
            )
        else:
            response = LedgerApiMessage(
                performative=LedgerApiMessage.Performative.BALANCE,
                message_id=message.message_id + 1,
                target=message.message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                balance=balance,
                ledger_id=message.ledger_id,
            )
            response.counterparty = message.counterparty
            dialogue.update(response)
        return response
Ejemplo n.º 3
0
def test_send_signed_transaction_serialization():
    """Test the serialization for 'send_signed_transaction' speech-act works."""
    msg = LedgerApiMessage(
        message_id=2,
        target=1,
        performative=LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION,
        signed_transaction=LedgerApiMessage.SignedTransaction(
            "some_ledger_id", b"some_body"),
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        protocol_id=LedgerApiMessage.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 = LedgerApiMessage.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
Ejemplo n.º 4
0
    def send_signed_transaction(
        self, api: LedgerApi, message: LedgerApiMessage, dialogue: LedgerApiDialogue,
    ) -> LedgerApiMessage:
        """
        Send the request 'send_signed_tx'.

        :param api: the API object.
        :param message: the Ledger API message
        :return: None
        """
        transaction_digest = api.send_signed_transaction(
            message.signed_transaction.body
        )
        if transaction_digest is None:  # pragma: nocover
            response = self.get_error_message(
                ValueError("No transaction_digest returned"), api, message, dialogue
            )
        else:
            response = LedgerApiMessage(
                performative=LedgerApiMessage.Performative.TRANSACTION_DIGEST,
                message_id=message.message_id + 1,
                target=message.message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                transaction_digest=TransactionDigest(
                    message.signed_transaction.ledger_id, transaction_digest
                ),
            )
            response.counterparty = message.counterparty
            dialogue.update(response)
        return response
Ejemplo n.º 5
0
def test_error_serialization():
    """Test the serialization for 'error' speech-act works."""
    msg = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.ERROR,
        code=7,
        message="some_error_message",
        data=b"some_error_data",
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        protocol_id=LedgerApiMessage.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 = LedgerApiMessage.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
Ejemplo n.º 6
0
    def get_error_message(
        self, e: Exception, api: LedgerApi, message: Message, dialogue: BaseDialogue,
    ) -> LedgerApiMessage:
        """
        Build an error message.

        :param e: the exception.
        :param api: the Ledger API.
        :param message: the request message.
        :return: an error message response.
        """
        message = cast(LedgerApiMessage, message)
        dialogue = cast(LedgerApiDialogue, dialogue)
        response = LedgerApiMessage(
            performative=LedgerApiMessage.Performative.ERROR,
            message_id=message.message_id + 1,
            target=message.message_id,
            dialogue_reference=dialogue.dialogue_label.dialogue_reference,
            code=500,
            message=str(e),
            data=b"",
        )
        response.counterparty = message.counterparty
        dialogue.update(response)
        return response
Ejemplo n.º 7
0
    def get_raw_transaction(
        self, api: LedgerApi, message: LedgerApiMessage, dialogue: LedgerApiDialogue,
    ) -> LedgerApiMessage:
        """
        Send the request 'get_raw_transaction'.

        :param api: the API object.
        :param message: the Ledger API message
        :return: None
        """
        raw_transaction = api.get_transfer_transaction(
            sender_address=message.terms.sender_address,
            destination_address=message.terms.counterparty_address,
            amount=message.terms.sender_payable_amount,
            tx_fee=message.terms.fee,
            tx_nonce=message.terms.nonce,
            **message.terms.kwargs,
        )
        if raw_transaction is None:
            response = self.get_error_message(
                ValueError("No raw transaction returned"), api, message, dialogue
            )
        else:
            response = LedgerApiMessage(
                performative=LedgerApiMessage.Performative.RAW_TRANSACTION,
                message_id=message.message_id + 1,
                target=message.message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                raw_transaction=RawTransaction(
                    message.terms.ledger_id, raw_transaction
                ),
            )
            response.counterparty = message.counterparty
            dialogue.update(response)
        return response
Ejemplo n.º 8
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
        """
        self.context.logger.info("transaction signing was successful.")
        fipa_dialogue = signing_dialogue.associated_fipa_dialogue
        ledger_api_dialogue = fipa_dialogue.associated_ledger_api_dialogue
        last_ledger_api_msg = ledger_api_dialogue.last_incoming_message
        assert (last_ledger_api_msg is not None
                ), "Could not retrieve last message in ledger api dialogue"
        ledger_api_msg = LedgerApiMessage(
            performative=LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION,
            dialogue_reference=ledger_api_dialogue.dialogue_label.
            dialogue_reference,
            target=last_ledger_api_msg.message_id,
            message_id=last_ledger_api_msg.message_id + 1,
            signed_transaction=signing_msg.signed_transaction,
        )
        ledger_api_msg.counterparty = LEDGER_API_ADDRESS
        ledger_api_dialogue.update(ledger_api_msg)
        self.context.outbox.put_message(message=ledger_api_msg)
        self.context.logger.info("sending transaction to ledger.")
Ejemplo n.º 9
0
def test_get_balance_serialization():
    """Test the serialization for 'get_balance' speech-act works."""
    msg = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.GET_BALANCE,
        ledger_id="some_ledger_id",
        address="some_address",
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        protocol_id=LedgerApiMessage.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 = LedgerApiMessage.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
Ejemplo n.º 10
0
async def test_no_raw_tx():
    """Test no raw tx returned."""
    dispatcher = LedgerApiRequestDispatcher(ConnectionStatus())
    mock_api = Mock()
    contract_api_dialogues = ContractApiDialogues()
    message = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.GET_RAW_TRANSACTION,
        dialogue_reference=contract_api_dialogues.
        new_self_initiated_dialogue_reference(),
        terms=Terms(
            ledger_id=EthereumCrypto.identifier,
            sender_address="1111",
            counterparty_address="22222",
            amount_by_currency_id={"ETH": -1},
            quantities_by_good_id={"some_service_id": 1},
            is_sender_payable_tx_fee=True,
            nonce="",
            fee_by_currency_id={"ETH": 10},
            chain_id=3,
        ),
    )
    message.counterparty = "test"
    dialogue = contract_api_dialogues.update(message)
    mock_api.get_transfer_transaction.return_value = None
    msg = dispatcher.get_raw_transaction(mock_api, message, dialogue)

    assert msg.performative == LedgerApiMessage.Performative.ERROR
Ejemplo n.º 11
0
def test_transaction_receipt_serialization():
    """Test the serialization for 'transaction_receipt' speech-act works."""
    msg = LedgerApiMessage(
        message_id=2,
        target=1,
        performative=LedgerApiMessage.Performative.TRANSACTION_RECEIPT,
        transaction_receipt=LedgerApiMessage.TransactionReceipt(
            "some_ledger_id", b"some_receit", b"some_transaction"),
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        protocol_id=LedgerApiMessage.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 = LedgerApiMessage.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
Ejemplo n.º 12
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
        """
        self.context.logger.info(
            "[{}]: transaction signing was successful.".format(
                self.context.agent_name))
        ledger_api_dialogues = cast(LedgerApiDialogues,
                                    self.context.ledger_api_dialogues)
        ledger_api_msg = LedgerApiMessage(
            performative=LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION,
            dialogue_reference=ledger_api_dialogues.
            new_self_initiated_dialogue_reference(),
            signed_transaction=signing_msg.signed_transaction,
        )
        ledger_api_msg.counterparty = LEDGER_API_ADDRESS
        ledger_api_dialogue = cast(Optional[LedgerApiDialogue],
                                   ledger_api_dialogues.update(ledger_api_msg))
        assert ledger_api_dialogue is not None, "Error when creating signing dialogue."
        ledger_api_dialogue.associated_signing_dialogue = signing_dialogue
        self.context.outbox.put_message(message=ledger_api_msg)
        self.context.logger.info("[{}]: sending transaction to ledger.".format(
            self.context.agent_name))
Ejemplo n.º 13
0
    def get_transaction_receipt(
        self,
        api: LedgerApi,
        message: LedgerApiMessage,
        dialogue: LedgerApiDialogue,
    ) -> LedgerApiMessage:
        """
        Send the request 'get_transaction_receipt'.

        :param api: the API object.
        :param message: the Ledger API message
        :return: None
        """
        is_settled = False
        attempts = 0
        while (not is_settled and attempts < self.MAX_ATTEMPTS
               and self.connection_state.get() == ConnectionStates.connected):
            time.sleep(self.TIMEOUT)
            transaction_receipt = api.get_transaction_receipt(
                message.transaction_digest.body)
            is_settled = api.is_transaction_settled(transaction_receipt)
            attempts += 1
        attempts = 0
        transaction = api.get_transaction(message.transaction_digest.body)
        while (transaction is None and attempts < self.MAX_ATTEMPTS
               and self.connection_state.get() == ConnectionStates.connected):
            time.sleep(self.TIMEOUT)
            transaction = api.get_transaction(message.transaction_digest.body)
            attempts += 1
        if not is_settled:  # pragma: nocover
            response = self.get_error_message(
                ValueError("Transaction not settled within timeout"),
                api,
                message,
                dialogue,
            )
        elif transaction_receipt is None:  # pragma: nocover
            response = self.get_error_message(
                ValueError("No transaction_receipt returned"), api, message,
                dialogue)
        elif transaction is None:  # pragma: nocover
            response = self.get_error_message(ValueError("No tx returned"),
                                              api, message, dialogue)
        else:
            response = LedgerApiMessage(
                performative=LedgerApiMessage.Performative.TRANSACTION_RECEIPT,
                message_id=message.message_id + 1,
                target=message.message_id,
                dialogue_reference=dialogue.dialogue_label.dialogue_reference,
                transaction_receipt=TransactionReceipt(
                    message.transaction_digest.ledger_id,
                    transaction_receipt,
                    transaction,
                ),
            )
            response.counterparty = message.counterparty
            dialogue.update(response)
        return response
Ejemplo n.º 14
0
    def _handle_match_accept(
        self, fipa_msg: FipaMessage, fipa_dialogue: FipaDialogue
    ) -> None:
        """
        Handle the match accept.

        :param fipa_msg: the message
        :param fipa_dialogue: the dialogue object
        :return: None
        """
        self.context.logger.info(
            "received MATCH_ACCEPT_W_INFORM from sender={} with info={}".format(
                fipa_msg.counterparty[-5:], fipa_msg.info
            )
        )
        strategy = cast(GenericStrategy, self.context.strategy)
        if strategy.is_ledger_tx:
            transfer_address = fipa_msg.info.get("address", None)
            if transfer_address is not None and isinstance(transfer_address, str):
                fipa_dialogue.terms.counterparty_address = transfer_address
            ledger_api_dialogues = cast(
                LedgerApiDialogues, self.context.ledger_api_dialogues
            )
            ledger_api_msg = LedgerApiMessage(
                performative=LedgerApiMessage.Performative.GET_RAW_TRANSACTION,
                dialogue_reference=ledger_api_dialogues.new_self_initiated_dialogue_reference(),
                terms=fipa_dialogue.terms,
            )
            ledger_api_msg.counterparty = LEDGER_API_ADDRESS
            ledger_api_dialogue = cast(
                Optional[LedgerApiDialogue], ledger_api_dialogues.update(ledger_api_msg)
            )
            assert (
                ledger_api_dialogue is not None
            ), "Error when creating ledger api dialogue."
            ledger_api_dialogue.associated_fipa_dialogue = fipa_dialogue
            fipa_dialogue.associated_ledger_api_dialogue = ledger_api_dialogue
            self.context.outbox.put_message(message=ledger_api_msg)
            self.context.logger.info(
                "requesting transfer transaction from ledger api..."
            )
        else:
            inform_msg = FipaMessage(
                message_id=fipa_msg.message_id + 1,
                dialogue_reference=fipa_dialogue.dialogue_label.dialogue_reference,
                target=fipa_msg.message_id,
                performative=FipaMessage.Performative.INFORM,
                info={"Done": "Sending payment via bank transfer"},
            )
            inform_msg.counterparty = fipa_msg.counterparty
            fipa_dialogue.update(inform_msg)
            self.context.outbox.put_message(message=inform_msg)
            self.context.logger.info(
                "informing counterparty={} of payment.".format(
                    fipa_msg.counterparty[-5:]
                )
            )
Ejemplo n.º 15
0
 def setup(self) -> None:
     """Implement the setup for the behaviour."""
     strategy = cast(Strategy, self.context.strategy)
     ledger_api_dialogues = cast(
         LedgerApiDialogues, self.context.ledger_api_dialogues
     )
     ledger_api_msg = LedgerApiMessage(
         performative=LedgerApiMessage.Performative.GET_BALANCE,
         dialogue_reference=ledger_api_dialogues.new_self_initiated_dialogue_reference(),
         ledger_id=strategy.ledger_id,
         address=cast(str, self.context.agent_addresses.get(strategy.ledger_id)),
     )
     ledger_api_msg.counterparty = LEDGER_API_ADDRESS
     ledger_api_dialogues.update(ledger_api_msg)
     self.context.outbox.put_message(message=ledger_api_msg)
Ejemplo n.º 16
0
async def test_no_balance():
    """Test no balance."""
    dispatcher = LedgerApiRequestDispatcher(AsyncState())
    mock_api = Mock()
    message = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.GET_BALANCE,
        dialogue_reference=dispatcher.dialogues.
        new_self_initiated_dialogue_reference(),
        ledger_id=ETHEREUM,
        address="test",
    )
    message.counterparty = "test"
    dialogue = dispatcher.dialogues.update(message)
    mock_api.get_balance.return_value = None
    msg = dispatcher.get_balance(mock_api, message, dialogue)

    assert msg.performative == LedgerApiMessage.Performative.ERROR
Ejemplo n.º 17
0
async def test_no_balance():
    """Test no balance."""
    dispatcher = LedgerApiRequestDispatcher(ConnectionStatus())
    mock_api = Mock()
    contract_api_dialogues = ContractApiDialogues()
    message = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.GET_BALANCE,
        dialogue_reference=contract_api_dialogues.
        new_self_initiated_dialogue_reference(),
        ledger_id=EthereumCrypto.identifier,
        address="test",
    )
    message.counterparty = "test"
    dialogue = contract_api_dialogues.update(message)
    mock_api.get_balance.return_value = None
    msg = dispatcher.get_balance(mock_api, message, dialogue)

    assert msg.performative == LedgerApiMessage.Performative.ERROR
Ejemplo n.º 18
0
def test_incorrect_message(mocked_enforce):
    """Test that we raise an exception when the message is incorrect."""
    with mock.patch.object(ledger_api_message_logger, "error") as mock_logger:
        LedgerApiMessage(
            performative=LedgerApiMessage.Performative.GET_BALANCE,
            ledger_id="some_ledger_id",
            address="some_address",
        )

        mock_logger.assert_any_call("some error")
Ejemplo n.º 19
0
def test_get_raw_transaction_serialization():
    """Test the serialization for 'get_raw_transaction' speech-act works."""
    terms_arg = LedgerApiMessage.Terms(
        ledger_id="some_ledger_id",
        sender_address="some_sender_address",
        counterparty_address="some_counterparty_address",
        amount_by_currency_id={"currency_id_1": 1},
        quantities_by_good_id={
            "good_id_1": -1,
            "good_id_2": -2
        },
        nonce="some_nonce",
        is_sender_payable_tx_fee=False,
        fee_by_currency_id={"currency_id_1": 1},
        is_strict=True,
    )
    msg = LedgerApiMessage(
        message_id=2,
        target=1,
        performative=LedgerApiMessage.Performative.GET_RAW_TRANSACTION,
        terms=terms_arg,
    )
    msg.to = "receiver"
    envelope = Envelope(
        to=msg.to,
        sender="sender",
        protocol_id=LedgerApiMessage.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 = LedgerApiMessage.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
Ejemplo n.º 20
0
    def _request_balance(self) -> None:
        """
        Request ledger balance.

        :return: None
        """
        strategy = cast(Strategy, self.context.strategy)
        ledger_api_dialogues = cast(
            LedgerApiDialogues, self.context.ledger_api_dialogues
        )
        ledger_api_msg = LedgerApiMessage(
            performative=LedgerApiMessage.Performative.GET_BALANCE,
            dialogue_reference=ledger_api_dialogues.new_self_initiated_dialogue_reference(),
            ledger_id=strategy.ledger_id,
            address=cast(str, self.context.agent_addresses.get(strategy.ledger_id)),
        )
        ledger_api_msg.counterparty = LEDGER_API_ADDRESS
        ledger_api_dialogues.update(ledger_api_msg)
        self.context.outbox.put_message(message=ledger_api_msg)
Ejemplo n.º 21
0
async def test_get_balance(ledger_id, address, config,
                           ledger_apis_connection: Connection):
    """Test get balance."""
    import aea  # noqa # to load registries

    ledger_api_dialogues = LedgerApiDialogues(address)
    request = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.GET_BALANCE,
        dialogue_reference=ledger_api_dialogues.
        new_self_initiated_dialogue_reference(),
        ledger_id=ledger_id,
        address=address,
    )

    request.counterparty = str(ledger_apis_connection.connection_id)
    ledger_api_dialogue = ledger_api_dialogues.update(request)
    assert ledger_api_dialogue is not None
    envelope = Envelope(
        to=str(ledger_apis_connection.connection_id),
        sender=address,
        protocol_id=request.protocol_id,
        message=request,
    )

    await ledger_apis_connection.send(envelope)
    await asyncio.sleep(0.01)
    response = await ledger_apis_connection.receive()

    assert response is not None
    assert type(response.message) == LedgerApiMessage
    response_msg_orig = cast(LedgerApiMessage, response.message)
    response_msg = copy.copy(response_msg_orig)
    response_msg.is_incoming = True
    response_msg.counterparty = response_msg_orig.sender
    response_dialogue = ledger_api_dialogues.update(response_msg)
    assert response_dialogue == ledger_api_dialogue
    assert response_msg.performative == LedgerApiMessage.Performative.BALANCE
    actual_balance_amount = response_msg.balance
    expected_balance_amount = make_ledger_api(ledger_id,
                                              **config).get_balance(address)
    assert actual_balance_amount == expected_balance_amount
Ejemplo n.º 22
0
async def test_attempts_get_transaction_receipt():
    """Test retry and sleep."""
    dispatcher = LedgerApiRequestDispatcher(ConnectionStatus())
    dispatcher.connection_status.is_connected = True
    mock_api = Mock()
    contract_api_dialogues = ContractApiDialogues()
    message = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT,
        dialogue_reference=contract_api_dialogues.
        new_self_initiated_dialogue_reference(),
        transaction_digest=TransactionDigest("asdad", "sdfdsf"),
    )
    message.counterparty = "test"
    dialogue = contract_api_dialogues.update(message)
    mock_api.get_transaction.return_value = None
    mock_api.is_transaction_settled.return_value = True
    with patch.object(dispatcher, "MAX_ATTEMPTS", 2):
        with patch.object(dispatcher, "TIMEOUT", 0.001):
            msg = dispatcher.get_transaction_receipt(mock_api, message,
                                                     dialogue)

    assert msg.performative == LedgerApiMessage.Performative.ERROR
Ejemplo n.º 23
0
def test_encoding_unknown_performative():
    """Test that we raise an exception when the performative is unknown during encoding."""
    msg = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.GET_BALANCE,
        ledger_id="some_ledger_id",
        address="some_address",
    )

    with pytest.raises(ValueError, match="Performative not valid:"):
        with mock.patch.object(LedgerApiMessage.Performative,
                               "__eq__",
                               return_value=False):
            LedgerApiMessage.serializer.encode(msg)
Ejemplo n.º 24
0
    def setup(self) -> None:
        """
        Implement the setup.

        :return: None
        """
        strategy = cast(GenericStrategy, self.context.strategy)
        if strategy.is_ledger_tx:
            ledger_api_dialogues = cast(LedgerApiDialogues,
                                        self.context.ledger_api_dialogues)
            ledger_api_msg = LedgerApiMessage(
                performative=LedgerApiMessage.Performative.GET_BALANCE,
                dialogue_reference=ledger_api_dialogues.
                new_self_initiated_dialogue_reference(),
                ledger_id=strategy.ledger_id,
                address=cast(
                    str, self.context.agent_addresses.get(strategy.ledger_id)),
            )
            ledger_api_msg.counterparty = LEDGER_API_ADDRESS
            ledger_api_dialogues.update(ledger_api_msg)
            self.context.outbox.put_message(message=ledger_api_msg)
        self._register_agent()
        self._register_service()
Ejemplo n.º 25
0
    def test__handle_invalid(self):
        """Test handling an invalid performative"""
        # setup
        dialogue = self.prepare_skill_dialogue(
            self.ledger_api_dialogues, self.list_of_ledger_api_messages[3:4])
        incoming_message = self.build_incoming_message_for_skill_dialogue(
            dialogue=dialogue,
            performative=LedgerApiMessage.Performative.STATE,
            ledger_id=LEDGER_ID,
            state=LedgerApiMessage.State(LEDGER_ID, {}),
        )

        # operation
        with patch.object(self.ledger_api_handler.context.logger,
                          "log") as mock_logger:
            self.ledger_api_handler.handle(incoming_message)

        # after
        mock_logger.assert_any_call(
            logging.WARNING,
            f"cannot handle ledger_api message of performative={incoming_message.performative} in dialogue={dialogue}.",
        )

        self.assert_quantity_in_outbox(0)
Ejemplo n.º 26
0
    def decode(obj: bytes) -> Message:
        """
        Decode bytes into a 'LedgerApi' message.

        :param obj: the bytes object.
        :return: the 'LedgerApi' message.
        """
        ledger_api_pb = ledger_api_pb2.LedgerApiMessage()
        ledger_api_pb.ParseFromString(obj)
        message_id = ledger_api_pb.message_id
        dialogue_reference = (
            ledger_api_pb.dialogue_starter_reference,
            ledger_api_pb.dialogue_responder_reference,
        )
        target = ledger_api_pb.target

        performative = ledger_api_pb.WhichOneof("performative")
        performative_id = LedgerApiMessage.Performative(str(performative))
        performative_content = dict()  # type: Dict[str, Any]
        if performative_id == LedgerApiMessage.Performative.GET_BALANCE:
            ledger_id = ledger_api_pb.get_balance.ledger_id
            performative_content["ledger_id"] = ledger_id
            address = ledger_api_pb.get_balance.address
            performative_content["address"] = address
        elif performative_id == LedgerApiMessage.Performative.GET_RAW_TRANSACTION:
            pb2_terms = ledger_api_pb.get_raw_transaction.terms
            terms = Terms.decode(pb2_terms)
            performative_content["terms"] = terms
        elif performative_id == LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION:
            pb2_signed_transaction = (
                ledger_api_pb.send_signed_transaction.signed_transaction)
            signed_transaction = SignedTransaction.decode(
                pb2_signed_transaction)
            performative_content["signed_transaction"] = signed_transaction
        elif performative_id == LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT:
            pb2_transaction_digest = (
                ledger_api_pb.get_transaction_receipt.transaction_digest)
            transaction_digest = TransactionDigest.decode(
                pb2_transaction_digest)
            performative_content["transaction_digest"] = transaction_digest
        elif performative_id == LedgerApiMessage.Performative.BALANCE:
            ledger_id = ledger_api_pb.balance.ledger_id
            performative_content["ledger_id"] = ledger_id
            balance = ledger_api_pb.balance.balance
            performative_content["balance"] = balance
        elif performative_id == LedgerApiMessage.Performative.RAW_TRANSACTION:
            pb2_raw_transaction = ledger_api_pb.raw_transaction.raw_transaction
            raw_transaction = RawTransaction.decode(pb2_raw_transaction)
            performative_content["raw_transaction"] = raw_transaction
        elif performative_id == LedgerApiMessage.Performative.TRANSACTION_DIGEST:
            pb2_transaction_digest = ledger_api_pb.transaction_digest.transaction_digest
            transaction_digest = TransactionDigest.decode(
                pb2_transaction_digest)
            performative_content["transaction_digest"] = transaction_digest
        elif performative_id == LedgerApiMessage.Performative.TRANSACTION_RECEIPT:
            pb2_transaction_receipt = (
                ledger_api_pb.transaction_receipt.transaction_receipt)
            transaction_receipt = TransactionReceipt.decode(
                pb2_transaction_receipt)
            performative_content["transaction_receipt"] = transaction_receipt
        elif performative_id == LedgerApiMessage.Performative.ERROR:
            code = ledger_api_pb.error.code
            performative_content["code"] = code
            if ledger_api_pb.error.message_is_set:
                message = ledger_api_pb.error.message
                performative_content["message"] = message
            if ledger_api_pb.error.data_is_set:
                data = ledger_api_pb.error.data
                performative_content["data"] = data
        else:
            raise ValueError(
                "Performative not valid: {}.".format(performative_id))

        return LedgerApiMessage(message_id=message_id,
                                dialogue_reference=dialogue_reference,
                                target=target,
                                performative=performative,
                                **performative_content)
Ejemplo n.º 27
0
async def test_send_signed_transaction_ethereum(
        ledger_apis_connection: Connection):
    """Test send signed transaction with Ethereum APIs."""
    import aea  # noqa # to load registries

    crypto1 = EthereumCrypto(private_key_path=ETHEREUM_PRIVATE_KEY_PATH)
    crypto2 = EthereumCrypto()
    api = aea.crypto.registries.make_ledger_api(EthereumCrypto.identifier,
                                                **ETHEREUM_TESTNET_CONFIG)
    api = cast(EthereumApi, api)
    ledger_api_dialogues = LedgerApiDialogues()

    amount = 40000
    fee = 30000

    request = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.GET_RAW_TRANSACTION,
        dialogue_reference=ledger_api_dialogues.
        new_self_initiated_dialogue_reference(),
        terms=Terms(
            ledger_id=EthereumCrypto.identifier,
            sender_address=crypto1.address,
            counterparty_address=crypto2.address,
            amount_by_currency_id={"ETH": -amount},
            quantities_by_good_id={"some_service_id": 1},
            is_sender_payable_tx_fee=True,
            nonce="",
            fee_by_currency_id={"ETH": fee},
            chain_id=3,
        ),
    )
    request.counterparty = str(ledger_apis_connection.connection_id)
    ledger_api_dialogue = ledger_api_dialogues.update(request)
    assert ledger_api_dialogue is not None
    envelope = Envelope(
        to=str(ledger_apis_connection.connection_id),
        sender=crypto1.address,
        protocol_id=request.protocol_id,
        message=request,
    )
    await ledger_apis_connection.send(envelope)
    await asyncio.sleep(0.01)
    response = await ledger_apis_connection.receive()

    assert response is not None
    assert type(response.message) == LedgerApiMessage
    response_message = cast(LedgerApiMessage, response.message)
    assert (response_message.performative ==
            LedgerApiMessage.Performative.RAW_TRANSACTION)
    response_dialogue = ledger_api_dialogues.update(response_message)
    assert response_dialogue == ledger_api_dialogue
    assert type(response_message.raw_transaction) == RawTransaction
    assert response_message.raw_transaction.ledger_id == request.terms.ledger_id

    # raw_tx = api.get_transfer_transaction(
    #     sender_address=crypto1.address,
    #     destination_address=crypto2.address,
    #     amount=amount,
    #     tx_fee=fee,
    #     tx_nonce="",
    #     chain_id=3,
    # )

    signed_transaction = crypto1.sign_transaction(
        response_message.raw_transaction.body)
    request = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION,
        dialogue_reference=ledger_api_dialogue.dialogue_label.
        dialogue_reference,
        signed_transaction=SignedTransaction(EthereumCrypto.identifier,
                                             signed_transaction),
    )
    request.counterparty = str(ledger_apis_connection.connection_id)
    ledger_api_dialogue.update(request)
    envelope = Envelope(
        to=str(ledger_apis_connection.connection_id),
        sender=crypto1.address,
        protocol_id=request.protocol_id,
        message=request,
    )
    await ledger_apis_connection.send(envelope)
    await asyncio.sleep(0.01)
    response = await ledger_apis_connection.receive()

    assert response is not None
    assert type(response.message) == LedgerApiMessage
    response_message = cast(LedgerApiMessage, response.message)
    assert (response_message.performative !=
            LedgerApiMessage.Performative.ERROR
            ), f"Received error: {response_message.message}"
    assert (response_message.performative ==
            LedgerApiMessage.Performative.TRANSACTION_DIGEST)
    response_dialogue = ledger_api_dialogues.update(response_message)
    assert response_dialogue == ledger_api_dialogue
    assert type(response_message.transaction_digest) == TransactionDigest
    assert type(response_message.transaction_digest.body) == str
    assert (response_message.transaction_digest.ledger_id ==
            request.signed_transaction.ledger_id)
    assert type(response_message.transaction_digest.body.startswith("0x"))

    request = LedgerApiMessage(
        performative=LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT,
        dialogue_reference=ledger_api_dialogue.dialogue_label.
        dialogue_reference,
        transaction_digest=response_message.transaction_digest,
    )
    request.counterparty = str(ledger_apis_connection.connection_id)
    ledger_api_dialogue.update(request)
    envelope = Envelope(
        to=str(ledger_apis_connection.connection_id),
        sender=crypto1.address,
        protocol_id=request.protocol_id,
        message=request,
    )
    await ledger_apis_connection.send(envelope)
    await asyncio.sleep(0.01)
    response = await ledger_apis_connection.receive()

    assert response is not None
    assert type(response.message) == LedgerApiMessage
    response_message = cast(LedgerApiMessage, response.message)
    assert (response_message.performative ==
            LedgerApiMessage.Performative.TRANSACTION_RECEIPT)
    response_dialogue = ledger_api_dialogues.update(response_message)
    assert response_dialogue == ledger_api_dialogue
    assert type(response_message.transaction_receipt) == TransactionReceipt
    assert response_message.transaction_receipt.receipt is not None
    assert response_message.transaction_receipt.transaction is not None
    assert (response_message.transaction_receipt.ledger_id ==
            request.transaction_digest.ledger_id)
Ejemplo n.º 28
0
    def setup(cls, **kwargs):
        """Setup the test class."""
        super().setup(**kwargs)
        cls.ledger_api_handler = cast(
            LedgerApiHandler, cls._skill.skill_context.handlers.ledger_api)
        cls.logger = cls._skill.skill_context.logger
        cls.simple_oracle_behaviour = cast(
            SimpleOracleBehaviour,
            cls._skill.skill_context.behaviours.simple_oracle_behaviour,
        )
        cls.ledger_api_dialogues = cast(
            LedgerApiDialogues, cls._skill.skill_context.ledger_api_dialogues)
        cls.contract_api_dialogues = cast(
            ContractApiDialogues,
            cls._skill.skill_context.contract_api_dialogues)
        cls.signing_dialogues = cast(
            SigningDialogues, cls._skill.skill_context.signing_dialogues)

        cls.list_of_ledger_api_messages = (
            DialogueMessage(
                LedgerApiMessage.Performative.GET_BALANCE,
                {
                    "ledger_id": LEDGER_ID,
                    "address": "some_eth_address"
                },
            ),
            DialogueMessage(
                LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION,
                {
                    "signed_transaction": SignedTransaction(
                        LEDGER_ID, DEFAULT_TX)
                },
            ),
            DialogueMessage(
                LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT,
                {
                    "transaction_digest":
                    TransactionDigest(LEDGER_ID, "some_digest")
                },
            ),
            DialogueMessage(
                LedgerApiMessage.Performative.GET_STATE,
                {
                    "ledger_id": LEDGER_ID,
                    "callable": "some_callable",
                    "args": (),
                    "kwargs": LedgerApiMessage.Kwargs({}),
                },
            ),
        )
        cls.list_of_contract_api_messages = (DialogueMessage(
            ContractApiMessage.Performative.GET_DEPLOY_TRANSACTION,
            {
                "ledger_id": LEDGER_ID,
                "contract_id": "some_contract_id",
                "callable": "some_callable",
                "kwargs": ContractApiKwargs({"some_key": "some_value"}),
            },
        ), )
        cls.list_of_signing_messages = (DialogueMessage(
            SigningMessage.Performative.SIGN_TRANSACTION,
            {
                "terms": Terms(*DEFAULT_TERMS),
                "raw_transaction": RawTransaction(LEDGER_ID, DEFAULT_TX),
            },
        ), )
Ejemplo n.º 29
0
    def _handle_inform(self, fipa_msg: FipaMessage,
                       fipa_dialogue: FipaDialogue) -> None:
        """
        Handle the INFORM.

        If the INFORM message contains the transaction_digest then verify that it is settled, otherwise do nothing.
        If the transaction is settled, send the data, otherwise do nothing.

        :param fipa_msg: the message
        :param fipa_dialogue: the dialogue object
        :return: None
        """
        new_message_id = fipa_msg.message_id + 1
        new_target = fipa_msg.message_id
        self.context.logger.info("[{}]: received INFORM from sender={}".format(
            self.context.agent_name, fipa_msg.counterparty[-5:]))

        strategy = cast(GenericStrategy, self.context.strategy)
        if strategy.is_ledger_tx and "transaction_digest" in fipa_msg.info.keys(
        ):
            self.context.logger.info(
                "[{}]: checking whether transaction={} has been received ...".
                format(self.context.agent_name,
                       fipa_msg.info["transaction_digest"]))
            ledger_api_dialogues = cast(LedgerApiDialogues,
                                        self.context.ledger_api_dialogues)
            ledger_api_msg = LedgerApiMessage(
                performative=LedgerApiMessage.Performative.
                GET_TRANSACTION_RECEIPT,
                dialogue_reference=ledger_api_dialogues.
                new_self_initiated_dialogue_reference(),
                transaction_digest=TransactionDigest(
                    fipa_dialogue.terms.ledger_id,
                    fipa_msg.info["transaction_digest"]),
            )
            ledger_api_msg.counterparty = LEDGER_API_ADDRESS
            ledger_api_dialogue = cast(
                Optional[LedgerApiDialogue],
                ledger_api_dialogues.update(ledger_api_msg))
            assert (ledger_api_dialogue
                    is not None), "LedgerApiDialogue construction failed."
            ledger_api_dialogue.associated_fipa_dialogue = fipa_dialogue
            self.context.outbox.put_message(message=ledger_api_msg)
        elif strategy.is_ledger_tx:
            self.context.logger.warning(
                "[{}]: did not receive transaction digest from sender={}.".
                format(self.context.agent_name, fipa_msg.counterparty[-5:]))
        elif not strategy.is_ledger_tx and "Done" in fipa_msg.info.keys():
            inform_msg = FipaMessage(
                message_id=new_message_id,
                dialogue_reference=fipa_dialogue.dialogue_label.
                dialogue_reference,
                target=new_target,
                performative=FipaMessage.Performative.INFORM,
                info=fipa_dialogue.data_for_sale,
            )
            inform_msg.counterparty = fipa_msg.counterparty
            fipa_dialogue.update(inform_msg)
            self.context.outbox.put_message(message=inform_msg)
            fipa_dialogues = cast(FipaDialogues, self.context.fipa_dialogues)
            fipa_dialogues.dialogue_stats.add_dialogue_endstate(
                FipaDialogue.EndState.SUCCESSFUL,
                fipa_dialogue.is_self_initiated)
            self.context.logger.info(
                "[{}]: transaction confirmed, sending data={} to buyer={}.".
                format(
                    self.context.agent_name,
                    fipa_dialogue.data_for_sale,
                    fipa_msg.counterparty[-5:],
                ))
        else:
            self.context.logger.warning(
                "[{}]: did not receive transaction confirmation from sender={}."
                .format(self.context.agent_name, fipa_msg.counterparty[-5:]))
Ejemplo n.º 30
0
    def _handle_terms(self, ml_trade_msg: MlTradeMessage,
                      ml_trade_dialogue: MlTradeDialogue) -> None:
        """
        Handle the terms of the request.

        :param ml_trade_msg: the ml trade message
        :param ml_trade_dialogue: the dialogue object
        :return: None
        """
        terms = ml_trade_msg.terms
        self.context.logger.info(
            "received terms message from {}: terms={}".format(
                ml_trade_msg.counterparty[-5:], terms.values))

        strategy = cast(Strategy, self.context.strategy)
        acceptable = strategy.is_acceptable_terms(terms)
        affordable = strategy.is_affordable_terms(terms)
        if not acceptable and affordable:
            self.context.logger.info(
                "rejecting, terms are not acceptable and/or affordable")
            return

        if strategy.is_ledger_tx:
            # construct a tx for settlement on the ledger
            ledger_api_dialogues = cast(LedgerApiDialogues,
                                        self.context.ledger_api_dialogues)
            ledger_api_msg = LedgerApiMessage(
                performative=LedgerApiMessage.Performative.GET_RAW_TRANSACTION,
                dialogue_reference=ledger_api_dialogues.
                new_self_initiated_dialogue_reference(),
                terms=Terms(
                    ledger_id=terms.values["ledger_id"],
                    sender_address=self.context.agent_addresses[
                        terms.values["ledger_id"]],
                    counterparty_address=terms.values["address"],
                    amount_by_currency_id={
                        terms.values["currency_id"]: -terms.values["price"]
                    },
                    is_sender_payable_tx_fee=True,
                    quantities_by_good_id={"ml_training_data": 1},
                    nonce=uuid.uuid4().hex,
                    fee_by_currency_id={terms.values["currency_id"]: 1},
                ),
            )
            ledger_api_msg.counterparty = LEDGER_API_ADDRESS
            ledger_api_dialogue = cast(
                Optional[LedgerApiDialogue],
                ledger_api_dialogues.update(ledger_api_msg))
            assert (ledger_api_dialogue
                    is not None), "Error when creating ledger api dialogue."
            ledger_api_dialogue.associated_ml_trade_dialogue = ml_trade_dialogue
            self.context.outbox.put_message(message=ledger_api_msg)
            self.context.logger.info(
                "requesting transfer transaction from ledger api...")
        else:
            # accept directly with a dummy transaction digest, no settlement
            ml_accept = MlTradeMessage(
                performative=MlTradeMessage.Performative.ACCEPT,
                dialogue_reference=ml_trade_dialogue.dialogue_label.
                dialogue_reference,
                message_id=ml_trade_msg.message_id + 1,
                target=ml_trade_msg.message_id,
                tx_digest=DUMMY_DIGEST,
                terms=terms,
            )
            ml_accept.counterparty = ml_trade_msg.counterparty
            ml_trade_dialogue.update(ml_accept)
            self.context.outbox.put_message(message=ml_accept)
            self.context.logger.info("sending dummy transaction digest ...")