def initialize_block(self, block_header): """Do initialization necessary for the consensus to claim a block, this may include initiating voting activities, starting proof of work hash generation, or create a PoET wait timer. Args: block_header (BlockHeader): The BlockHeader to initialize. Returns: Boolean: True if the candidate block should be built. False if no candidate should be built. """ # HACER: Once we have PoET consensus state, we should be looking in # there for the sealed signup data. For the time being, signup # information will be tied to the lifetime of the validator. # HACER: Once the genesis utility is creating the validator registry # transaction, we no longer need to do this. But for now, if we are # creating the genesis block, we need to re-establish the state of # the enclave using pre-canned sealed signup data so that we can # create the wait timer and certificate. Note that this is only # used for the genesis block. Going forward after the genesis block, # all validators will use generated signup information. if utils.block_id_is_genesis(block_header.previous_block_id): LOGGER.debug( 'Creating genesis block, so will use sealed signup data') SignupInfo.unseal_signup_data( poet_enclave_module=self._poet_enclave_module, validator_address=block_header.signer_pubkey, sealed_signup_data=PoetBlockPublisher._sealed_signup_data) # HACER: Otherwise, if it is not the first block and we don't already # have a public key, we need to create signup information and create a # transaction to add it to the validator registry. elif PoetBlockPublisher._poet_public_key is None: self._register_signup_information(block_header=block_header) # Create a list of certificates for the wait timer. This seems to have # a little too much knowledge of the WaitTimer implementation, but # there is no use getting more than # WaitTimer.certificate_sample_length wait certificates. certificates = \ utils.build_certificate_list( block_header=block_header, block_cache=self._block_cache, poet_enclave_module=self._poet_enclave_module, maximum_number=WaitTimer.certificate_sample_length) # We need to create a wait timer for the block...this is what we # will check when we are asked if it is time to publish the block self._wait_timer = \ WaitTimer.create_wait_timer( poet_enclave_module=self._poet_enclave_module, validator_address=block_header.signer_pubkey, certificates=list(certificates)) LOGGER.debug('Created wait timer: %s', self._wait_timer) return True
def test_verify_unsealing_data(self): signup_info = \ SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NULL_BLOCK_IDENTIFIER) poet_public_key = \ SignupInfo.unseal_signup_data( validator_address='1660 Pennsylvania Avenue NW', sealed_signup_data=signup_info.sealed_signup_data) self.assertEqual( signup_info.poet_public_key, poet_public_key, msg="PoET public key in signup info and sealed data don't match")
def _on_journal_initialization_complete(self, journal): """ Callback journal makes after the journal has completed initialization Args: journal (Journal): The journal object that has completed initialization. Returns: True """ # If we have sealed signup data (meaning that we have previously # created signup info), we can request that the enclave unseal it, # in the process restoring the enclave to its previous state. If # we don't have sealed signup data, we need to create and register it. # # Note - this MUST be done AFTER the journal has completed # initialization so that there is at least one peer node to which # we can send the validator registry transaction to. Otherwise, # we will never, ever be able to be added to the validator registry # and, to paraphrase Martha Stewart, that is a bad thing. sealed_signup_data = journal.local_store.get('sealed_signup_data') if sealed_signup_data is not None: self.poet_public_key = \ SignupInfo.unseal_signup_data( validator_address=journal.local_node.signing_address(), sealed_signup_data=sealed_signup_data) LOGGER.info( 'Restore signup info for %s (ID = %s, PoET public key = %s)', journal.local_node.Name, journal.local_node.Identifier, self.poet_public_key) else: self.register_signup_information(journal) return True
def test_create_wait_timer(self): # Need to create signup information first signup_info = \ SignupInfo.create_signup_info( validator_address='1060 W Addison Street', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NULL_BLOCK_IDENTIFIER) stake_in_the_sand = time.time() # An empty certificate list should result in a local mean that is # the target wait time wt = wait_timer.WaitTimer.create_wait_timer( validator_address='1060 W Addison Street', certificates=[]) self.assertIsNotNone(wt) self.assertEqual(wt.local_mean, wait_timer.WaitTimer.target_wait_time) self.assertEqual(wt.previous_certificate_id, NULL_BLOCK_IDENTIFIER) self.assertGreaterEqual(wt.request_time, stake_in_the_sand) self.assertLessEqual(wt.request_time, time.time()) self.assertGreaterEqual(wt.duration, wait_timer.WaitTimer.minimum_wait_time) self.assertEqual(wt.validator_address, '1060 W Addison Street') wt = wait_timer.WaitTimer.create_wait_timer( validator_address='1060 W Addison Street', certificates=tuple()) self.assertIsNotNone(wt) self.assertEqual(wt.local_mean, wait_timer.WaitTimer.target_wait_time) self.assertEqual(wt.previous_certificate_id, NULL_BLOCK_IDENTIFIER) self.assertGreaterEqual(wt.request_time, stake_in_the_sand) self.assertLessEqual(wt.request_time, time.time()) self.assertGreaterEqual(wt.duration, wait_timer.WaitTimer.minimum_wait_time) self.assertEqual(wt.validator_address, '1060 W Addison Street') # Ensure that the enclave is set back to initial state SignupInfo.poet_enclave = reload(poet_enclave) wait_timer.WaitTimer.poet_enclave = SignupInfo.poet_enclave # Make sure that trying to create a wait timer before signup # information is provided causes an error with self.assertRaises(ValueError): wait_timer.WaitTimer.create_wait_timer( validator_address='1060 W Addison Street', certificates=[]) with self.assertRaises(ValueError): wait_timer.WaitTimer.create_wait_timer( validator_address='1060 W Addison Street', certificates=tuple()) # Initialize the enclave with sealed signup data SignupInfo.unseal_signup_data( validator_address='1660 Pennsylvania Avenue NW', sealed_signup_data=signup_info.sealed_signup_data) stake_in_the_sand = time.time() # An empty certificate list should result in a local mean that is # the target wait time wt = wait_timer.WaitTimer.create_wait_timer( validator_address='1060 W Addison Street', certificates=[]) self.assertIsNotNone(wt) self.assertEqual(wt.local_mean, wait_timer.WaitTimer.target_wait_time) self.assertEqual(wt.previous_certificate_id, NULL_BLOCK_IDENTIFIER) self.assertGreaterEqual(wt.request_time, stake_in_the_sand) self.assertLessEqual(wt.request_time, time.time()) self.assertGreaterEqual(wt.duration, wait_timer.WaitTimer.minimum_wait_time) self.assertEqual(wt.validator_address, '1060 W Addison Street') wt = wait_timer.WaitTimer.create_wait_timer( validator_address='1600 Pennsylvania Avenue NW', certificates=tuple()) self.assertIsNotNone(wt) self.assertEqual(wt.local_mean, wait_timer.WaitTimer.target_wait_time) self.assertEqual(wt.previous_certificate_id, NULL_BLOCK_IDENTIFIER) self.assertGreaterEqual(wt.request_time, stake_in_the_sand) self.assertLessEqual(wt.request_time, time.time()) self.assertGreaterEqual(wt.duration, wait_timer.WaitTimer.minimum_wait_time) self.assertEqual(wt.validator_address, '1600 Pennsylvania Avenue NW')