Kagome
Polkadot Runtime Engine in C++17
application_injector.cpp
Go to the documentation of this file.
1 
7 
8 #define BOOST_DI_CFG_DIAGNOSTICS_LEVEL 2
9 #define BOOST_DI_CFG_CTOR_LIMIT_SIZE \
10  16 // TODO(Harrm): check how it influences on compilation time
11 
12 #include <rocksdb/filter_policy.h>
13 #include <rocksdb/table.h>
14 #include <boost/di.hpp>
15 #include <boost/di/extension/scopes/shared.hpp>
16 #include <libp2p/injector/host_injector.hpp>
17 #include <libp2p/injector/kademlia_injector.hpp>
18 #include <libp2p/log/configurator.hpp>
19 
20 #undef U64 // comes from OpenSSL and messes with WAVM
21 
61 #include "common/fd_limit.hpp"
62 #include "common/outcome_throw.hpp"
90 #include "log/configurator.hpp"
91 #include "log/logger.hpp"
95 #include "metrics/metrics.hpp"
112 #include "outcome/outcome.hpp"
148 #include "runtime/wavm/module.hpp"
162 
163 namespace {
164  template <class T>
165  using sptr = std::shared_ptr<T>;
166 
167  template <class T>
168  using uptr = std::unique_ptr<T>;
169 
170  namespace di = boost::di;
171  namespace fs = boost::filesystem;
172  using namespace kagome; // NOLINT
173 
174  template <typename C>
175  auto useConfig(C c) {
176  return boost::di::bind<std::decay_t<C>>().template to(
177  std::move(c))[boost::di::override];
178  }
179 
180  template <typename T, typename Fun>
181  auto bind_by_lambda(const Fun &fun) {
182  return di::bind<T>.to([fun](auto const &injector) {
183  static sptr<T> initialized = fun(injector);
184  return initialized;
185  });
186  }
187 
188  template <typename Injector>
189  auto &get_session_keys(const Injector &injector) {
190  static const auto initialized = [&] {
191  auto &app_config =
192  injector.template create<const application::AppConfiguration &>();
193  if (auto dev = app_config.devMnemonicPhrase()) {
194  auto &crypto_store = injector.template create<crypto::CryptoStore &>();
195  crypto_store.generateEd25519Keypair(crypto::KEY_TYPE_GRAN, *dev)
196  .value();
197  crypto_store.generateSr25519Keypair(crypto::KEY_TYPE_BABE, *dev)
198  .value();
199  crypto_store.generateSr25519Keypair(crypto::KEY_TYPE_IMON, *dev)
200  .value();
201  crypto_store.generateSr25519Keypair(crypto::KEY_TYPE_AUDI, *dev)
202  .value();
203  crypto_store.generateSr25519Keypair(crypto::KEY_TYPE_ASGN, *dev)
204  .value();
205  crypto_store.generateSr25519Keypair(crypto::KEY_TYPE_PARA, *dev)
206  .value();
207  }
208  return injector.template create<sptr<crypto::SessionKeys>>();
209  }();
210  return initialized;
211  }
212 
213  sptr<api::HttpListenerImpl> get_jrpc_api_http_listener(
214  application::AppConfiguration const &config,
215  sptr<application::AppStateManager> app_state_manager,
216  sptr<api::RpcContext> context,
217  api::HttpSession::Configuration http_session_config) {
218  static auto initialized =
219  std::optional<sptr<api::HttpListenerImpl>>(std::nullopt);
220  if (initialized) {
221  return initialized.value();
222  }
223 
224  auto &endpoint = config.rpcHttpEndpoint();
225 
226  api::HttpListenerImpl::Configuration listener_config;
227  listener_config.endpoint = endpoint;
228 
229  auto listener = std::make_shared<api::HttpListenerImpl>(
230  app_state_manager, context, listener_config, http_session_config);
231 
232  initialized.emplace(std::move(listener));
233  return initialized.value();
234  }
235 
236  sptr<api::WsListenerImpl> get_jrpc_api_ws_listener(
237  application::AppConfiguration const &app_config,
238  api::WsSession::Configuration ws_session_config,
239  sptr<api::RpcContext> context,
240  sptr<application::AppStateManager> app_state_manager) {
241  static auto initialized =
242  std::optional<sptr<api::WsListenerImpl>>(std::nullopt);
243  if (initialized) {
244  return initialized.value();
245  }
246 
247  api::WsListenerImpl::Configuration listener_config;
248  listener_config.endpoint = app_config.rpcWsEndpoint();
249  listener_config.ws_max_connections = app_config.maxWsConnections();
250 
251  auto listener =
252  std::make_shared<api::WsListenerImpl>(app_state_manager,
253  context,
254  listener_config,
255  std::move(ws_session_config));
256 
257  initialized.emplace(std::move(listener));
258  return initialized.value();
259  }
260 
261  sptr<blockchain::BlockStorage> get_block_storage(
262  storage::trie::RootHash state_root,
263  sptr<crypto::Hasher> hasher,
265  static auto initialized =
266  std::optional<sptr<blockchain::BlockStorage>>(std::nullopt);
267 
268  if (initialized) {
269  return initialized.value();
270  }
271 
272  auto block_storage_res =
273  blockchain::BlockStorageImpl::create(state_root, storage, hasher);
274 
275  if (block_storage_res.has_error()) {
276  common::raise(block_storage_res.error());
277  }
278  auto &block_storage = block_storage_res.value();
279 
280  initialized.emplace(std::move(block_storage));
281  return initialized.value();
282  }
283 
284  sptr<storage::trie::TrieStorageBackendImpl> get_trie_storage_backend(
286  static auto initialized =
287  std::optional<sptr<storage::trie::TrieStorageBackendImpl>>(
288  std::nullopt);
289 
290  if (initialized) {
291  return initialized.value();
292  }
293 
294  auto backend = std::make_shared<storage::trie::TrieStorageBackendImpl>(
296 
297  initialized.emplace(std::move(backend));
298  return initialized.value();
299  }
300 
301  template <typename Injector>
302  std::pair<sptr<storage::trie::TrieStorage>, kagome::storage::trie::RootHash>
303  get_trie_storage_and_root_hash(const Injector &injector) {
304  static auto initialized =
305  std::optional<std::pair<sptr<storage::trie::TrieStorage>,
306  kagome::storage::trie::RootHash>>(std::nullopt);
307 
308  if (initialized) {
309  return initialized.value();
310  }
311 
312  auto factory =
313  injector.template create<sptr<storage::trie::PolkadotTrieFactory>>();
314  auto codec = injector.template create<sptr<storage::trie::Codec>>();
315  auto configuration_storage =
316  injector.template create<sptr<application::ChainSpec>>();
317  auto serializer =
318  injector.template create<sptr<storage::trie::TrieSerializer>>();
319  auto tracker =
320  injector.template create<sptr<storage::changes_trie::ChangesTracker>>();
321 
322  auto trie_storage_res = storage::trie::TrieStorageImpl::createEmpty(
323  factory, codec, serializer, tracker);
324 
325  if (!trie_storage_res) {
326  common::raise(trie_storage_res.error());
327  }
328 
329  const auto &genesis_raw_configs =
330  configuration_storage->getGenesisTopSection();
331  auto &trie_storage = trie_storage_res.value();
332 
333  auto log = log::createLogger("Injector", "injector");
334  auto batch_with_raw_data = [&log, &serializer, &trie_storage](
335  const auto &raw_configs) {
336  auto batch_res =
337  trie_storage->getPersistentBatchAt(serializer->getEmptyRootHash());
338  if (not batch_res) {
339  common::raise(batch_res.error());
340  }
341  auto batch = std::move(batch_res.value());
342 
343  for (const auto &[key_, val_] : raw_configs) {
344  auto &key = key_;
345  auto &val = val_;
346  SL_TRACE(
347  log, "Key: {}, Val: {}", key.toHex(), val.toHex().substr(0, 200));
348  if (auto res = batch->put(key, val); not res) {
349  common::raise(res.error());
350  }
351  }
352 
353  return batch;
354  };
355 
356  auto batch = batch_with_raw_data(genesis_raw_configs);
357 
358  const auto &children_default_raw_configs =
359  configuration_storage->getGenesisChildrenDefaultSection();
360  for (const auto &[key_, val_] : children_default_raw_configs) {
361  auto child_batch = batch_with_raw_data(val_);
362 
363  auto root_hash_res = child_batch->commit();
364  if (root_hash_res.has_error()) {
365  common::raise(root_hash_res.error());
366  }
367 
368  auto &root_hash = root_hash_res.value();
369 
370  common::Buffer child_key;
371  child_key.put(storage::kChildStorageDefaultPrefix).put(root_hash);
372  auto res = batch->put(child_key, root_hash);
373  if (res.has_error()) {
374  common::raise(res.error());
375  }
376  }
377 
378  auto res = batch->commit();
379  if (res.has_error()) {
380  common::raise(res.error());
381  }
382 
383  auto &root_hash = res.value();
384 
385  SL_TRACE(log, "root hash is {}", root_hash.toHex());
386 
387  initialized.emplace(std::move(trie_storage), root_hash);
388  return initialized.value();
389  }
390 
391  sptr<storage::BufferStorage> get_rocks_db(
392  application::AppConfiguration const &app_config,
393  sptr<application::ChainSpec> chain_spec) {
394  static auto initialized =
395  std::optional<sptr<storage::BufferStorage>>(std::nullopt);
396  if (initialized) {
397  return initialized.value();
398  }
399 
400  // hack for recovery mode (otherwise - fails due to rocksdb bug)
401  bool prevent_destruction = app_config.recoverState().has_value();
402 
403  rocksdb::BlockBasedTableOptions table_options;
404  table_options.block_cache = rocksdb::NewLRUCache(512 * 1024 * 1024);
405  table_options.block_size = 32 * 1024;
406  table_options.cache_index_and_filter_blocks = true;
407  table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10, false));
408 
409  auto options = rocksdb::Options{};
410  options.create_if_missing = true;
411  options.optimize_filters_for_hits = true;
412  options.table_factory.reset(
413  rocksdb::NewBlockBasedTableFactory(table_options));
414 
415  // Setting limit for open rocksdb files to a half of system soft limit
416  auto soft_limit = common::getFdLimit();
417  if (!soft_limit) {
418  exit(EXIT_FAILURE);
419  }
420  options.max_open_files = soft_limit.value() / 2;
421 
422  auto db_res =
423  storage::RocksDB::create(app_config.databasePath(chain_spec->id()),
424  options,
425  prevent_destruction);
426  if (!db_res) {
427  auto log = log::createLogger("Injector", "injector");
428  log->critical("Can't create RocksDB in {}: {}",
429  fs::absolute(app_config.databasePath(chain_spec->id()),
430  fs::current_path())
431  .native(),
432  db_res.error().message());
433  exit(EXIT_FAILURE);
434  }
435  auto &db = db_res.value();
436 
437  initialized.emplace(std::move(db));
438  return initialized.value();
439  }
440 
441  std::shared_ptr<application::ChainSpec> get_chain_spec(
442  application::AppConfiguration const &config) {
443  static auto initialized =
444  std::optional<sptr<application::ChainSpec>>(std::nullopt);
445  if (initialized) {
446  return initialized.value();
447  }
448  auto const &chainspec_path = config.chainSpecPath();
449 
450  auto chain_spec_res =
451  application::ChainSpecImpl::loadFrom(chainspec_path.native());
452  if (not chain_spec_res.has_value()) {
453  auto log = log::createLogger("Injector", "injector");
454  log->critical(
455  "Can't load chain spec from {}: {}",
456  fs::absolute(chainspec_path.native(), fs::current_path()).native(),
457  chain_spec_res.error().message());
458  exit(EXIT_FAILURE);
459  }
460  auto &chain_spec = chain_spec_res.value();
461 
462  initialized.emplace(std::move(chain_spec));
463  return initialized.value();
464  }
465 
466  sptr<crypto::KeyFileStorage> get_key_file_storage(
467  application::AppConfiguration const &config,
468  sptr<application::ChainSpec> chain_spec) {
469  static std::optional<sptr<crypto::KeyFileStorage>> initialized =
470  std::nullopt;
471  static std::optional<fs::path> initialized_path = std::nullopt;
472 
473  auto path = config.keystorePath(chain_spec->id());
474  if (initialized and initialized_path and initialized_path.value() == path) {
475  return initialized.value();
476  }
477  auto key_file_storage_res = crypto::KeyFileStorage::createAt(path);
478  if (not key_file_storage_res) {
479  common::raise(key_file_storage_res.error());
480  }
481 
482  initialized = std::move(key_file_storage_res.value());
483  initialized_path = std::move(path);
484 
485  return initialized.value();
486  }
487 
488  sptr<libp2p::protocol::kademlia::Config> get_kademlia_config(
489  const application::ChainSpec &chain_spec,
490  std::chrono::seconds random_wak_interval) {
491  static auto initialized =
492  std::optional<sptr<libp2p::protocol::kademlia::Config>>(std::nullopt);
493  if (initialized) {
494  return initialized.value();
495  }
496 
497  auto kagome_config = std::make_shared<libp2p::protocol::kademlia::Config>(
498  libp2p::protocol::kademlia::Config{
499  .protocolId = "/" + chain_spec.protocolId() + "/kad",
500  .maxBucketSize = 1000,
501  .randomWalk = {.interval = random_wak_interval}});
502 
503  initialized.emplace(std::move(kagome_config));
504  return initialized.value();
505  }
506 
507  template <typename Injector>
508  sptr<api::ApiServiceImpl> get_jrpc_api_service(const Injector &injector) {
509  static auto initialized =
510  std::optional<sptr<api::ApiServiceImpl>>(std::nullopt);
511  if (initialized) {
512  return initialized.value();
513  }
514 
515  auto asmgr =
516  injector
517  .template create<std::shared_ptr<application::AppStateManager>>();
518  auto thread_pool = injector.template create<sptr<api::RpcThreadPool>>();
519  auto server = injector.template create<sptr<api::JRpcServer>>();
520  auto listeners =
521  injector.template create<api::ApiServiceImpl::ListenerList>();
522  auto processors =
523  injector.template create<api::ApiServiceImpl::ProcessorSpan>();
524  auto storage_sub_engine = injector.template create<
526  auto chain_sub_engine =
527  injector
528  .template create<primitives::events::ChainSubscriptionEnginePtr>();
529  auto ext_sub_engine = injector.template create<
531  auto extrinsic_event_key_repo =
532  injector
533  .template create<sptr<subscription::ExtrinsicEventKeyRepository>>();
534  auto block_tree = injector.template create<sptr<blockchain::BlockTree>>();
535  auto trie_storage =
536  injector.template create<sptr<storage::trie::TrieStorage>>();
537  auto core = injector.template create<sptr<runtime::Core>>();
538 
539  auto api_service =
540  std::make_shared<api::ApiServiceImpl>(asmgr,
541  thread_pool,
542  listeners,
543  server,
544  processors,
545  storage_sub_engine,
546  chain_sub_engine,
547  ext_sub_engine,
548  extrinsic_event_key_repo,
549  block_tree,
550  trie_storage,
551  core);
552 
553  auto child_state_api =
554  injector.template create<std::shared_ptr<api::ChildStateApi>>();
555  child_state_api->setApiService(api_service);
556 
557  auto state_api = injector.template create<std::shared_ptr<api::StateApi>>();
558  state_api->setApiService(api_service);
559 
560  auto chain_api = injector.template create<std::shared_ptr<api::ChainApi>>();
561  chain_api->setApiService(api_service);
562 
563  auto author_api =
564  injector.template create<std::shared_ptr<api::AuthorApi>>();
565  author_api->setApiService(api_service);
566 
567  initialized.emplace(std::move(api_service));
568  return initialized.value();
569  }
570 
571  template <typename Injector>
572  sptr<blockchain::BlockTree> get_block_tree(const Injector &injector) {
573  static auto initialized =
574  std::optional<sptr<blockchain::BlockTree>>(std::nullopt);
575 
576  if (initialized) {
577  return initialized.value();
578  }
579 
580  auto header_repo =
581  injector.template create<sptr<blockchain::BlockHeaderRepository>>();
582 
583  auto storage = injector.template create<sptr<blockchain::BlockStorage>>();
584 
585  auto extrinsic_observer =
586  injector.template create<sptr<network::ExtrinsicObserver>>();
587 
588  auto hasher = injector.template create<sptr<crypto::Hasher>>();
589 
590  auto chain_events_engine =
591  injector
592  .template create<primitives::events::ChainSubscriptionEnginePtr>();
593  auto ext_events_engine = injector.template create<
595  auto ext_events_key_repo = injector.template create<
596  std::shared_ptr<subscription::ExtrinsicEventKeyRepository>>();
597 
598  auto changes_tracker = injector.template create<
599  std::shared_ptr<storage::changes_trie::ChangesTracker>>();
600  auto justification_storage_policy = injector.template create<
601  std::shared_ptr<blockchain::JustificationStoragePolicy>>();
602 
603  auto block_tree_res = blockchain::BlockTreeImpl::create(
604  header_repo,
605  std::move(storage),
606  std::move(extrinsic_observer),
607  std::move(hasher),
608  chain_events_engine,
609  std::move(ext_events_engine),
610  std::move(ext_events_key_repo),
611  std::move(changes_tracker),
612  std::move(justification_storage_policy));
613 
614  if (not block_tree_res.has_value()) {
615  common::raise(block_tree_res.error());
616  }
617  auto &block_tree = block_tree_res.value();
618 
619  auto tagged_transaction_queue = injector.template create<
620  std::shared_ptr<runtime::TaggedTransactionQueueImpl>>();
621  tagged_transaction_queue->setBlockTree(block_tree);
622 
623  auto protocol_factory =
624  injector.template create<std::shared_ptr<network::ProtocolFactory>>();
625  protocol_factory->setBlockTree(block_tree);
626 
627  auto runtime_upgrade_tracker =
628  injector.template create<sptr<runtime::RuntimeUpgradeTrackerImpl>>();
629 
630  runtime_upgrade_tracker->subscribeToBlockchainEvents(chain_events_engine,
631  block_tree);
632 
633  initialized.emplace(std::move(block_tree));
634  return initialized.value();
635  }
636 
637  template <class Injector>
638  sptr<network::PeerManager> get_peer_manager(const Injector &injector) {
639  static auto initialized =
640  std::optional<sptr<network::PeerManager>>(std::nullopt);
641  if (initialized) {
642  return initialized.value();
643  }
644 
645  auto peer_manager = std::make_shared<network::PeerManagerImpl>(
646  injector.template create<sptr<application::AppStateManager>>(),
647  injector.template create<libp2p::Host &>(),
648  injector.template create<sptr<libp2p::protocol::Identify>>(),
649  injector.template create<sptr<libp2p::protocol::kademlia::Kademlia>>(),
650  injector.template create<sptr<libp2p::basic::Scheduler>>(),
651  injector.template create<sptr<network::StreamEngine>>(),
652  injector.template create<const application::AppConfiguration &>(),
653  injector.template create<sptr<clock::SteadyClock>>(),
654  injector.template create<const network::BootstrapNodes &>(),
655  injector.template create<const network::OwnPeerInfo &>(),
656  injector.template create<sptr<network::Router>>(),
657  injector.template create<sptr<storage::BufferStorage>>(),
658  injector.template create<sptr<crypto::Hasher>>(),
659  injector.template create<sptr<network::ReputationRepository>>());
660 
661  auto protocol_factory =
662  injector.template create<std::shared_ptr<network::ProtocolFactory>>();
663 
664  protocol_factory->setPeerManager(peer_manager);
665 
666  static auto address_publisher =
667  injector.template create<sptr<authority_discovery::AddressPublisher>>();
668 
669  initialized.emplace(std::move(peer_manager));
670  return initialized.value();
671  }
672 
673  template <typename Injector>
674  sptr<consensus::BlockExecutorImpl> get_block_executor(
675  const Injector &injector) {
676  static auto initialized =
677  std::optional<sptr<consensus::BlockExecutorImpl>>(std::nullopt);
678  if (initialized) {
679  return initialized.value();
680  }
681 
682  auto block_executor = std::make_shared<consensus::BlockExecutorImpl>(
683  injector.template create<sptr<blockchain::BlockTree>>(),
684  injector.template create<sptr<runtime::Core>>(),
685  injector.template create<sptr<consensus::babe::BabeConfigRepository>>(),
686  injector.template create<sptr<consensus::BlockValidator>>(),
687  injector.template create<sptr<consensus::grandpa::Environment>>(),
688  injector.template create<sptr<transaction_pool::TransactionPool>>(),
689  injector.template create<sptr<crypto::Hasher>>(),
690  injector.template create<sptr<blockchain::DigestTracker>>(),
691  injector.template create<sptr<consensus::BabeUtil>>(),
692  injector.template create<sptr<runtime::OffchainWorkerApi>>(),
693  injector.template create<sptr<consensus::babe::ConsistencyKeeper>>());
694 
695  initialized.emplace(std::move(block_executor));
696  return initialized.value();
697  }
698 
699  template <typename Injector>
700  sptr<parachain::ParachainObserverImpl> get_parachain_observer_impl(
701  const Injector &injector) {
702  auto get_instance = [&]() {
703  auto instance = std::make_shared<parachain::ParachainObserverImpl>(
704  injector.template create<std::shared_ptr<network::PeerManager>>(),
705  injector.template create<std::shared_ptr<crypto::Sr25519Provider>>(),
706  injector.template create<
707  std::shared_ptr<parachain::ParachainProcessorImpl>>());
708 
709  auto protocol_factory =
710  injector.template create<std::shared_ptr<network::ProtocolFactory>>();
711 
712  protocol_factory->setCollactionObserver(instance);
713  protocol_factory->setReqCollationObserver(instance);
714  return instance;
715  };
716 
717  static auto instance = get_instance();
718  return instance;
719  }
720 
721  template <typename Injector>
722  sptr<parachain::ParachainProcessorImpl> get_parachain_processor_impl(
723  const Injector &injector) {
724  auto get_instance = [&]() {
725  auto &session_keys = get_session_keys(injector);
726  auto ptr = std::make_shared<parachain::ParachainProcessorImpl>(
727  injector.template create<std::shared_ptr<network::PeerManager>>(),
728  injector.template create<std::shared_ptr<crypto::Sr25519Provider>>(),
729  injector.template create<std::shared_ptr<network::Router>>(),
730  injector
731  .template create<std::shared_ptr<::boost::asio::io_context>>(),
732  session_keys->getBabeKeyPair(),
733  injector.template create<std::shared_ptr<crypto::Hasher>>());
734 
735  auto asmgr =
736  injector
737  .template create<std::shared_ptr<application::AppStateManager>>();
738  asmgr->takeControl(*ptr);
739  return ptr;
740  };
741 
742  static auto instance = get_instance();
743  return instance;
744  }
745 
746  template <typename... Ts>
747  auto makeWavmInjector(
749  Ts &&...args) {
750  return di::make_injector(
751  di::bind<runtime::wavm::CompartmentWrapper>.template to(
752  [](const auto &injector) {
753  static auto compartment =
754  std::make_shared<kagome::runtime::wavm::CompartmentWrapper>(
755  "Runtime Compartment");
756  return compartment;
757  }),
758  di::bind<runtime::wavm::IntrinsicModule>.template to(
759  [](const auto &injector) {
760  static std::shared_ptr<runtime::wavm::IntrinsicModule> module =
761  [&injector]() {
762  auto compartment = injector.template create<
764  runtime::wavm::ModuleParams module_params{};
765  auto module =
766  std::make_unique<runtime::wavm::IntrinsicModule>(
767  compartment, module_params.intrinsicMemoryType);
769 
770  return module;
771  }();
772  return module;
773  }),
774  di::bind<runtime::wavm::IntrinsicModuleInstance>.template to(
775  [](const auto &injector) {
776  static std::shared_ptr<runtime::wavm::IntrinsicModuleInstance>
777  instance = [&injector]() {
778  auto module = injector.template create<
780  return module->instantiate();
781  }();
782  return instance;
783  }),
784  di::bind<runtime::wavm::IntrinsicResolver>.template to<runtime::wavm::IntrinsicResolverImpl>(),
785  std::forward<decltype(args)>(args)...);
786  }
787 
788  template <typename... Ts>
789  auto makeBinaryenInjector(
791  Ts &&...args) {
792  return di::make_injector(
793  di::bind<runtime::binaryen::RuntimeExternalInterface>.template to(
794  [](const auto &injector) {
795  static auto rei = [&injector]() {
796  auto host_api =
797  injector.template create<sptr<host_api::HostApi>>();
798  auto rei = std::make_shared<
800  auto memory_provider = injector.template create<
802  memory_provider->setExternalInterface(rei);
803  return rei;
804  }();
805  return rei;
806  }),
807  std::forward<decltype(args)>(args)...);
808  }
809 
810  template <typename CommonType,
811  typename BinaryenType,
812  typename WavmType,
813  typename Injector>
814  auto choose_runtime_implementation(
815  Injector const &injector,
817  using RuntimeExecutionMethod =
819  static sptr<CommonType> impl = [method, &injector]() {
820  switch (method) {
821  case RuntimeExecutionMethod::Interpret:
822  return std::static_pointer_cast<CommonType>(
823  injector.template create<sptr<BinaryenType>>());
824  case RuntimeExecutionMethod::Compile:
825  return std::static_pointer_cast<CommonType>(
826  injector.template create<sptr<WavmType>>());
827  }
828  throw std::runtime_error("Unknown runtime execution method");
829  }();
830  return impl;
831  }
832 
833  template <typename Injector>
834  std::shared_ptr<runtime::RuntimeUpgradeTrackerImpl>
835  get_runtime_upgrade_tracker(const Injector &injector) {
836  static std::shared_ptr<runtime::RuntimeUpgradeTrackerImpl> instance =
837  [&injector]() {
838  auto header_repo = injector.template create<
840  auto storage =
841  injector.template create<sptr<storage::BufferStorage>>();
842  auto substitutes = injector.template create<
844  auto block_storage =
845  injector.template create<sptr<blockchain::BlockStorage>>();
847  std::move(header_repo),
848  std::move(storage),
849  std::move(substitutes),
850  std::move(block_storage));
851  if (res.has_error()) {
852  throw std::runtime_error(
853  "Error creating RuntimeUpgradeTrackerImpl: "
854  + res.error().message());
855  }
856  return std::shared_ptr<runtime::RuntimeUpgradeTrackerImpl>(
857  std::move(res.value()));
858  }();
859  return instance;
860  }
861 
862  template <typename... Ts>
863  auto makeRuntimeInjector(
865  Ts &&...args) {
866  return di::make_injector(
867  di::bind<runtime::TrieStorageProvider>.template to<runtime::TrieStorageProviderImpl>(),
868  di::bind<runtime::RuntimeUpgradeTrackerImpl>.template to(
869  [](auto const &injector) {
870  return get_runtime_upgrade_tracker(injector);
871  }),
872  di::bind<runtime::RuntimeUpgradeTracker>.template to(
873  [](auto const &injector) {
874  return get_runtime_upgrade_tracker(injector);
875  }),
876  makeWavmInjector(method),
877  makeBinaryenInjector(method),
878  di::bind<runtime::ModuleRepository>.template to<runtime::ModuleRepositoryImpl>(),
879  di::bind<runtime::CoreApiFactory>.template to(
880  [method](const auto &injector) {
881  return choose_runtime_implementation<
884  runtime::wavm::CoreApiFactoryImpl>(injector, method);
885  }),
886  di::bind<runtime::wavm::ModuleFactoryImpl>.template to(
887  [](const auto &injector) {
888  std::optional<std::shared_ptr<runtime::wavm::ModuleCache>>
889  module_cache_opt;
890  auto &app_config =
891  injector
892  .template create<const application::AppConfiguration &>();
893  if (app_config.useWavmCache()) {
894  module_cache_opt = std::make_shared<runtime::wavm::ModuleCache>(
895  injector.template create<sptr<crypto::Hasher>>(),
896  app_config.runtimeCacheDirPath());
897  }
898  return std::make_shared<runtime::wavm::ModuleFactoryImpl>(
899  injector.template create<
901  injector.template create<sptr<runtime::wavm::ModuleParams>>(),
902  injector.template create<
904  injector
905  .template create<sptr<runtime::wavm::IntrinsicModule>>(),
906  module_cache_opt,
907  injector.template create<sptr<crypto::Hasher>>());
908  }),
909  di::bind<runtime::ModuleFactory>.template to(
910  [method](const auto &injector) {
911  return choose_runtime_implementation<
914  runtime::wavm::ModuleFactoryImpl>(injector, method);
915  }),
916  di::bind<runtime::RawExecutor>.template to<runtime::Executor>(),
917  di::bind<runtime::TaggedTransactionQueue>.template to<runtime::TaggedTransactionQueueImpl>(),
918  di::bind<runtime::ParachainHost>.template to<runtime::ParachainHostImpl>(),
919  di::bind<runtime::OffchainWorkerApi>.template to<runtime::OffchainWorkerApiImpl>(),
920  di::bind<offchain::OffchainWorkerFactory>.template to<offchain::OffchainWorkerFactoryImpl>(),
921  di::bind<offchain::OffchainWorker>.template to<offchain::OffchainWorkerImpl>(),
922  di::bind<offchain::OffchainWorkerPool>.template to<offchain::OffchainWorkerPoolImpl>(),
923  di::bind<offchain::OffchainPersistentStorage>.template to<offchain::OffchainPersistentStorageImpl>(),
924  di::bind<offchain::OffchainLocalStorage>.template to<offchain::OffchainLocalStorageImpl>(),
925  di::bind<runtime::Metadata>.template to<runtime::MetadataImpl>(),
926  di::bind<runtime::GrandpaApi>.template to<runtime::GrandpaApiImpl>(),
927  di::bind<runtime::Core>.template to<runtime::CoreImpl>(),
928  di::bind<runtime::BabeApi>.template to<runtime::BabeApiImpl>(),
929  di::bind<runtime::SessionKeysApi>.template to<runtime::SessionKeysApiImpl>(),
930  di::bind<runtime::BlockBuilder>.template to<runtime::BlockBuilderImpl>(),
931  di::bind<runtime::TransactionPaymentApi>.template to<runtime::TransactionPaymentApiImpl>(),
932  di::bind<runtime::AccountNonceApi>.template to<runtime::AccountNonceApiImpl>(),
933  di::bind<runtime::AuthorityDiscoveryApi>.template to<runtime::AuthorityDiscoveryApiImpl>(),
934  di::bind<runtime::SingleModuleCache>.template to<runtime::SingleModuleCache>(),
935  di::bind<runtime::RuntimePropertiesCache>.template to<runtime::RuntimePropertiesCacheImpl>(),
936  std::forward<Ts>(args)...);
937  }
938 
939  template <typename Injector>
940  sptr<primitives::GenesisBlockHeader> get_genesis_block_header(
941  const Injector &injector) {
942  static auto initialized =
943  std::optional<sptr<primitives::GenesisBlockHeader>>(std::nullopt);
944  if (initialized) {
945  return initialized.value();
946  }
947 
948  auto block_storage =
949  injector.template create<sptr<blockchain::BlockStorage>>();
950  auto block_header_repository =
951  injector.template create<sptr<blockchain::BlockHeaderRepository>>();
952 
953  auto hash_res =
954  block_header_repository->getHashByNumber(primitives::BlockNumber(0));
955  BOOST_ASSERT(hash_res.has_value());
956  auto &hash = hash_res.value();
957 
958  auto header_res = block_storage->getBlockHeader(hash);
959  BOOST_ASSERT(header_res.has_value());
960  auto &header_opt = header_res.value();
961  BOOST_ASSERT(header_opt.has_value());
962 
963  initialized.emplace(new primitives::GenesisBlockHeader(
964  {.header = header_opt.value(), .hash = hash}));
965 
966  return initialized.value();
967  }
968 
969  template <typename... Ts>
970  auto makeApplicationInjector(const application::AppConfiguration &config,
971  Ts &&...args) {
972  // default values for configurations
973  api::RpcThreadPool::Configuration rpc_thread_pool_config{};
974  api::HttpSession::Configuration http_config{};
975  api::WsSession::Configuration ws_config{};
976  transaction_pool::PoolModeratorImpl::Params pool_moderator_config{};
978  libp2p::protocol::PingConfig ping_config{};
979  host_api::OffchainExtensionConfig offchain_ext_config{
980  config.isOffchainIndexingEnabled()};
981 
982  auto get_state_observer_impl = [](auto const &injector) {
983  auto state_observer =
984  std::make_shared<network::StateProtocolObserverImpl>(
985  injector
986  .template create<sptr<blockchain::BlockHeaderRepository>>(),
987  injector.template create<sptr<storage::trie::TrieStorage>>());
988 
989  auto protocol_factory =
990  injector.template create<std::shared_ptr<network::ProtocolFactory>>();
991 
992  protocol_factory->setStateObserver(state_observer);
993 
994  return state_observer;
995  };
996 
997  auto get_sync_observer_impl = [](auto const &injector) {
998  auto sync_observer = std::make_shared<network::SyncProtocolObserverImpl>(
999  injector.template create<sptr<blockchain::BlockTree>>(),
1000  injector.template create<sptr<blockchain::BlockHeaderRepository>>());
1001 
1002  auto protocol_factory =
1003  injector.template create<std::shared_ptr<network::ProtocolFactory>>();
1004 
1005  protocol_factory->setSyncObserver(sync_observer);
1006 
1007  return sync_observer;
1008  };
1009 
1010  return di::make_injector(
1011  // bind configs
1012  useConfig(rpc_thread_pool_config),
1013  useConfig(http_config),
1014  useConfig(ws_config),
1015  useConfig(pool_moderator_config),
1016  useConfig(tp_pool_limits),
1017  useConfig(ping_config),
1018  useConfig(offchain_ext_config),
1019 
1020  // inherit host injector
1021  libp2p::injector::makeHostInjector(
1022  libp2p::injector::useSecurityAdaptors<
1023  libp2p::security::Noise>()[di::override]),
1024 
1025  // inherit kademlia injector
1026  libp2p::injector::makeKademliaInjector(),
1027  di::bind<libp2p::protocol::kademlia::Config>.to(
1028  [random_walk{config.getRandomWalkInterval()}](
1029  auto const &injector) {
1030  auto &chain_spec =
1031  injector.template create<application::ChainSpec &>();
1032  return get_kademlia_config(chain_spec, random_walk);
1033  })[boost::di::override],
1034 
1035  di::bind<application::AppStateManager>.template to<application::AppStateManagerImpl>(),
1036  di::bind<application::AppConfiguration>.to(config),
1037  di::bind<primitives::CodeSubstituteBlockIds>.to(
1038  get_chain_spec(config)->codeSubstitutes()),
1039 
1040  // compose peer keypair
1041  di::bind<libp2p::crypto::KeyPair>.to([](auto const &injector) {
1042  auto &app_config =
1043  injector.template create<const application::AppConfiguration &>();
1044  auto &crypto_provider =
1045  injector.template create<const crypto::Ed25519Provider &>();
1046  auto &crypto_store =
1047  injector.template create<crypto::CryptoStore &>();
1049  app_config, crypto_provider, crypto_store);
1050  })[boost::di::override],
1051 
1052  // bind io_context: 1 per injector
1053  di::bind<::boost::asio::io_context>.in(
1054  di::extension::shared)[boost::di::override],
1055 
1056  di::bind<api::ApiServiceImpl::ListenerList>.to([](auto const
1057  &injector) {
1058  std::vector<std::shared_ptr<api::Listener>> listeners{
1059  injector
1060  .template create<std::shared_ptr<api::HttpListenerImpl>>(),
1061  injector.template create<std::shared_ptr<api::WsListenerImpl>>(),
1062  };
1063  return api::ApiServiceImpl::ListenerList{std::move(listeners)};
1064  }),
1065  di::bind<api::ApiServiceImpl::ProcessorSpan>.to([](auto const
1066  &injector) {
1067  static std::vector<std::shared_ptr<api::JRpcProcessor>> processors{
1068  injector.template create<
1069  std::shared_ptr<api::child_state::ChildStateJrpcProcessor>>(),
1070  injector.template create<
1071  std::shared_ptr<api::state::StateJrpcProcessor>>(),
1072  injector.template create<
1073  std::shared_ptr<api::author::AuthorJRpcProcessor>>(),
1074  injector.template create<
1075  std::shared_ptr<api::chain::ChainJrpcProcessor>>(),
1076  injector.template create<
1077  std::shared_ptr<api::system::SystemJrpcProcessor>>(),
1078  injector.template create<
1079  std::shared_ptr<api::rpc::RpcJRpcProcessor>>(),
1080  injector.template create<
1081  std::shared_ptr<api::payment::PaymentJRpcProcessor>>(),
1082  injector.template create<
1083  std::shared_ptr<api::internal::InternalJrpcProcessor>>()};
1084  return api::ApiServiceImpl::ProcessorSpan{processors};
1085  }),
1086  // bind interfaces
1087  di::bind<api::HttpListenerImpl>.to([](const auto &injector) {
1088  const application::AppConfiguration &config =
1089  injector.template create<application::AppConfiguration const &>();
1090  auto app_state_manager =
1091  injector.template create<sptr<application::AppStateManager>>();
1092  auto context = injector.template create<sptr<api::RpcContext>>();
1093  auto &&http_session_config =
1094  injector.template create<api::HttpSession::Configuration>();
1095 
1096  return get_jrpc_api_http_listener(
1097  config, app_state_manager, context, http_session_config);
1098  }),
1099  di::bind<api::WsListenerImpl>.to([](const auto &injector) {
1100  auto config =
1101  injector.template create<api::WsSession::Configuration>();
1102  auto context = injector.template create<sptr<api::RpcContext>>();
1103  auto app_state_manager =
1104  injector.template create<sptr<application::AppStateManager>>();
1105  const application::AppConfiguration &app_config =
1106  injector.template create<application::AppConfiguration const &>();
1107  return get_jrpc_api_ws_listener(
1108  app_config, config, context, app_state_manager);
1109  }),
1110  // starting metrics interfaces
1111  di::bind<metrics::Handler>.template to<metrics::PrometheusHandler>(),
1112  di::bind<metrics::Exposer>.template to<metrics::ExposerImpl>(),
1113  di::bind<metrics::Exposer::Configuration>.to([](const auto &injector) {
1115  injector.template create<application::AppConfiguration const &>()
1116  .openmetricsHttpEndpoint()};
1117  }),
1118  // hardfix for Mac clang
1119  di::bind<metrics::Session::Configuration>.to([](const auto &injector) {
1121  }),
1122  // ending metrics interfaces
1123  di::bind<libp2p::crypto::random::RandomGenerator>.template to<libp2p::crypto::random::BoostRandomGenerator>()
1124  [di::override],
1125  di::bind<api::AuthorApi>.template to<api::AuthorApiImpl>(),
1126  di::bind<crypto::SessionKeys>.template to<crypto::SessionKeys>(),
1127  di::bind<network::Roles>.to(config.roles()),
1128  di::bind<api::ChainApi>.template to<api::ChainApiImpl>(),
1129  di::bind<api::ChildStateApi>.template to<api::ChildStateApiImpl>(),
1130  di::bind<api::StateApi>.template to<api::StateApiImpl>(),
1131  di::bind<api::SystemApi>.template to<api::SystemApiImpl>(),
1132  di::bind<api::RpcApi>.template to<api::RpcApiImpl>(),
1133  di::bind<api::PaymentApi>.template to<api::PaymentApiImpl>(),
1134  di::bind<api::ApiService>.to([](const auto &injector) {
1135  return get_jrpc_api_service(injector);
1136  }),
1137  di::bind<api::JRpcServer>.template to<api::JRpcServerImpl>(),
1138  di::bind<authorship::Proposer>.template to<authorship::ProposerImpl>(),
1139  di::bind<authorship::BlockBuilder>.template to<authorship::BlockBuilderImpl>(),
1140  di::bind<authorship::BlockBuilderFactory>.template to<authorship::BlockBuilderFactoryImpl>(),
1141  di::bind<storage::BufferStorage>.to([](const auto &injector) {
1142  const application::AppConfiguration &config =
1143  injector.template create<application::AppConfiguration const &>();
1144  auto chain_spec =
1145  injector.template create<sptr<application::ChainSpec>>();
1146  BOOST_ASSERT( // since rocksdb is the only possible option now
1147  config.storageBackend()
1149  return get_rocks_db(config, chain_spec);
1150  }),
1151  di::bind<blockchain::BlockStorage>.to([](const auto &injector) {
1152  auto root_hash = get_trie_storage_and_root_hash(injector).second;
1153  const auto &hasher = injector.template create<sptr<crypto::Hasher>>();
1154  const auto &storage =
1155  injector.template create<sptr<storage::BufferStorage>>();
1156  return get_block_storage(root_hash, hasher, storage);
1157  }),
1158  di::bind<blockchain::JustificationStoragePolicy>.template to<blockchain::JustificationStoragePolicyImpl>(),
1159  di::bind<blockchain::BlockTree>.to(
1160  [](auto const &injector) { return get_block_tree(injector); }),
1161  di::bind<blockchain::BlockHeaderRepository>.template to<blockchain::BlockHeaderRepositoryImpl>(),
1162  di::bind<clock::SystemClock>.template to<clock::SystemClockImpl>(),
1163  di::bind<clock::SteadyClock>.template to<clock::SteadyClockImpl>(),
1164  di::bind<clock::Timer>.template to<clock::BasicWaitableTimer>(),
1165  di::bind<network::Synchronizer>.template to<network::SynchronizerImpl>(),
1166  di::bind<consensus::grandpa::Environment>.template to<consensus::grandpa::EnvironmentImpl>(),
1167  di::bind<consensus::BlockValidator>.template to<consensus::BabeBlockValidator>(),
1168  di::bind<crypto::EcdsaProvider>.template to<crypto::EcdsaProviderImpl>(),
1169  di::bind<crypto::Ed25519Provider>.template to<crypto::Ed25519ProviderImpl>(),
1170  di::bind<crypto::Hasher>.template to<crypto::HasherImpl>(),
1171  di::bind<crypto::Sr25519Provider>.template to<crypto::Sr25519ProviderImpl>(),
1172  di::bind<crypto::VRFProvider>.template to<crypto::VRFProviderImpl>(),
1173  di::bind<network::StreamEngine>.template to<network::StreamEngine>(),
1174  di::bind<network::ReputationRepository>.template to<network::ReputationRepositoryImpl>(),
1175  di::bind<crypto::Bip39Provider>.template to<crypto::Bip39ProviderImpl>(),
1176  di::bind<crypto::Pbkdf2Provider>.template to<crypto::Pbkdf2ProviderImpl>(),
1177  di::bind<crypto::Secp256k1Provider>.template to<crypto::Secp256k1ProviderImpl>(),
1178  di::bind<crypto::KeyFileStorage>.template to([](auto const &injector) {
1179  const application::AppConfiguration &config =
1180  injector.template create<application::AppConfiguration const &>();
1181  auto chain_spec =
1182  injector.template create<sptr<application::ChainSpec>>();
1183 
1184  return get_key_file_storage(config, chain_spec);
1185  }),
1186  di::bind<crypto::CryptoStore>.template to<crypto::CryptoStoreImpl>(),
1187  di::bind<host_api::HostApi>.template to<host_api::HostApiImpl>(),
1188  di::bind<host_api::HostApiFactory>.template to<host_api::HostApiFactoryImpl>(),
1189  makeRuntimeInjector(config.runtimeExecMethod()),
1190  di::bind<transaction_pool::TransactionPool>.template to<transaction_pool::TransactionPoolImpl>(),
1191  di::bind<transaction_pool::PoolModerator>.template to<transaction_pool::PoolModeratorImpl>(),
1192  di::bind<storage::changes_trie::ChangesTracker>.template to<storage::changes_trie::StorageChangesTrackerImpl>(),
1193  bind_by_lambda<network::StateProtocolObserver>(get_state_observer_impl),
1194  bind_by_lambda<network::SyncProtocolObserver>(get_sync_observer_impl),
1195  di::bind<parachain::AvailabilityStore>.template to<parachain::AvailabilityStoreImpl>(),
1196  di::bind<parachain::BitfieldStore>.template to<parachain::BitfieldStoreImpl>(),
1197  di::bind<parachain::ParachainObserverImpl>.to([](auto const &injector) {
1198  return get_parachain_observer_impl(injector);
1199  }),
1200  di::bind<parachain::ParachainProcessorImpl>.to(
1201  [](auto const &injector) {
1202  return get_parachain_processor_impl(injector);
1203  }),
1204  di::bind<storage::trie::TrieStorageBackend>.to(
1205  [](auto const &injector) {
1206  auto storage =
1207  injector.template create<sptr<storage::BufferStorage>>();
1208  return get_trie_storage_backend(storage);
1209  }),
1210  di::bind<storage::trie::TrieStorage>.to([](auto const &injector) {
1211  return get_trie_storage_and_root_hash(injector).first;
1212  }),
1213  di::bind<storage::trie::PolkadotTrieFactory>.template to<storage::trie::PolkadotTrieFactoryImpl>(),
1214  di::bind<storage::trie::Codec>.template to<storage::trie::PolkadotCodec>(),
1215  di::bind<storage::trie::TrieSerializer>.template to<storage::trie::TrieSerializerImpl>(),
1216  di::bind<runtime::RuntimeCodeProvider>.template to<runtime::StorageCodeProvider>(),
1217  di::bind<application::ChainSpec>.to([](const auto &injector) {
1218  const application::AppConfiguration &config =
1219  injector.template create<application::AppConfiguration const &>();
1220  return get_chain_spec(config);
1221  }),
1222  di::bind<network::ExtrinsicObserver>.to([](const auto &injector) {
1223  return get_extrinsic_observer_impl(injector);
1224  }),
1225  di::bind<authority::AuthorityUpdateObserver>.template to<authority::AuthorityManagerImpl>(),
1226  bind_by_lambda<authority::AuthorityManager>([](auto const &injector) {
1227  auto auth_manager_impl =
1228  injector.template create<sptr<authority::AuthorityManagerImpl>>();
1229  auto block_tree_impl =
1230  injector.template create<sptr<blockchain::BlockTree>>();
1231  auto justification_storage_policy = injector.template create<
1233  justification_storage_policy->initBlockchainInfo(block_tree_impl);
1234  return auth_manager_impl;
1235  }),
1236  di::bind<network::PeerManager>.to(
1237  [](auto const &injector) { return get_peer_manager(injector); }),
1238  di::bind<network::Router>.template to<network::RouterLibp2p>(),
1239  di::bind<consensus::BlockAppender>.template to<consensus::BlockAppenderImpl>(),
1240  di::bind<consensus::BlockExecutor>.to(
1241  [](auto const &injector) { return get_block_executor(injector); }),
1242  di::bind<consensus::grandpa::Grandpa>.to(
1243  [](auto const &injector) { return get_grandpa_impl(injector); }),
1244  di::bind<consensus::grandpa::RoundObserver>.to(
1245  [](auto const &injector) { return get_grandpa_impl(injector); }),
1246  di::bind<consensus::grandpa::CatchUpObserver>.to(
1247  [](auto const &injector) { return get_grandpa_impl(injector); }),
1248  di::bind<consensus::grandpa::NeighborObserver>.to(
1249  [](auto const &injector) { return get_grandpa_impl(injector); }),
1250  di::bind<consensus::grandpa::GrandpaObserver>.to(
1251  [](auto const &injector) { return get_grandpa_impl(injector); }),
1252  di::bind<consensus::BabeUtil>.template to<consensus::babe::BabeConfigRepositoryImpl>(),
1253  di::bind<network::BlockAnnounceTransmitter>.template to<network::BlockAnnounceTransmitterImpl>(),
1254  di::bind<network::GrandpaTransmitter>.template to<network::GrandpaTransmitterImpl>(),
1255  di::bind<network::TransactionsTransmitter>.template to<network::TransactionsTransmitterImpl>(),
1256  di::bind<primitives::GenesisBlockHeader>.to([](auto const &injector) {
1257  return get_genesis_block_header(injector);
1258  }),
1259  di::bind<application::mode::RecoveryMode>.to(
1260  [](auto const &injector) { return get_recovery_mode(injector); }),
1261  di::bind<telemetry::TelemetryService>.template to<telemetry::TelemetryServiceImpl>(),
1262  di::bind<consensus::babe::ConsistencyKeeper>.template to<consensus::babe::ConsistencyKeeperImpl>(),
1263  di::bind<api::InternalApi>.template to<api::InternalApiImpl>(),
1264  di::bind<consensus::babe::BabeConfigRepository>.template to<consensus::babe::BabeConfigRepositoryImpl>(),
1265  di::bind<blockchain::DigestTracker>.template to<blockchain::DigestTrackerImpl>(),
1266  di::bind<consensus::BabeDigestObserver>.template to<consensus::babe::BabeConfigRepositoryImpl>(),
1267 
1268  // user-defined overrides...
1269  std::forward<decltype(args)>(args)...);
1270  }
1271 
1272  template <typename Injector>
1273  sptr<network::OwnPeerInfo> get_own_peer_info(const Injector &injector) {
1274  static std::optional<sptr<network::OwnPeerInfo>> initialized{std::nullopt};
1275  if (initialized) {
1276  return initialized.value();
1277  }
1278 
1279  libp2p::crypto::PublicKey public_key;
1280 
1281  const auto &config =
1282  injector.template create<application::AppConfiguration const &>();
1283 
1284  if (config.roles().flags.authority) {
1285  auto &crypto_provider =
1286  injector.template create<const crypto::Ed25519Provider &>();
1287  auto &crypto_store = injector.template create<crypto::CryptoStore &>();
1288 
1289  auto &local_pair =
1290  injector::get_peer_keypair(config, crypto_provider, crypto_store);
1291 
1292  public_key = local_pair->publicKey;
1293  } else {
1294  auto &&local_pair = injector.template create<libp2p::crypto::KeyPair>();
1295  public_key = local_pair.publicKey;
1296  }
1297 
1298  auto &key_marshaller =
1299  injector.template create<libp2p::crypto::marshaller::KeyMarshaller &>();
1300 
1301  libp2p::peer::PeerId peer_id =
1302  libp2p::peer::PeerId::fromPublicKey(
1303  key_marshaller.marshal(public_key).value())
1304  .value();
1305 
1306  std::vector<libp2p::multi::Multiaddress> listen_addrs =
1307  config.listenAddresses();
1308  std::vector<libp2p::multi::Multiaddress> public_addrs =
1309  config.publicAddresses();
1310 
1311  auto log = log::createLogger("Injector", "injector");
1312  for (auto &addr : listen_addrs) {
1313  SL_DEBUG(log, "Peer listening on multiaddr: {}", addr.getStringAddress());
1314  }
1315  for (auto &addr : public_addrs) {
1316  SL_DEBUG(log, "Peer public multiaddr: {}", addr.getStringAddress());
1317  }
1318 
1319  initialized = std::make_shared<network::OwnPeerInfo>(
1320  std::move(peer_id), std::move(public_addrs), std::move(listen_addrs));
1321  return initialized.value();
1322  }
1323 
1324  template <typename Injector>
1325  sptr<consensus::babe::Babe> get_babe(const Injector &injector) {
1326  static auto initialized =
1327  std::optional<sptr<consensus::babe::Babe>>(std::nullopt);
1328  if (initialized) {
1329  return initialized.value();
1330  }
1331 
1332  auto &session_keys = get_session_keys(injector);
1333 
1334  initialized = std::make_shared<consensus::babe::BabeImpl>(
1335  injector.template create<const application::AppConfiguration &>(),
1336  injector.template create<sptr<application::AppStateManager>>(),
1337  injector.template create<sptr<consensus::BabeLottery>>(),
1338  injector.template create<sptr<consensus::babe::BabeConfigRepository>>(),
1339  injector.template create<sptr<authorship::Proposer>>(),
1340  injector.template create<sptr<blockchain::BlockTree>>(),
1341  injector.template create<sptr<network::BlockAnnounceTransmitter>>(),
1342  injector.template create<sptr<crypto::Sr25519Provider>>(),
1343  session_keys->getBabeKeyPair(),
1344  injector.template create<sptr<clock::SystemClock>>(),
1345  injector.template create<sptr<crypto::Hasher>>(),
1346  injector.template create<uptr<clock::Timer>>(),
1347  injector.template create<sptr<authority::AuthorityUpdateObserver>>(),
1348  injector.template create<sptr<network::Synchronizer>>(),
1349  injector.template create<sptr<consensus::BabeUtil>>(),
1350  injector
1351  .template create<primitives::events::ChainSubscriptionEnginePtr>(),
1352  injector.template create<sptr<runtime::OffchainWorkerApi>>(),
1353  injector.template create<sptr<runtime::Core>>(),
1354  injector.template create<sptr<consensus::babe::ConsistencyKeeper>>());
1355 
1356  auto protocol_factory =
1357  injector.template create<std::shared_ptr<network::ProtocolFactory>>();
1358 
1359  protocol_factory->setBabe(initialized.value());
1360 
1361  return initialized.value();
1362  }
1363 
1364  template <typename Injector>
1365  sptr<network::ExtrinsicObserverImpl> get_extrinsic_observer_impl(
1366  const Injector &injector) {
1367  static auto initialized =
1368  std::optional<sptr<network::ExtrinsicObserverImpl>>(std::nullopt);
1369  if (initialized) {
1370  return initialized.value();
1371  }
1372 
1373  initialized = std::make_shared<network::ExtrinsicObserverImpl>(
1374  injector.template create<sptr<transaction_pool::TransactionPool>>());
1375 
1376  auto protocol_factory =
1377  injector.template create<std::shared_ptr<network::ProtocolFactory>>();
1378 
1379  protocol_factory->setExtrinsicObserver(initialized.value());
1380 
1381  return initialized.value();
1382  }
1383 
1384  template <typename Injector>
1385  sptr<consensus::grandpa::GrandpaImpl> get_grandpa_impl(
1386  const Injector &injector) {
1387  static auto initialized =
1388  std::optional<sptr<consensus::grandpa::GrandpaImpl>>(std::nullopt);
1389  if (initialized) {
1390  return initialized.value();
1391  }
1392 
1393  auto &session_keys = get_session_keys(injector);
1394 
1395  initialized = std::make_shared<consensus::grandpa::GrandpaImpl>(
1396  injector.template create<sptr<application::AppStateManager>>(),
1397  injector.template create<sptr<consensus::grandpa::Environment>>(),
1398  injector.template create<sptr<crypto::Ed25519Provider>>(),
1399  injector.template create<sptr<runtime::GrandpaApi>>(),
1400  session_keys->getGranKeyPair(),
1401  injector.template create<const application::ChainSpec &>(),
1402  injector.template create<sptr<clock::SteadyClock>>(),
1403  injector.template create<sptr<libp2p::basic::Scheduler>>(),
1404  injector.template create<sptr<authority::AuthorityManager>>(),
1405  injector.template create<sptr<network::Synchronizer>>(),
1406  injector.template create<sptr<network::PeerManager>>(),
1407  injector.template create<sptr<blockchain::BlockTree>>(),
1408  injector.template create<sptr<network::ReputationRepository>>());
1409 
1410  auto protocol_factory =
1411  injector.template create<std::shared_ptr<network::ProtocolFactory>>();
1412 
1413  protocol_factory->setGrandpaObserver(initialized.value());
1414 
1415  return initialized.value();
1416  }
1417 
1418  template <typename Injector>
1419  sptr<application::mode::RecoveryMode> get_recovery_mode(
1420  const Injector &injector) {
1421  static auto initialized =
1422  std::optional<sptr<application::mode::RecoveryMode>>(std::nullopt);
1423  if (initialized) {
1424  return initialized.value();
1425  }
1426 
1427  const auto &app_config =
1428  injector.template create<const application::AppConfiguration &>();
1429  auto buffer_storage =
1430  injector.template create<sptr<storage::BufferStorage>>();
1431  auto storage = injector.template create<sptr<blockchain::BlockStorage>>();
1432  auto header_repo =
1433  injector.template create<sptr<blockchain::BlockHeaderRepository>>();
1434  auto trie_storage =
1435  injector.template create<sptr<const storage::trie::TrieStorage>>();
1436  auto authority_manager =
1437  injector.template create<sptr<authority::AuthorityManager>>();
1438  auto block_tree = injector.template create<sptr<blockchain::BlockTree>>();
1439 
1440  initialized.emplace(new application::mode::RecoveryMode(
1441  [&app_config,
1442  buffer_storage = std::move(buffer_storage),
1443  authority_manager,
1444  storage = std::move(storage),
1445  header_repo = std::move(header_repo),
1446  trie_storage = std::move(trie_storage),
1447  block_tree = std::move(block_tree)] {
1448  BOOST_ASSERT(app_config.recoverState().has_value());
1450  app_config.recoverState().value(),
1451  storage,
1452  header_repo,
1453  trie_storage,
1454  block_tree);
1455 
1456  auto log = log::createLogger("RecoveryMode", "main");
1457 
1458  buffer_storage->remove(storage::kAuthorityManagerStateLookupKey)
1459  .value();
1460  if (res.has_error()) {
1461  SL_ERROR(
1462  log, "Recovery mode has failed: {}", res.error().message());
1463  log->flush();
1464  return EXIT_FAILURE;
1465  }
1466 
1467  auto number =
1468  header_repo->getNumberById(app_config.recoverState().value());
1469  res = authority_manager->recalculateStoredState(number.value());
1470  if (res.has_error()) {
1471  SL_ERROR(
1472  log, "Recovery mode has failed: {}", res.error().message());
1473  log->flush();
1474  return EXIT_FAILURE;
1475  }
1476 
1477  return EXIT_SUCCESS;
1478  }));
1479 
1480  return initialized.value();
1481  }
1482 
1483  template <typename... Ts>
1484  auto makeKagomeNodeInjector(const application::AppConfiguration &app_config,
1485  Ts &&...args) {
1486  using namespace boost; // NOLINT;
1487 
1488  return di::make_injector(
1489  makeApplicationInjector(app_config),
1490  // compose peer info
1491  di::bind<network::OwnPeerInfo>.to(
1492  [](const auto &injector) { return get_own_peer_info(injector); }),
1493  di::bind<consensus::babe::Babe>.to(
1494  [](auto const &injector) { return get_babe(injector); }),
1495  di::bind<consensus::BabeLottery>.template to<consensus::BabeLotteryImpl>(),
1496  di::bind<network::BlockAnnounceObserver>.to(
1497  [](auto const &injector) { return get_babe(injector); }),
1498 
1499  // user-defined overrides...
1500  std::forward<decltype(args)>(args)...);
1501  }
1502 
1503 } // namespace
1504 
1505 namespace kagome::injector {
1506 
1508  public:
1509  using Injector = decltype(makeKagomeNodeInjector(
1510  std::declval<application::AppConfiguration const &>()));
1511 
1513  : injector_{std::move(injector)} {}
1515  };
1516 
1517  KagomeNodeInjector::KagomeNodeInjector(
1518  const application::AppConfiguration &app_config)
1519  : pimpl_{std::make_unique<KagomeNodeInjectorImpl>(
1520  makeKagomeNodeInjector(app_config))} {}
1521 
1523  return pimpl_->injector_.create<sptr<application::ChainSpec>>();
1524  }
1525 
1526  std::shared_ptr<blockchain::BlockStorage>
1528  return pimpl_->injector_.create<sptr<blockchain::BlockStorage>>();
1529  }
1530 
1533  return pimpl_->injector_.create<sptr<application::AppStateManager>>();
1534  }
1535 
1537  return pimpl_->injector_.create<sptr<boost::asio::io_context>>();
1538  }
1539 
1541  // registry here is temporary, it initiates static global registry
1542  // and registers handler in there
1543  auto registry = metrics::createRegistry();
1544  auto handler = pimpl_->injector_.create<sptr<metrics::Handler>>();
1545  registry->setHandler(*handler.get());
1546  auto exposer = pimpl_->injector_.create<sptr<metrics::Exposer>>();
1547  exposer->setHandler(handler);
1548  return exposer;
1549  }
1550 
1552  return pimpl_->injector_.create<sptr<network::Router>>();
1553  }
1554 
1556  return pimpl_->injector_.create<sptr<network::PeerManager>>();
1557  }
1558 
1560  return pimpl_->injector_.create<sptr<api::ApiService>>();
1561  }
1562 
1563  std::shared_ptr<clock::SystemClock> KagomeNodeInjector::injectSystemClock() {
1564  return pimpl_->injector_.create<sptr<clock::SystemClock>>();
1565  }
1566 
1567  std::shared_ptr<network::StateProtocolObserver>
1569  return pimpl_->injector_.create<sptr<network::StateProtocolObserver>>();
1570  }
1571 
1572  std::shared_ptr<network::SyncProtocolObserver>
1574  return pimpl_->injector_.create<sptr<network::SyncProtocolObserver>>();
1575  }
1576 
1577  std::shared_ptr<parachain::ParachainObserverImpl>
1579  return pimpl_->injector_.create<sptr<parachain::ParachainObserverImpl>>();
1580  }
1581 
1582  std::shared_ptr<parachain::ParachainProcessorImpl>
1584  return pimpl_->injector_.create<sptr<parachain::ParachainProcessorImpl>>();
1585  }
1586 
1587  std::shared_ptr<consensus::babe::Babe> KagomeNodeInjector::injectBabe() {
1588  return pimpl_->injector_.create<sptr<consensus::babe::Babe>>();
1589  }
1590 
1591  std::shared_ptr<consensus::grandpa::Grandpa>
1593  return pimpl_->injector_.create<sptr<consensus::grandpa::Grandpa>>();
1594  }
1595 
1596  std::shared_ptr<soralog::LoggingSystem>
1598  return std::make_shared<soralog::LoggingSystem>(
1599  std::make_shared<kagome::log::Configurator>(
1600  pimpl_->injector_.create<sptr<libp2p::log::Configurator>>()));
1601  }
1602 
1603  std::shared_ptr<storage::trie::TrieStorage>
1605  return pimpl_->injector_.create<sptr<storage::trie::TrieStorage>>();
1606  }
1607 
1608  std::shared_ptr<metrics::MetricsWatcher>
1610  return pimpl_->injector_.create<sptr<metrics::MetricsWatcher>>();
1611  }
1612 
1613  std::shared_ptr<telemetry::TelemetryService>
1615  return pimpl_->injector_.create<sptr<telemetry::TelemetryService>>();
1616  }
1617 
1618  std::shared_ptr<application::mode::PrintChainInfoMode>
1620  return pimpl_->injector_
1622  }
1623 
1624  std::shared_ptr<application::mode::RecoveryMode>
1626  return pimpl_->injector_.create<sptr<application::mode::RecoveryMode>>();
1627  }
1628 
1629  std::shared_ptr<blockchain::BlockTree> KagomeNodeInjector::injectBlockTree() {
1630  return pimpl_->injector_.create<sptr<blockchain::BlockTree>>();
1631  }
1632 
1633  std::shared_ptr<runtime::Executor> KagomeNodeInjector::injectExecutor() {
1634  return pimpl_->injector_.create<sptr<runtime::Executor>>();
1635  }
1636 
1637  std::shared_ptr<storage::BufferStorage> KagomeNodeInjector::injectStorage() {
1638  return pimpl_->injector_.create<sptr<storage::BufferStorage>>();
1639  }
1640 
1641 } // namespace kagome::injector
static outcome::result< std::shared_ptr< BlockTreeImpl > > create(std::shared_ptr< BlockHeaderRepository > header_repo, std::shared_ptr< BlockStorage > storage, std::shared_ptr< network::ExtrinsicObserver > extrinsic_observer, std::shared_ptr< crypto::Hasher > hasher, primitives::events::ChainSubscriptionEnginePtr chain_events_engine, primitives::events::ExtrinsicSubscriptionEnginePtr extrinsic_events_engine, std::shared_ptr< subscription::ExtrinsicEventKeyRepository > extrinsic_event_key_repo, std::shared_ptr< storage::changes_trie::ChangesTracker > changes_tracker, std::shared_ptr< const class JustificationStoragePolicy > justification_storage_policy)
Create an instance of block tree.
Class represents arbitrary (including empty) byte buffer.
Definition: buffer.hpp:29
std::shared_ptr< network::Router > injectRouter()
void raise(T t)
throws outcome::result error as boost exception
struct kagome::network::Roles::@11 flags
static outcome::result< void > recover(primitives::BlockId target_block, std::shared_ptr< BlockStorage > storage, std::shared_ptr< BlockHeaderRepository > header_repo, std::shared_ptr< const storage::trie::TrieStorage > trie_storage, std::shared_ptr< blockchain::BlockTree > block_tree)
Recover block tree state at provided block.
std::shared_ptr< clock::SystemClock > injectSystemClock()
const std::shared_ptr< libp2p::crypto::KeyPair > & get_peer_keypair(const application::AppConfiguration &app_config, const crypto::Ed25519Provider &crypto_provider, crypto::CryptoStore &crypto_store)
virtual boost::filesystem::path databasePath(std::string chain_id) const =0
std::shared_ptr< StorageSubscriptionEngine > StorageSubscriptionEnginePtr
std::shared_ptr< consensus::grandpa::Grandpa > injectGrandpa()
virtual std::optional< primitives::BlockId > recoverState() const =0
std::shared_ptr< soralog::LoggingSystem > injectLoggingSystem()
std::shared_ptr< telemetry::TelemetryService > injectTelemetryService()
virtual const std::vector< libp2p::multi::Multiaddress > & listenAddresses() const =0
Global parameters for module instantiation. Currently contains only memory type that may be changed o...
virtual network::Roles roles() const =0
std::shared_ptr< T > sptr
std::shared_ptr< application::mode::PrintChainInfoMode > injectPrintChainInfoMode()
Mode for recover state to provided block.
static outcome::result< std::shared_ptr< ChainSpecImpl > > loadFrom(const std::string &config_path)
std::shared_ptr< parachain::ParachainObserverImpl > injectParachainObserver()
std::shared_ptr< class KagomeNodeInjectorImpl > pimpl_
virtual bool useWavmCache() const =0
std::shared_ptr< blockchain::BlockStorage > injectBlockStorage()
static outcome::result< std::unique_ptr< RuntimeUpgradeTrackerImpl > > create(std::shared_ptr< const blockchain::BlockHeaderRepository > header_repo, std::shared_ptr< storage::BufferStorage > storage, std::shared_ptr< const primitives::CodeSubstituteBlockIds > code_substitutes, std::shared_ptr< blockchain::BlockStorage > block_storage)
const common::Buffer kChildStorageDefaultPrefix
std::shared_ptr< api::ApiService > injectRpcApiService()
RegistryPtr createRegistry()
virtual boost::filesystem::path keystorePath(std::string chain_id) const =0
std::shared_ptr< network::StateProtocolObserver > injectStateObserver()
common::Blob< constants::kGeneralPublicKeySize > PublicKey
uint32_t BlockNumber
Definition: common.hpp:18
virtual boost::filesystem::path chainSpecPath() const =0
libp2p::peer::PeerId PeerId
SLBuffer & put(std::string_view view)
Put a string into byte buffer.
Definition: buffer.hpp:117
std::shared_ptr< parachain::ParachainProcessorImpl > injectParachainProcessor()
std::shared_ptr< boost::asio::io_context > injectIoContext()
virtual const std::string & protocolId() const =0
static outcome::result< std::shared_ptr< BlockStorageImpl > > create(storage::trie::RootHash state_root, const std::shared_ptr< storage::BufferStorage > &storage, const std::shared_ptr< crypto::Hasher > &hasher)
const common::Buffer kAuthorityManagerStateLookupKey
std::shared_ptr< blockchain::BlockTree > injectBlockTree()
virtual std::chrono::seconds getRandomWalkInterval() const =0
std::shared_ptr< network::SyncProtocolObserver > injectSyncObserver()
std::shared_ptr< metrics::Exposer > injectOpenMetricsService()
std::shared_ptr< application::ChainSpec > injectChainSpec()
std::shared_ptr< ExtrinsicSubscriptionEngine > ExtrinsicSubscriptionEnginePtr
virtual bool isOffchainIndexingEnabled() const =0
std::shared_ptr< storage::BufferStorage > injectStorage()
std::shared_ptr< storage::trie::TrieStorage > injectTrieStorage()
decltype(makeKagomeNodeInjector(std::declval< application::AppConfiguration const & >())) Injector
std::shared_ptr< application::mode::RecoveryMode > injectRecoveryMode()
static outcome::result< std::unique_ptr< TrieStorageImpl > > createEmpty(const std::shared_ptr< PolkadotTrieFactory > &trie_factory, std::shared_ptr< Codec > codec, std::shared_ptr< TrieSerializer > serializer, std::optional< std::shared_ptr< changes_trie::ChangesTracker >> changes)
virtual uint32_t maxWsConnections() const =0
virtual const boost::asio::ip::tcp::endpoint & rpcHttpEndpoint() const =0
virtual StorageBackend storageBackend() const =0
virtual const boost::asio::ip::tcp::endpoint & rpcWsEndpoint() const =0
std::shared_ptr< consensus::babe::Babe > injectBabe()
static outcome::result< std::unique_ptr< KeyFileStorage > > createAt(Path keystore_path)
static outcome::result< std::unique_ptr< RocksDB > > create(const boost::filesystem::path &path, rocksdb::Options options=rocksdb::Options(), bool prevent_destruction=false)
Factory method to create an instance of RocksDB class.
Definition: rocksdb.cpp:37
virtual RuntimeExecutionMethod runtimeExecMethod() const =0
std::shared_ptr< application::AppStateManager > injectAppStateManager()
Logger createLogger(const std::string &tag)
Definition: logger.cpp:112
std::shared_ptr< runtime::Executor > injectExecutor()
std::shared_ptr< metrics::MetricsWatcher > injectMetricsWatcher()
std::shared_ptr< network::PeerManager > injectPeerManager()
virtual boost::filesystem::path runtimeCacheDirPath() const =0
void registerHostApiMethods(IntrinsicModule &module)
std::optional< size_t > getFdLimit()
Definition: fd_limit.cpp:36
virtual const std::vector< libp2p::multi::Multiaddress > & publicAddresses() const =0