Beispiel #1
0
    def test_raise_key_error_on_missing_receipt(self):
        """Tests that we correctly raise key error on a missing receipt
        """
        receipt_store = TransactionReceiptStore(DictDatabase())

        with self.assertRaises(KeyError):
            receipt_store.get('unknown')
Beispiel #2
0
    def test_get_receipts(self):
        """Tests that the TransactionReceiptGetRequestHandler will return a
        response with the receipt for the transaction requested.
        """
        receipt_store = TransactionReceiptStore(DictDatabase())

        receipt = TransactionReceipt(
            data=["beef".encode()])

        receipt_store.put("deadbeef", receipt)

        handler = ClientReceiptGetRequestHandler(receipt_store)

        request = ClientReceiptGetRequest(
            transaction_ids=['deadbeef']).SerializeToString()

        response = handler.handle('test_conn_id', request)
        self.assertEqual(HandlerStatus.RETURN, response.status)
        self.assertEqual(ClientReceiptGetResponse.OK,
                         response.message_out.status)

        self.assertEqual([receipt], [r for r in response.message_out.receipts])

        request = ClientReceiptGetRequest(
            transaction_ids=['unknown']).SerializeToString()

        response = handler.handle('test_conn_id', request)
        self.assertEqual(HandlerStatus.RETURN, response.status)
        self.assertEqual(ClientReceiptGetResponse.NO_RESOURCE,
                         response.message_out.status)
Beispiel #3
0
    def test_get_receipts(self):
        """Tests that the TransactionReceiptGetRequestHandler will return a
        response with the receipt for the transaction requested.
        """
        receipt_store = TransactionReceiptStore(DictDatabase())

        receipt = TransactionReceipt(
            data=[TransactionReceipt.Data(
                data_type="dead", data="beef".encode())])

        receipt_store.put("deadbeef", receipt)

        handler = ClientReceiptGetRequestHandler(receipt_store)

        request = ClientReceiptGetRequest(
            transaction_ids=['deadbeef']).SerializeToString()

        response = handler.handle('test_conn_id', request)
        self.assertEqual(HandlerStatus.RETURN, response.status)
        self.assertEqual(ClientReceiptGetResponse.OK,
                         response.message_out.status)

        self.assertEqual([receipt], [r for r in response.message_out.receipts])


        request = ClientReceiptGetRequest(
            transaction_ids=['unknown']).SerializeToString()

        response = handler.handle('test_conn_id', request)
        self.assertEqual(HandlerStatus.RETURN, response.status)
        self.assertEqual(ClientReceiptGetResponse.NO_RESOURCE,
                         response.message_out.status)
Beispiel #4
0
    def test_raise_key_error_on_missing_receipt(self):
        """Tests that we correctly raise key error on a missing receipt
        """
        receipt_store = TransactionReceiptStore(DictDatabase())

        with self.assertRaises(KeyError):
            receipt_store.get('unknown')
Beispiel #5
0
class ClientEventsGetRequestHandlerTest(unittest.TestCase):
    def setUp(self):
        self.block_store = BlockStore(DictDatabase())
        self.receipt_store = TransactionReceiptStore(DictDatabase())
        self._txn_ids_by_block_id = {}
        for block_id, blk_w, txn_ids in create_chain():
            self.block_store[block_id] = blk_w
            self._txn_ids_by_block_id[block_id] = txn_ids
            for txn_id in txn_ids:
                receipt = create_receipt(txn_id=txn_id,
                                         key_values=[("address", block_id)])
                self.receipt_store.put(
                    txn_id=txn_id,
                    txn_receipt=receipt)

    def test_get_events_by_block_id(self):
        """Tests that the correct events are returned by the
        ClientEventsGetRequest handler for each block id.

        """

        event_broadcaster = EventBroadcaster(
            Mock(),
            block_store=self.block_store,
            receipt_store=self.receipt_store)
        for block_id, _ in self._txn_ids_by_block_id.items():
            request = client_event_pb2.ClientEventsGetRequest()
            request.block_ids.extend([block_id])
            subscription = request.subscriptions.add()
            subscription.event_type = "sawtooth/block-commit"
            event_filter = subscription.filters.add()
            event_filter.key = "address"
            event_filter.match_string = block_id
            event_filter.filter_type = event_filter.SIMPLE_ALL

            event_filter2 = subscription.filters.add()
            event_filter2.key = "block_id"
            event_filter2.match_string = block_id
            event_filter2.filter_type = event_filter2.SIMPLE_ALL

            handler = ClientEventsGetRequestHandler(event_broadcaster)
            handler_output = handler.handle(
                "dummy_conn_id",
                request.SerializeToString())

            self.assertEqual(handler_output.message_type,
                             validator_pb2.Message.CLIENT_EVENTS_GET_RESPONSE)

            self.assertEqual(handler_output.status, HandlerStatus.RETURN)
            self.assertTrue(
                all(any(a.value == block_id
                        for a in e.attributes)
                    for e in handler_output.message_out.events),
                "Each Event has at least one attribute value that is the"
                " block id for the block.")
            self.assertEqual(handler_output.message_out.status,
                             client_event_pb2.ClientEventsGetResponse.OK)
            self.assertTrue(len(handler_output.message_out.events) > 0)
Beispiel #6
0
class ClientEventsGetRequestHandlerTest(unittest.TestCase):
    def setUp(self):
        self.block_store = BlockStore(DictDatabase())
        self.receipt_store = TransactionReceiptStore(DictDatabase())
        self._txn_ids_by_block_id = {}
        for block_id, blk_w, txn_ids in create_chain():
            self.block_store[block_id] = blk_w
            self._txn_ids_by_block_id[block_id] = txn_ids
            for txn_id in txn_ids:
                receipt = create_receipt(txn_id=txn_id,
                                         key_values=[("address", block_id)])
                self.receipt_store.put(
                    txn_id=txn_id,
                    txn_receipt=receipt)

    def test_get_events_by_block_id(self):
        """Tests that the correct events are returned by the
        ClientEventsGetRequest handler for each block id.

        """

        event_broadcaster = EventBroadcaster(
            Mock(),
            block_store=self.block_store,
            receipt_store=self.receipt_store)
        for block_id, _ in self._txn_ids_by_block_id.items():
            request = client_event_pb2.ClientEventsGetRequest()
            request.block_ids.extend([block_id])
            subscription = request.subscriptions.add()
            subscription.event_type = "sawtooth/block-commit"
            event_filter = subscription.filters.add()
            event_filter.key = "address"
            event_filter.match_string = block_id
            event_filter.filter_type = event_filter.SIMPLE_ALL

            event_filter2 = subscription.filters.add()
            event_filter2.key = "block_id"
            event_filter2.match_string = block_id
            event_filter2.filter_type = event_filter2.SIMPLE_ALL

            handler = ClientEventsGetRequestHandler(event_broadcaster)
            handler_output = handler.handle(
                "dummy_conn_id",
                request.SerializeToString())

            self.assertEqual(handler_output.message_type,
                             validator_pb2.Message.CLIENT_EVENTS_GET_RESPONSE)

            self.assertEqual(handler_output.status, HandlerStatus.RETURN)
            self.assertTrue(
                all(any(a.value == block_id
                        for a in e.attributes)
                    for e in handler_output.message_out.events),
                "Each Event has at least one attribute value that is the"
                " block id for the block.")
            self.assertEqual(handler_output.message_out.status,
                             client_event_pb2.ClientEventsGetResponse.OK)
            self.assertTrue(len(handler_output.message_out.events) > 0)
Beispiel #7
0
 def setUp(self):
     self.block_store = BlockStore(DictDatabase())
     self.receipt_store = TransactionReceiptStore(DictDatabase())
     self._txn_ids_by_block_id = {}
     for block_id, blk_w, txn_ids in create_chain():
         self.block_store[block_id] = blk_w
         self._txn_ids_by_block_id[block_id] = txn_ids
         for txn_id in txn_ids:
             receipt = create_receipt(txn_id=txn_id,
                                      key_values=[("address", block_id)])
             self.receipt_store.put(txn_id=txn_id, txn_receipt=receipt)
Beispiel #8
0
 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.receipt_store = TransactionReceiptStore(DictDatabase())
     self._txn_ids_by_block_id = {}
     for block_id, blk_w, txn_ids in create_chain():
         self.block_store.put_blocks([blk_w.block])
         self._txn_ids_by_block_id[block_id] = txn_ids
         for txn_id in txn_ids:
             receipt = create_receipt(txn_id=txn_id,
                                      key_values=[("address", block_id)])
             self.receipt_store.put(txn_id=txn_id, txn_receipt=receipt)
Beispiel #9
0
    def test_receipt_store_get_and_set(self):
        """Tests that we correctly get and set state changes to a ReceiptStore.

        This test sets a list of receipts and then gets them back, ensuring that
        the data is the same.
        """

        receipt_store = TransactionReceiptStore(DictDatabase())

        receipts = []
        for i in range(10):
            state_changes = []
            events = []
            data = []

            for j in range(10):
                string = str(j)
                byte = string.encode()

                state_changes.append(
                    StateChange(address='a100000' + string,
                                value=byte,
                                type=StateChange.SET))
                events.append(
                    Event(
                        event_type="test",
                        data=byte,
                        attributes=[Event.Attribute(key=string,
                                                    value=string)]))
                data.append(
                    TransactionReceipt.Data(data_type="test", data=byte))

            receipts.append(
                TransactionReceipt(state_changes=state_changes,
                                   events=events,
                                   data=data))

        for i in range(len(receipts)):
            receipt_store.put(str(i), receipts[i])

        for i in range(len(receipts)):
            stored_receipt = receipt_store.get(str(i))

            self.assertEqual(stored_receipt.state_changes,
                             receipts[i].state_changes)
            self.assertEqual(stored_receipt.events, receipts[i].events)
            self.assertEqual(stored_receipt.data, receipts[i].data)
Beispiel #10
0
    def test_receipt_store_get_and_set(self):
        """Tests that we correctly get and set state changes to a ReceiptStore.

        This test sets a list of receipts and then gets them back,
        ensuring that the data is the same.
        """

        receipt_store = TransactionReceiptStore(DictDatabase())

        receipts = []
        for i in range(10):
            state_changes = []
            events = []
            data = []

            for j in range(10):
                string = str(j)
                byte = string.encode()

                state_changes.append(
                    StateChange(
                        address='a100000' + string,
                        value=byte,
                        type=StateChange.SET))
                events.append(
                    Event(
                        event_type="test",
                        data=byte,
                        attributes=[Event.Attribute(key=string,
                                                    value=string)]))
                data.append(byte)

            receipts.append(
                TransactionReceipt(
                    state_changes=state_changes, events=events, data=data))

        for i, receipt in enumerate(receipts):
            receipt_store.put(str(i), receipt)

        for i, receipt in enumerate(receipts):
            stored_receipt = receipt_store.get(str(i))

            self.assertEqual(stored_receipt.state_changes,
                             receipt.state_changes)
            self.assertEqual(stored_receipt.events, receipt.events)
            self.assertEqual(stored_receipt.data, receipt.data)
Beispiel #11
0
    def do_get_receipts():
        receipt_store = TransactionReceiptStore(DictDatabase())

        receipt = TransactionReceipt(
            data=["beef".encode()])

        receipt_store.put("deadbeef", receipt)

        handler = ClientReceiptGetRequestHandler(receipt_store)

        request = ClientReceiptGetRequest(
            transaction_ids=['deadbeef']).SerializeToString()

        response = handler.handle('test_conn_id', request)
        assert HandlerStatus.RETURN == response.status        
        
        request = ClientReceiptGetRequest(
            transaction_ids=['unknown']).SerializeToString()

        response = handler.handle('test_conn_id', request)
        assert HandlerStatus.RETURN == response.status        
Beispiel #12
0
 def setUp(self):
     self.block_store = BlockStore(DictDatabase())
     self.receipt_store = TransactionReceiptStore(DictDatabase())
     self._txn_ids_by_block_id = {}
     for block_id, blk_w, txn_ids in create_chain():
         self.block_store[block_id] = blk_w
         self._txn_ids_by_block_id[block_id] = txn_ids
         for txn_id in txn_ids:
             receipt = create_receipt(txn_id=txn_id,
                                      key_values=[("address", block_id)])
             self.receipt_store.put(
                 txn_id=txn_id,
                 txn_receipt=receipt)
def test_get_receipts():
    """Tests that the TransactionReceiptGetRequestHandler will return a
    response with the receipt for the transaction requested.
    """

    receipt_store = TransactionReceiptStore(DictDatabase())

    receipt = TransactionReceipt(
        data=["beef".encode()])

    receipt_store.put("deadbeef", receipt)

    handler = ClientReceiptGetRequestHandler(receipt_store)

    request = ClientReceiptGetRequest(
        transaction_ids=['deadbeef']).SerializeToString()

    response = handler.handle('test_conn_id', request)

    request = ClientReceiptGetRequest(
        transaction_ids=['unknown']).SerializeToString()

    response = handler.handle('test_conn_id', request)
Beispiel #14
0
    def do_receipt_store_get_and_set():
        receipt_store = TransactionReceiptStore(DictDatabase())

        receipts = []
        for i in range(10):
            state_changes = []
            events = []
            data = []

            for j in range(10):
                string = str(j)
                byte = string.encode()

                state_changes.append(
                    StateChange(
                        address='a100000' + string,
                        value=byte,
                        type=StateChange.SET))
                events.append(
                    Event(
                        event_type="test",
                        data=byte,
                        attributes=[Event.Attribute(key=string,
                                                    value=string)]))
                data.append(byte)

            receipts.append(
                TransactionReceipt(
                    state_changes=state_changes, events=events, data=data))

        for i, receipt in enumerate(receipts):
            receipt_store.put(str(i), receipt)

        for i, receipt in enumerate(receipts):
            stored_receipt = receipt_store.get(str(i))

            assert stored_receipt.state_changes == receipt.state_changes
Beispiel #15
0
 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.receipt_store = TransactionReceiptStore(DictDatabase())
     self._txn_ids_by_block_id = {}
     for block_id, blk_w, txn_ids in create_chain():
         self.block_store.put_blocks([blk_w.block])
         self._txn_ids_by_block_id[block_id] = txn_ids
         for txn_id in txn_ids:
             receipt = create_receipt(txn_id=txn_id,
                                      key_values=[("address", block_id)])
             self.receipt_store.put(
                 txn_id=txn_id,
                 txn_receipt=receipt)
Beispiel #16
0
    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,
                 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)

        # -- 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_cache = BlockCache(block_store,
                                 keep_time=int(base_keep_time * 9 / 8),
                                 purge_frequency=30)

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

        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)

        # -- Setup P2P Networking -- #
        gossip = Gossip(network_service,
                        settings_cache,
                        lambda: block_store.chain_head,
                        block_store.chain_head_state_root,
                        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_store,
                              gossip,
                              cache_keep_time=base_keep_time,
                              cache_purge_frequency=30,
                              requested_keep_time=300)

        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)

        # -- 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,
                                         monitor=True,
                                         max_future_callback_workers=10)

        consensus_notifier = ConsensusNotifier(consensus_service)

        # -- Setup Journal -- #
        batch_injector_factory = DefaultBatchInjectorFactory(
            block_cache=block_cache,
            state_view_factory=state_view_factory,
            signer=identity_signer)

        block_publisher = BlockPublisher(
            transaction_executor=transaction_executor,
            block_cache=block_cache,
            state_view_factory=state_view_factory,
            settings_cache=settings_cache,
            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,
            check_publish_block_frequency=0.1,
            batch_observers=[batch_tracker],
            batch_injector_factory=batch_injector_factory)

        block_publisher_batch_sender = block_publisher.batch_sender()

        block_validator = BlockValidator(
            block_cache=block_cache,
            state_view_factory=state_view_factory,
            transaction_executor=transaction_executor,
            identity_signer=identity_signer,
            data_dir=data_dir,
            config_dir=config_dir,
            permission_verifier=permission_verifier)

        chain_controller = ChainController(
            block_store=block_store,
            block_cache=block_cache,
            block_validator=block_validator,
            state_database=global_state_db,
            chain_head_lock=block_publisher.chain_head_lock,
            state_pruning_block_depth=state_pruning_block_depth,
            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_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_batch_received(block_publisher_batch_sender.send)
        completer.set_on_block_received(chain_controller.queue_block)
        completer.set_chain_has_block(chain_controller.has_block)

        # -- Register Message Handler -- #
        network_handlers.add(network_dispatcher, network_service, gossip,
                             completer, responder, network_thread_pool,
                             sig_pool, chain_controller.has_block,
                             block_publisher.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)

        # -- 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_cache=block_cache,
            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)

        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._chain_controller = chain_controller
        self._block_validator = block_validator
Beispiel #17
0
    def do_raise_key_error_on_missing_receipt():
        receipt_store = TransactionReceiptStore(DictDatabase())

        with pytest.raises(KeyError):
            receipt_store.get('unknown')
Beispiel #18
0
    def __init__(self,
                 bind_network,
                 bind_component,
                 endpoint,
                 peering,
                 seeds_list,
                 peer_list,
                 data_dir,
                 config_dir,
                 identity_signing_key,
                 scheduler_type,
                 permissions,
                 network_public_key=None,
                 network_private_key=None,
                 roles=None,
                 metrics_registry=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_signing_key (str): key validator uses for signing
        """
        db_filename = os.path.join(data_dir,
                                   'merkle-{}.lmdb'.format(bind_network[-2:]))
        LOGGER.debug('database file is %s', db_filename)

        merkle_db = LMDBNoLockDatabase(db_filename, 'c')

        delta_db_filename = os.path.join(
            data_dir, 'state-deltas-{}.lmdb'.format(bind_network[-2:]))
        LOGGER.debug('state delta store file is %s', delta_db_filename)
        state_delta_db = LMDBNoLockDatabase(delta_db_filename, 'c')

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

        state_delta_store = StateDeltaStore(state_delta_db)
        receipt_store = TransactionReceiptStore(receipt_db)

        context_manager = ContextManager(merkle_db, state_delta_store)
        self._context_manager = context_manager

        state_view_factory = StateViewFactory(merkle_db)

        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 = LMDBNoLockDatabase(block_db_filename, 'c')
        block_store = BlockStore(block_db)

        batch_tracker = BatchTracker(block_store)

        # setup network
        self._dispatcher = Dispatcher(metrics_registry=metrics_registry)

        thread_pool = ThreadPoolExecutor(max_workers=10)
        sig_pool = ThreadPoolExecutor(max_workers=3)

        self._thread_pool = thread_pool
        self._sig_pool = sig_pool

        self._service = Interconnect(bind_component,
                                     self._dispatcher,
                                     secured=False,
                                     heartbeat=False,
                                     max_incoming_connections=20,
                                     monitor=True,
                                     max_future_callback_workers=10,
                                     metrics_registry=metrics_registry)

        executor = TransactionExecutor(
            service=self._service,
            context_manager=context_manager,
            settings_view_factory=SettingsViewFactory(
                StateViewFactory(merkle_db)),
            scheduler_type=scheduler_type,
            invalid_observers=[batch_tracker],
            metrics_registry=metrics_registry)

        self._executor = executor
        self._service.set_check_connections(executor.check_connections)

        state_delta_processor = StateDeltaProcessor(self._service,
                                                    state_delta_store,
                                                    block_store)
        event_broadcaster = EventBroadcaster(self._service, block_store,
                                             receipt_store)

        zmq_identity = hashlib.sha512(
            time.time().hex().encode()).hexdigest()[:23]

        network_thread_pool = ThreadPoolExecutor(max_workers=10)
        self._network_thread_pool = network_thread_pool

        self._network_dispatcher = Dispatcher(
            metrics_registry=metrics_registry)

        secure = False
        if network_public_key is not None and network_private_key is not None:
            secure = True

        self._network = Interconnect(
            bind_network,
            dispatcher=self._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=30,
            max_incoming_connections=100,
            max_future_callback_workers=10,
            authorize=True,
            public_key=signing.generate_pubkey(identity_signing_key),
            priv_key=identity_signing_key,
            roles=roles,
            metrics_registry=metrics_registry)

        self._gossip = Gossip(self._network,
                              endpoint=endpoint,
                              peering_mode=peering,
                              initial_seed_endpoints=seeds_list,
                              initial_peer_endpoints=peer_list,
                              minimum_peer_connectivity=3,
                              maximum_peer_connectivity=10,
                              topology_check_frequency=1)

        completer = Completer(block_store, self._gossip)

        block_sender = BroadcastBlockSender(completer, self._gossip)
        batch_sender = BroadcastBatchSender(completer, self._gossip)
        chain_id_manager = ChainIdManager(data_dir)

        identity_view_factory = IdentityViewFactory(
            StateViewFactory(merkle_db))

        id_cache = IdentityCache(identity_view_factory,
                                 block_store.chain_head_state_root)

        permission_verifier = PermissionVerifier(
            permissions, block_store.chain_head_state_root, id_cache)

        identity_observer = IdentityObserver(to_update=id_cache.invalidate,
                                             forked=id_cache.forked)

        # Create and configure journal
        self._journal = Journal(
            block_store=block_store,
            state_view_factory=StateViewFactory(merkle_db),
            block_sender=block_sender,
            batch_sender=batch_sender,
            transaction_executor=executor,
            squash_handler=context_manager.get_squash_handler(),
            identity_signing_key=identity_signing_key,
            chain_id_manager=chain_id_manager,
            data_dir=data_dir,
            config_dir=config_dir,
            permission_verifier=permission_verifier,
            check_publish_block_frequency=0.1,
            block_cache_purge_frequency=30,
            block_cache_keep_time=300,
            batch_observers=[batch_tracker],
            chain_observers=[
                state_delta_processor, event_broadcaster, receipt_store,
                batch_tracker, identity_observer
            ],
            metrics_registry=metrics_registry)

        self._genesis_controller = GenesisController(
            context_manager=context_manager,
            transaction_executor=executor,
            completer=completer,
            block_store=block_store,
            state_view_factory=state_view_factory,
            identity_key=identity_signing_key,
            data_dir=data_dir,
            config_dir=config_dir,
            chain_id_manager=chain_id_manager,
            batch_sender=batch_sender)

        responder = Responder(completer)

        completer.set_on_batch_received(self._journal.on_batch_received)
        completer.set_on_block_received(self._journal.on_block_received)

        self._dispatcher.add_handler(
            validator_pb2.Message.TP_ADD_RECEIPT_DATA_REQUEST,
            tp_state_handlers.TpAddReceiptDataHandler(context_manager),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.TP_ADD_EVENT_REQUEST,
            tp_state_handlers.TpAddEventHandler(context_manager), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.TP_STATE_DEL_REQUEST,
            tp_state_handlers.TpStateDeleteHandler(context_manager),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.TP_STATE_GET_REQUEST,
            tp_state_handlers.TpStateGetHandler(context_manager), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.TP_STATE_SET_REQUEST,
            tp_state_handlers.TpStateSetHandler(context_manager), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.TP_REGISTER_REQUEST,
            processor_handlers.ProcessorRegisterHandler(executor.processors),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.TP_UNREGISTER_REQUEST,
            processor_handlers.ProcessorUnRegisterHandler(executor.processors),
            thread_pool)

        # Set up base network handlers
        self._network_dispatcher.add_handler(
            validator_pb2.Message.NETWORK_PING,
            PingHandler(network=self._network), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.NETWORK_CONNECT,
            ConnectHandler(network=self._network), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.NETWORK_DISCONNECT,
            DisconnectHandler(network=self._network), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.AUTHORIZATION_VIOLATION,
            AuthorizationViolationHandler(network=self._network,
                                          gossip=self._gossip),
            network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.AUTHORIZATION_TRUST_REQUEST,
            AuthorizationTrustRequestHandler(
                network=self._network,
                permission_verifier=permission_verifier,
                gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.AUTHORIZATION_CHALLENGE_REQUEST,
            AuthorizationChallengeRequestHandler(network=self._network),
            network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.AUTHORIZATION_CHALLENGE_SUBMIT,
            AuthorizationChallengeSubmitHandler(
                network=self._network,
                permission_verifier=permission_verifier,
                gossip=self._gossip), network_thread_pool)

        # Set up gossip handlers
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_GET_PEERS_REQUEST,
            NetworkPermissionHandler(network=self._network,
                                     permission_verifier=permission_verifier,
                                     gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_GET_PEERS_REQUEST,
            GetPeersRequestHandler(gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_GET_PEERS_RESPONSE,
            NetworkPermissionHandler(network=self._network,
                                     permission_verifier=permission_verifier,
                                     gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_GET_PEERS_RESPONSE,
            GetPeersResponseHandler(gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_REGISTER,
            NetworkPermissionHandler(network=self._network,
                                     permission_verifier=permission_verifier,
                                     gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_REGISTER,
            PeerRegisterHandler(gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_UNREGISTER,
            PeerUnregisterHandler(gossip=self._gossip), network_thread_pool)

        # GOSSIP_MESSAGE 1) Sends acknowledgement to the sender
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_MESSAGE, GossipMessageHandler(),
            network_thread_pool)

        # GOSSIP_MESSAGE 2) Verify Network Permissions
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_MESSAGE,
            NetworkPermissionHandler(network=self._network,
                                     permission_verifier=permission_verifier,
                                     gossip=self._gossip), network_thread_pool)

        # GOSSIP_MESSAGE 3) Verifies signature
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_MESSAGE,
            signature_verifier.GossipMessageSignatureVerifier(), sig_pool)

        # GOSSIP_MESSAGE 4) Verifies batch structure
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_MESSAGE,
            structure_verifier.GossipHandlerStructureVerifier(),
            network_thread_pool)

        # GOSSIP_MESSAGE 4) Verifies that the node is allowed to publish a
        # block
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_MESSAGE,
            NetworkConsensusPermissionHandler(
                network=self._network,
                permission_verifier=permission_verifier,
                gossip=self._gossip), network_thread_pool)

        # GOSSIP_MESSAGE 5) Determines if we should broadcast the
        # message to our peers. It is important that this occur prior
        # to the sending of the message to the completer, as this step
        # relies on whether the  gossip message has previously been
        # seen by the validator to determine whether or not forwarding
        # should occur
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_MESSAGE,
            GossipBroadcastHandler(gossip=self._gossip, completer=completer),
            network_thread_pool)

        # GOSSIP_MESSAGE 6) Send message to completer
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_MESSAGE,
            CompleterGossipHandler(completer), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BLOCK_REQUEST,
            NetworkPermissionHandler(network=self._network,
                                     permission_verifier=permission_verifier,
                                     gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BLOCK_REQUEST,
            BlockResponderHandler(responder, self._gossip),
            network_thread_pool)

        # GOSSIP_BLOCK_RESPONSE 1) Sends ack to the sender
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
            GossipBlockResponseHandler(), network_thread_pool)

        # GOSSIP_MESSAGE 2) Verify Network Permissions
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
            NetworkPermissionHandler(network=self._network,
                                     permission_verifier=permission_verifier,
                                     gossip=self._gossip), network_thread_pool)

        # GOSSIP_BLOCK_RESPONSE 3) Verifies signature
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
            signature_verifier.GossipBlockResponseSignatureVerifier(),
            sig_pool)

        # GOSSIP_BLOCK_RESPONSE 4) Check batch structure
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
            structure_verifier.GossipBlockResponseStructureVerifier(),
            network_thread_pool)

        # GOSSIP_BLOCK_RESPONSE 5) Send message to completer
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
            CompleterGossipBlockResponseHandler(completer),
            network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
            ResponderBlockResponseHandler(responder, self._gossip),
            network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_BY_BATCH_ID_REQUEST,
            NetworkPermissionHandler(network=self._network,
                                     permission_verifier=permission_verifier,
                                     gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_BY_BATCH_ID_REQUEST,
            BatchByBatchIdResponderHandler(responder, self._gossip),
            network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_BY_TRANSACTION_ID_REQUEST,
            NetworkPermissionHandler(network=self._network,
                                     permission_verifier=permission_verifier,
                                     gossip=self._gossip), network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_BY_TRANSACTION_ID_REQUEST,
            BatchByTransactionIdResponderHandler(responder, self._gossip),
            network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_RESPONSE,
            NetworkPermissionHandler(network=self._network,
                                     permission_verifier=permission_verifier,
                                     gossip=self._gossip), network_thread_pool)

        # GOSSIP_BATCH_RESPONSE 1) Sends ack to the sender
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_RESPONSE,
            GossipBatchResponseHandler(), network_thread_pool)

        # GOSSIP_BATCH_RESPONSE 2) Verifies signature
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_RESPONSE,
            signature_verifier.GossipBatchResponseSignatureVerifier(),
            sig_pool)

        # GOSSIP_BATCH_RESPONSE 3) Check batch structure
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_RESPONSE,
            structure_verifier.GossipBatchResponseStructureVerifier(),
            network_thread_pool)

        # GOSSIP_BATCH_RESPONSE 4) Send message to completer
        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_RESPONSE,
            CompleterGossipBatchResponseHandler(completer),
            network_thread_pool)

        self._network_dispatcher.add_handler(
            validator_pb2.Message.GOSSIP_BATCH_RESPONSE,
            ResponderBatchResponseHandler(responder, self._gossip),
            network_thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BATCH_SUBMIT_REQUEST,
            BatchListPermissionVerifier(
                permission_verifier=permission_verifier), sig_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BATCH_SUBMIT_REQUEST,
            signature_verifier.BatchListSignatureVerifier(), sig_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BATCH_SUBMIT_REQUEST,
            structure_verifier.BatchListStructureVerifier(),
            network_thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BATCH_SUBMIT_REQUEST,
            CompleterBatchListBroadcastHandler(completer, self._gossip),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BATCH_SUBMIT_REQUEST,
            client_handlers.BatchSubmitFinisher(batch_tracker), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BATCH_STATUS_REQUEST,
            client_handlers.BatchStatusRequest(batch_tracker), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_STATE_LIST_REQUEST,
            client_handlers.StateListRequest(merkle_db,
                                             self._journal.get_block_store()),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_STATE_GET_REQUEST,
            client_handlers.StateGetRequest(merkle_db,
                                            self._journal.get_block_store()),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BLOCK_LIST_REQUEST,
            client_handlers.BlockListRequest(self._journal.get_block_store()),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BLOCK_GET_REQUEST,
            client_handlers.BlockGetRequest(self._journal.get_block_store()),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BATCH_LIST_REQUEST,
            client_handlers.BatchListRequest(self._journal.get_block_store()),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_BATCH_GET_REQUEST,
            client_handlers.BatchGetRequest(self._journal.get_block_store()),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_TRANSACTION_LIST_REQUEST,
            client_handlers.TransactionListRequest(
                self._journal.get_block_store()), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_TRANSACTION_GET_REQUEST,
            client_handlers.TransactionGetRequest(
                self._journal.get_block_store()), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_STATE_CURRENT_REQUEST,
            client_handlers.StateCurrentRequest(
                self._journal.get_current_root), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_RECEIPT_GET_REQUEST,
            ClientReceiptGetRequestHandler(receipt_store), thread_pool)

        # State Delta Subscription Handlers
        self._dispatcher.add_handler(
            validator_pb2.Message.STATE_DELTA_SUBSCRIBE_REQUEST,
            StateDeltaSubscriberValidationHandler(state_delta_processor),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.STATE_DELTA_SUBSCRIBE_REQUEST,
            StateDeltaAddSubscriberHandler(state_delta_processor), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.STATE_DELTA_UNSUBSCRIBE_REQUEST,
            StateDeltaUnsubscriberHandler(state_delta_processor), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.STATE_DELTA_GET_EVENTS_REQUEST,
            StateDeltaGetEventsHandler(block_store, state_delta_store),
            thread_pool)

        # Client Events Handlers
        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
            ClientEventsSubscribeValidationHandler(event_broadcaster),
            thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
            ClientEventsSubscribeHandler(event_broadcaster), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_EVENTS_UNSUBSCRIBE_REQUEST,
            ClientEventsUnsubscribeHandler(event_broadcaster), thread_pool)

        self._dispatcher.add_handler(
            validator_pb2.Message.CLIENT_EVENTS_GET_REQUEST,
            ClientEventsGetRequestHandler(event_broadcaster), thread_pool)