Ejemplo n.º 1
0
    def test_that_signing_service_should_reconnect_when_expected_socket_error_was_caught(self):
        with mock.patch('socket.socket.connect', side_effect=socket.error()) as mock_socket_connect:
            with mock.patch('signing_service.signing_service.SigningService._was_sigterm_caught', side_effect=[False, False, True]):
                signing_service = SigningService(*self.parameters)
                signing_service.run()

        assertpy.assert_that(mock_socket_connect.call_count).is_equal_to(2)
Ejemplo n.º 2
0
    def test_that_signing_service_should_run_full_loop_when_instantiated_with_all_parameters(
            self):
        with mock.patch('socket.socket.connect') as mock_socket_connect:
            with mock.patch(
                    'signing_service.signing_service.SigningService._authenticate'
            ) as mock___authenticate:
                with mock.patch(
                        'signing_service.signing_service.SigningService._get_signing_service_daily_transaction_sum_so_far'
                ) as mock_daily_transaction_sum:
                    with mock.patch(
                            'signing_service.signing_service.SigningService._handle_connection'
                    ) as mock__handle_connection:
                        with mock.patch(
                                'socket.socket.close') as mock_socket_close:
                            with mock.patch(
                                    'signing_service.signing_service.SigningService._was_sigterm_caught',
                                    side_effect=[False, True]):
                                signing_service = SigningService(
                                    *self.parameters)
                                signing_service.run()

        mock_socket_connect.assert_called_once_with(('127.0.0.1', self.port))
        mock_socket_close.assert_called_once()
        mock___authenticate.assert_called_once()
        mock_daily_transaction_sum.assert_called_once()
        mock__handle_connection.assert_called_once()
Ejemplo n.º 3
0
    def test_that_signing_service_should_exit_gracefully_on_keyboard_interrupt(self):
        with mock.patch('socket.socket.connect', side_effect=KeyboardInterrupt()) as mock_socket_connect:
            with mock.patch('socket.socket.close') as mock_socket_close:
                signing_service = SigningService(*self.parameters)
                signing_service.run()

        mock_socket_connect.assert_called_once_with(('127.0.0.1', self.port))
        mock_socket_close.assert_called_once()
Ejemplo n.º 4
0
    def test_that_signing_service_should_reraise_unrecognized_exception(self):
        with mock.patch('socket.socket.connect', side_effect=Exception()) as mock_socket_connect:
            with mock.patch('socket.socket.close') as mock_socket_close:
                signing_service = SigningService(*self.parameters)
                with pytest.raises(Exception):
                    signing_service.run()

        mock_socket_connect.assert_called_once_with(('127.0.0.1', self.port))
        mock_socket_close.assert_called_once()
    def _prepare_and_execute_handle_connection(
            self,
            raw_message,
            handle_connection_wrapper=None,
            expect_response_from_scoket=True):
        def mocked_generator():
            yield raw_message
            raise SigningServiceValidationError()

        with mock.patch('signing_service.signing_service.SigningService.run'):
            with closing(socket.socket(
                    socket.AF_INET,
                    socket.SOCK_STREAM)) as signing_service_socket:
                signing_service_socket.setsockopt(socket.SOL_SOCKET,
                                                  socket.SO_REUSEADDR, 1)
                with closing(socket.socket(
                        socket.AF_INET, socket.SOCK_STREAM)) as client_socket:
                    client_socket.setsockopt(socket.SOL_SOCKET,
                                             socket.SO_REUSEADDR, 1)
                    signing_service = SigningService(
                        self.host,
                        self.port,
                        self.initial_reconnect_delay,
                        CONCENT_PUBLIC_KEY,
                        SIGNING_SERVICE_PRIVATE_KEY,
                        TEST_ETHEREUM_PRIVATE_KEY,
                        SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
                        ConsoleNotifier(),
                    )

                    # For test purposes we reverse roles, so signing service works as server.
                    signing_service_socket.bind(
                        ('127.0.0.1', self.signing_service_port))
                    signing_service_socket.listen(1)
                    client_socket.connect(
                        ('127.0.0.1', self.signing_service_port))
                    (connection, _address) = signing_service_socket.accept()
                    client_socket.setblocking(False)

                    with pytest.raises(SigningServiceValidationError):
                        if handle_connection_wrapper is not None:
                            handle_connection_wrapper(signing_service,
                                                      connection,
                                                      mocked_generator())
                        else:
                            signing_service._handle_connection(
                                mocked_generator(), connection)

                    if expect_response_from_scoket:
                        response = next(
                            unescape_stream(connection=client_socket))
                    else:
                        # We do not expect to get anything from the socket, dummy response is returned.
                        response = mock.sentinel.no_response

        return response
Ejemplo n.º 6
0
 def test_that_signing_service_will_reconnect_after_authentication_fails(self):
     with mock.patch('socket.socket.connect') as mock_socket_connect:
         with mock.patch('socket.socket.close') as mock_socket_close:
             with mock.patch('signing_service.signing_service.SigningService._authenticate', side_effect=socket.error()) as mock___authenticate:
                 with mock.patch('signing_service.signing_service.sleep'):
                     signing_service = SigningService(*self.parameters)
                     signing_service.run()
     assertpy.assert_that(mock_socket_connect.call_count).is_equal_to(SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS + 1)
     assertpy.assert_that(mock_socket_close.call_count).is_equal_to(SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS + 1)
     assertpy.assert_that(mock___authenticate.call_count).is_equal_to(SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS + 1)
Ejemplo n.º 7
0
class SigningServiceValidateArgumentsTestCase(TestCase):
    def setUp(self):
        super().setUp()
        self.host = '127.0.0.1'
        self.port = 8000
        self.initial_reconnect_delay = 2

        self.signing_service = SigningService(
            self.host,
            self.port,
            self.initial_reconnect_delay,
            CONCENT_PUBLIC_KEY,
            SIGNING_SERVICE_PRIVATE_KEY,
            TEST_ETHEREUM_PRIVATE_KEY,
            SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
            ConsoleNotifier(),
        )

    def test_that_signing_service__validate_arguments_should_raise_exception_on_port_number_below_or_above_range(
            self):
        for wrong_port in [0, 65535 + 1]:
            self.signing_service.port = wrong_port

            with self.assertRaises(SigningServiceValidationError):
                self.signing_service._validate_arguments()

    def test_that_signing_service__validate_arguments_should_raise_exception_on_initial_reconnect_delay_lower_than_zero(
            self):
        self.signing_service.initial_reconnect_delay = -1

        with self.assertRaises(SigningServiceValidationError):
            self.signing_service._validate_arguments()

    def test_that_signing_service__validate_arguments_should_raise_exception_on_wrong_length_of_concent_public_key(
            self):
        self.signing_service.concent_public_key = CONCENT_PUBLIC_KEY[:-1]

        with self.assertRaises(SigningServiceValidationError):
            self.signing_service._validate_arguments()

    def test_that_signing_service__validate_arguments_should_raise_exception_on_wrong_length_of_ethereum_private_key(
            self):
        self.signing_service.ethereum_private_key = TEST_ETHEREUM_PRIVATE_KEY[:
                                                                              -1]

        with self.assertRaises(SigningServiceValidationError):
            self.signing_service._validate_arguments()

    def test_that_signing_service__validate_arguments_should_raise_exception_on_wrong_characters_in_ethereum_private_key(
            self):
        self.signing_service.ethereum_private_key = self.signing_service.ethereum_private_key[:
                                                                                              -1] + 'g'

        with self.assertRaises(SigningServiceValidationError):
            self.signing_service._validate_arguments()
 def setUp(self, unused_tcp_port_factory):
     self.signing_service = SigningService(
         '127.0.0.1',
         unused_tcp_port_factory(),
         2,
         CONCENT_PUBLIC_KEY,
         SIGNING_SERVICE_PRIVATE_KEY,
         TEST_ETHEREUM_PRIVATE_KEY,
         SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
         ConsoleNotifier(),
     )
class SigningServiceGetSignedTransactionTestCase(SigningServiceIntegrationTestCase, TestCase):

    def setUp(self):
        self.host = '127.0.0.1'
        self.port = 8000
        self.initial_reconnect_delay = 2

        with mock.patch('signing_service.signing_service.SigningService.run'):
            self.signing_service = SigningService(
                self.host,
                self.port,
                self.initial_reconnect_delay,
                CONCENT_PUBLIC_KEY,
                SIGNING_SERVICE_PRIVATE_KEY,
                TEST_ETHEREUM_PRIVATE_KEY,
                SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
                ConsoleNotifier(),
            )

    def test_that_get_signed_transaction_should_return_transaction_signed_if_transaction_was_signed_correctly(self):
        transaction_signing_request = self._get_deserialized_transaction_signing_request()

        transaction_signed = self.signing_service._get_signed_transaction(transaction_signing_request)

        self.assertIsInstance(transaction_signed, SignedTransaction)
        self.assertEqual(transaction_signed.nonce, transaction_signing_request.nonce)  # pylint: disable=no-member
        self.assertEqual(transaction_signed.gasprice, transaction_signing_request.gasprice)  # pylint: disable=no-member
        self.assertEqual(transaction_signed.startgas, transaction_signing_request.startgas)  # pylint: disable=no-member
        self.assertEqual(transaction_signed.to, transaction_signing_request.to)  # pylint: disable=no-member
        self.assertEqual(transaction_signed.value, transaction_signing_request.value)  # pylint: disable=no-member
        self.assertEqual(transaction_signed.data, transaction_signing_request.data)  # pylint: disable=no-member
        self.assertEqual(transaction_signed.v, 27)  # pylint: disable=no-member
        self.assertEqual(transaction_signed.r, 30388804072119173430692318653717116791007045427887199775992056799290419449340)  # pylint: disable=no-member
        self.assertEqual(transaction_signed.s, 12415095341641447952516229207372622127096123813439844824954905697584046077123)  # pylint: disable=no-member

    def test_that_get_signed_transaction_should_return_transaction_rejected_if_transaction_cannot_be_recreated_from_received_transaction_signing_request(self):
        transaction_signing_request = self._get_deserialized_transaction_signing_request()
        transaction_signing_request.nonce = 'invalid_nonce'

        transaction_rejected = self.signing_service._get_signed_transaction(transaction_signing_request)

        self.assertIsInstance(transaction_rejected, TransactionRejected)
        self.assertEqual(transaction_rejected.reason, TransactionRejected.REASON.InvalidTransaction)  # pylint: disable=no-member

    def test_that_get_signed_transaction_should_return_transaction_rejected_if_transaction_cannot_be_signed(self):
        transaction_signing_request = self._get_deserialized_transaction_signing_request()
        self.signing_service.ethereum_private_key = b'\x00'

        transaction_rejected = self.signing_service._get_signed_transaction(transaction_signing_request)

        self.assertIsInstance(transaction_rejected, TransactionRejected)
        self.assertEqual(transaction_rejected.reason, TransactionRejected.REASON.UnauthorizedAccount)  # pylint: disable=no-member
Ejemplo n.º 10
0
class SigningServiceDailyThresholdTestCase(TestCase):
    def setUp(self):
        self.host = '127.0.0.1'
        self.port = 8000
        self.initial_reconnect_delay = 2

        with mock.patch('signing_service.signing_service.SigningService.run'):
            self.signing_service = SigningService(
                self.host,
                self.port,
                self.initial_reconnect_delay,
                CONCENT_PUBLIC_KEY,
                SIGNING_SERVICE_PRIVATE_KEY,
                TEST_ETHEREUM_PRIVATE_KEY,
                SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
                ConsoleNotifier(),
            )

    def test_that_signing_service_get_daily_transaction_threshold_file_directory_should_return_existing_file(
            self):
        threshold_file = self.signing_service._get_daily_transaction_threshold_file_path(
        )
        self.assertTrue(threshold_file.exists())  # pylint: disable=no-member
        self.assertTrue(threshold_file.is_file())  # pylint: disable=no-member
        threshold_file.unlink()  # pylint: disable=no-member

    def test_that_add_payload_value_to_daily_transactions_sum_write_int_and_get_signing_service_daily_transaction_sum_so_far_returns_correct_value(
            self):
        threshold_file = self.signing_service._get_daily_transaction_threshold_file_path(
        )
        self.signing_service._add_payload_value_to_daily_transactions_sum(1337)
        transaction_sum = self.signing_service._get_signing_service_daily_transaction_sum_so_far(
        )
        self.assertEqual(transaction_sum, 1337)
        threshold_file.unlink()  # pylint: disable=no-member

    def test_that_signing_service_get_signing_service_daily_transaction_sum_so_far_returns_zero_in_case_of_value_error(
            self):
        threshold_file = self.signing_service._get_daily_transaction_threshold_file_path(
        )
        threshold_file.write_text('GolemConcent')  # pylint: disable=no-member
        transaction_sum = self.signing_service._get_signing_service_daily_transaction_sum_so_far(
        )
        self.assertEqual(transaction_sum, 0)
        threshold_file.unlink()  # pylint: disable=no-member

    def test_that_signing_service_update_daily_transactions_limit_file_name_overwrite_old_value(
            self):
        self.signing_service.daily_transactions_limit_file_name = '1970-01-01'
        self.signing_service.signing_service_daily_transaction_sum_so_far = 10000
        self.signing_service._update_daily_transactions_limit_file_name()
        self.assertEqual(
            self.signing_service.daily_transactions_limit_file_name,
            datetime.datetime.now().strftime('%Y-%m-%d'))
        self.assertEqual(
            self.signing_service.signing_service_daily_transaction_sum_so_far,
            0)
Ejemplo n.º 11
0
 def test_that_signing_service_will_reconnect_on_socket_errors_and_exit_gracefully_when_exceeds_maximum_number_of_reconnection_attempts(self):
     with mock.patch('socket.socket.connect', side_effect=socket.error()) as mock_socket_connect:
         with mock.patch('socket.socket.close') as mock_socket_close:
             with mock.patch('signing_service.signing_service.sleep'):
                 signing_service = SigningService(*self.parameters)
                 with mock.patch('signing_service.signing_service.logger.error') as mock_logger_error:
                     signing_service.run()
     assertpy.assert_that(mock_socket_connect.call_count).is_equal_to(SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS + 1)
     assertpy.assert_that(mock_socket_close.call_count).is_equal_to(SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS + 1)
     assertpy.assert_that(
         mock_logger_error.call_args_list[mock_logger_error.call_count - 1],
         ['Maximum number of reconnection exceeded.'],
     )
Ejemplo n.º 12
0
 def test_that_signing_service_will_reconnect_on_socket_errors_and_raise_exception_when_exceeds_maxium_number_of_reconnection_attempts(
         self):
     with mock.patch('socket.socket.connect',
                     side_effect=socket.error()) as mock_socket_connect:
         with mock.patch('socket.socket.close') as mock_socket_close:
             with mock.patch('signing_service.signing_service.sleep'):
                 signing_service = SigningService(*self.parameters)
                 with pytest.raises(
                         SigningServiceMaximumReconnectionAttemptsExceeded):
                     signing_service.run()
     assertpy.assert_that(mock_socket_connect.call_count).is_equal_to(
         SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS + 1)
     assertpy.assert_that(mock_socket_close.call_count).is_equal_to(
         SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS + 1)
    def setUp(self):
        self.host = '127.0.0.1'
        self.port = 8000
        self.initial_reconnect_delay = 2

        with mock.patch('signing_service.signing_service.SigningService.run'):
            self.signing_service = SigningService(
                self.host,
                self.port,
                self.initial_reconnect_delay,
                CONCENT_PUBLIC_KEY,
                SIGNING_SERVICE_PRIVATE_KEY,
                TEST_ETHEREUM_PRIVATE_KEY,
                SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
                ConsoleNotifier(),
            )
class SigningServiceGetAuthenticationChallengeSignatureTestCase(SigningServiceIntegrationTestCase, TestCase):

    def setUp(self):
        self.host = '127.0.0.1'
        self.port = 8000
        self.initial_reconnect_delay = 2

        with mock.patch('signing_service.signing_service.SigningService.run'):
            self.signing_service = SigningService(
                self.host,
                self.port,
                self.initial_reconnect_delay,
                CONCENT_PUBLIC_KEY,
                SIGNING_SERVICE_PRIVATE_KEY,
                TEST_ETHEREUM_PRIVATE_KEY,
                SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
                ConsoleNotifier(),
            )

    def test_that_get_authentication_challenge_signature_should_return_signature_of_passed_bytes(self):
        authentication_challenge = bytes(os.urandom(1000))

        signature = self.signing_service._get_authentication_challenge_signature(authentication_challenge)

        self.assertIsInstance(signature, bytes)
        self.assertTrue(
            ecdsa_verify(
                self.signing_service.signing_service_public_key,
                signature,
                authentication_challenge,
            )
        )
Ejemplo n.º 15
0
    def test_that_signing_service_should_be_instantiated_correctly_with_all_parameters(self):
        signing_service = SigningService(*self.parameters)

        assertpy.assert_that(signing_service).is_instance_of(SigningService)
        assertpy.assert_that(signing_service.host).is_equal_to(self.host)
        assertpy.assert_that(signing_service.port).is_equal_to(self.port)
        assertpy.assert_that(signing_service.initial_reconnect_delay).is_equal_to(self.initial_reconnect_delay)
class TestSigningServiceIncreaseDelay:

    @pytest.fixture(autouse=True)
    def setUp(self, unused_tcp_port_factory):
        self.signing_service = SigningService(
            '127.0.0.1',
            unused_tcp_port_factory(),
            2,
            CONCENT_PUBLIC_KEY,
            SIGNING_SERVICE_PRIVATE_KEY,
            TEST_ETHEREUM_PRIVATE_KEY,
            SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
            ConsoleNotifier(),
        )

    def test_that_initial_reconnect_delay_should_be_set_to_passed_value(self):
        assertpy.assert_that(self.signing_service.current_reconnect_delay).is_equal_to(None)
        assertpy.assert_that(self.signing_service.initial_reconnect_delay).is_equal_to(2)

    def test_that_current_reconnect_delay_should_be_set_to_reconnect_delay_after_first_call_to__increase_delay(self):
        self.signing_service._increase_delay()
        assertpy.assert_that(self.signing_service.current_reconnect_delay).is_equal_to(2)

    def test_that_current_reconnect_delay_should_be_doubled_after_next_call_to__increase_delay(self):
        self.signing_service._increase_delay()
        self.signing_service._increase_delay()
        assertpy.assert_that(self.signing_service.current_reconnect_delay).is_equal_to(2 * 2)

    def test_that_current_reconnect_delay_should_be_set_to_allowed_maximum_after_it_extends_it(self):
        self.signing_service.current_reconnect_delay = SIGNING_SERVICE_MAXIMUM_RECONNECT_TIME - 1
        self.signing_service._increase_delay()
        assertpy.assert_that(self.signing_service.current_reconnect_delay).is_equal_to(SIGNING_SERVICE_MAXIMUM_RECONNECT_TIME)
Ejemplo n.º 17
0
    def _prepare_and_execute_handle_connection(self, raw_message):
        def mocked_generator():
            yield raw_message

        with mock.patch('signing_service.signing_service.SigningService.run'):
            with closing(socket.socket(
                    socket.AF_INET,
                    socket.SOCK_STREAM)) as signing_service_socket:
                signing_service_socket.setsockopt(socket.SOL_SOCKET,
                                                  socket.SO_REUSEADDR, 1)
                with closing(socket.socket(
                        socket.AF_INET, socket.SOCK_STREAM)) as client_socket:
                    client_socket.setsockopt(socket.SOL_SOCKET,
                                             socket.SO_REUSEADDR, 1)
                    signing_service = SigningService(
                        self.host,
                        self.port,
                        self.initial_reconnect_delay,
                        CONCENT_PUBLIC_KEY,
                        SIGNING_SERVICE_PRIVATE_KEY,
                        TEST_ETHEREUM_PRIVATE_KEY,
                        SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
                        ConsoleNotifier(),
                    )

                    # For test purposes we reverse roles, so signing service works as server.
                    signing_service_socket.bind(
                        ('127.0.0.1', self.signing_service_port))
                    signing_service_socket.listen(1)
                    client_socket.connect(
                        ('127.0.0.1', self.signing_service_port))
                    (connection, _address) = signing_service_socket.accept()

                    signing_service._authenticate(mocked_generator(),
                                                  connection)
                    raw_message_received = next(
                        unescape_stream(connection=client_socket))

        return raw_message_received
class SigningServiceSetSigtermTestCase(TestCase):

    def setUp(self):
        self.host = '127.0.0.1'
        self.port = 8000
        self.initial_reconnect_delay = 2

        with mock.patch('signing_service.signing_service.SigningService.run'):
            self.signing_service = SigningService(
                self.host,
                self.port,
                self.initial_reconnect_delay,
                CONCENT_PUBLIC_KEY,
                SIGNING_SERVICE_PRIVATE_KEY,
                TEST_ETHEREUM_PRIVATE_KEY,
                SIGNING_SERVICE_DEFAULT_RECONNECT_ATTEMPTS,
                ConsoleNotifier(),
            )

    def test_that_calling_set_was_sigterm_caught_sets_was_sigterm_caught_to_true(self):
        self.signing_service._set_was_sigterm_caught_true(mock.Mock(), mock.Mock())
        self.assertTrue(self.signing_service.was_sigterm_caught)
Ejemplo n.º 19
0
if __name__ == '__main__':

    logging.config.fileConfig(
        os.path.join(os.path.dirname(os.path.abspath(__file__)), '..',
                     'logging.ini'))

    # Parse required arguments.
    args = _parse_arguments()

    raven_client = Client(
        dsn=args.sentry_dsn,
        environment=args.sentry_environment,
        tags={
            'component': 'signing-service',
        },
    )
    crash_logger.handlers[0].client = raven_client  # type: ignore

    notifier = get_notifier(args)

    SigningService(
        args.concent_cluster_host,
        args.concent_cluster_port,
        args.initial_reconnect_delay,
        args.concent_public_key,
        args.signing_service_private_key,
        args.ethereum_private_key,
        args.max_reconnect_attempts,
        notifier,
    ).run()