From 5d388dbae2c83f4f559e6c12ab35d70351ad0cbe Mon Sep 17 00:00:00 2001 From: turuslan Date: Thu, 4 Aug 2022 11:41:14 +0300 Subject: [PATCH 1/5] save lp2p key Signed-off-by: turuslan --- .../crypto/crypto_store/crypto_store_impl.cpp | 3 +- .../crypto/crypto_store/crypto_store_impl.hpp | 5 +-- core/injector/application_injector.cpp | 37 ++++++++----------- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/core/crypto/crypto_store/crypto_store_impl.cpp b/core/crypto/crypto_store/crypto_store_impl.cpp index 1880f1abf0..5a89eee6c3 100644 --- a/core/crypto/crypto_store/crypto_store_impl.cpp +++ b/core/crypto/crypto_store/crypto_store_impl.cpp @@ -238,8 +238,7 @@ namespace kagome::crypto { return ed25519KeyToLibp2pKeypair(kp); } - libp2p::crypto::KeyPair CryptoStoreImpl::ed25519KeyToLibp2pKeypair( - const Ed25519Keypair &kp) const { + libp2p::crypto::KeyPair ed25519KeyToLibp2pKeypair(const Ed25519Keypair &kp) { const auto &secret_key = kp.secret_key; const auto &public_key = kp.public_key; libp2p::crypto::PublicKey lp2p_public{ diff --git a/core/crypto/crypto_store/crypto_store_impl.hpp b/core/crypto/crypto_store/crypto_store_impl.hpp index af11cffa4d..0d98414ff9 100644 --- a/core/crypto/crypto_store/crypto_store_impl.hpp +++ b/core/crypto/crypto_store/crypto_store_impl.hpp @@ -32,6 +32,8 @@ namespace kagome::crypto { WRONG_PUBLIC_KEY, }; + libp2p::crypto::KeyPair ed25519KeyToLibp2pKeypair(const Ed25519Keypair &kp); + /// TODO(Harrm) Add policies to emit a warning when found a keypair /// with incompatible type and algorithm (e. g. ed25519 BABE keypair, /// whereas BABE has to be sr25519 only) or when trying to generate more @@ -185,9 +187,6 @@ namespace kagome::crypto { return it->second; } - libp2p::crypto::KeyPair ed25519KeyToLibp2pKeypair( - const Ed25519Keypair &kp) const; - mutable std::unordered_map> ecdsa_caches_; mutable std::unordered_map> ed_caches_; mutable std::unordered_map> sr_caches_; diff --git a/core/injector/application_injector.cpp b/core/injector/application_injector.cpp index 4832097622..43537fc108 100644 --- a/core/injector/application_injector.cpp +++ b/core/injector/application_injector.cpp @@ -500,15 +500,8 @@ namespace { crypto_provider.generateKeypair(app_config.nodeKey().value()); BOOST_ASSERT(provided_keypair.secret_key == app_config.nodeKey().value()); - auto &&pub = provided_keypair.public_key; - auto &&priv = provided_keypair.secret_key; - - auto key_pair = - std::make_shared(libp2p::crypto::KeyPair{ - .publicKey = {{.type = libp2p::crypto::Key::Type::Ed25519, - .data = {pub.begin(), pub.end()}}}, - .privateKey = {{.type = libp2p::crypto::Key::Type::Ed25519, - .data = {priv.begin(), priv.end()}}}}); + auto key_pair = std::make_shared( + crypto::ed25519KeyToLibp2pKeypair(provided_keypair)); initialized.emplace(std::move(key_pair)); return initialized.value(); @@ -547,19 +540,21 @@ namespace { log->warn( "Can not obtain a libp2p keypair from crypto storage. " - "A unique one will be generated for the current session"); - - auto generated_keypair = crypto_provider.generateKeypair(); - - auto &&pub = generated_keypair.public_key; - auto &&priv = generated_keypair.secret_key; + "A unique one will be generated"); + + kagome::crypto::Ed25519Keypair generated_keypair; + auto generated_keypair_res = const_cast(crypto_store) + .generateEd25519KeypairOnDisk( + crypto::KnownKeyTypeId::KEY_TYPE_LP2P); + if (not generated_keypair_res) { + log->warn("Can't save libp2p keypair: {}", generated_keypair_res.error()); + generated_keypair = crypto_provider.generateKeypair(); + } else { + generated_keypair = generated_keypair_res.value(); + } - auto key_pair = - std::make_shared(libp2p::crypto::KeyPair{ - .publicKey = {{.type = libp2p::crypto::Key::Type::Ed25519, - .data = {pub.begin(), pub.end()}}}, - .privateKey = {{.type = libp2p::crypto::Key::Type::Ed25519, - .data = {priv.begin(), priv.end()}}}}); + auto key_pair = std::make_shared( + crypto::ed25519KeyToLibp2pKeypair(generated_keypair)); initialized.emplace(std::move(key_pair)); return initialized.value(); From 885e96900911d17aaf4816fa4ee3842777bfc286 Mon Sep 17 00:00:00 2001 From: turuslan Date: Wed, 31 Aug 2022 13:39:23 +0300 Subject: [PATCH 2/5] don't save node key by default Signed-off-by: turuslan --- core/application/app_configuration.hpp | 5 +++ .../impl/app_configuration_impl.cpp | 4 +++ .../impl/app_configuration_impl.hpp | 7 +++- core/injector/application_injector.cpp | 33 +++++++++++-------- .../application/app_configuration_mock.hpp | 2 ++ 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/core/application/app_configuration.hpp b/core/application/app_configuration.hpp index fdad345b86..85e5379a84 100644 --- a/core/application/app_configuration.hpp +++ b/core/application/app_configuration.hpp @@ -86,6 +86,11 @@ namespace kagome::application { */ virtual const std::optional &nodeKeyFile() const = 0; + /** + * @return true if generated libp2p networking key should be saved + */ + virtual bool saveNodeKey() const = 0; + /** * @return port for peer to peer interactions. */ diff --git a/core/application/impl/app_configuration_impl.cpp b/core/application/impl/app_configuration_impl.cpp index b099b7c25d..03b0b6d045 100644 --- a/core/application/impl/app_configuration_impl.cpp +++ b/core/application/impl/app_configuration_impl.cpp @@ -139,6 +139,7 @@ namespace kagome::application { AppConfigurationImpl::AppConfigurationImpl(log::Logger logger) : logger_(std::move(logger)), roles_(def_roles), + save_node_key_(false), is_telemetry_enabled_(true), p2p_port_(def_p2p_port), max_blocks_in_response_(kAbsolutMaxBlocksInResponse), @@ -676,6 +677,7 @@ namespace kagome::application { ("public-addr", po::value>()->multitoken(), "multiaddresses that other nodes use to connect to it") ("node-key", po::value(), "the secret key to use for libp2p networking") ("node-key-file", po::value(), "path to the secret key used for libp2p networking (raw binary or hex-encoded") + ("save-node-key", po::bool_switch(), "save generated libp2p networking key, key will be reused on node restart") ("bootnodes", po::value>()->multitoken(), "multiaddresses of bootstrap nodes") ("port,p", po::value(), "port for peer to peer interactions") ("rpc-host", po::value(), "address for RPC over HTTP") @@ -915,6 +917,8 @@ namespace kagome::application { }); } + save_node_key_ = vm.count("save-node-key") != 0; + find_argument(vm, "port", [&](uint16_t val) { p2p_port_ = val; }); auto parse_multiaddrs = diff --git a/core/application/impl/app_configuration_impl.hpp b/core/application/impl/app_configuration_impl.hpp index 9445809a4a..7c91570393 100644 --- a/core/application/impl/app_configuration_impl.hpp +++ b/core/application/impl/app_configuration_impl.hpp @@ -82,7 +82,11 @@ namespace kagome::application { const std::optional &nodeKeyFile() const override { return node_key_file_; - }; + } + + bool saveNodeKey() const override { + return save_node_key_; + } const std::vector &listenAddresses() const override { @@ -269,6 +273,7 @@ namespace kagome::application { network::Roles roles_; std::optional node_key_; std::optional node_key_file_; + bool save_node_key_; std::vector listen_addresses_; std::vector public_addresses_; std::vector boot_nodes_; diff --git a/core/injector/application_injector.cpp b/core/injector/application_injector.cpp index cd393f2b80..027daa64b3 100644 --- a/core/injector/application_injector.cpp +++ b/core/injector/application_injector.cpp @@ -514,6 +514,7 @@ namespace { log->error("Unable to load user provided key from {}. Error: {}", path, key.error().message()); + common::raise(key.error()); } else { auto key_pair = std::make_shared(std::move(key.value())); @@ -541,14 +542,20 @@ namespace { "A unique one will be generated"); kagome::crypto::Ed25519Keypair generated_keypair; - auto generated_keypair_res = const_cast(crypto_store) - .generateEd25519KeypairOnDisk( - crypto::KnownKeyTypeId::KEY_TYPE_LP2P); - if (not generated_keypair_res) { - log->warn("Can't save libp2p keypair: {}", generated_keypair_res.error()); + auto save = app_config.saveNodeKey(); + if (save) { + auto res = const_cast(crypto_store) + .generateEd25519KeypairOnDisk( + crypto::KnownKeyTypeId::KEY_TYPE_LP2P); + if (res.has_error()) { + log->warn("Can't save libp2p keypair: {}", res.error()); + save = false; + } else { + generated_keypair = res.value(); + } + } + if (not save) { generated_keypair = crypto_provider.generateKeypair(); - } else { - generated_keypair = generated_keypair_res.value(); } auto key_pair = std::make_shared( @@ -811,7 +818,7 @@ namespace { template auto makeWavmInjector( application::AppConfiguration::RuntimeExecutionMethod method, - Ts &&... args) { + Ts &&...args) { return di::make_injector( di::bind.template to( [](const auto &injector) { @@ -853,7 +860,7 @@ namespace { template auto makeBinaryenInjector( application::AppConfiguration::RuntimeExecutionMethod method, - Ts &&... args) { + Ts &&...args) { return di::make_injector( di::bind.template to( [](const auto &injector) { @@ -927,7 +934,7 @@ namespace { template auto makeRuntimeInjector( application::AppConfiguration::RuntimeExecutionMethod method, - Ts &&... args) { + Ts &&...args) { return di::make_injector( di::bind.template to(), di::bind.template to( @@ -1025,7 +1032,7 @@ namespace { template auto makeApplicationInjector(const application::AppConfiguration &config, - Ts &&... args) { + Ts &&...args) { // default values for configurations api::RpcThreadPool::Configuration rpc_thread_pool_config{}; api::HttpSession::Configuration http_config{}; @@ -1513,7 +1520,7 @@ namespace { template auto makeKagomeNodeInjector(const application::AppConfiguration &app_config, - Ts &&... args) { + Ts &&...args) { using namespace boost; // NOLINT; return di::make_injector( @@ -1548,7 +1555,7 @@ namespace kagome::injector { KagomeNodeInjector::KagomeNodeInjector( const application::AppConfiguration &app_config) : pimpl_{std::make_unique( - makeKagomeNodeInjector(app_config))} {} + makeKagomeNodeInjector(app_config))} {} sptr KagomeNodeInjector::injectChainSpec() { return pimpl_->injector_.create>(); diff --git a/test/mock/core/application/app_configuration_mock.hpp b/test/mock/core/application/app_configuration_mock.hpp index b1ce67a6ec..e475ad6332 100644 --- a/test/mock/core/application/app_configuration_mock.hpp +++ b/test/mock/core/application/app_configuration_mock.hpp @@ -53,6 +53,8 @@ namespace kagome::application { (), (const, override)); + MOCK_METHOD(bool, saveNodeKey, (), (const, override)); + MOCK_METHOD(const std::vector &, listenAddresses, (), From 12c53702af9c23e545147304307535446dceba54 Mon Sep 17 00:00:00 2001 From: turuslan Date: Wed, 31 Aug 2022 14:20:18 +0300 Subject: [PATCH 3/5] rename Signed-off-by: turuslan --- core/application/app_configuration.hpp | 2 +- core/application/impl/app_configuration_impl.hpp | 2 +- core/injector/application_injector.cpp | 2 +- test/mock/core/application/app_configuration_mock.hpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/application/app_configuration.hpp b/core/application/app_configuration.hpp index 85e5379a84..293a2c0358 100644 --- a/core/application/app_configuration.hpp +++ b/core/application/app_configuration.hpp @@ -89,7 +89,7 @@ namespace kagome::application { /** * @return true if generated libp2p networking key should be saved */ - virtual bool saveNodeKey() const = 0; + virtual bool shouldSaveNodeKey() const = 0; /** * @return port for peer to peer interactions. diff --git a/core/application/impl/app_configuration_impl.hpp b/core/application/impl/app_configuration_impl.hpp index 7c91570393..6df725c59d 100644 --- a/core/application/impl/app_configuration_impl.hpp +++ b/core/application/impl/app_configuration_impl.hpp @@ -84,7 +84,7 @@ namespace kagome::application { return node_key_file_; } - bool saveNodeKey() const override { + bool shouldSaveNodeKey() const override { return save_node_key_; } diff --git a/core/injector/application_injector.cpp b/core/injector/application_injector.cpp index 027daa64b3..a37db96152 100644 --- a/core/injector/application_injector.cpp +++ b/core/injector/application_injector.cpp @@ -542,7 +542,7 @@ namespace { "A unique one will be generated"); kagome::crypto::Ed25519Keypair generated_keypair; - auto save = app_config.saveNodeKey(); + auto save = app_config.shouldSaveNodeKey(); if (save) { auto res = const_cast(crypto_store) .generateEd25519KeypairOnDisk( diff --git a/test/mock/core/application/app_configuration_mock.hpp b/test/mock/core/application/app_configuration_mock.hpp index e475ad6332..cdf9c90629 100644 --- a/test/mock/core/application/app_configuration_mock.hpp +++ b/test/mock/core/application/app_configuration_mock.hpp @@ -53,7 +53,7 @@ namespace kagome::application { (), (const, override)); - MOCK_METHOD(bool, saveNodeKey, (), (const, override)); + MOCK_METHOD(bool, shouldSaveNodeKey, (), (const, override)); MOCK_METHOD(const std::vector &, listenAddresses, From 39f9850e448fc053e27546d35a04f8bdc77e5184 Mon Sep 17 00:00:00 2001 From: turuslan Date: Wed, 31 Aug 2022 14:37:45 +0300 Subject: [PATCH 4/5] injector const Signed-off-by: turuslan --- core/injector/application_injector.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/core/injector/application_injector.cpp b/core/injector/application_injector.cpp index a37db96152..ad381bde53 100644 --- a/core/injector/application_injector.cpp +++ b/core/injector/application_injector.cpp @@ -481,7 +481,7 @@ namespace { const sptr &get_peer_keypair( const application::AppConfiguration &app_config, const crypto::Ed25519Provider &crypto_provider, - const crypto::CryptoStore &crypto_store) { + crypto::CryptoStore &crypto_store) { static auto initialized = std::optional>(std::nullopt); @@ -544,9 +544,8 @@ namespace { kagome::crypto::Ed25519Keypair generated_keypair; auto save = app_config.shouldSaveNodeKey(); if (save) { - auto res = const_cast(crypto_store) - .generateEd25519KeypairOnDisk( - crypto::KnownKeyTypeId::KEY_TYPE_LP2P); + auto res = crypto_store.generateEd25519KeypairOnDisk( + crypto::KnownKeyTypeId::KEY_TYPE_LP2P); if (res.has_error()) { log->warn("Can't save libp2p keypair: {}", res.error()); save = false; @@ -1108,7 +1107,7 @@ namespace { auto &crypto_provider = injector.template create(); auto &crypto_store = - injector.template create(); + injector.template create(); return get_peer_keypair(app_config, crypto_provider, crypto_store); })[boost::di::override], @@ -1352,8 +1351,7 @@ namespace { if (config.roles().flags.authority) { auto &crypto_provider = injector.template create(); - auto &crypto_store = - injector.template create(); + auto &crypto_store = injector.template create(); auto &local_pair = get_peer_keypair(config, crypto_provider, crypto_store); From 0f450765ce17ad341cc692a5cdee96e02d353f3e Mon Sep 17 00:00:00 2001 From: turuslan Date: Wed, 31 Aug 2022 15:02:19 +0300 Subject: [PATCH 5/5] split some code from injector Signed-off-by: turuslan --- core/injector/application_injector.cpp | 92 +--------------------- core/injector/get_peer_keypair.hpp | 102 +++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 88 deletions(-) create mode 100644 core/injector/get_peer_keypair.hpp diff --git a/core/injector/application_injector.cpp b/core/injector/application_injector.cpp index ad381bde53..d4a3c2d991 100644 --- a/core/injector/application_injector.cpp +++ b/core/injector/application_injector.cpp @@ -83,6 +83,7 @@ #include "crypto/vrf/vrf_provider_impl.hpp" #include "host_api/impl/host_api_factory_impl.hpp" #include "host_api/impl/host_api_impl.hpp" +#include "injector/get_peer_keypair.hpp" #include "log/configurator.hpp" #include "log/logger.hpp" #include "metrics/impl/exposer_impl.hpp" @@ -478,92 +479,6 @@ namespace { return initialized.value(); } - const sptr &get_peer_keypair( - const application::AppConfiguration &app_config, - const crypto::Ed25519Provider &crypto_provider, - crypto::CryptoStore &crypto_store) { - static auto initialized = - std::optional>(std::nullopt); - - if (initialized) { - return initialized.value(); - } - - auto log = log::createLogger("Injector", "injector"); - - if (app_config.nodeKey()) { - log->info("Will use LibP2P keypair from config or 'node-key' CLI arg"); - - auto provided_keypair = - crypto_provider.generateKeypair(app_config.nodeKey().value()); - BOOST_ASSERT(provided_keypair.secret_key == app_config.nodeKey().value()); - - auto key_pair = std::make_shared( - crypto::ed25519KeyToLibp2pKeypair(provided_keypair)); - - initialized.emplace(std::move(key_pair)); - return initialized.value(); - } - - if (app_config.nodeKeyFile()) { - const auto &path = app_config.nodeKeyFile().value(); - log->info( - "Will use LibP2P keypair from config or 'node-key-file' CLI arg"); - auto key = crypto_store.loadLibp2pKeypair(path); - if (key.has_error()) { - log->error("Unable to load user provided key from {}. Error: {}", - path, - key.error().message()); - common::raise(key.error()); - } else { - auto key_pair = - std::make_shared(std::move(key.value())); - initialized.emplace(std::move(key_pair)); - return initialized.value(); - } - } - - if (crypto_store.getLibp2pKeypair().has_value()) { - log->info( - "Will use LibP2P keypair from config or args (loading from base " - "path)"); - - auto stored_keypair = crypto_store.getLibp2pKeypair().value(); - - auto key_pair = - std::make_shared(std::move(stored_keypair)); - - initialized.emplace(std::move(key_pair)); - return initialized.value(); - } - - log->warn( - "Can not obtain a libp2p keypair from crypto storage. " - "A unique one will be generated"); - - kagome::crypto::Ed25519Keypair generated_keypair; - auto save = app_config.shouldSaveNodeKey(); - if (save) { - auto res = crypto_store.generateEd25519KeypairOnDisk( - crypto::KnownKeyTypeId::KEY_TYPE_LP2P); - if (res.has_error()) { - log->warn("Can't save libp2p keypair: {}", res.error()); - save = false; - } else { - generated_keypair = res.value(); - } - } - if (not save) { - generated_keypair = crypto_provider.generateKeypair(); - } - - auto key_pair = std::make_shared( - crypto::ed25519KeyToLibp2pKeypair(generated_keypair)); - - initialized.emplace(std::move(key_pair)); - return initialized.value(); - } - sptr get_kademlia_config( const application::ChainSpec &chain_spec, std::chrono::seconds random_wak_interval) { @@ -1108,7 +1023,8 @@ namespace { injector.template create(); auto &crypto_store = injector.template create(); - return get_peer_keypair(app_config, crypto_provider, crypto_store); + return injector::get_peer_keypair( + app_config, crypto_provider, crypto_store); })[boost::di::override], // bind io_context: 1 per injector @@ -1354,7 +1270,7 @@ namespace { auto &crypto_store = injector.template create(); auto &local_pair = - get_peer_keypair(config, crypto_provider, crypto_store); + injector::get_peer_keypair(config, crypto_provider, crypto_store); public_key = local_pair->publicKey; } else { diff --git a/core/injector/get_peer_keypair.hpp b/core/injector/get_peer_keypair.hpp new file mode 100644 index 0000000000..b5447c212e --- /dev/null +++ b/core/injector/get_peer_keypair.hpp @@ -0,0 +1,102 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef KAGOME_CORE_INJECTOR_GET_PEER_KEYPAIR_HPP +#define KAGOME_CORE_INJECTOR_GET_PEER_KEYPAIR_HPP + +#include "application/app_configuration.hpp" +#include "common/outcome_throw.hpp" +#include "crypto/crypto_store/crypto_store_impl.hpp" +#include "crypto/ed25519_provider.hpp" + +namespace kagome::injector { + inline const std::shared_ptr &get_peer_keypair( + const application::AppConfiguration &app_config, + const crypto::Ed25519Provider &crypto_provider, + crypto::CryptoStore &crypto_store) { + static auto initialized = + std::optional>(std::nullopt); + + if (initialized) { + return initialized.value(); + } + + auto log = log::createLogger("Injector", "injector"); + + if (app_config.nodeKey()) { + log->info("Will use LibP2P keypair from config or 'node-key' CLI arg"); + + auto provided_keypair = + crypto_provider.generateKeypair(app_config.nodeKey().value()); + BOOST_ASSERT(provided_keypair.secret_key == app_config.nodeKey().value()); + + auto key_pair = std::make_shared( + crypto::ed25519KeyToLibp2pKeypair(provided_keypair)); + + initialized.emplace(std::move(key_pair)); + return initialized.value(); + } + + if (app_config.nodeKeyFile()) { + const auto &path = app_config.nodeKeyFile().value(); + log->info( + "Will use LibP2P keypair from config or 'node-key-file' CLI arg"); + auto key = crypto_store.loadLibp2pKeypair(path); + if (key.has_error()) { + log->error("Unable to load user provided key from {}. Error: {}", + path, + key.error().message()); + common::raise(key.error()); + } else { + auto key_pair = + std::make_shared(std::move(key.value())); + initialized.emplace(std::move(key_pair)); + return initialized.value(); + } + } + + if (crypto_store.getLibp2pKeypair().has_value()) { + log->info( + "Will use LibP2P keypair from config or args (loading from base " + "path)"); + + auto stored_keypair = crypto_store.getLibp2pKeypair().value(); + + auto key_pair = + std::make_shared(std::move(stored_keypair)); + + initialized.emplace(std::move(key_pair)); + return initialized.value(); + } + + log->warn( + "Can not obtain a libp2p keypair from crypto storage. " + "A unique one will be generated"); + + kagome::crypto::Ed25519Keypair generated_keypair; + auto save = app_config.shouldSaveNodeKey(); + if (save) { + auto res = crypto_store.generateEd25519KeypairOnDisk( + crypto::KnownKeyTypeId::KEY_TYPE_LP2P); + if (res.has_error()) { + log->warn("Can't save libp2p keypair: {}", res.error()); + save = false; + } else { + generated_keypair = res.value(); + } + } + if (not save) { + generated_keypair = crypto_provider.generateKeypair(); + } + + auto key_pair = std::make_shared( + crypto::ed25519KeyToLibp2pKeypair(generated_keypair)); + + initialized.emplace(std::move(key_pair)); + return initialized.value(); + } +} // namespace kagome::injector + +#endif // KAGOME_CORE_INJECTOR_GET_PEER_KEYPAIR_HPP