Example #1
0
    def validator_signup_was_committed_too_late(self, validator_info,
                                                poet_settings_view,
                                                block_cache):
        """Determines if a validator's registry transaction committing it
        current PoET keys, etc., was committed too late - i.e., the number of
        blocks between when the transaction was submitted and when it was
        committed is greater than signup commit maximum delay.

        Args:
            validator_info (ValidatorInfo): The current validator information
            poet_settings_view (PoetSettingsView): The current Poet config view
            block_cache (BlockCache): The block store cache

        Returns:
            bool: True if the validator's registry transaction was committed
                beyond the signup commit maximum delay, False otherwise
        """
        # Figure out the block in which the current validator information
        # was committed.
        block = \
            block_cache.block_store.get_block_by_transaction_id(
                validator_info.transaction_id)
        commit_block_id = block.identifier

        # Starting with that block's immediate predecessor, walk back until
        # either we match the block ID with the nonce field in the signup
        # info, we have checked the maximum number of blocks, or we somehow
        # reached the beginning of the blockchain.  The first case is
        # success (i.e., the validator signup info passed the freshness
        # test) while the other two cases are failure.
        for _ in range(poet_settings_view.signup_commit_maximum_delay + 1):
            if SignupInfo.block_id_to_nonce(block.previous_block_id) == \
                    validator_info.signup_info.nonce:
                LOGGER.debug(
                    'Validator %s (ID=%s...%s): Signup committed block %s, '
                    'chain head was block %s', validator_info.name,
                    validator_info.id[:8], validator_info.id[-8:],
                    commit_block_id[:8], block.previous_block_id[:8])
                return False

            if utils.block_id_is_genesis(block.previous_block_id):
                LOGGER.error(
                    'Validator %s (ID=%s...%s): Signup committed block %s, '
                    'hit start of blockchain looking for block %s',
                    validator_info.name, validator_info.id[:8],
                    validator_info.id[-8:], commit_block_id[:8],
                    validator_info.signup_info.nonce[:8])
                return True

            block = block_cache[block.previous_block_id]

        LOGGER.error(
            'Validator %s (ID=%s...%s): Signup committed block %s, failed to '
            'find block with ID ending in %s in %d previous block(s)',
            validator_info.name, validator_info.id[:8], validator_info.id[-8:],
            commit_block_id[:8], validator_info.signup_info.nonce,
            poet_settings_view.signup_commit_maximum_delay + 1)
        return True
    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
Example #3
0
    def _block_for_id(block_id, block_cache):
        """A convenience method retrieving a block given a block ID.  Takes care
        of the special case of NULL_BLOCK_IDENTIFIER.

        Args:
            block_id (str): The ID of block to retrieve.
            block_cache (BlockCache): Block cache from which block will be
                retrieved.

        Returns:
            BlockWrapper for block, or None for no block found.
        """
        block = None
        try:
            block = \
                None if utils.block_id_is_genesis(block_id) else \
                block_cache[block_id]
        except KeyError:
            LOGGER.error('Failed to retrieve block: %s', block_id[:8])

        return block
    def _block_for_id(block_id, block_cache):
        """A convenience method retrieving a block given a block ID. Takes
        care of the special case of NULL_BLOCK_IDENTIFIER.

        Args:
            block_id (str): The ID of block to retrieve.
            block_cache (BlockCache): Block cache from which block will be
                retrieved.

        Returns:
            BlockWrapper for block, or None for no block found.
        """
        block = None
        try:
            block = \
                None if utils.block_id_is_genesis(block_id) else \
                block_cache[block_id]
        except KeyError:
            LOGGER.error('Failed to retrieve block: %s', block_id[:8])

        return block
    def validator_signup_was_committed_too_late(self,
                                                validator_info,
                                                poet_settings_view,
                                                block_cache):
        """Determines if a validator's registry transaction committing it
        current PoET keys, etc., was committed too late - i.e., the number of
        blocks between when the transaction was submitted and when it was
        committed is greater than signup commit maximum delay.

        Args:
            validator_info (ValidatorInfo): The current validator information
            poet_settings_view (PoetSettingsView): The current Poet config view
            block_cache (BlockCache): The block store cache

        Returns:
            bool: True if the validator's registry transaction was committed
                beyond the signup commit maximum delay, False otherwise
        """
        # Figure out the block in which the current validator information
        # was committed.
        try:
            block = block_cache.block_store.get_block_by_transaction_id(
                validator_info.transaction_id)
        except ValueError:
            LOGGER.warning(
                'Validator %s (ID=%s...%s): Signup txn %s not found in block.',
                validator_info.name,
                validator_info.id[:8],
                validator_info.id[-8:],
                validator_info.transaction_id[:8])
            return False

        commit_block_id = block.identifier

        # Starting with that block's immediate predecessor, walk back until
        # either we match the block ID with the nonce field in the signup
        # info, we have checked the maximum number of blocks, or we somehow
        # reached the beginning of the blockchain.  The first case is
        # success (i.e., the validator signup info passed the freshness
        # test) while the other two cases are failure.
        for _ in range(poet_settings_view.signup_commit_maximum_delay + 1):
            if SignupInfo.block_id_to_nonce(block.previous_block_id) == \
                    validator_info.signup_info.nonce:
                LOGGER.debug(
                    'Validator %s (ID=%s...%s): Signup committed block %s, '
                    'chain head was block %s',
                    validator_info.name,
                    validator_info.id[:8],
                    validator_info.id[-8:],
                    commit_block_id[:8],
                    block.previous_block_id[:8])
                return False

            if utils.block_id_is_genesis(block.previous_block_id):
                LOGGER.info(
                    'Validator %s (ID=%s...%s): Signup committed block %s, '
                    'hit start of blockchain looking for block %s',
                    validator_info.name,
                    validator_info.id[:8],
                    validator_info.id[-8:],
                    commit_block_id[:8],
                    validator_info.signup_info.nonce[:8])
                return True

            block = block_cache[block.previous_block_id]

        LOGGER.info(
            'Validator %s (ID=%s...%s): Signup committed block %s, failed to '
            'find block with ID ending in %s in %d previous block(s)',
            validator_info.name,
            validator_info.id[:8],
            validator_info.id[-8:],
            commit_block_id[:8],
            validator_info.signup_info.nonce,
            poet_settings_view.signup_commit_maximum_delay + 1)
        return True