def test_that__handle_connection_should_send_error_frame_if_payload_golem_message_type_is_unexpected(
            self):
        # Prepare frame payload which is Golem message other than TransactionSigningRequest.
        middleman_message = GolemMessageFrame(
            payload=Ping(),
            request_id=99,
        )
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)

        raw_message_received = self._prepare_and_execute_handle_connection(
            raw_message)

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=SIGNING_SERVICE_PUBLIC_KEY,
        )

        assertpy.assert_that(
            deserialized_message.payload).is_instance_of(tuple)
        assertpy.assert_that(deserialized_message.payload).is_length(2)
        assertpy.assert_that(deserialized_message.payload[0]).is_equal_to(
            ErrorCode.UnexpectedMessage)
        assertpy.assert_that(deserialized_message.request_id).is_equal_to(
            REQUEST_ID_FOR_RESPONSE_FOR_INVALID_FRAME)
    def test_that__handle_connection_should_send_golem_message_signed_transaction_if_warning_daily_threshold_exceeded(
            self):
        middleman_message = GolemMessageFrame(
            payload=self._get_deserialized_transaction_signing_request(),
            request_id=99,
        )
        middleman_message.payload.value = WARNING_DAILY_THRESHOLD + 1
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)

        def handle_connection_wrapper(signing_service, connection,
                                      receive_frame_generator):
            with mock.patch(
                    'signing_service.signing_service.SigningService._get_signed_transaction',
                    return_value=self._get_deserialized_signed_transaction(),
            ):
                with mock.patch(
                        'signing_service.signing_service.SigningService._add_payload_value_to_daily_transactions_sum'
                ):
                    signing_service._handle_connection(receive_frame_generator,
                                                       connection)

        raw_message_received = self._prepare_and_execute_handle_connection(
            raw_message,
            handle_connection_wrapper,
        )

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=SIGNING_SERVICE_PUBLIC_KEY,
        )

        assertpy.assert_that(
            deserialized_message.payload).is_instance_of(SignedTransaction)
    def test_that__handle_connection_should_send_error_frame_if_frame_signature_is_wrong(
            self):
        # Prepare message with wrong signature.
        middleman_message = GolemMessageFrame(
            payload=self._get_deserialized_transaction_signing_request(),
            request_id=99,
        )
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)
        first_byte = 2 if raw_message[0] == 0 else raw_message[0]
        malformed_raw_message = bytes(bytearray([first_byte - 1
                                                 ])) + raw_message[1:]

        raw_message_received = self._prepare_and_execute_handle_connection(
            malformed_raw_message)

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=SIGNING_SERVICE_PUBLIC_KEY,
        )

        assertpy.assert_that(
            deserialized_message.payload).is_instance_of(tuple)
        assertpy.assert_that(deserialized_message.payload).is_length(2)
        assertpy.assert_that(deserialized_message.payload[0]).is_equal_to(
            ErrorCode.InvalidFrameSignature)
        assertpy.assert_that(deserialized_message.request_id).is_equal_to(
            REQUEST_ID_FOR_RESPONSE_FOR_INVALID_FRAME)
    def test_that__handle_connection_should_send_error_frame_if_payload_golem_message_type_cannot_be_deserialized(
            self):
        # Prepare frame payload which is Golem message that cannot be deserialized.
        middleman_message = GolemMessageFrame(
            payload=self._get_deserialized_transaction_signing_request(
                nonce=
                'not_int_nonce_which_will_fail_on_deserialization_causing_message_error'
            ),
            request_id=99,
        )
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)

        raw_message_received = self._prepare_and_execute_handle_connection(
            raw_message)

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=SIGNING_SERVICE_PUBLIC_KEY,
        )

        assertpy.assert_that(
            deserialized_message.payload).is_instance_of(tuple)
        assertpy.assert_that(deserialized_message.payload).is_length(2)
        assertpy.assert_that(deserialized_message.payload[0]).is_equal_to(
            ErrorCode.InvalidPayload)
        assertpy.assert_that(deserialized_message.request_id).is_equal_to(
            REQUEST_ID_FOR_RESPONSE_FOR_INVALID_FRAME)
Пример #5
0
    def test_that_serializing_and_deserializing_message_with_wrong_payload_type_should_raise_exception(
            self):
        middleman_message = GolemMessageFrame(Ping(), self.request_id)
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)

        payload_type_position = FRAME_SIGNATURE_BYTES_LENGTH + FRAME_REQUEST_ID_BYTES_LENGTH
        invalid_payload_type = 100

        # Sanity check for payload type in this case to be between expected bytes
        assert raw_message[payload_type_position:payload_type_position +
                           1] == b'\x00'
        assert invalid_payload_type not in PAYLOAD_TYPE_TO_MIDDLEMAN_MESSAGE_CLASS

        # Replace bytes with payload length
        raw_message = (
            raw_message[:payload_type_position] +
            bytes(bytearray([invalid_payload_type])) +
            raw_message[payload_type_position + FRAME_PAYLOAD_TYPE_LENGTH:])

        # Replace message signature
        new_signature = ecdsa_sign(CONCENT_PRIVATE_KEY,
                                   raw_message[FRAME_SIGNATURE_BYTES_LENGTH:])
        raw_message_with_new_signature = new_signature + raw_message[
            FRAME_SIGNATURE_BYTES_LENGTH:]

        with pytest.raises(PayloadTypeInvalidMiddlemanProtocolError):
            AbstractFrame.deserialize(raw_message_with_new_signature,
                                      CONCENT_PUBLIC_KEY)
Пример #6
0
    def test_that_receiving_a_series_of_messages_should_be_handled_correctly(
            self, unused_tcp_port):
        payload = Ping()
        middleman_message = GolemMessageFrame(payload, self.request_id)
        raw_message = escape_encode_raw_message(
            middleman_message.serialize(private_key=CONCENT_PRIVATE_KEY))
        raw_message_with_separator = append_frame_separator(raw_message)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                for _i in range(10):
                    client_socket.send(raw_message_with_separator)

                split_stream_generator = split_stream(connection=connection)

                for _i in range(10):
                    raw_message_received = next(split_stream_generator)

                    assertpy.assert_that(raw_message).is_equal_to(
                        raw_message_received)
Пример #7
0
    def test_that_receiving_wrongly_encoded_message_should_return_none(
            self, unused_tcp_port):
        middleman_message = GolemMessageFrame(Ping(), self.request_id)
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY, )

        raw_message_encoded = escape_encode_raw_message(raw_message)
        raw_message_encoded = raw_message_encoded + ESCAPE_CHARACTER + b'\xff'
        raw_message_encoded = append_frame_separator(raw_message_encoded)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(raw_message_encoded)
                raw_message_received = next(
                    unescape_stream(connection=connection))

        assertpy.assert_that(raw_message_received).is_none()
Пример #8
0
def test_that_sent_data_is_escaped_and_contains_frame_separator(event_loop):
    frame = GolemMessageFrame(Ping(), 777)
    expected_data = append_frame_separator(
        escape_encode_raw_message(frame.serialize(CONCENT_PRIVATE_KEY)))
    mocked_writer = prepare_mocked_writer()

    task = _run_test_in_event_loop(event_loop, send_over_stream_async, frame,
                                   mocked_writer, CONCENT_PRIVATE_KEY)

    assert_that(task.done()).is_true()
    mocked_writer.write.assert_called_once_with(expected_data)
    mocked_writer.drain.mock.assert_called_once_with()
Пример #9
0
def test_that_when_frame_with_escaped_sequence_and_separator_is_received_unescaped_frame_is_returned(
        event_loop):
    golem_message_frame = GolemMessageFrame(Ping(), 777)
    data_to_send = escape_encode_raw_message(
        golem_message_frame.serialize(CONCENT_PRIVATE_KEY)
    ) + ESCAPE_SEQUENCES[ESCAPE_CHARACTER] + FRAME_SEPARATOR
    mocked_reader = prepare_mocked_reader(data_to_send)

    task = _run_test_in_event_loop(event_loop, handle_frame_receive_async,
                                   mocked_reader, CONCENT_PUBLIC_KEY)

    assert_that(task.done()).is_true()
    mocked_reader.readuntil.mock.assert_called_once_with(FRAME_SEPARATOR)
    assert_that(task.result()).is_equal_to(golem_message_frame)
Пример #10
0
    def test_that_exceeding_maximum_frame_length_should_treat_exceeded_frame_as_invalid(
            self, unused_tcp_port):
        first_middleman_message = GolemMessageFrame(Ping(), self.request_id)
        first_raw_message = append_frame_separator(
            escape_encode_raw_message(
                first_middleman_message.serialize(
                    private_key=CONCENT_PRIVATE_KEY)))
        second_middleman_message = AuthenticationChallengeFrame(
            payload=b'',
            request_id=100,
        )
        second_raw_message = append_frame_separator(
            escape_encode_raw_message(
                second_middleman_message.serialize(
                    private_key=CONCENT_PRIVATE_KEY)))

        assert len(first_raw_message) > len(second_raw_message) + 10

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(first_raw_message)
                client_socket.send(second_raw_message)

                with mock.patch(
                        'middleman_protocol.stream.MAXIMUM_FRAME_LENGTH',
                        len(first_raw_message) - 10):
                    raw_message_received = next(
                        unescape_stream(connection=connection))

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=CONCENT_PUBLIC_KEY,
        )

        assertpy.assert_that(deserialized_message.request_id).is_equal_to(100)
    def test_that__handle_connection_should_send_error_frame_if_payload_type_is_invalid(
            self):
        # Prepare frame with malformed payload_type.
        middleman_message = GolemMessageFrame(
            payload=self._get_deserialized_transaction_signing_request(),
            request_id=99,
        )
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)

        payload_type_position = FRAME_SIGNATURE_BYTES_LENGTH + FRAME_REQUEST_ID_BYTES_LENGTH
        invalid_payload_type = 100

        # Replace bytes with payload length.
        malformed_raw_message = (
            raw_message[:payload_type_position] +
            bytes(bytearray([invalid_payload_type])) +
            raw_message[payload_type_position + FRAME_PAYLOAD_TYPE_LENGTH:])

        # Replace message signature
        new_signature = ecdsa_sign(
            CONCENT_PRIVATE_KEY,
            malformed_raw_message[FRAME_SIGNATURE_BYTES_LENGTH:])
        malformed_raw_message_with_new_signature = new_signature + malformed_raw_message[
            FRAME_SIGNATURE_BYTES_LENGTH:]

        raw_message_received = self._prepare_and_execute_handle_connection(
            malformed_raw_message_with_new_signature)

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=SIGNING_SERVICE_PUBLIC_KEY,
        )

        assertpy.assert_that(
            deserialized_message.payload).is_instance_of(tuple)
        assertpy.assert_that(deserialized_message.payload).is_length(2)
        assertpy.assert_that(deserialized_message.payload[0]).is_equal_to(
            ErrorCode.InvalidFrame)
        assertpy.assert_that(deserialized_message.request_id).is_equal_to(
            REQUEST_ID_FOR_RESPONSE_FOR_INVALID_FRAME)
Пример #12
0
    def test_that_receiving_encoded_message_should_decode_on_the_fly(
            self, unused_tcp_port):
        middleman_message = GolemMessageFrame(Ping(), self.request_id)
        raw_message = append_frame_separator(
            middleman_message.serialize(private_key=CONCENT_PRIVATE_KEY))

        raw_message = raw_message[:10] + ESCAPE_CHARACTER + raw_message[
            len(ESCAPE_CHARACTER) + 10:]
        raw_message_encoded = escape_encode_raw_message(raw_message)

        assert FRAME_SEPARATOR not in raw_message_encoded

        raw_message_encoded = append_frame_separator(raw_message_encoded)

        with closing(socket.socket(socket.AF_INET,
                                   socket.SOCK_STREAM)) as server_socket:
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                     True)
            with closing(socket.socket(socket.AF_INET,
                                       socket.SOCK_STREAM)) as client_socket:
                client_socket.setsockopt(socket.SOL_SOCKET,
                                         socket.SO_REUSEADDR, True)
                server_socket.bind(('127.0.0.1', unused_tcp_port))
                server_socket.listen(1)

                client_socket.connect(('127.0.0.1', unused_tcp_port))

                (connection, _address) = server_socket.accept()

                client_socket.send(raw_message_encoded)
                raw_message_received = next(
                    unescape_stream(connection=connection))

        assertpy_bytes_starts_with(raw_message, raw_message_received)
        assertpy.assert_that(
            len(raw_message_received)).is_greater_than_or_equal_to(
                FRAME_PAYLOAD_STARTING_BYTE)
    def test_that__handle_connection_should_send_error_frame_if_payload_is_invalid(
            self):
        # Prepare frame payload which is not Golem message.
        middleman_message = GolemMessageFrame(
            payload=Ping(),
            request_id=99,
        )
        raw_message = middleman_message.serialize(
            private_key=CONCENT_PRIVATE_KEY)
        malformed_raw_message = (
            raw_message[:FRAME_PAYLOAD_STARTING_BYTE] +
            AbstractFrame.get_frame_format(
            ).signed_part_of_the_frame.payload.build(b'\x00' * 100))

        # Replace message signature
        new_signature = ecdsa_sign(
            CONCENT_PRIVATE_KEY,
            malformed_raw_message[FRAME_SIGNATURE_BYTES_LENGTH:])
        malformed_raw_message_with_new_signature = new_signature + malformed_raw_message[
            FRAME_SIGNATURE_BYTES_LENGTH:]

        raw_message_received = self._prepare_and_execute_handle_connection(
            malformed_raw_message_with_new_signature)

        deserialized_message = AbstractFrame.deserialize(
            raw_message=raw_message_received,
            public_key=SIGNING_SERVICE_PUBLIC_KEY,
        )

        assertpy.assert_that(
            deserialized_message.payload).is_instance_of(tuple)
        assertpy.assert_that(deserialized_message.payload).is_length(2)
        assertpy.assert_that(deserialized_message.payload[0]).is_equal_to(
            ErrorCode.InvalidPayload)
        assertpy.assert_that(deserialized_message.request_id).is_equal_to(
            REQUEST_ID_FOR_RESPONSE_FOR_INVALID_FRAME)