Ejemplo n.º 1
0
    def test_new_fork_head_not_poet_block(
            self,
            mock_utils,
            mock_validator_registry_view,
            mock_consensus_state,
            mock_poet_enclave_factory,
            mock_consensus_state_store):

        """ Test verifies that if the new fork head is not a valid block,
            raises appropriate exception
        """

        # create a mock_validator_registry_view
        mock_validator_registry_view.return_value.get_validator_info. \
            return_value = \
            ValidatorInfo(
                name='validator_001',
                id='validator_deadbeef',
                signup_info=SignUpInfo(
                    poet_public_key='00112233445566778899aabbccddeeff'))

        # Make utils pretend it cannot deserialize the wait certificate
        # of the new fork head
        mock_utils.deserialize_wait_certificate.return_value = None

        mock_block_cache = mock.MagicMock()
        mock_state_view_factory = mock.Mock()

        # create mock_cur_fork_head
        mock_cur_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543210',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='2',
                header_signature='00112233445566778899aabbccddeeff')

        # create mock_new_fork_head
        mock_new_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543211',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='2',
                header_signature='00112233445566778899aabbccddeeff')

        # check test
        fork_resolver = \
            poet_fork_resolver.PoetForkResolver(
                block_cache=mock_block_cache,
                state_view_factory=mock_state_view_factory,
                data_dir=self._temp_dir,
                config_dir=self._temp_dir,
                validator_id='validator_deadbeef')

        with self.assertRaises(TypeError) as cm:
            fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_new_fork_header)
            self.assertEqual(
                'New fork head {} is not a PoET block',
                str(cm.exception))
Ejemplo n.º 2
0
    def test_different_previous_block_id(
            self,
            mock_utils,
            mock_validator_registry_view,
            mock_consensus_state,
            mock_poet_enclave_factory,
            mock_consensus_state_store):

        """ When both current and new fork heads are valid
            PoET blocks with different previous block ids,
            the test verifies that the one with
            the higher aggregate local mean wins
        """

        # create a mock_validator_registry_view
        mock_validator_registry_view.return_value.get_validator_info. \
            return_value = \
            ValidatorInfo(
                name='validator_001',
                id='validator_deadbeef',
                signup_info=SignUpInfo(
                    poet_public_key='00112233445566778899aabbccddeeff'))

        # create a mock_wait_certificate that does nothing in check_valid
        mock_wait_certificate = mock.Mock()
        mock_wait_certificate.check_valid.return_value = None
        # set new_mock_wait_certificate local_mean and duration
        mock_wait_certificate.local_mean = 0.0

        # set mock_utils.deserialize_wait_certificate
        # to return a specific value for each fork_head
        # with cur_fork_head being deserialized first
        mock_utils.deserialize_wait_certificate.side_effect = \
            [mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate
             ]

        mock_block_cache = mock.MagicMock()
        mock_state_view_factory = mock.Mock()

        # create mock_cur_fork_head
        mock_cur_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543210',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='2',
                header_signature='00112233445566778899aabbccddeeff')

        # create mock_new_fork_head
        mock_new_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543211',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='3',
                header_signature='00112233445566778899aabbccddeeff')

        fork_resolver = \
            poet_fork_resolver.PoetForkResolver(
                block_cache=mock_block_cache,
                state_view_factory=mock_state_view_factory,
                data_dir=self._temp_dir,
                config_dir=self._temp_dir,
                validator_id='validator_deadbeef')

        # Subtest 1: when the current fork head has
        # the higher aggregate local mean
        # create a mock_cur_fork_consensus_state
        mock_cur_fork_consensus_state = mock.Mock()
        mock_cur_fork_consensus_state.aggregate_local_mean = 1.0

        # create a mock_new_fork_consensus_state
        mock_new_fork_consensus_state = mock.Mock()
        mock_new_fork_consensus_state.aggregate_local_mean = 0.0

        # set mock_consensus_state.consensus_state_for_block_id return
        # the current & new fork consensus states
        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_cur_fork_consensus_state,
             mock_new_fork_consensus_state]

        # check test
        with mock.patch('sawtooth_poet.poet_consensus.poet_fork_resolver.'
                        'LOGGER') as mock_logger:
            self.assertFalse(fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_new_fork_header))

            # Could be a hack, but verify that the appropriate log message is
            # generated - so we at least have some faith that the failure was
            # because of what we are testing and not something else.  I know
            # that this is fragile if the log message is changed, so would
            # accept any suggestions on a better way to verify that the
            # function fails for the reason we expect.

            (message, *_), _ = mock_logger.info.call_args
            self.assertTrue('Current fork aggregate local mean (%f) '
                            'greater than new fork aggregate local mean'
                            in message)

        # Subtest 2: when the new fork head has
        # the higher aggregate local mean

        # set mock_consensus_state.consensus_state_for_block_id return
        # the current & new fork consensus states
        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_cur_fork_consensus_state,
             mock_new_fork_consensus_state,
             mock_new_fork_consensus_state]

        # change the aggregate_local_mean values
        mock_cur_fork_consensus_state.aggregate_local_mean = 0.0
        mock_new_fork_consensus_state.aggregate_local_mean = 1.0

        # check test
        with mock.patch('sawtooth_poet.poet_consensus.poet_fork_resolver.'
                        'LOGGER') as mock_logger:
            self.assertTrue(fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_new_fork_header))

            # Could be a hack, but verify that the appropriate log message is
            # generated - so we at least have some faith that the failure was
            # because of what we are testing and not something else.  I know
            # that this is fragile if the log message is changed, so would
            # accept any suggestions on a better way to verify that the
            # function fails for the reason we expect.

            (message, *_), _ = mock_logger.info.call_args
            self.assertTrue('New fork aggregate local mean (%f) '
                            'greater than current fork aggregate local mean '
                            in message)

        # Subtest 3: when both the new & current fork heads have
        # the same aggregate local mean

        # set mock_consensus_state.consensus_state_for_block_id return
        # the current & new fork consensus states
        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_cur_fork_consensus_state,
             mock_new_fork_consensus_state,
             mock_new_fork_consensus_state]

        # set the aggregate_local_mean values equal
        mock_cur_fork_consensus_state.aggregate_local_mean = 1.0
        mock_new_fork_consensus_state.aggregate_local_mean = 1.0

        # check test
        with mock.patch('sawtooth_poet.poet_consensus.poet_fork_resolver.'
                        'LOGGER') as mock_logger:
            self.assertTrue(fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_new_fork_header))

            # Could be a hack, but verify that the appropriate log message is
            # generated - so we at least have some faith that the failure was
            # because of what we are testing and not something else.  I know
            # that this is fragile if the log message is changed, so would
            # accept any suggestions on a better way to verify that the
            # function fails for the reason we expect.

            (message, *_), _ = mock_logger.info.call_args
            self.assertTrue('New fork header signature (%s) '
                            'greater than current fork header signature (%s)'
                            in message)

        # Subset 4: If we have gotten to this point and we have not chosen
        # a fork head yet, we are going to fall back
        # on using the block identifiers (header signatures).
        # The lexicographically larger one will be the chosen one.

        # create mock_new_fork_head with a smaller header_signature
        mock_smaller_header_signature = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543211',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='4',
                header_signature='00112233445566778899aabbccddee')

        # create a mock_smaller_header_signature_consensus_state
        mock_smaller_header_signature_consensus_state = mock.Mock()
        mock_smaller_header_signature_consensus_state.\
            aggregate_local_mean = 0.0

        mock_cur_fork_consensus_state.aggregate_local_mean = 0.0

        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_cur_fork_consensus_state,
             mock_smaller_header_signature_consensus_state]

        # check test when Current fork header signature is greater than
        # the new fork header signature
        with mock.patch('sawtooth_poet.poet_consensus.poet_fork_resolver.'
                        'LOGGER') as mock_logger:
            self.assertFalse(fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_smaller_header_signature))

            # Could be a hack, but verify that the appropriate log message is
            # generated - so we at least have some faith that the failure was
            # because of what we are testing and not something else.  I know
            # that this is fragile if the log message is changed, so would
            # accept any suggestions on a better way to verify that the
            # function fails for the reason we expect.

            (message, *_), _ = mock_logger.info.call_args
            self.assertTrue('Current fork header signature'
                            '(%s) greater than new fork header signature (%s)'
                            in message)

        # Subtest 5: Check when new header signature is greater than
        # the current fork header signature

        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_smaller_header_signature_consensus_state,
             mock_new_fork_consensus_state,
             mock_new_fork_consensus_state]

        mock_smaller_header_signature_consensus_state.\
            aggregate_local_mean = 0.0
        mock_new_fork_consensus_state.aggregate_local_mean = 0.0

        # check test
        with mock.patch('sawtooth_poet.poet_consensus.poet_fork_resolver.'
                        'LOGGER') as mock_logger:
            self.assertTrue(fork_resolver.compare_forks(
                cur_fork_head=mock_smaller_header_signature,
                new_fork_head=mock_new_fork_header))

            # Could be a hack, but verify that the appropriate log message is
            # generated - so we at least have some faith that the failure was
            # because of what we are testing and not something else.  I know
            # that this is fragile if the log message is changed, so would
            # accept any suggestions on a better way to verify that the
            # function fails for the reason we expect.

            (message, *_), _ = mock_logger.info.call_args
            self.assertTrue('New fork header signature (%s) '
                            'greater than current fork header signature (%s)'
                            in message)
Ejemplo n.º 3
0
    def test_cur_fork_head_not_poet_block(
            self,
            mock_utils,
            mock_validator_registry_view,
            mock_consensus_state,
            mock_poet_enclave_factory,
            mock_consensus_state_store):

        """ Test verifies that if the current fork head is not a valid block,
            and if new_fork_head.previous_block_id == cur_fork_head.identifier
            then the new fork head switches consensus. Otherwise, raises the
            appropriate exception - trying to compare a PoET block to a
            non-PoET block that is not the direct predecessor
        """

        # create a mock_validator_registry_view
        mock_validator_registry_view.return_value.get_validator_info. \
            return_value = \
            ValidatorInfo(
                name='validator_001',
                id='validator_deadbeef',
                signup_info=SignUpInfo(
                    poet_public_key='00112233445566778899aabbccddeeff'))

        # create a mock_wait_certificate that does nothing in check_valid
        mock_wait_certificate = mock.Mock()
        mock_wait_certificate.check_valid.return_value = None

        # set mock_utils.deserialize_wait_certificate
        # to return a specific value for each fork_head that is used in
        # poet_fork_resolver.compare()
        # with cur_fork_head being deserialized first
        mock_utils.deserialize_wait_certificate.side_effect = \
            [None,
             mock_wait_certificate,
             None,
             mock_wait_certificate]

        mock_block_cache = mock.MagicMock()
        mock_state_view_factory = mock.Mock()

        # create mock_cur_fork_head
        mock_cur_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543210',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='2',
                header_signature='00112233445566778899aabbccddeeff')

        # create mock_new_fork_head
        mock_new_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543211',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='2',
                header_signature='00112233445566778899aabbccddeeff')

        fork_resolver = \
            poet_fork_resolver.PoetForkResolver(
                block_cache=mock_block_cache,
                state_view_factory=mock_state_view_factory,
                data_dir=self._temp_dir,
                config_dir=self._temp_dir,
                validator_id='validator_deadbeef')

        # Subtest 1: check that the test fails when the current
        # fork head is not a valid PoET block
        with self.assertRaises(TypeError) as cm:
            fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_new_fork_header)
            self.assertEqual(
                'Trying to compare a PoET block to a non-PoET '
                'block that is not the direct predecessor',
                str(cm.exception))

        # Subtest 2: check that if new_fork_head.previous_block_id
        # == cur_fork_head.identifier
        # then the new fork head switches consensus

        # modify mock_cur_fork_header.identifier
        mock_cur_fork_header.identifier = \
            mock_new_fork_header.previous_block_id

        # check test
        with mock.patch('sawtooth_poet.poet_consensus.poet_fork_resolver.'
                        'LOGGER') as mock_logger:
            self.assertTrue(fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_new_fork_header))

            # Could be a hack, but verify that the appropriate log message is
            # generated - so we at least have some faith that the failure was
            # because of what we are testing and not something else.  I know
            # that this is fragile if the log message is changed, so would
            # accept any suggestions on a better way to verify that the
            # function fails for the reason we expect.

            (message, *_), _ = mock_logger.info.call_args
            self.assertTrue('New fork head switches consensus to PoET'
                            in message)
Ejemplo n.º 4
0
    def test_both_valid_poet_blocks(
            self,
            mock_utils,
            mock_validator_registry_view,
            mock_consensus_state,
            mock_poet_enclave_factory,
            mock_consensus_state_store):

        """ If both current and new fork heads are valid PoET blocks,
            the test checks if they share the same immediate previous block,
            then the one with the smaller wait duration is chosen
        """

        # create a mock_validator_registry_view
        mock_validator_registry_view.return_value.get_validator_info. \
            return_value = \
            ValidatorInfo(
                name='validator_001',
                id='validator_deadbeef',
                signup_info=SignUpInfo(
                    poet_public_key='00112233445566778899aabbccddeeff'))

        # create a mock_wait_certificate that does nothing in check_valid
        mock_wait_certificate = mock.Mock()
        mock_wait_certificate.check_valid.return_value = None

        # set new_mock_wait_certificate local_mean and duration
        mock_wait_certificate.local_mean = 0.0
        mock_wait_certificate.duration = 1.0

        # create a new_fork_mock_wait_certificate with a higher duration time
        new_fork_mock_wait_certificate = mock.Mock()
        new_fork_mock_wait_certificate.check_valid.return_value = None
        new_fork_mock_wait_certificate.local_mean = 0.0
        new_fork_mock_wait_certificate.duration = 2.0

        # set mock_utils.deserialize_wait_certificate
        # to return a specific value for each fork_head that is used in
        # poet_fork_resolver.compare()
        # with cur_fork_head being deserialized first
        mock_utils.deserialize_wait_certificate.side_effect = \
            [mock_wait_certificate,
             new_fork_mock_wait_certificate
             ]

        mock_block_cache = mock.MagicMock()
        mock_state_view_factory = mock.Mock()

        # create mock_cur_fork_head
        mock_cur_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543210',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='2',
                header_signature='00112233445566778899aabbccddeeff')

        # create mock_new_fork_head with same previous block id
        mock_new_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543211',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='2',
                header_signature='00112233445566778899aabbccddeeff')

        fork_resolver = \
            poet_fork_resolver.PoetForkResolver(
                block_cache=mock_block_cache,
                state_view_factory=mock_state_view_factory,
                data_dir=self._temp_dir,
                config_dir=self._temp_dir,
                validator_id='validator_deadbeef')

        # Subtest 1: when current fork head has the smaller wait duration
        with mock.patch('sawtooth_poet.poet_consensus.poet_fork_resolver.'
                        'LOGGER') as mock_logger:
            self.assertFalse(fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_new_fork_header))

            # Could be a hack, but verify that the appropriate log message is
            # generated - so we at least have some faith that the failure was
            # because of what we are testing and not something else.  I know
            # that this is fragile if the log message is changed, so would
            # accept any suggestions on a better way to verify that the
            # function fails for the reason we expect.

            (message, *_), _ = mock_logger.info.call_args
            self.assertTrue('Current fork wait duration (%f) '
                            'less than new fork wait duration (%f)' in message)

        # Subtest 2: when new fork head has the smaller wait duration

        # change new_fork_mock_wait_certificate duration to a smaller value
        new_fork_mock_wait_certificate.duration = 0.0

        # set mock_utils.deserialize_wait_certificate
        # to return a specific value for each fork_head
        # with cur_fork_head being deserialized first
        mock_utils.deserialize_wait_certificate.side_effect = \
            [mock_wait_certificate,
             new_fork_mock_wait_certificate]

        # check test
        with mock.patch('sawtooth_poet.poet_consensus.poet_fork_resolver.'
                        'LOGGER') as mock_logger:
            self.assertTrue(fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_new_fork_header))

            # Could be a hack, but verify that the appropriate log message is
            # generated - so we at least have some faith that the failure was
            # because of what we are testing and not something else.  I know
            # that this is fragile if the log message is changed, so would
            # accept any suggestions on a better way to verify that the
            # function fails for the reason we expect.

            (message, *_), _ = mock_logger.info.call_args
            self.assertTrue('New fork wait duration (%f) '
                            'less than current fork wait duration '
                            in message)

        # Subtest 3: when new & current fork heads have
        # the same wait duration

        # change new_fork_mock_wait_certificate duration to a smaller value
        new_fork_mock_wait_certificate.duration = 1.0

        # set mock_utils.deserialize_wait_certificate
        # to return a specific value for each fork_head
        # with cur_fork_head being deserialized first
        mock_utils.deserialize_wait_certificate.side_effect = \
            [mock_wait_certificate,
             new_fork_mock_wait_certificate]

        # check test
        with mock.patch('sawtooth_poet.poet_consensus.poet_fork_resolver.'
                        'LOGGER') as mock_logger:
            self.assertTrue(fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_new_fork_header))

            # Could be a hack, but verify that the appropriate log message is
            # generated - so we at least have some faith that the failure was
            # because of what we are testing and not something else.  I know
            # that this is fragile if the log message is changed, so would
            # accept any suggestions on a better way to verify that the
            # function fails for the reason we expect.

            (message, *_), _ = mock_logger.info.call_args
            self.assertTrue('New fork header signature (%s) '
                            'greater than current fork header signature (%s)'
                            in message)
Ejemplo n.º 5
0
    def test_different_previous_block_id(self, mock_utils,
                                         mock_validator_registry_view,
                                         mock_consensus_state,
                                         mock_poet_enclave_factory,
                                         mock_consensus_state_store):
        """ When both current and new fork heads are valid
            PoET blocks with different previous block ids,
            the test verifies that the one with
            the higher aggregate local mean wins
        """

        # create a mock_validator_registry_view
        mock_validator_registry_view.return_value.get_validator_info. \
            return_value = \
            ValidatorInfo(
                name='validator_001',
                id='validator_deadbeef',
                signup_info=SignUpInfo(
                    poet_public_key='00112233445566778899aabbccddeeff'))

        # create a mock_wait_certificate that does nothing in check_valid
        mock_wait_certificate = mock.Mock()
        mock_wait_certificate.check_valid.return_value = None
        # set new_mock_wait_certificate local_mean and duration
        mock_wait_certificate.local_mean = 0.0

        # set mock_utils.deserialize_wait_certificate
        # to return a specific value for each fork_head
        # with cur_fork_head being deserialized first
        mock_utils.deserialize_wait_certificate.side_effect = \
            [mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate,
             mock_wait_certificate
             ]

        mock_block_cache = mock.MagicMock()
        mock_state_view_factory = mock.Mock()

        # create mock_cur_fork_head
        mock_cur_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543210',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='2',
                header_signature='00112233445566778899aabbccddeeff')

        # create mock_new_fork_head, with different header signature
        mock_new_fork_header = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543211',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='3',
                header_signature='00112233445566778899aabbccddefff')

        fork_resolver = \
            poet_fork_resolver.PoetForkResolver(
                block_cache=mock_block_cache,
                state_view_factory=mock_state_view_factory,
                data_dir=self._temp_dir,
                config_dir=self._temp_dir,
                validator_id='validator_deadbeef')

        # Subtest 1: when the current fork head has
        # the higher aggregate local mean
        # create a mock_cur_fork_consensus_state
        mock_cur_fork_consensus_state = mock.Mock()
        mock_cur_fork_consensus_state.aggregate_local_mean = 1.0

        # create a mock_new_fork_consensus_state
        mock_new_fork_consensus_state = mock.Mock()
        mock_new_fork_consensus_state.aggregate_local_mean = 0.0

        # set mock_consensus_state.consensus_state_for_block_id return
        # the current & new fork consensus states
        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_cur_fork_consensus_state,
             mock_new_fork_consensus_state]

        # check test
        self.assertFalse(
            fork_resolver.compare_forks(cur_fork_head=mock_cur_fork_header,
                                        new_fork_head=mock_new_fork_header))

        # Subtest 2: when the new fork head has
        # the higher aggregate local mean

        # set mock_consensus_state.consensus_state_for_block_id return
        # the current & new fork consensus states
        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_cur_fork_consensus_state,
             mock_new_fork_consensus_state,
             mock_new_fork_consensus_state]

        # change the aggregate_local_mean values
        mock_cur_fork_consensus_state.aggregate_local_mean = 0.0
        mock_new_fork_consensus_state.aggregate_local_mean = 1.0

        # check test
        self.assertTrue(
            fork_resolver.compare_forks(cur_fork_head=mock_cur_fork_header,
                                        new_fork_head=mock_new_fork_header))

        # Subtest 3: when both the new & current fork heads have
        # the same aggregate local mean

        # set mock_consensus_state.consensus_state_for_block_id return
        # the current & new fork consensus states
        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_cur_fork_consensus_state,
             mock_new_fork_consensus_state,
             mock_new_fork_consensus_state]

        # set the aggregate_local_mean values equal
        mock_cur_fork_consensus_state.aggregate_local_mean = 1.0
        mock_new_fork_consensus_state.aggregate_local_mean = 1.0

        # check test, return true indicates that new fork won
        self.assertTrue(
            fork_resolver.compare_forks(cur_fork_head=mock_cur_fork_header,
                                        new_fork_head=mock_new_fork_header))

        # Subset 4: If we have gotten to this point and we have not chosen
        # a fork head yet, we are going to fall back
        # on using the block identifiers (header signatures).
        # The lexicographically larger one will be the chosen one.

        # create mock_new_fork_head with a smaller header_signature
        mock_smaller_header_signature = \
            mock.Mock(
                identifier='0123456789abcdefedcba9876543211',
                signer_public_key='90834587139405781349807435098745',
                previous_block_id='4',
                header_signature='00112233445566778899aabbccddee')

        # create a mock_smaller_header_signature_consensus_state
        mock_smaller_header_signature_consensus_state = mock.Mock()
        mock_smaller_header_signature_consensus_state.\
            aggregate_local_mean = 0.0

        mock_cur_fork_consensus_state.aggregate_local_mean = 0.0

        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_cur_fork_consensus_state,
             mock_smaller_header_signature_consensus_state]

        # check test when Current fork header signature is greater than
        # the new fork header signature
        self.assertFalse(
            fork_resolver.compare_forks(
                cur_fork_head=mock_cur_fork_header,
                new_fork_head=mock_smaller_header_signature))

        # Subtest 5: Check when new header signature is greater than
        # the current fork header signature

        mock_consensus_state.consensus_state_for_block_id.side_effect = \
            [mock_smaller_header_signature_consensus_state,
             mock_new_fork_consensus_state,
             mock_new_fork_consensus_state]

        mock_smaller_header_signature_consensus_state.\
            aggregate_local_mean = 0.0
        mock_new_fork_consensus_state.aggregate_local_mean = 0.0

        # check test
        self.assertTrue(
            fork_resolver.compare_forks(
                cur_fork_head=mock_smaller_header_signature,
                new_fork_head=mock_new_fork_header))