def setUp(self): self.dir = tempfile.mkdtemp() self.block_db = NativeLmdbDatabase( os.path.join(self.dir, 'block.lmdb'), BlockStore.create_index_configuration()) self.block_store = BlockStore(self.block_db) self.block_manager = BlockManager() self.block_manager.add_commit_store(self.block_store) self.gossip = MockGossip() self.completer = Completer( block_manager=self.block_manager, transaction_committed=self.block_store.has_transaction, get_committed_batch_by_id=self.block_store.get_batch, get_committed_batch_by_txn_id=( self.block_store.get_batch_by_transaction), gossip=self.gossip) self.completer.set_get_chain_head(lambda: self.block_store.chain_head) self.completer.set_on_block_received(self._on_block_received) self.completer.set_on_batch_received(self._on_batch_received) self._has_block_value = True context = create_context('secp256k1') private_key = context.new_random_private_key() crypto_factory = CryptoFactory(context) self.signer = crypto_factory.new_signer(private_key) self.blocks = [] self.batches = []
def setUp(self): self.block_store = BlockStore( DictDatabase(indexes=BlockStore.create_index_configuration())) self.block_manager = BlockManager() self.block_manager.add_store("commit_store", self.block_store) self.gossip = MockGossip() self.completer = Completer( block_manager=self.block_manager, transaction_committed=self.block_store.has_transaction, get_committed_batch_by_id=self.block_store.get_batch, get_committed_batch_by_txn_id=( self.block_store.get_batch_by_transaction), get_chain_head=lambda: self.block_store.chain_head, gossip=self.gossip) self.completer.set_on_block_received(self._on_block_received) self.completer.set_on_batch_received(self._on_batch_received) self._has_block_value = True context = create_context('secp256k1') private_key = context.new_random_private_key() crypto_factory = CryptoFactory(context) self.signer = crypto_factory.new_signer(private_key) self.blocks = [] self.batches = []
def test_requires_genesis_fails_if_joins_network_with_file(self): """ In this case, when there is - a genesis_batch_file - network id the validator should produce an assertion error, as it is joining a network, and not a genesis node. """ self._with_empty_batch_file() self._with_network_name('some_block_chain_id') block_store = self.make_block_store() block_manager = BlockManager() block_manager.add_commit_store(block_store) genesis_ctrl = GenesisController( context_manager=Mock('context_manager'), transaction_executor=Mock('txn_executor'), completer=Mock('completer'), block_store=block_store, state_view_factory=Mock('StateViewFactory'), identity_signer=self._signer, block_manager=block_manager, data_dir=self._temp_dir, config_dir=self._temp_dir, chain_id_manager=ChainIdManager(self._temp_dir), batch_sender=Mock('batch_sender'), receipt_store=MagicMock()) with self.assertRaises(InvalidGenesisStateError): genesis_ctrl.requires_genesis()
def test_does_not_require_genesis_with_no_file_no_network(self): """ In this case, when there is: - no genesis.batch file - no chain head - no network the the GenesisController should not require genesis. """ block_store = self.make_block_store() block_manager = BlockManager() block_manager.add_commit_store(block_store) genesis_ctrl = GenesisController( context_manager=Mock('context_manager'), transaction_executor=Mock('txn_executor'), completer=Mock('completer'), block_store=block_store, state_view_factory=Mock('StateViewFactory'), identity_signer=self._signer, block_manager=block_manager, data_dir=self._temp_dir, config_dir=self._temp_dir, chain_id_manager=ChainIdManager(self._temp_dir), batch_sender=Mock('batch_sender'), receipt_store=MagicMock()) self.assertEqual(False, genesis_ctrl.requires_genesis())
def test_requires_genesis_fails_if_block_exists(self): """ In this case, when there is - a genesis_batch_file - a chain head id the validator should produce an assertion, as it already has a genesis block and should not attempt to produce another. """ self._with_empty_batch_file() block = self._create_block() block_store = self.make_block_store([block.block]) block_manager = BlockManager() block_manager.add_commit_store(block_store) genesis_ctrl = GenesisController( context_manager=Mock('context_manager'), transaction_executor=Mock('txn_executor'), completer=Mock('completer'), block_store=block_store, state_view_factory=Mock('StateViewFactory'), identity_signer=self._signer, block_manager=block_manager, data_dir=self._temp_dir, config_dir=self._temp_dir, chain_id_manager=ChainIdManager(self._temp_dir), batch_sender=Mock('batch_sender'), receipt_store=MagicMock()) with self.assertRaises(InvalidGenesisStateError): genesis_ctrl.requires_genesis()
def test_empty_batch_file_should_produce_block( self, mock_scheduler_complete ): """ In this case, the genesis batch, even with an empty list of batches, should produce a genesis block. Also: - the genesis.batch file should be deleted - the block_chain_id file should be created and populated """ genesis_file = self._with_empty_batch_file() block_store = self.make_block_store() block_manager = BlockManager() block_manager.add_commit_store(block_store) state_database = NativeLmdbDatabase( os.path.join(self._temp_dir, 'test_genesis.lmdb'), indexes=MerkleDatabase.create_index_configuration(), _size=10 * 1024 * 1024) merkle_db = MerkleDatabase(state_database) ctx_mgr = Mock(name='ContextManager') ctx_mgr.get_squash_handler.return_value = Mock() ctx_mgr.get_first_root.return_value = merkle_db.get_merkle_root() txn_executor = Mock(name='txn_executor') completer = Mock('completer') completer.add_block = Mock('add_block') genesis_ctrl = GenesisController( context_manager=ctx_mgr, transaction_executor=txn_executor, completer=completer, block_store=block_store, state_view_factory=StateViewFactory(state_database), identity_signer=self._signer, block_manager=block_manager, data_dir=self._temp_dir, config_dir=self._temp_dir, chain_id_manager=ChainIdManager(self._temp_dir), batch_sender=Mock('batch_sender'), receipt_store=MagicMock()) on_done_fn = Mock(return_value='') genesis_ctrl.start(on_done_fn) self.assertEqual(False, os.path.exists(genesis_file)) self.assertEqual(True, block_store.chain_head is not None) self.assertEqual(1, on_done_fn.call_count) self.assertEqual(1, completer.add_block.call_count) self.assertEqual(block_store.chain_head.identifier, self._read_block_chain_id())
def __init__(self, with_genesis=True): self.block_sender = MockBlockSender() self.batch_sender = MockBatchSender() self.block_store = BlockStore( DictDatabase(indexes=BlockStore.create_index_configuration())) self.block_cache = BlockCache(self.block_store) self.state_db = {} self.block_manager = BlockManager() self.block_manager.add_store("commit_store", self.block_store) # add the mock reference to the consensus consensus_setting_addr = SettingsView.setting_address( 'sawtooth.consensus.algorithm') self.state_db[consensus_setting_addr] = _setting_entry( 'sawtooth.consensus.algorithm', 'test_journal.mock_consensus') self.state_view_factory = MockStateViewFactory(self.state_db) context = create_context('secp256k1') private_key = context.new_random_private_key() crypto_factory = CryptoFactory(context) self.signer = crypto_factory.new_signer(private_key) identity_private_key = context.new_random_private_key() self.identity_signer = crypto_factory.new_signer(identity_private_key) chain_head = None if with_genesis: self.genesis_block = self.generate_genesis_block() chain_head = self.genesis_block self.block_manager.put([chain_head.block]) self.block_manager.persist(chain_head.block.header_signature, "commit_store") self.block_publisher = BlockPublisher( block_manager=self.block_manager, transaction_executor=MockTransactionExecutor(), transaction_committed=self.block_store.has_transaction, batch_committed=self.block_store.has_batch, state_view_factory=self.state_view_factory, settings_cache=SettingsCache( SettingsViewFactory(self.state_view_factory), ), block_sender=self.block_sender, batch_sender=self.block_sender, chain_head=chain_head.block, identity_signer=self.identity_signer, data_dir=None, config_dir=None, permission_verifier=MockPermissionVerifier(), batch_observers=[])
def __init__(self, with_genesis=True): self.block_sender = MockBlockSender() self.batch_sender = MockBatchSender() self.dir = tempfile.mkdtemp() self.block_db = NativeLmdbDatabase( os.path.join(self.dir, 'block.lmdb'), BlockStore.create_index_configuration()) self.block_store = BlockStore(self.block_db) self.block_cache = BlockCache(self.block_store) self.state_db = NativeLmdbDatabase( os.path.join(self.dir, "merkle.lmdb"), MerkleDatabase.create_index_configuration()) self.state_view_factory = NativeStateViewFactory(self.state_db) self.block_manager = BlockManager() self.block_manager.add_commit_store(self.block_store) context = create_context('secp256k1') private_key = context.new_random_private_key() crypto_factory = CryptoFactory(context) self.signer = crypto_factory.new_signer(private_key) identity_private_key = context.new_random_private_key() self.identity_signer = crypto_factory.new_signer(identity_private_key) chain_head = None if with_genesis: self.genesis_block = self.generate_genesis_block() chain_head = self.genesis_block self.block_manager.put([chain_head.block]) self.block_manager.persist(chain_head.block.header_signature, "commit_store") self.block_publisher = BlockPublisher( block_manager=self.block_manager, transaction_executor=MockTransactionExecutor(), transaction_committed=self.block_store.has_transaction, batch_committed=self.block_store.has_batch, state_view_factory=self.state_view_factory, block_sender=self.block_sender, batch_sender=self.block_sender, chain_head=chain_head.block, identity_signer=self.identity_signer, data_dir=None, config_dir=None, permission_verifier=MockPermissionVerifier(), batch_observers=[])
def test_does_not_require_genesis_block_exists(self): block = self._create_block() block_store = self.make_block_store({block.header_signature: block}) block_manager = BlockManager() block_manager.add_store("commit_store", block_store) genesis_ctrl = GenesisController( context_manager=Mock('context_manager'), transaction_executor=Mock('txn_executor'), completer=Mock('completer'), block_store=block_store, state_view_factory=Mock('StateViewFactory'), identity_signer=self._signer, block_manager=block_manager, data_dir=self._temp_dir, config_dir=self._temp_dir, chain_id_manager=ChainIdManager(self._temp_dir), batch_sender=Mock('batch_sender')) self.assertEqual(False, genesis_ctrl.requires_genesis())
def test_requires_genesis(self): self._with_empty_batch_file() block_store = self.make_block_store() block_manager = BlockManager() block_manager.add_store("commit_store", block_store) genesis_ctrl = GenesisController( context_manager=Mock('context_manager'), transaction_executor=Mock('txn_executor'), completer=Mock('completer'), block_store=block_store, # Empty block store state_view_factory=Mock('StateViewFactory'), identity_signer=self._signer, block_manager=block_manager, data_dir=self._temp_dir, config_dir=self._temp_dir, chain_id_manager=ChainIdManager(self._temp_dir), batch_sender=Mock('batch_sender')) self.assertEqual(True, genesis_ctrl.requires_genesis())
def test_does_not_require_genesis_join_network(self): self._with_network_name('some_network_name') block_store = self.make_block_store() block_manager = BlockManager() block_manager.add_commit_store(block_store) genesis_ctrl = GenesisController( context_manager=Mock('context_manager'), transaction_executor=Mock('txn_executor'), completer=Mock('completer'), block_store=block_store, state_view_factory=Mock('StateViewFactory'), identity_signer=self._signer, block_manager=block_manager, data_dir=self._temp_dir, config_dir=self._temp_dir, chain_id_manager=ChainIdManager(self._temp_dir), batch_sender=Mock('batch_sender')) self.assertEqual(False, genesis_ctrl.requires_genesis())
def __init__(self, bind_network, bind_component, bind_consensus, endpoint, peering, seeds_list, peer_list, data_dir, config_dir, identity_signer, scheduler_type, permissions, minimum_peer_connectivity, maximum_peer_connectivity, state_pruning_block_depth, fork_cache_keep_time, network_public_key=None, network_private_key=None, roles=None): """Constructs a validator instance. Args: bind_network (str): the network endpoint bind_component (str): the component endpoint endpoint (str): the zmq-style URI of this validator's publically reachable endpoint peering (str): The type of peering approach. Either 'static' or 'dynamic'. In 'static' mode, no attempted topology buildout occurs -- the validator only attempts to initiate peering connections with endpoints specified in the peer_list. In 'dynamic' mode, the validator will first attempt to initiate peering connections with endpoints specified in the peer_list and then attempt to do a topology buildout starting with peer lists obtained from endpoints in the seeds_list. In either mode, the validator will accept incoming peer requests up to max_peers. seeds_list (list of str): a list of addresses to connect to in order to perform the initial topology buildout peer_list (list of str): a list of peer addresses data_dir (str): path to the data directory config_dir (str): path to the config directory identity_signer (str): cryptographic signer the validator uses for signing """ # -- Setup Global State Database and Factory -- # global_state_db_filename = os.path.join( data_dir, 'merkle-{}.lmdb'.format(bind_network[-2:])) LOGGER.debug('global state database file is %s', global_state_db_filename) global_state_db = NativeLmdbDatabase( global_state_db_filename, indexes=MerkleDatabase.create_index_configuration()) state_view_factory = StateViewFactory(global_state_db) native_state_view_factory = NativeStateViewFactory(global_state_db) # -- Setup Receipt Store -- # receipt_db_filename = os.path.join( data_dir, 'txn_receipts-{}.lmdb'.format(bind_network[-2:])) LOGGER.debug('txn receipt store file is %s', receipt_db_filename) receipt_db = LMDBNoLockDatabase(receipt_db_filename, 'c') receipt_store = TransactionReceiptStore(receipt_db) # -- Setup Block Store -- # block_db_filename = os.path.join( data_dir, 'block-{}.lmdb'.format(bind_network[-2:])) LOGGER.debug('block store file is %s', block_db_filename) block_db = IndexedDatabase( block_db_filename, BlockStore.serialize_block, BlockStore.deserialize_block, flag='c', indexes=BlockStore.create_index_configuration()) block_store = BlockStore(block_db) # The cache keep time for the journal's block cache must be greater # than the cache keep time used by the completer. base_keep_time = 1200 block_manager = BlockManager() block_manager.add_store("commit_store", block_store) block_status_store = BlockValidationResultStore() # -- Setup Thread Pools -- # component_thread_pool = InstrumentedThreadPoolExecutor( max_workers=10, name='Component') network_thread_pool = InstrumentedThreadPoolExecutor(max_workers=10, name='Network') client_thread_pool = InstrumentedThreadPoolExecutor(max_workers=5, name='Client') sig_pool = InstrumentedThreadPoolExecutor(max_workers=3, name='Signature') # -- Setup Dispatchers -- # component_dispatcher = Dispatcher() network_dispatcher = Dispatcher() # -- Setup Services -- # component_service = Interconnect(bind_component, component_dispatcher, secured=False, heartbeat=False, max_incoming_connections=20, monitor=True, max_future_callback_workers=10) zmq_identity = hashlib.sha512( time.time().hex().encode()).hexdigest()[:23] secure = False if network_public_key is not None and network_private_key is not None: secure = True network_service = Interconnect(bind_network, dispatcher=network_dispatcher, zmq_identity=zmq_identity, secured=secure, server_public_key=network_public_key, server_private_key=network_private_key, heartbeat=True, public_endpoint=endpoint, connection_timeout=120, max_incoming_connections=100, max_future_callback_workers=10, authorize=True, signer=identity_signer, roles=roles) # -- Setup Transaction Execution Platform -- # context_manager = ContextManager(global_state_db) batch_tracker = BatchTracker(block_store.has_batch) settings_cache = SettingsCache( SettingsViewFactory(state_view_factory), ) transaction_executor = TransactionExecutor( service=component_service, context_manager=context_manager, settings_view_factory=SettingsViewFactory(state_view_factory), scheduler_type=scheduler_type, invalid_observers=[batch_tracker]) component_service.set_check_connections( transaction_executor.check_connections) event_broadcaster = EventBroadcaster(component_service, block_store, receipt_store) # -- Consensus Engine -- # consensus_thread_pool = InstrumentedThreadPoolExecutor( max_workers=3, name='Consensus') consensus_dispatcher = Dispatcher() consensus_service = Interconnect(bind_consensus, consensus_dispatcher, secured=False, heartbeat=False, max_incoming_connections=20, max_future_callback_workers=10) consensus_notifier = ConsensusNotifier(consensus_service) # -- Setup P2P Networking -- # gossip = Gossip(network_service, settings_cache, lambda: block_store.chain_head, block_store.chain_head_state_root, consensus_notifier, endpoint=endpoint, peering_mode=peering, initial_seed_endpoints=seeds_list, initial_peer_endpoints=peer_list, minimum_peer_connectivity=minimum_peer_connectivity, maximum_peer_connectivity=maximum_peer_connectivity, topology_check_frequency=1) completer = Completer( block_manager=block_manager, transaction_committed=block_store.has_transaction, get_committed_batch_by_id=block_store.get_batch, get_committed_batch_by_txn_id=( block_store.get_batch_by_transaction), get_chain_head=lambda: unwrap_if_not_none(block_store.chain_head), gossip=gossip, cache_keep_time=base_keep_time, cache_purge_frequency=30, requested_keep_time=300) self._completer = completer block_sender = BroadcastBlockSender(completer, gossip) batch_sender = BroadcastBatchSender(completer, gossip) chain_id_manager = ChainIdManager(data_dir) identity_view_factory = IdentityViewFactory( StateViewFactory(global_state_db)) id_cache = IdentityCache(identity_view_factory) # -- Setup Permissioning -- # permission_verifier = PermissionVerifier( permissions, block_store.chain_head_state_root, id_cache) identity_observer = IdentityObserver(to_update=id_cache.invalidate, forked=id_cache.forked) settings_observer = SettingsObserver( to_update=settings_cache.invalidate, forked=settings_cache.forked) # -- Setup Journal -- # batch_injector_factory = DefaultBatchInjectorFactory( state_view_factory=state_view_factory, signer=identity_signer) block_publisher = BlockPublisher( block_manager=block_manager, transaction_executor=transaction_executor, transaction_committed=block_store.has_transaction, batch_committed=block_store.has_batch, state_view_factory=native_state_view_factory, block_sender=block_sender, batch_sender=batch_sender, chain_head=block_store.chain_head, identity_signer=identity_signer, data_dir=data_dir, config_dir=config_dir, permission_verifier=permission_verifier, batch_observers=[batch_tracker], batch_injector_factory=batch_injector_factory) block_validator = BlockValidator( block_manager=block_manager, block_store=block_store, view_factory=native_state_view_factory, transaction_executor=transaction_executor, block_status_store=block_status_store, permission_verifier=permission_verifier) chain_controller = ChainController( block_store=block_store, block_manager=block_manager, block_validator=block_validator, state_database=global_state_db, chain_head_lock=block_publisher.chain_head_lock, block_status_store=block_status_store, consensus_notifier=consensus_notifier, state_pruning_block_depth=state_pruning_block_depth, fork_cache_keep_time=fork_cache_keep_time, data_dir=data_dir, observers=[ event_broadcaster, receipt_store, batch_tracker, identity_observer, settings_observer ]) genesis_controller = GenesisController( context_manager=context_manager, transaction_executor=transaction_executor, completer=completer, block_manager=block_manager, block_store=block_store, state_view_factory=state_view_factory, identity_signer=identity_signer, data_dir=data_dir, config_dir=config_dir, chain_id_manager=chain_id_manager, batch_sender=batch_sender) responder = Responder(completer) completer.set_on_block_received(chain_controller.queue_block) self._incoming_batch_sender = None # -- Register Message Handler -- # network_handlers.add(network_dispatcher, network_service, gossip, completer, responder, network_thread_pool, sig_pool, lambda block_id: block_id in block_manager, self.has_batch, permission_verifier, block_publisher, consensus_notifier) component_handlers.add(component_dispatcher, gossip, context_manager, transaction_executor, completer, block_store, batch_tracker, global_state_db, self.get_chain_head_state_root_hash, receipt_store, event_broadcaster, permission_verifier, component_thread_pool, client_thread_pool, sig_pool, block_publisher, identity_signer.get_public_key().as_hex()) # -- Store Object References -- # self._component_dispatcher = component_dispatcher self._component_service = component_service self._component_thread_pool = component_thread_pool self._network_dispatcher = network_dispatcher self._network_service = network_service self._network_thread_pool = network_thread_pool consensus_proxy = ConsensusProxy( block_manager=block_manager, chain_controller=chain_controller, block_publisher=block_publisher, gossip=gossip, identity_signer=identity_signer, settings_view_factory=SettingsViewFactory(state_view_factory), state_view_factory=state_view_factory) consensus_handlers.add(consensus_dispatcher, consensus_thread_pool, consensus_proxy, consensus_notifier) self._block_status_store = block_status_store self._consensus_dispatcher = consensus_dispatcher self._consensus_service = consensus_service self._consensus_thread_pool = consensus_thread_pool self._client_thread_pool = client_thread_pool self._sig_pool = sig_pool self._context_manager = context_manager self._transaction_executor = transaction_executor self._genesis_controller = genesis_controller self._gossip = gossip self._block_publisher = block_publisher self._block_validator = block_validator self._chain_controller = chain_controller self._block_validator = block_validator
def setUp(self): self.block_manager = BlockManager()