def test_create_before_create_signup_info(self): # Make sure that trying to create a wait certificate before signup # information is provided causes an error with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data='', wait_timer=None, block_hash="Reader's Digest")
def test_create_before_create_wait_timer(self): # Need to create signup information signup_info = SignupInfo.create_signup_info( poet_enclave_module=self.poet_enclave_module, originator_public_key_hash=self._originator_public_key_hash, nonce=NULL_BLOCK_IDENTIFIER) # Make sure that trying to create a wait certificate before creating # a wait timer causes an error with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=None, block_hash="Reader's Digest")
def deserialize_wait_certificate(block, poet_enclave_module): """Deserializes the wait certificate associated with the block. Args: block (Block or BlockWrapper): The block that has the wait certificate poet_enclave_module (module): The PoET enclave module Returns: WaitCertificate: The reconstituted wait certificate associated with the block or None if cannot deserialize """ # The wait certificate is a JSON string placed in the consensus # field/property of the block header. Parse the JSON and then use the # serialized wait certificate and signature to create a # WaitCertificate object. wait_certificate = None if block is not None: try: wait_certificate_dict = \ json.loads(block.header.consensus.decode()) wait_certificate = \ WaitCertificate.wait_certificate_from_serialized( poet_enclave_module=poet_enclave_module, serialized=wait_certificate_dict['SerializedCertificate'], signature=wait_certificate_dict['Signature']) except (json.decoder.JSONDecodeError, KeyError): pass return wait_certificate
def test_create_with_wrong_signup_data(self): # Need to create signup information signup_info = SignupInfo.create_signup_info( poet_enclave_module=self.poet_enclave_module, originator_public_key_hash=self._originator_public_key_hash, nonce=NULL_BLOCK_IDENTIFIER) signup_info2 = SignupInfo.create_signup_info( poet_enclave_module=self.poet_enclave_module, originator_public_key_hash=self._originator_public_key_hash, nonce=NULL_BLOCK_IDENTIFIER) # Create two timers and try to create the wait certificate with the # first one, which should fail as it is not the current wait timer wt1 = \ WaitTimer.create_wait_timer( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, validator_address='1660 Pennsylvania Avenue NW', previous_certificate_id=NULL_BLOCK_IDENTIFIER, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) wt2 = \ WaitTimer.create_wait_timer( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info2.sealed_signup_data, validator_address='1660 Pennsylvania Avenue NW', previous_certificate_id=NULL_BLOCK_IDENTIFIER, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) # Verify that we cannot create a wait certificate using the first # wait timer with the second signup data with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info2.sealed_signup_data, wait_timer=wt1, block_hash="Reader's Digest") WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info2.sealed_signup_data, wait_timer=wt2, block_hash="Reader's Digest")
def test_create_with_reused_wait_timer(self): # Need to create signup information signup_info = SignupInfo.create_signup_info( poet_enclave_module=self.poet_enclave_module, originator_public_key_hash=self._originator_public_key_hash, nonce=NULL_BLOCK_IDENTIFIER) # Create a wait certificate for the genesis block so that we can # create another wait certificate that has to play by the rules. wt = \ WaitTimer.create_wait_timer( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, validator_address='1660 Pennsylvania Avenue NW', previous_certificate_id=NULL_BLOCK_IDENTIFIER, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) wc = \ WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=wt, block_hash="Reader's Digest") consumed_wt = wt # Verify that we cannot use the consumed wait timer to create a wait # certificate either before or after creating a new wait timer with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=consumed_wt, block_hash="Reader's Digest") wt = \ WaitTimer.create_wait_timer( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, validator_address='1660 Pennsylvania Avenue NW', previous_certificate_id=wc.identifier, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=consumed_wt, block_hash="Reader's Digest") # Verify that once the new timer expires, we can create a wait # certificate with it while not wt.has_expired(time.time()): time.sleep(1) WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=wt, block_hash="Reader's Digest")
def finalize_block(self, block_header): """Finalize a block to be claimed. Provide any signatures and data updates that need to be applied to the block before it is signed and broadcast to the network. Args: block_header (BlockHeader): The block header for the candidate block that needs to be finalized. Returns: Boolean: True if the candidate block good and should be generated. False if the block should be abandoned. """ # To compute the block hash, we are going to perform a hash using the # previous block ID and the batch IDs contained in the block hasher = hashlib.sha256(block_header.previous_block_id.encode()) for batch_id in block_header.batch_ids: hasher.update(batch_id.encode()) block_hash = hasher.hexdigest() # Using the current chain head, we need to create a state view so we # can create a PoET enclave. state_view = \ BlockWrapper.state_view_for_block( block_wrapper=self._block_cache.block_store.chain_head, state_view_factory=self._state_view_factory) poet_enclave_module = \ factory.PoetEnclaveFactory.get_poet_enclave_module( state_view=state_view, config_dir=self._config_dir, data_dir=self._data_dir) # We need to create a wait certificate for the block and then serialize # that into the block header consensus field. active_key = self._poet_key_state_store.active_key poet_key_state = self._poet_key_state_store[active_key] sealed_signup_data = poet_key_state.sealed_signup_data try: wait_certificate = \ WaitCertificate.create_wait_certificate( poet_enclave_module=poet_enclave_module, sealed_signup_data=sealed_signup_data, wait_timer=self._wait_timer, block_hash=block_hash) block_header.consensus = \ json.dumps(wait_certificate.dump()).encode() except ValueError as ve: LOGGER.error('Failed to create wait certificate: %s', ve) return False LOGGER.debug('Created wait certificate: %s', wait_certificate) return True
def test_create_before_wait_timer_expires(self): # Need to create signup information signup_info = SignupInfo.create_signup_info( poet_enclave_module=self.poet_enclave_module, originator_public_key_hash=self._originator_public_key_hash, nonce=NULL_BLOCK_IDENTIFIER) # Create a wait certificate for the genesis block so that we can # create another wait certificate that has to play by the rules. wt = \ WaitTimer.create_wait_timer( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, validator_address='1660 Pennsylvania Avenue NW', previous_certificate_id=NULL_BLOCK_IDENTIFIER, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) wc = \ WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=wt, block_hash="Reader's Digest") wt = \ WaitTimer.create_wait_timer( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, validator_address='1660 Pennsylvania Avenue NW', previous_certificate_id=wc.identifier, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( poet_enclave_module=self.poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=wt, block_hash="Reader's Digest")
def test_serialization(self): # Need to create signup information and wait timer first signup_info = \ SignupInfo.create_signup_info( poet_enclave_module=self.poet_enclave_module, originator_public_key_hash=self._originator_public_key_hash, nonce=NULL_BLOCK_IDENTIFIER) # create mock_poet_enclave_wait_timer mock_poet_enclave_wait_timer = \ mock.Mock(validator_address='1060 W Addison Street', duration=1.0, previous_certificate_id=NULL_BLOCK_IDENTIFIER, local_mean=5.0, signature='00112233445566778899aabbccddeeff', serialized_timer=None, request_time=time.time()) # create mock_poet_enclave_wait_certificate mock_poet_enclave_wait_certificate = \ mock.Mock(duration=1.0, previous_certificate_id=NULL_BLOCK_IDENTIFIER, local_mean=5.0, request_time=time.time(), validator_address='1060 W Addison Street', nonce=NULL_BLOCK_IDENTIFIER, block_hash="Reader's Digest", signature='00112233445566778899aabbccddeeff', serialized_certificate=None) # create mock_poet_enclave_module mock_poet_enclave_module = mock.Mock() mock_poet_enclave_module.create_wait_timer.return_value = \ mock_poet_enclave_wait_timer # set the mock enclave wait certificate and wait timer to # have the same previous_certificate_id mock_poet_enclave_wait_certificate.previous_certificate_id = \ mock_poet_enclave_wait_timer.previous_certificate_id mock_poet_enclave_module.create_wait_certificate.return_value = \ mock_poet_enclave_wait_certificate mock_poet_enclave_module.deserialize_wait_certificate.return_value = \ mock_poet_enclave_wait_certificate wt = \ WaitTimer.create_wait_timer( poet_enclave_module=mock_poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, validator_address='1660 Pennsylvania Avenue NW', previous_certificate_id=NULL_BLOCK_IDENTIFIER, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) # Now we can create a wait certificate and serialize wc = \ WaitCertificate.create_wait_certificate( poet_enclave_module=mock_poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=wt, block_hash="Reader's Digest") dumped = wc.dump() self.assertIsNotNone(dumped.get('SerializedCertificate')) self.assertIsNotNone(dumped.get('Signature')) # Deserialize and verify that wait certificates are the same # and that deserialized one is valid wc_copy = \ WaitCertificate.wait_certificate_from_serialized( poet_enclave_module=mock_poet_enclave_module, serialized=dumped.get('SerializedCertificate'), signature=dumped.get('Signature')) self.assertEqual(wc.previous_certificate_id, wc_copy.previous_certificate_id) self.assertEqual(wc.local_mean, wc_copy.local_mean) self.assertAlmostEqual(wc.request_time, wc_copy.request_time) self.assertAlmostEqual(wc.duration, wc_copy.duration) self.assertEqual(wc.validator_address, wc_copy.validator_address) self.assertEqual(wc.block_hash, wc_copy.block_hash) self.assertEqual(wc.signature, wc_copy.signature) self.assertEqual(wc.identifier, wc_copy.identifier) # Serialize the copy and verify that its serialization and # signature are the same dumped_copy = wc_copy.dump() self.assertTrue(dumped.get('SerializedCertificate'), dumped_copy.get('SerializedCertificate')) self.assertTrue(dumped.get('Signature'), dumped_copy.get('Signature')) wc_copy.check_valid(poet_enclave_module=mock_poet_enclave_module, previous_certificate_id=NULL_BLOCK_IDENTIFIER, poet_public_key=signup_info.poet_public_key, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view)
def test_create(self): # Need to create signup information and wait timer first signup_info = \ SignupInfo.create_signup_info( poet_enclave_module=self.poet_enclave_module, originator_public_key_hash=self._originator_public_key_hash, nonce=NULL_BLOCK_IDENTIFIER) # create mock_poet_enclave_wait_timer mock_poet_enclave_wait_timer = \ mock.Mock(sealed_signup_data=signup_info.sealed_signup_data, validator_address='1060 W Addison Street', duration=1.0, previous_certificate_id=NULL_BLOCK_IDENTIFIER, local_mean=5.0, signature='00112233445566778899aabbccddeeff', serialized_timer=None, request_time=time.time()) # create mock_poet_enclave_wait_certificate mock_poet_enclave_wait_certificate = \ mock.Mock(sealed_signup_data=signup_info.sealed_signup_data, duration=1.0, previous_certificate_id=NULL_BLOCK_IDENTIFIER, local_mean=5.0, request_time=time.time(), validator_address='1060 W Addison Street', nonce=NULL_BLOCK_IDENTIFIER, block_hash="Reader's Digest", signature='00112233445566778899aabbccddeeff', serialized_certificate='001122334455667' '78899aabbccddeeff') # create mock_poet_enclave_module mock_poet_enclave_module = mock.Mock() mock_poet_enclave_module.create_wait_timer.return_value = \ mock_poet_enclave_wait_timer # set the mock enclave wait certificate and wait timer to # have the same request_time mock_poet_enclave_wait_certificate.request_time = \ mock_poet_enclave_wait_timer.request_time # set the mock enclave wait certificate and wait timer to # have the same previous_certificate_id mock_poet_enclave_wait_certificate.previous_certificate_id = \ mock_poet_enclave_wait_timer.previous_certificate_id # set the identifier for mock_poet_enclave_wait_certificate mock_poet_enclave_wait_certificate.identifier.return_value = \ mock_poet_enclave_wait_certificate.previous_certificate_id[:16] mock_poet_enclave_module.create_wait_certificate.return_value = \ mock_poet_enclave_wait_certificate mock_poet_enclave_module.deserialize_wait_certificate.return_value = \ mock_poet_enclave_wait_certificate # create wait timer wt = \ WaitTimer.create_wait_timer( poet_enclave_module=mock_poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, validator_address='1660 Pennsylvania Avenue NW', previous_certificate_id=NULL_BLOCK_IDENTIFIER, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) # Now we can create a wait certificate and verify that it correlates # to the wait timer we just created wc = \ WaitCertificate.create_wait_certificate( poet_enclave_module=mock_poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=wt, block_hash="Reader's Digest") self.assertIsNotNone(wc) self.assertEqual(wc.previous_certificate_id, wt.previous_certificate_id) self.assertAlmostEqual(wc.local_mean, wt.local_mean) self.assertAlmostEqual(wc.request_time, wt.request_time) self.assertAlmostEqual(wc.duration, wt.duration) self.assertEqual(wc.validator_address, wt.validator_address) self.assertEqual(wc.block_hash, "Reader's Digest") self.assertIsNotNone(wc.signature) self.assertIsNotNone(wc.identifier) # A newly-created wait certificate should be valid wc.check_valid(poet_enclave_module=mock_poet_enclave_module, previous_certificate_id=NULL_BLOCK_IDENTIFIER, poet_public_key=signup_info.poet_public_key, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) validator_info = \ ValidatorInfo( id='validator_001', signup_info=SignUpInfo( poet_public_key='key_001')) self.mock_consensus_state.validator_did_claim_block( validator_info=validator_info, wait_certificate=wc, poet_settings_view=self.mock_poet_settings_view) # Create another wait certificate and verify it is valid also wt = \ WaitTimer.create_wait_timer( poet_enclave_module=mock_poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, validator_address='1660 Pennsylvania Avenue NW', previous_certificate_id=wc.identifier, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view) # Now we can create a wait certificate and verify that it correlates # to the wait timer we just created another_wc = \ WaitCertificate.create_wait_certificate( poet_enclave_module=mock_poet_enclave_module, sealed_signup_data=signup_info.sealed_signup_data, wait_timer=wt, block_hash="Pepto Bismol") another_wc.check_valid(poet_enclave_module=mock_poet_enclave_module, previous_certificate_id=wc.identifier, poet_public_key=signup_info.poet_public_key, consensus_state=self.mock_consensus_state, poet_settings_view=self.mock_poet_settings_view)