From 97ef53f3089f0502699f5a0bd608c3c22dd64701 Mon Sep 17 00:00:00 2001 From: Boris <31869190+ErakhtinB@users.noreply.github.com> Date: Tue, 10 Dec 2024 19:26:41 +0500 Subject: [PATCH] 2299 feature request kagome node key generate util (#2308) --- core/application/CMakeLists.txt | 8 +++ .../impl/app_configuration_impl.cpp | 2 +- core/application/modes/key.hpp | 55 +++++++++++++++++++ core/application/modes/key_main.cpp | 41 ++++++++++++++ core/injector/CMakeLists.txt | 1 + core/injector/application_injector.cpp | 5 ++ core/injector/application_injector.hpp | 6 ++ node/CMakeLists.txt | 1 + node/main.cpp | 5 ++ 9 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 core/application/modes/key.hpp create mode 100644 core/application/modes/key_main.cpp diff --git a/core/application/CMakeLists.txt b/core/application/CMakeLists.txt index 85a3012494..772f55561c 100644 --- a/core/application/CMakeLists.txt +++ b/core/application/CMakeLists.txt @@ -83,6 +83,14 @@ target_link_libraries(recovery_mode logger ) +add_library(kagome_key + modes/key_main.cpp +) + +target_link_libraries(kagome_key + application_injector +) + add_library(kagome_application impl/kagome_application_impl.cpp ) diff --git a/core/application/impl/app_configuration_impl.cpp b/core/application/impl/app_configuration_impl.cpp index dd5deb2c0a..7e34615377 100644 --- a/core/application/impl/app_configuration_impl.cpp +++ b/core/application/impl/app_configuration_impl.cpp @@ -913,7 +913,7 @@ namespace kagome::application { if (vm.count("help") > 0) { std::cout - << "Available subcommands: storage-explorer db-editor benchmark\n"; + << "Available subcommands: storage-explorer db-editor benchmark key\n"; std::cout << desc << '\n'; return false; } diff --git a/core/application/modes/key.hpp b/core/application/modes/key.hpp new file mode 100644 index 0000000000..aab200c665 --- /dev/null +++ b/core/application/modes/key.hpp @@ -0,0 +1,55 @@ +/** + * Copyright Quadrivium LLC + * All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include +#include +#include "crypto/ed25519_provider.hpp" +#include "crypto/key_store.hpp" +#include "crypto/random_generator/boost_generator.hpp" + +namespace kagome::key { + + class Key { + public: + Key(std::shared_ptr ed_crypto_provider, + std::shared_ptr + key_marshaller) + : ed_crypto_provider_{std::move(ed_crypto_provider)}, + key_marshaller_{std::move(key_marshaller)} { + BOOST_ASSERT(ed_crypto_provider_ != nullptr); + BOOST_ASSERT(key_marshaller_ != nullptr); + } + + outcome::result run() { + auto random_generator = std::make_unique(); + OUTCOME_TRY( + seed, + crypto::Ed25519Seed::from(crypto::SecureCleanGuard{ + random_generator->randomBytes(crypto::Ed25519Seed::size())})); + OUTCOME_TRY(keypair, ed_crypto_provider_->generateKeypair(seed, {})); + const auto libp2p_key = crypto::ed25519KeyToLibp2pKeypair(keypair); + const libp2p::crypto::ProtobufKey protobuf_key{ + key_marshaller_->marshal(libp2p_key.publicKey).value()}; + auto peer_id = libp2p::peer::PeerId::fromPublicKey(protobuf_key); + if (not peer_id) { + return peer_id.error(); + } + std::cerr << peer_id.value().toBase58() << "\n"; + std::cout << kagome::common::hex_lower(keypair.secret_key.unsafeBytes()) + << "\n"; + + return outcome::success(); + } + + private: + std::shared_ptr ed_crypto_provider_; + std::shared_ptr key_marshaller_; + }; +} // namespace kagome::key diff --git a/core/application/modes/key_main.cpp b/core/application/modes/key_main.cpp new file mode 100644 index 0000000000..9cd385a550 --- /dev/null +++ b/core/application/modes/key_main.cpp @@ -0,0 +1,41 @@ +/** + * Copyright Quadrivium LLC + * All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + */ +#include "application/impl/app_configuration_impl.hpp" +#include "injector/application_injector.hpp" +#include "key.hpp" + +namespace kagome { + int key_main(int argc, const char **argv) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + const std::string_view key_command = argv[0]; + if (argc == 2) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + const std::string_view command = argv[1]; + if (command == "--generate-node-key") { + auto injector = std::make_unique( + std::make_shared()); + auto key = injector->injectKey(); + if (auto res = key->run(); not res) { + std::cerr << "Error: " << res.error().message() << "\n"; + return 2; + } + } else if (command == "--help") { + std::cerr << "Usage: " << key_command << " --generate-node-key" + << "\nGenerates a node key and prints the peer ID to stderr " + "and the secret key to stdout.\n"; + } else { + std::cerr << "Unknown command: " << command << "\n"; + std::cerr << "Usage: " << key_command << " --generate-node-key\n"; + return 3; + } + } else { + std::cerr << "Usage: " << key_command << " --generate-node-key\n"; + return 1; + } + return 0; + } + +} // namespace kagome diff --git a/core/injector/CMakeLists.txt b/core/injector/CMakeLists.txt index ee180e700b..924c0134fd 100644 --- a/core/injector/CMakeLists.txt +++ b/core/injector/CMakeLists.txt @@ -45,6 +45,7 @@ target_link_libraries(application_injector grandpa_api host_api_factory kagome_benchmarks + kagome_key log_configurator metadata_api metrics diff --git a/core/injector/application_injector.cpp b/core/injector/application_injector.cpp index b5c2ba0b57..5cd324eb08 100644 --- a/core/injector/application_injector.cpp +++ b/core/injector/application_injector.cpp @@ -50,6 +50,7 @@ #include "application/modes/precompile_wasm.hpp" #include "application/modes/print_chain_info_mode.hpp" #include "application/modes/recovery_mode.hpp" +#include "application/modes/key.hpp" #include "authority_discovery/publisher/address_publisher.hpp" #include "authority_discovery/query/audi_store_impl.hpp" #include "authority_discovery/query/query_impl.hpp" @@ -1119,6 +1120,10 @@ namespace kagome::injector { .template create>(); } + std::shared_ptr KagomeNodeInjector::injectKey() { + return pimpl_->injector_.template create>(); + } + std::shared_ptr KagomeNodeInjector::injectWatchdog() { return pimpl_->injector_.template create>(); } diff --git a/core/injector/application_injector.hpp b/core/injector/application_injector.hpp index ea68b4ebfe..efa9b1fcca 100644 --- a/core/injector/application_injector.hpp +++ b/core/injector/application_injector.hpp @@ -31,6 +31,7 @@ namespace kagome { class PrecompileWasmMode; class RecoveryMode; class BenchmarkMode; + class Key; } // namespace application::mode namespace authority_discovery { @@ -104,6 +105,10 @@ namespace kagome { class TelemetryService; } + namespace key { + class Key; + } + class Watchdog; } // namespace kagome @@ -163,6 +168,7 @@ namespace kagome::injector { injectPrecompileWasmMode(); std::shared_ptr injectRecoveryMode(); std::shared_ptr injectBlockBenchmark(); + std::shared_ptr injectKey(); protected: std::shared_ptr pimpl_; diff --git a/node/CMakeLists.txt b/node/CMakeLists.txt index 1ad9c128a1..1a0bf7c33c 100644 --- a/node/CMakeLists.txt +++ b/node/CMakeLists.txt @@ -32,6 +32,7 @@ target_link_libraries(kagome kagome-db-editor storage_explorer filesystem + kagome_key ) if (BACKWARD) add_backward(kagome) diff --git a/node/main.cpp b/node/main.cpp index 8fe1385b6b..f6492370f9 100644 --- a/node/main.cpp +++ b/node/main.cpp @@ -35,6 +35,7 @@ int db_editor_main(int argc, const char **argv); namespace kagome { int benchmark_main(int argc, const char **argv); + int key_main(int argc, const char **argv); } namespace { @@ -184,6 +185,10 @@ int main(int argc, const char **argv, const char **env) { exit_code = kagome::benchmark_main(argc - 1, argv + 1); } + else if (name == "key") { + exit_code = kagome::key_main(argc - 1, argv + 1); + } + else if (name.substr(0, 1) == "-") { // The first argument isn't subcommand, run as node exit_code = run_node(argc, argv);