示例#1
0
 def _load_consensus(self, block):
     """Load the consensus module using the state as of the given block."""
     if block is not None:
         return ConsensusFactory.get_configured_consensus_module(
             block.header_signature,
             BlockWrapper.state_view_for_block(block,
                                               self._state_view_factory))
     return ConsensusFactory.get_consensus_module('genesis')
 def _load_consensus(self, block):
     """Load the consensus module using the state as of the given block."""
     if block is not None:
         return ConsensusFactory.get_configured_consensus_module(
             block.header_signature,
             BlockWrapper.state_view_for_block(
                 block,
                 self._state_view_factory))
     return ConsensusFactory.get_consensus_module('genesis')
示例#3
0
    def _get_block_publisher(self, state_hash):
        """Returns the block publisher based on the consensus module set by the
        "sawtooth_config" transaction family.

        Args:
            state_hash (str): The current state root hash for reading settings.

        Raises:
            InvalidGenesisStateError: if any errors occur getting the
                BlockPublisher.
        """
        state_view = self._state_view_factory.create_view(state_hash)
        try:

            class BatchPublisher(object):
                def send(self, transactions):
                    # Consensus implementations are expected to have handling
                    # in place for genesis operation. This should includes
                    # adding any authorization and registrations required
                    # for the genesis node to the Genesis Batch list and
                    # detecting validation of the Genesis Block and handle it
                    # correctly. Batch publication is not allowed during
                    # genesis operation since there is no network to validate
                    # the batch yet.
                    raise InvalidGenesisConsensusError(
                        'Consensus cannot send transactions during genesis.')

            consensus = ConsensusFactory.get_configured_consensus_module(
                state_view)
            return consensus.BlockPublisher(BlockCache(self._block_store),
                                            state_view=state_view,
                                            batch_publisher=BatchPublisher(),
                                            data_dir=self._data_dir)
        except UnknownConsensusModuleError as e:
            raise InvalidGenesisStateError(e)
示例#4
0
    def _set_genesis(self, block):
        # This is used by a non-genesis journal when it has received the
        # genesis block from the genesis validator
        if block.previous_block_id == NULL_BLOCK_IDENTIFIER:
            chain_id = self._chain_id_manager.get_block_chain_id()
            if chain_id is not None and chain_id != block.identifier:
                LOGGER.warning("Block id does not match block chain id %s. "
                               "Cannot set initial chain head.: %s",
                               chain_id[:8], block.identifier[:8])
            else:
                state_view = self._state_view_factory.create_view()
                consensus_module = \
                    ConsensusFactory.get_configured_consensus_module(
                        NULL_BLOCK_IDENTIFIER,
                        state_view)

                valid = self._block_validator.validate_block(
                    block, consensus_module)
                if valid:
                    if chain_id is None:
                        self._chain_id_manager.save_block_chain_id(
                            block.identifier)
                    self._block_store.update_chain([block])
                    self._chain_head = block
                    self._notify_on_chain_updated(self._chain_head)
                else:
                    LOGGER.warning(
                        "The genesis block is not valid: Cannot "
                        "set chain head: %s", block)

        else:
            LOGGER.warning("Cannot set initial chain head, this is not a "
                           "genesis block: %s", block)
示例#5
0
    def _submit_blocks_for_verification(self, blocks):
        for blkw in blocks:
            state_view = BlockWrapper.state_view_for_block(
                self.chain_head,
                self._state_view_factory)
            consensus_module = \
                ConsensusFactory.get_configured_consensus_module(
                    self.chain_head.header_signature,
                    state_view)

            validator = BlockValidator(
                consensus_module=consensus_module,
                new_block=blkw,
                block_cache=self._block_cache,
                state_view_factory=self._state_view_factory,
                done_cb=self.on_block_validated,
                executor=self._transaction_executor,
                squash_handler=self._squash_handler,
                identity_signer=self._identity_signer,
                data_dir=self._data_dir,
                config_dir=self._config_dir,
                permission_verifier=self._permission_verifier,
                metrics_registry=self._metrics_registry)
            self._blocks_processing[blkw.block.header_signature] = validator
            self._thread_pool.submit(validator.run)
示例#6
0
    def _build_candidate_block(self, chain_head):
        """ Build a candidate block and construct the consensus object to
        validate it.
        :param chain_head: The block to build on top of.
        :return: (BlockBuilder) - The candidate block in a BlockBuilder
        wrapper.
        """
        state_view = BlockWrapper.state_view_for_block(
            chain_head,
            self._state_view_factory)
        consensus_module = ConsensusFactory.get_configured_consensus_module(
            chain_head.header_signature,
            state_view)

        settings_view = SettingsView(state_view)
        max_batches = settings_view.get_setting(
            'sawtooth.publisher.max_batches_per_block',
            default_value=0, value_type=int)

        consensus = consensus_module.\
            BlockPublisher(block_cache=self._block_cache,
                           state_view_factory=self._state_view_factory,
                           batch_publisher=self._batch_publisher,
                           data_dir=self._data_dir,
                           config_dir=self._config_dir,
                           validator_id=self._identity_public_key)

        block_header = BlockHeader(
            block_num=chain_head.block_num + 1,
            previous_block_id=chain_head.header_signature,
            signer_pubkey=self._identity_public_key)
        block_builder = BlockBuilder(block_header)
        if not consensus.initialize_block(block_builder.block_header):
            LOGGER.debug("Consensus not ready to build candidate block.")
            return None

        # create a new scheduler
        scheduler = self._transaction_executor.create_scheduler(
            self._squash_handler, chain_head.state_root_hash)

        # build the TransactionCache
        committed_txn_cache = TransactionCache(self._block_cache.block_store)

        self._transaction_executor.execute(scheduler)
        self._candidate_block = _CandidateBlock(self._block_cache.block_store,
                                                consensus, scheduler,
                                                committed_txn_cache,
                                                block_builder,
                                                max_batches)
        for batch in self._pending_batches:
            if self._candidate_block.can_add_batch:
                self._candidate_block.add_batch(batch)
            else:
                break
示例#7
0
    def _build_candidate_block(self, chain_head):
        """ Build a candidate block and construct the consensus object to
        validate it.
        :param chain_head: The block to build on top of.
        :return: (BlockBuilder) - The candidate block in a BlockBuilder
        wrapper.
        """
        state_view = BlockWrapper.state_view_for_block(
            chain_head,
            self._state_view_factory)
        consensus_module = ConsensusFactory.get_configured_consensus_module(
            chain_head.header_signature,
            state_view)

        config_view = ConfigView(state_view)
        max_batches = config_view.get_setting(
            'sawtooth.publisher.max_batches_per_block',
            default_value=0, value_type=int)

        consensus = consensus_module.\
            BlockPublisher(block_cache=self._block_cache,
                           state_view_factory=self._state_view_factory,
                           batch_publisher=self._batch_publisher,
                           data_dir=self._data_dir,
                           config_dir=self._config_dir,
                           validator_id=self._identity_public_key)

        block_header = BlockHeader(
            block_num=chain_head.block_num + 1,
            previous_block_id=chain_head.header_signature,
            signer_pubkey=self._identity_public_key)
        block_builder = BlockBuilder(block_header)
        if not consensus.initialize_block(block_builder.block_header):
            LOGGER.debug("Consensus not ready to build candidate block.")
            return None

        # create a new scheduler
        scheduler = self._transaction_executor.create_scheduler(
            self._squash_handler, chain_head.state_root_hash)

        # build the TransactionCache
        committed_txn_cache = TransactionCache(self._block_cache.block_store)

        self._transaction_executor.execute(scheduler)
        self._candidate_block = _CandidateBlock(self._block_cache.block_store,
                                                consensus, scheduler,
                                                committed_txn_cache,
                                                block_builder,
                                                max_batches)
        for batch in self._pending_batches:
            if self._candidate_block.can_add_batch:
                self._candidate_block.add_batch(batch)
            else:
                break
示例#8
0
    def _build_block(self, chain_head):
        """ Build a candidate block and construct the consensus object to
        validate it.
        :param chain_head: The block to build on top of.
        :return: (BlockBuilder) - The candidate block in a BlockBuilder
        wrapper.
        """
        state_view = BlockWrapper.state_view_for_block(
            chain_head, self._state_view_factory)
        consensus_module = ConsensusFactory.get_configured_consensus_module(
            chain_head.header_signature, state_view)

        self._consensus = consensus_module.\
            BlockPublisher(block_cache=self._block_cache,
                           state_view_factory=self._state_view_factory,
                           batch_publisher=self._batch_publisher,
                           data_dir=self._data_dir,
                           validator_id=self._identity_public_key)

        block_header = BlockHeader(
            block_num=chain_head.block_num + 1,
            previous_block_id=chain_head.header_signature,
            signer_pubkey=self._identity_public_key)
        block_builder = BlockBuilder(block_header)
        if not self._consensus.initialize_block(block_builder.block_header):
            LOGGER.debug("Consensus not ready to build candidate block.")
            return None

        # Cancel the previous scheduler if it did not complete.
        if self._scheduler is not None \
                and not self._scheduler.complete(block=False):
            self._scheduler.cancel()

        # create a new scheduler
        self._scheduler = self._transaction_executor.create_scheduler(
            self._squash_handler, chain_head.state_root_hash)

        # build the TransactionCache
        self._committed_txn_cache = TransactionCache(
            self._block_cache.block_store)
        if chain_head.header_signature not in self._block_cache.block_store:
            # if we opportunistically building a block
            # we need to check make sure we track that blocks transactions
            # as recorded.
            for batch in chain_head.block.batches:
                for txn in batch.transactions:
                    self._committed_txn_cache.add_txn(txn.header_signature)

        self._transaction_executor.execute(self._scheduler)
        for batch in self._pending_batches:
            self._validate_batch(batch)

        return block_builder
示例#9
0
    def _submit_blocks_for_verification(self, blocks):
        state_view = BlockWrapper.state_view_for_block(
            self.chain_head, self._state_view_factory)
        consensus_module = \
            ConsensusFactory.get_configured_consensus_module(
                self.chain_head.header_signature,
                state_view)

        for blkw in blocks:
            self._blocks_processing[blkw.block.header_signature] =\
                self._block_validator

        self._block_validator.submit_blocks_for_verification(
            blocks, consensus_module, self.on_block_validated)
示例#10
0
    def _set_genesis(self, block):
        # This is used by a non-genesis journal when it has received the
        # genesis block from the genesis validator
        if block.previous_block_id == NULL_BLOCK_IDENTIFIER:
            chain_id = self._chain_id_manager.get_block_chain_id()
            if chain_id is not None and chain_id != block.identifier:
                LOGGER.warning(
                    "Block id does not match block chain id %s. "
                    "Cannot set initial chain head.: %s", chain_id[:8],
                    block.identifier[:8])
            else:
                state_view = self._state_view_factory.create_view()
                consensus_module = \
                    ConsensusFactory.get_configured_consensus_module(
                        NULL_BLOCK_IDENTIFIER,
                        state_view)

                committed_txn = TransactionCache(self._block_cache.block_store)

                validator = BlockValidator(
                    consensus_module=consensus_module,
                    new_block=block,
                    chain_head=self._chain_head,
                    block_cache=self._block_cache,
                    state_view_factory=self._state_view_factory,
                    done_cb=self.on_block_validated,
                    executor=self._transaction_executor,
                    squash_handler=self._squash_handler,
                    identity_signing_key=self._identity_signing_key,
                    data_dir=self._data_dir,
                    config_dir=self._config_dir)

                valid = validator.validate_block(block, committed_txn)
                if valid:
                    if chain_id is None:
                        self._chain_id_manager.save_block_chain_id(
                            block.identifier)
                    self._block_store.update_chain([block])
                    self._chain_head = block
                    self._notify_on_chain_updated(self._chain_head)
                else:
                    LOGGER.warning(
                        "The genesis block is not valid. Cannot "
                        "set chain head: %s", block)

        else:
            LOGGER.warning(
                "Cannot set initial chain head, this is not a "
                "genesis block: %s", block)
示例#11
0
    def _load_consensus(self, block, state_view, public_key):
        """Load the configured consensus module's BlockPublisher to use for
        blocks built on this block."""
        consensus_module = ConsensusFactory.get_configured_consensus_module(
            block.header_signature, state_view)

        consensus = consensus_module.\
            BlockPublisher(block_cache=self._block_cache,
                           state_view_factory=self._state_view_factory,
                           batch_publisher=self._batch_publisher,
                           data_dir=self._data_dir,
                           config_dir=self._config_dir,
                           validator_id=public_key)

        return consensus
示例#12
0
    def _set_genesis(self, block):
        # This is used by a non-genesis journal when it has received the
        # genesis block from the genesis validator
        if block.previous_block_id == NULL_BLOCK_IDENTIFIER:
            chain_id = self._chain_id_manager.get_block_chain_id()
            if chain_id is not None and chain_id != block.identifier:
                LOGGER.warning("Block id does not match block chain id %s. "
                               "Cannot set initial chain head.: %s",
                               chain_id[:8], block.identifier[:8])
            else:
                state_view = self._state_view_factory.create_view()
                consensus_module = \
                    ConsensusFactory.get_configured_consensus_module(
                        NULL_BLOCK_IDENTIFIER,
                        state_view)

                committed_txn = TransactionCache(self._block_cache.block_store)

                validator = BlockValidator(
                    consensus_module=consensus_module,
                    new_block=block,
                    chain_head=self._chain_head,
                    block_cache=self._block_cache,
                    state_view_factory=self._state_view_factory,
                    done_cb=self.on_block_validated,
                    executor=self._transaction_executor,
                    squash_handler=self._squash_handler,
                    identity_signing_key=self._identity_signing_key,
                    data_dir=self._data_dir,
                    config_dir=self._config_dir)

                valid = validator.validate_block(block, committed_txn)
                if valid:
                    if chain_id is None:
                        self._chain_id_manager.save_block_chain_id(
                            block.identifier)
                    self._block_store.update_chain([block])
                    self._chain_head = block
                    self._notify_on_chain_updated(self._chain_head)
                else:
                    LOGGER.warning("The genesis block is not valid. Cannot "
                                   "set chain head: %s", block)

        else:
            LOGGER.warning("Cannot set initial chain head, this is not a "
                           "genesis block: %s", block)
示例#13
0
    def _verify_block(self, blkw):

        state_view = self._state_view_factory.create_view(
            self.chain_head.header.state_root_hash)
        consensus_module = ConsensusFactory.get_configured_consensus_module(
            state_view)

        validator = BlockValidator(consensus_module=consensus_module,
                                   new_block=blkw,
                                   chain_head=self._chain_head,
                                   block_cache=self._block_cache,
                                   state_view_factory=self._state_view_factory,
                                   done_cb=self.on_block_validated,
                                   executor=self._transaction_executor,
                                   squash_handler=self._sqaush_handler)
        self._blocks_processing[blkw.block.header_signature] = validator
        self._executor.submit(validator.run)
示例#14
0
    def _build_block(self, chain_head):
        """ Build a candidate block and construct the consensus object to
        validate it.
        :param chain_head: The block to build on top of.
        :return: (BlockBuilder) - The candidate block in a BlockBuilder
        wrapper.
        """
        prev_state = self._get_previous_block_root_state_hash(chain_head)
        state_view = self._state_view_factory. \
            create_view(prev_state)
        consensus_module = ConsensusFactory.get_configured_consensus_module(
            state_view)
        self._consensus = consensus_module.\
            BlockPublisher(block_cache=self._block_cache,
                           state_view=state_view)

        block_header = BlockHeader(
            block_num=chain_head.block_num + 1,
            previous_block_id=chain_head.header_signature)
        block_builder = BlockBuilder(block_header)
        if not self._consensus.initialize_block(block_builder.block_header):
            LOGGER.debug("Consensus not ready to build candidate block.")

        # create a new scheduler
        self._scheduler = self._transaction_executor.create_scheduler(
            self._squash_handler, chain_head.state_root_hash)

        # build the TransactionCache
        self._committed_txn_cache = TransactionCache(
            self._block_cache.block_store)
        if chain_head.header_signature not in self._block_cache.block_store:
            # if we opportunistically building a block
            # we need to check make sure we track that blocks transactions
            # as recorded.
            for batch in chain_head.block.batches:
                for txn in batch.transactions:
                    self._committed_txn_cache.add_txn(txn.header_signature)

        self._transaction_executor.execute(self._scheduler)
        for batch in self._pending_batches:
            self._validate_batch(batch)

        return block_builder
示例#15
0
    def _get_block_publisher(self, state_hash):
        """Returns the block publisher based on the consensus module set by the
        "sawtooth_config" transaction family.

        Args:
            state_hash (str): The current state root hash for reading settings.

        Raises:
            InvalidGenesisStateError: if any errors occur getting the
                BlockPublisher.
        """
        state_view = self._state_view_factory.create_view(state_hash)
        try:
            consensus = ConsensusFactory.get_configured_consensus_module(
                state_view)
            return consensus.BlockPublisher(BlockCache(self._block_store),
                                            state_view=state_view)
        except UnknownConsensusModuleError as e:
            raise InvalidGenesisStateError(e)
示例#16
0
    def _get_block_publisher(self, state_hash):
        """Returns the block publisher based on the consensus module set by the
        "sawtooth_settings" transaction family.

        Args:
            state_hash (str): The current state root hash for reading settings.

        Raises:
            InvalidGenesisStateError: if any errors occur getting the
                BlockPublisher.
        """
        state_view = self._state_view_factory.create_view(state_hash)
        try:
            class BatchPublisher:
                def send(self, transactions):
                    # Consensus implementations are expected to have handling
                    # in place for genesis operation. This should includes
                    # adding any authorization and registrations required
                    # for the genesis node to the Genesis Batch list and
                    # detecting validation of the Genesis Block and handle it
                    # correctly. Batch publication is not allowed during
                    # genesis operation since there is no network to validate
                    # the batch yet.
                    raise InvalidGenesisConsensusError(
                        'Consensus cannot send transactions during genesis.')

            consensus = ConsensusFactory.get_configured_consensus_module(
                NULL_BLOCK_IDENTIFIER,
                state_view)
            return consensus.BlockPublisher(
                BlockCache(self._block_store),
                state_view_factory=self._state_view_factory,
                batch_publisher=BatchPublisher(),
                data_dir=self._data_dir,
                config_dir=self._config_dir,
                validator_id=self._identity_signer.get_public_key().as_hex())
        except UnknownConsensusModuleError as e:
            raise InvalidGenesisStateError(e)
示例#17
0
    def _submit_blocks_for_verification(self, blocks):
        for blkw in blocks:
            state_view = BlockWrapper.state_view_for_block(
                self.chain_head,
                self._state_view_factory)
            consensus_module = \
                ConsensusFactory.get_configured_consensus_module(
                    self.chain_head.header_signature,
                    state_view)

            validator = BlockValidator(
                consensus_module=consensus_module,
                new_block=blkw,
                chain_head=self._chain_head,
                block_cache=self._block_cache,
                state_view_factory=self._state_view_factory,
                done_cb=self.on_block_validated,
                executor=self._transaction_executor,
                squash_handler=self._squash_handler,
                identity_signing_key=self._identity_signing_key,
                data_dir=self._data_dir,
                config_dir=self._config_dir)
            self._blocks_processing[blkw.block.header_signature] = validator
            self._executor.submit(validator.run)
示例#18
0
    def _build_candidate_block(self, chain_head):
        """ Build a candidate block and construct the consensus object to
        validate it.
        :param chain_head: The block to build on top of.
        :return: (BlockBuilder) - The candidate block in a BlockBuilder
        wrapper.
        """
        state_view = BlockWrapper.state_view_for_block(
            chain_head,
            self._state_view_factory)
        consensus_module = ConsensusFactory.get_configured_consensus_module(
            chain_head.header_signature,
            state_view)

        # using chain_head so so we can use the setting_cache
        max_batches = int(self._settings_cache.get_setting(
            'sawtooth.publisher.max_batches_per_block',
            chain_head.state_root_hash,
            default_value=0))

        public_key = self._identity_signer.get_public_key().as_hex()
        consensus = consensus_module.\
            BlockPublisher(block_cache=self._block_cache,
                           state_view_factory=self._state_view_factory,
                           batch_publisher=self._batch_publisher,
                           data_dir=self._data_dir,
                           config_dir=self._config_dir,
                           validator_id=public_key)

        batch_injectors = []
        if self._batch_injector_factory is not None:
            batch_injectors = self._batch_injector_factory.create_injectors(
                chain_head.identifier)
            if batch_injectors:
                LOGGER.debug("Loaded batch injectors: %s", batch_injectors)

        block_header = BlockHeader(
            block_num=chain_head.block_num + 1,
            previous_block_id=chain_head.header_signature,
            signer_public_key=public_key)
        block_builder = BlockBuilder(block_header)

        if not consensus.initialize_block(block_builder.block_header):
            if not self._logging_states.consensus_not_ready:
                self._logging_states.consensus_not_ready = True
                LOGGER.debug("Consensus not ready to build candidate block.")
            return None

        if self._logging_states.consensus_not_ready:
            self._logging_states.consensus_not_ready = False
            LOGGER.debug("Consensus is ready to build candidate block.")

        # create a new scheduler
        scheduler = self._transaction_executor.create_scheduler(
            self._squash_handler, chain_head.state_root_hash)

        # build the TransactionCommitCache
        committed_txn_cache = TransactionCommitCache(
            self._block_cache.block_store)

        self._transaction_executor.execute(scheduler)
        self._candidate_block = _CandidateBlock(
            self._block_cache.block_store,
            consensus, scheduler,
            committed_txn_cache,
            block_builder,
            max_batches,
            batch_injectors,
            SettingsView(state_view),
            public_key)

        for batch in self._pending_batches:
            if self._candidate_block.can_add_batch:
                self._candidate_block.add_batch(batch)
            else:
                break
示例#19
0
    def _build_candidate_block(self, chain_head):
        """ Build a candidate block and construct the consensus object to
        validate it.
        :param chain_head: The block to build on top of.
        :return: (BlockBuilder) - The candidate block in a BlockBuilder
        wrapper.
        """
        state_view = BlockWrapper.state_view_for_block(
            chain_head, self._state_view_factory)
        consensus_module = ConsensusFactory.get_configured_consensus_module(
            chain_head.header_signature, state_view)

        # using chain_head so so we can use the setting_cache
        max_batches = int(
            self._settings_cache.get_setting(
                'sawtooth.publisher.max_batches_per_block',
                chain_head.state_root_hash,
                default_value=0))

        public_key = self._identity_signer.get_public_key().as_hex()
        consensus = consensus_module.\
            BlockPublisher(block_cache=self._block_cache,
                           state_view_factory=self._state_view_factory,
                           batch_publisher=self._batch_publisher,
                           data_dir=self._data_dir,
                           config_dir=self._config_dir,
                           validator_id=public_key)

        batch_injectors = []
        if self._batch_injector_factory is not None:
            batch_injectors = self._batch_injector_factory.create_injectors(
                chain_head.identifier)
            if batch_injectors:
                LOGGER.debug("Loaded batch injectors: %s", batch_injectors)

        block_header = BlockHeader(
            block_num=chain_head.block_num + 1,
            previous_block_id=chain_head.header_signature,
            signer_public_key=public_key)
        block_builder = BlockBuilder(block_header)

        if not consensus.initialize_block(block_builder.block_header):
            if not self._logging_states.consensus_not_ready:
                self._logging_states.consensus_not_ready = True
                LOGGER.debug("Consensus not ready to build candidate block.")
            return None

        if self._logging_states.consensus_not_ready:
            self._logging_states.consensus_not_ready = False
            LOGGER.debug("Consensus is ready to build candidate block.")

        # create a new scheduler
        scheduler = self._transaction_executor.create_scheduler(
            self._squash_handler, chain_head.state_root_hash)

        # build the TransactionCommitCache
        committed_txn_cache = TransactionCommitCache(
            self._block_cache.block_store)

        self._transaction_executor.execute(scheduler)
        self._candidate_block = _CandidateBlock(
            self._block_cache.block_store, consensus, scheduler,
            committed_txn_cache, block_builder, max_batches, batch_injectors,
            SettingsView(state_view), public_key)

        for batch in self._pending_batches:
            if self._candidate_block.can_add_batch:
                self._candidate_block.add_batch(batch)
            else:
                break