def test_z_policy(self, mock_utils, mock_validator_registry_view, mock_consensus_state, mock_poet_enclave_factory, mock_poet_settings_view, mock_block_wrapper, mock_consensus_state_store): """ Test verifies the Z Policy: that PoET Block Verifier fails if a validator attempts to claim more blocks frequently than is allowed """ # create a mock_validator_registry_view that does nothing # in get_validator_info 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 mock_utils.deserialize_wait_certificate.return_value = \ mock_wait_certificate # create a mock_consensus_state that returns a mock with # the following settings: mock_state = MockConsensusState.create_mock_consensus_state( claiming_too_frequently=True) mock_consensus_state.consensus_state_for_block_id.return_value = \ mock_state # check test mock_block_cache = mock.MagicMock() mock_state_view_factory = mock.Mock() mock_block = mock.Mock(identifier='0123456789abcdefedcba9876543210') with mock.patch('sawtooth_poet.poet_consensus.poet_block_verifier.' 'LOGGER') as mock_logger: block_verifier = \ PoetBlockVerifier( 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') self.assertFalse( block_verifier.verify_block(block_wrapper=mock_block)) # 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.error.call_args self.assertTrue('Validator is claiming blocks too ' 'frequently' in message)
def test_non_poet_block(self, mock_utils, mock_validator_registry_view, mock_consensus_state, mock_poet_enclave_factory, mock_poet_config_view, mock_block_wrapper, mock_consensus_state_store): """Verify that the PoET block verifier indicates failure if the block is not a PoET block (i.e., the consensus field in the block header is not a serialized wait certificate). """ # Ensure that the consensus state does not generate failures that would # allow this test to pass mock_state = mock.Mock() mock_state.validator_signup_was_committed_too_late.return_value = False mock_state.validator_has_claimed_block_limit.return_value = False mock_state.validator_is_claiming_too_early.return_value = False mock_state.validator_is_claiming_too_frequently.return_value = False mock_consensus_state.consensus_state_for_block_id.return_value = \ mock_state # Make utils pretend it cannot deserialize the wait certificate mock_utils.deserialize_wait_certificate.return_value = None mock_block_cache = mock.MagicMock() mock_state_view_factory = mock.Mock() mock_block = mock.Mock(identifier='0123456789abcdefedcba9876543210') 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')) with mock.patch('sawtooth_poet.poet_consensus.poet_block_verifier.' 'LOGGER') as mock_logger: block_verifier = \ PoetBlockVerifier( block_cache=mock_block_cache, state_view_factory=mock_state_view_factory, data_dir=self._temp_dir, validator_id='validator_deadbeef') self.assertFalse( block_verifier.verify_block( block_wrapper=mock_block)) # 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.error.call_args self.assertTrue( 'was not created by PoET consensus module' in message)
def test_block_claimed_by_unknown_validator( self, mock_utils, mock_validator_registry_view, mock_consensus_state, mock_poet_enclave_factory, mock_poet_config_view, mock_block_wrapper, mock_consensus_state_store): """ Test verifies that PoET Block Verifier fails if a block is claimed by an unknown validator (the validator is not listed in the validator registry) """ # create a mock_validator_registry_view that throws KeyError mock_validator_registry_view.return_value.get_validator_info.\ side_effect = KeyError('Non-existent validator') # create a mock_wait_certificate that does nothing in check_valid mock_wait_certificate = mock.Mock() mock_wait_certificate.check_valid.return_value = None mock_utils.deserialize_wait_certificate.return_value = \ mock_wait_certificate # create a mock_consensus_state that returns a mock with # the following settings: mock_state = mock.Mock() mock_state.validator_signup_was_committed_too_late.return_value = False mock_state.validator_has_claimed_block_limit.return_value = False mock_state.validator_is_claiming_too_early.return_value = False mock_state.validator_is_claiming_too_frequently.return_value = False mock_consensus_state.consensus_state_for_block_id.return_value = \ mock_state # check test mock_block_cache = mock.MagicMock() mock_state_view_factory = mock.Mock() mock_block = mock.Mock(identifier='0123456789abcdefedcba9876543210') mock_block.header.signer_pubkey = '90834587139405781349807435098745' with mock.patch('sawtooth_poet.poet_consensus.poet_block_verifier.' 'LOGGER') as mock_logger: block_verifier = \ PoetBlockVerifier( block_cache=mock_block_cache, state_view_factory=mock_state_view_factory, data_dir=self._temp_dir, validator_id='validator_deadbeef') self.assertFalse( block_verifier.verify_block(block_wrapper=mock_block)) # 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.error.call_args self.assertTrue('Received block from an unregistered ' 'validator' in message)
def test_block_verifier_valid_block_claim( self, mock_utils, mock_validator_registry_view, mock_consensus_state, mock_poet_enclave_factory, mock_poet_config_view, mock_block_wrapper, mock_consensus_state_store): """ Test verifies that PoET Block Verifier succeeds if a validator successfully passes all criteria necessary to claim a block """ # create a mock_validator_registry_view with # get_validator_info that does nothing 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 mock_utils.deserialize_wait_certificate.return_value = \ mock_wait_certificate # create a mock_consensus_state that returns a mock with # the following settings: mock_state = mock.Mock() mock_state.validator_signup_was_committed_too_late.return_value = False mock_state.validator_has_claimed_block_limit.return_value = False mock_state.validator_is_claiming_too_early.return_value = False mock_state.validator_is_claiming_too_frequently.return_value = False mock_consensus_state.consensus_state_for_block_id.return_value = \ mock_state # check test mock_block_cache = mock.MagicMock() mock_state_view_factory = mock.Mock() mock_block = mock.Mock(identifier='0123456789abcdefedcba9876543210') block_verifier = \ PoetBlockVerifier( 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') self.assertTrue( block_verifier.verify_block( block_wrapper=mock_block))
def verify_block(self, block): verifier = PoetBlockVerifier( block_cache=self._block_cache, state_view_factory=self._state_view_factory, data_dir=self._data_dir, config_dir=self._config_dir, validator_id=self._validator_id) return verifier.verify_block(block)
def test_non_poet_block(self, mock_utils, mock_validator_registry_view, mock_consensus_state, mock_poet_enclave_factory, mock_poet_settings_view, mock_block_wrapper, mock_consensus_state_store): """Verify that the PoET block verifier indicates failure if the block is not a PoET block (i.e., the consensus field in the block header is not a serialized wait certificate). """ # Ensure that the consensus state does not generate failures that would # allow this test to pass mock_state = MockConsensusState.create_mock_consensus_state() mock_consensus_state.consensus_state_for_block_id.return_value = \ mock_state # Make utils pretend it cannot deserialize the wait certificate mock_utils.deserialize_wait_certificate.return_value = None mock_block_cache = mock.MagicMock() mock_state_view_factory = mock.Mock() mock_block = mock.Mock(identifier='0123456789abcdefedcba9876543210') 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')) with mock.patch('sawtooth_poet.poet_consensus.poet_block_verifier.' 'LOGGER') as mock_logger: block_verifier = \ PoetBlockVerifier( 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') self.assertFalse( block_verifier.verify_block( block_wrapper=mock_block)) # 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.error.call_args self.assertTrue( 'was not created by PoET consensus module' in message)
def test_block_verifier_valid_block_claim( self, mock_utils, mock_validator_registry_view, mock_consensus_state, mock_poet_enclave_factory, mock_poet_settings_view, mock_block_wrapper, mock_consensus_state_store): """ Test verifies that PoET Block Verifier succeeds if a validator successfully passes all criteria necessary to claim a block """ # create a mock_validator_registry_view with # get_validator_info that does nothing 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 mock_utils.deserialize_wait_certificate.return_value = \ mock_wait_certificate # create a mock_consensus_state that returns a mock with # the following settings: mock_state = MockConsensusState.create_mock_consensus_state() mock_consensus_state.consensus_state_for_block_id.return_value = \ mock_state # check test mock_block_cache = mock.MagicMock() mock_state_view_factory = mock.Mock() mock_block = mock.Mock(identifier='0123456789abcdefedcba9876543210') block_verifier = \ PoetBlockVerifier( 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') self.assertTrue( block_verifier.verify_block( block_wrapper=mock_block))
def test_invalid_wait_certificate( self, mock_utils, mock_validator_registry_view, mock_consensus_state, mock_poet_enclave_factory, mock_poet_settings_view, mock_block_wrapper, mock_consensus_state_store): # Ensure that the consensus state does not generate failures that would # allow this test to pass mock_state = MockConsensusState.create_mock_consensus_state() mock_consensus_state.consensus_state_for_block_id.return_value = \ mock_state # Make the certificate's check_valid pretend it failed mock_wait_certificate = mock.Mock() mock_wait_certificate.check_valid.side_effect = \ ValueError('Unit test fake failure') mock_utils.deserialize_wait_certificate.return_value = \ mock_wait_certificate mock_block_cache = mock.MagicMock() mock_state_view_factory = mock.Mock() mock_block = mock.Mock(identifier='0123456789abcdefedcba9876543210') 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')) with mock.patch('sawtooth_poet.poet_consensus.poet_block_verifier.' 'LOGGER') as mock_logger: block_verifier = \ PoetBlockVerifier( 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') self.assertFalse( block_verifier.verify_block(block_wrapper=mock_block)) # 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.error.call_args self.assertTrue('Wait certificate check failed' in message)
def test_z_policy(self, mock_utils, mock_validator_registry_view, mock_consensus_state, mock_poet_enclave_factory, mock_poet_settings_view, mock_block_wrapper, mock_consensus_state_store): """ Test verifies the Z Policy: that PoET Block Verifier fails if a validator attempts to claim more blocks frequently than is allowed """ # create a mock_validator_registry_view that does nothing # in get_validator_info 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 mock_utils.deserialize_wait_certificate.return_value = \ mock_wait_certificate # create a mock_consensus_state that returns a mock with # the following settings: mock_state = MockConsensusState.create_mock_consensus_state( claiming_too_frequently=True) mock_consensus_state.consensus_state_for_block_id.return_value = \ mock_state # check test mock_block_cache = mock.MagicMock() mock_state_view_factory = mock.Mock() mock_block = mock.Mock(identifier='0123456789abcdefedcba9876543210') with mock.patch('sawtooth_poet.poet_consensus.poet_block_verifier.' 'LOGGER') as mock_logger: block_verifier = \ PoetBlockVerifier( 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') self.assertFalse( block_verifier.verify_block( block_wrapper=mock_block)) # 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.error.call_args self.assertTrue('Validator is claiming blocks too ' 'frequently' in message)
def test_block_claimed_by_unknown_validator(self, mock_utils, mock_validator_registry_view, mock_consensus_state, mock_poet_enclave_factory, mock_poet_settings_view, mock_block_wrapper, mock_consensus_state_store): """ Test verifies that PoET Block Verifier fails if a block is claimed by an unknown validator (the validator is not listed in the validator registry) """ # create a mock_validator_registry_view that throws KeyError mock_validator_registry_view.return_value.get_validator_info.\ side_effect = KeyError('Non-existent validator') # create a mock_wait_certificate that does nothing in check_valid mock_wait_certificate = mock.Mock() mock_wait_certificate.check_valid.return_value = None mock_utils.deserialize_wait_certificate.return_value = \ mock_wait_certificate # create a mock_consensus_state that returns a mock with # the following settings: mock_state = MockConsensusState.create_mock_consensus_state() mock_consensus_state.consensus_state_for_block_id.return_value = \ mock_state # check test mock_block_cache = mock.MagicMock() mock_state_view_factory = mock.Mock() mock_block = mock.Mock(identifier='0123456789abcdefedcba9876543210') mock_block.header.signer_public_key = \ '90834587139405781349807435098745' with mock.patch('sawtooth_poet.poet_consensus.poet_block_verifier.' 'LOGGER') as mock_logger: block_verifier = \ PoetBlockVerifier( 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') self.assertFalse( block_verifier.verify_block( block_wrapper=mock_block)) # 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.error.call_args self.assertTrue('Received block from an unregistered ' 'validator' in message)