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")
Exemple #3
0
    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')