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')
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)
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)
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)
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
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
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
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)
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)
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
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)
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)
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
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)
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)
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)
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
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