From b00e1027b2d67b7fb1ea2024fb7e1dc918064a09 Mon Sep 17 00:00:00 2001 From: Dmitry Murzin Date: Tue, 7 May 2024 09:43:37 +0300 Subject: [PATCH] refactor!: Use multihash format for private keys (#4541) Signed-off-by: Dmitry Murzin --- client/src/config.rs | 2 +- config/iroha_test_config.toml | 4 +- config/src/parameters/user.rs | 116 +----- config/src/parameters/user/boilerplate.rs | 5 +- config/tests/fixtures.rs | 4 +- config/tests/fixtures/absolute_paths.toml | 2 +- .../tests/fixtures/bad.multiple_bad_envs.env | 5 +- config/tests/fixtures/base.toml | 5 +- config/tests/fixtures/full.env | 6 +- config/tests/fixtures/full.toml | 4 +- .../tests/fixtures/inconsistent_genesis.toml | 3 +- .../fixtures/minimal_alone_with_genesis.toml | 3 +- .../tests/fixtures/minimal_file_and_env.toml | 3 +- configs/client.template.toml | 2 +- configs/peer.template.toml | 2 +- configs/swarm/client.toml | 2 +- configs/swarm/docker-compose.local.yml | 15 +- configs/swarm/docker-compose.single.yml | 6 +- configs/swarm/docker-compose.yml | 15 +- configs/swarm/executor.wasm | Bin 526781 -> 526638 bytes crypto/src/lib.rs | 124 +++--- crypto/src/multihash.rs | 365 ++++++++---------- tools/kagami/src/crypto.rs | 6 +- tools/swarm/src/compose.rs | 59 +-- 24 files changed, 275 insertions(+), 483 deletions(-) diff --git a/client/src/config.rs b/client/src/config.rs index 72bb909d8c7..e93b119a43b 100644 --- a/client/src/config.rs +++ b/client/src/config.rs @@ -111,7 +111,7 @@ mod tests { [account] id = "alice@wonderland" public_key = "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" - private_key = { algorithm = "ed25519", payload = "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0" } + private_key = "8026409AC47ABF59B356E0BD7DCBBBB4DEC080E302156A48CA907E47CB6AEA1D32719E7233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" [transaction] time_to_live = 100_000 diff --git a/config/iroha_test_config.toml b/config/iroha_test_config.toml index ae71d8b8223..5279f76639c 100644 --- a/config/iroha_test_config.toml +++ b/config/iroha_test_config.toml @@ -1,6 +1,6 @@ chain_id = "00000000-0000-0000-0000-000000000000" public_key = "ed01201C61FAF8FE94E253B93114240394F79A607B7FA55F9E5A41EBEC74B88055768B" -private_key = { algorithm = "ed25519", payload = "282ED9F3CF92811C3818DBC4AE594ED59DC1A2F78E4241E31924E101D6B1FB831C61FAF8FE94E253B93114240394F79A607B7FA55F9E5A41EBEC74B88055768B" } +private_key = "802640282ED9F3CF92811C3818DBC4AE594ED59DC1A2F78E4241E31924E101D6B1FB831C61FAF8FE94E253B93114240394F79A607B7FA55F9E5A41EBEC74B88055768B" [network] address = "127.0.0.1:1337" @@ -8,7 +8,7 @@ address = "127.0.0.1:1337" [genesis] public_key = "ed01204CFFD0EE429B1BDD36B3910EC570852B8BB63F18750341772FB46BC856C5CAAF" file = "./genesis.json" -private_key = { algorithm = "ed25519", payload = "D748E18CE60CB30DEA3E73C9019B7AF45A8D465E3D71BCC9A5EF99A008205E534CFFD0EE429B1BDD36B3910EC570852B8BB63F18750341772FB46BC856C5CAAF" } +private_key = "802640D748E18CE60CB30DEA3E73C9019B7AF45A8D465E3D71BCC9A5EF99A008205E534CFFD0EE429B1BDD36B3910EC570852B8BB63F18750341772FB46BC856C5CAAF" [torii] address = "127.0.0.1:8080" diff --git a/config/src/parameters/user.rs b/config/src/parameters/user.rs index 35774e882a6..1a3c66f2026 100644 --- a/config/src/parameters/user.rs +++ b/config/src/parameters/user.rs @@ -10,7 +10,6 @@ #![allow(missing_docs)] use std::{ - error::Error, fmt::Debug, fs::File, io::Read, @@ -21,7 +20,7 @@ use std::{ pub use boilerplate::*; use eyre::{eyre, Report, WrapErr}; -use iroha_config_base::{Emitter, ErrorsCollection, HumanBytes, Merge, ParseEnvResult, ReadEnv}; +use iroha_config_base::{Emitter, ErrorsCollection, HumanBytes, Merge}; use iroha_crypto::{KeyPair, PrivateKey, PublicKey}; use iroha_data_model::{ metadata::Limits as MetadataLimits, peer::PeerId, transaction::TransactionLimits, ChainId, @@ -279,71 +278,6 @@ pub struct CliContext { pub submit_genesis: bool, } -pub(crate) fn private_key_from_env( - emitter: &mut Emitter, - env: &impl ReadEnv, - env_key_base: impl AsRef, - name_base: impl AsRef, -) -> ParseEnvResult { - let alg_env = format!("{}_ALGORITHM", env_key_base.as_ref()); - let alg_name = format!("{}.algorithm", name_base.as_ref()); - let payload_env = format!("{}_PAYLOAD", env_key_base.as_ref()); - let payload_name = format!("{}.payload", name_base.as_ref()); - - let algorithm = ParseEnvResult::parse_simple(emitter, env, &alg_env, &alg_name); - - // FIXME: errors handling is a mess - let payload = match env - .read_env(&payload_env) - .map_err(|err| eyre!("failed to read {payload_name}: {err}")) - .wrap_err("oops") - { - Ok(Some(value)) => ParseEnvResult::Value(value), - Ok(None) => ParseEnvResult::None, - Err(err) => { - emitter.emit(err); - ParseEnvResult::Error - } - }; - - match (algorithm, payload) { - (ParseEnvResult::Value(algorithm), ParseEnvResult::Value(payload)) => { - match PrivateKey::from_hex(algorithm, payload).wrap_err_with(|| { - eyre!( - "failed to construct `{}` from `{}` and `{}` environment variables", - name_base.as_ref(), - &alg_env, - &payload_env - ) - }) { - Ok(value) => return ParseEnvResult::Value(value), - Err(report) => { - emitter.emit(report); - } - } - } - (ParseEnvResult::None, ParseEnvResult::None) => return ParseEnvResult::None, - (ParseEnvResult::Value(_), ParseEnvResult::None) => emitter.emit(eyre!( - "`{}` env was provided, but `{}` was not", - &alg_env, - &payload_env - )), - (ParseEnvResult::None, ParseEnvResult::Value(_)) => { - emitter.emit(eyre!( - "`{}` env was provided, but `{}` was not", - &payload_env, - &alg_env - )); - } - (ParseEnvResult::Error, _) | (_, ParseEnvResult::Error) => { - // emitter already has these errors - // adding this branch for exhaustiveness - } - } - - ParseEnvResult::Error -} - #[derive(Debug)] pub struct Genesis { pub public_key: PublicKey, @@ -667,8 +601,7 @@ mod tests { #[test] fn parses_private_key_from_env() { let env = TestEnv::new() - .set("PRIVATE_KEY_ALGORITHM", "ed25519") - .set("PRIVATE_KEY_PAYLOAD", "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb"); + .set("PRIVATE_KEY", "8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB"); let private_key = RootPartial::from_env(&env) .expect("input is valid, should not fail") @@ -682,52 +615,15 @@ mod tests { } #[test] - fn fails_to_parse_private_key_in_env_without_payload() { - let env = TestEnv::new().set("PRIVATE_KEY_ALGORITHM", "ed25519"); - let error = - RootPartial::from_env(&env).expect_err("private key is incomplete, should fail"); - let expected = expect_test::expect![ - "`PRIVATE_KEY_ALGORITHM` env was provided, but `PRIVATE_KEY_PAYLOAD` was not" - ]; - expected.assert_eq(&format!("{error:#}")); - } - - #[test] - fn fails_to_parse_private_key_in_env_without_algorithm() { - let env = TestEnv::new().set("PRIVATE_KEY_PAYLOAD", "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb"); - let error = - RootPartial::from_env(&env).expect_err("private key is incomplete, should fail"); + fn fails_to_parse_private_key_from_env_with_invalid_value() { + let env = TestEnv::new().set("PRIVATE_KEY", "foo"); + let error = RootPartial::from_env(&env).expect_err("input is invalid, should fail"); let expected = expect_test::expect![ - "`PRIVATE_KEY_PAYLOAD` env was provided, but `PRIVATE_KEY_ALGORITHM` was not" + "failed to parse `iroha.private_key` field from `PRIVATE_KEY` env variable" ]; expected.assert_eq(&format!("{error:#}")); } - #[test] - fn fails_to_parse_private_key_from_env_with_invalid_payload() { - let env = TestEnv::new() - .set("PRIVATE_KEY_ALGORITHM", "ed25519") - .set("PRIVATE_KEY_PAYLOAD", "foo"); - - let error = RootPartial::from_env(&env).expect_err("input is invalid, should fail"); - - let expected = expect_test::expect!["failed to construct `iroha.private_key` from `PRIVATE_KEY_ALGORITHM` and `PRIVATE_KEY_PAYLOAD` environment variables"]; - expected.assert_eq(&format!("{error:#}")); - } - - #[test] - fn when_payload_provided_but_alg_is_invalid() { - let env = TestEnv::new() - .set("PRIVATE_KEY_ALGORITHM", "foo") - .set("PRIVATE_KEY_PAYLOAD", "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb"); - - let error = RootPartial::from_env(&env).expect_err("input is invalid, should fail"); - - // TODO: print the bad value and supported ones - let expected = expect_test::expect!["failed to parse `iroha.private_key.algorithm` field from `PRIVATE_KEY_ALGORITHM` env variable"]; - expected.assert_eq(&format!("{error:#}")); - } - #[test] fn deserialize_empty_input_works() { let _layer: RootPartial = toml::from_str("").unwrap(); diff --git a/config/src/parameters/user/boilerplate.rs b/config/src/parameters/user/boilerplate.rs index 07ef9aa4a16..51492e53d0c 100644 --- a/config/src/parameters/user/boilerplate.rs +++ b/config/src/parameters/user/boilerplate.rs @@ -30,7 +30,6 @@ use crate::{ logger::Format, parameters::{ defaults::{self, chain_wide::*, network::*, queue::*, torii::*}, - user, user::{ ChainWide, DevTelemetry, Genesis, Kura, KuraDebug, Logger, Network, Queue, Root, Snapshot, Sumeragi, SumeragiDebug, Telemetry, Torii, @@ -148,7 +147,7 @@ impl FromEnv for RootPartial { ParseEnvResult::parse_simple(&mut emitter, env, "PUBLIC_KEY", "iroha.public_key") .into(); let private_key = - user::private_key_from_env(&mut emitter, env, "PRIVATE_KEY", "iroha.private_key") + ParseEnvResult::parse_simple(&mut emitter, env, "PRIVATE_KEY", "iroha.private_key") .into(); let genesis = emitter.try_from_env(env); @@ -227,7 +226,7 @@ impl FromEnv for GenesisPartial { "genesis.public_key", ) .into(); - let private_key = user::private_key_from_env( + let private_key = ParseEnvResult::parse_simple( &mut emitter, env, "GENESIS_PRIVATE_KEY", diff --git a/config/tests/fixtures.rs b/config/tests/fixtures.rs index e88b2fdf155..e210b3946a9 100644 --- a/config/tests/fixtures.rs +++ b/config/tests/fixtures.rs @@ -444,8 +444,8 @@ fn multiple_env_parsing_errors() { let error = RootPartial::from_env(&env).expect_err("the input from env is invalid"); let expected = expect_test::expect![[r#" - `PRIVATE_KEY_PAYLOAD` env was provided, but `PRIVATE_KEY_ALGORITHM` was not - failed to parse `genesis.private_key.algorithm` field from `GENESIS_PRIVATE_KEY_ALGORITHM` env variable + failed to parse `iroha.private_key` field from `PRIVATE_KEY` env variable + failed to parse `genesis.private_key` field from `GENESIS_PRIVATE_KEY` env variable failed to parse `kura.debug.output_new_blocks` field from `KURA_DEBUG_OUTPUT_NEW_BLOCKS` env variable failed to parse `logger.format` field from `LOG_FORMAT` env variable failed to parse `torii.address` field from `API_ADDRESS` env variable"#]]; diff --git a/config/tests/fixtures/absolute_paths.toml b/config/tests/fixtures/absolute_paths.toml index 7a5a043a4d0..39430f39e5d 100644 --- a/config/tests/fixtures/absolute_paths.toml +++ b/config/tests/fixtures/absolute_paths.toml @@ -11,4 +11,4 @@ out_file = "/telemetry/file.json" [genesis] file = "/oh/my/genesis.json" -private_key = { algorithm = "ed25519", payload = "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb" } \ No newline at end of file +private_key = "8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" diff --git a/config/tests/fixtures/bad.multiple_bad_envs.env b/config/tests/fixtures/bad.multiple_bad_envs.env index 8e665fb38e4..9d390b8cd00 100644 --- a/config/tests/fixtures/bad.multiple_bad_envs.env +++ b/config/tests/fixtures/bad.multiple_bad_envs.env @@ -1,6 +1,5 @@ -PRIVATE_KEY_PAYLOAD=8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb -GENESIS_PRIVATE_KEY_ALGORITHM=BAD BAD BAD -GENESIS_PRIVATE_KEY_PAYLOAD=8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb +PRIVATE_KEY=BAD BAD BAD +GENESIS_PRIVATE_KEY=BAD BAD BAD API_ADDRESS=BAD BAD BAD KURA_DEBUG_OUTPUT_NEW_BLOCKS=TrueЪ LOG_FORMAT=what format? diff --git a/config/tests/fixtures/base.toml b/config/tests/fixtures/base.toml index 052b9a6df5b..201c8b56299 100644 --- a/config/tests/fixtures/base.toml +++ b/config/tests/fixtures/base.toml @@ -1,7 +1,6 @@ chain_id = "0" public_key = "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" -private_key.algorithm = "ed25519" -private_key.payload = "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb" +private_key = "8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" [network] address = "127.0.0.1:1337" @@ -10,4 +9,4 @@ address = "127.0.0.1:1337" public_key = "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" [torii] -address = "127.0.0.1:8080" \ No newline at end of file +address = "127.0.0.1:8080" diff --git a/config/tests/fixtures/full.env b/config/tests/fixtures/full.env index 35b61e9e5f7..ea6e3bf5956 100644 --- a/config/tests/fixtures/full.env +++ b/config/tests/fixtures/full.env @@ -1,11 +1,9 @@ CHAIN_ID=0-0 PUBLIC_KEY=ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB -PRIVATE_KEY_ALGORITHM=ed25519 -PRIVATE_KEY_PAYLOAD=8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb +PRIVATE_KEY=8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB P2P_ADDRESS=127.0.0.1:5432 GENESIS_PUBLIC_KEY=ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB -GENESIS_PRIVATE_KEY_ALGORITHM=ed25519 -GENESIS_PRIVATE_KEY_PAYLOAD=8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb +GENESIS_PRIVATE_KEY=8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB API_ADDRESS=127.0.0.1:8080 KURA_INIT_MODE=strict KURA_STORE_DIR=/store/path/from/env diff --git a/config/tests/fixtures/full.toml b/config/tests/fixtures/full.toml index aae107333d0..663ab418099 100644 --- a/config/tests/fixtures/full.toml +++ b/config/tests/fixtures/full.toml @@ -2,12 +2,12 @@ chain_id = "0" public_key = "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" -private_key = { algorithm = "ed25519", payload = "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb" } +private_key = "8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" [genesis] file = "genesis.json" public_key = "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" -private_key = { algorithm = "ed25519", payload = "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb" } +private_key = "8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" [network] address = "localhost:3840" diff --git a/config/tests/fixtures/inconsistent_genesis.toml b/config/tests/fixtures/inconsistent_genesis.toml index 6aabaa5e05f..0606e1ff90f 100644 --- a/config/tests/fixtures/inconsistent_genesis.toml +++ b/config/tests/fixtures/inconsistent_genesis.toml @@ -1,7 +1,6 @@ extends = "base.toml" [genesis] -private_key.algorithm = "ed25519" -private_key.payload = "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb" +private_key = "8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" # should fail without it: # file = ... diff --git a/config/tests/fixtures/minimal_alone_with_genesis.toml b/config/tests/fixtures/minimal_alone_with_genesis.toml index 3dd6c5f3c2c..a0e4916f611 100644 --- a/config/tests/fixtures/minimal_alone_with_genesis.toml +++ b/config/tests/fixtures/minimal_alone_with_genesis.toml @@ -2,5 +2,4 @@ extends = "base.toml" [genesis] file = "./empty_ok_genesis.json" -private_key.algorithm = "ed25519" -private_key.payload = "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb" +private_key = "8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" diff --git a/config/tests/fixtures/minimal_file_and_env.toml b/config/tests/fixtures/minimal_file_and_env.toml index 1cb37d5e2a6..91143ba49d9 100644 --- a/config/tests/fixtures/minimal_file_and_env.toml +++ b/config/tests/fixtures/minimal_file_and_env.toml @@ -2,8 +2,7 @@ extends = "base_trusted_peers.toml" chain_id = "0" public_key = "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" -private_key.algorithm = "ed25519" -private_key.payload = "8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb" +private_key = "8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" [network] address = "127.0.0.1:1337" diff --git a/configs/client.template.toml b/configs/client.template.toml index 3bad84abcc5..7322b788374 100644 --- a/configs/client.template.toml +++ b/configs/client.template.toml @@ -10,7 +10,7 @@ [account] # id = # public_key = -# private_key = { algorithm = "", payload = "" } +# private_key = [transaction] # time_to_live = "100s" diff --git a/configs/peer.template.toml b/configs/peer.template.toml index cce2aab5990..cce389bf000 100644 --- a/configs/peer.template.toml +++ b/configs/peer.template.toml @@ -16,7 +16,7 @@ [genesis] # file = # public_key = -# private_key = { algorithm = "", payload = "" } +# private_key = [network] # address = diff --git a/configs/swarm/client.toml b/configs/swarm/client.toml index 55eed0b2f4a..750be32505b 100644 --- a/configs/swarm/client.toml +++ b/configs/swarm/client.toml @@ -8,4 +8,4 @@ password = "ilovetea" [account] id = "alice@wonderland" public_key = "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" -private_key = { algorithm = "ed25519", payload = "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0" } +private_key = "8026409AC47ABF59B356E0BD7DCBBBB4DEC080E302156A48CA907E47CB6AEA1D32719E7233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0" diff --git a/configs/swarm/docker-compose.local.yml b/configs/swarm/docker-compose.local.yml index b0e560b17a6..30714875c45 100644 --- a/configs/swarm/docker-compose.local.yml +++ b/configs/swarm/docker-compose.local.yml @@ -9,13 +9,11 @@ services: environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb + PRIVATE_KEY: 8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - GENESIS_PRIVATE_KEY_ALGORITHM: ed25519 - GENESIS_PRIVATE_KEY_PAYLOAD: 82b3bde54aebeca4146257da0de8d59d8e46d5fe34887dcd8072866792fcb3ad4164bf554923ece1fd412d241036d863a6ae430476c898248b8237d77534cfc4 + GENESIS_PRIVATE_KEY: 80264082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD4164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 GENESIS_FILE: /config/genesis.json SUMERAGI_TRUSTED_PEERS: '[{"address":"iroha1:1338","public_key":"ed0120815BBDC9775D28C3633269B25F22D048E2AA2E36017CBE5AD85F15220BEB6F6F"},{"address":"iroha3:1340","public_key":"ed0120A66522370D60B9C09E79ADE2E9BB1EF2E78733A944B999B3A6AEE687CE476D61"},{"address":"iroha2:1339","public_key":"ed0120F417E0371E6ADB32FD66749477402B1AB67F84A8E9B082E997980CC91F327736"}]' ports: @@ -37,8 +35,7 @@ services: environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120815BBDC9775D28C3633269B25F22D048E2AA2E36017CBE5AD85F15220BEB6F6F - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: c02ffad5e455e7ec620d74de5769681e4d8385906bce5a437eb67452a9efbbc2815bbdc9775d28c3633269b25f22d048e2aa2e36017cbe5ad85f15220beb6f6f + PRIVATE_KEY: 802640C02FFAD5E455E7EC620D74DE5769681E4D8385906BCE5A437EB67452A9EFBBC2815BBDC9775D28C3633269B25F22D048E2AA2E36017CBE5AD85F15220BEB6F6F P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 @@ -61,8 +58,7 @@ services: environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120F417E0371E6ADB32FD66749477402B1AB67F84A8E9B082E997980CC91F327736 - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 29c5ed1409cb10fd791bc4ff8a6cb5e22a5fae7e36f448ef3ea2988b1319a88bf417e0371e6adb32fd66749477402b1ab67f84a8e9b082e997980cc91f327736 + PRIVATE_KEY: 80264029C5ED1409CB10FD791BC4FF8A6CB5E22A5FAE7E36F448EF3EA2988B1319A88BF417E0371E6ADB32FD66749477402B1AB67F84A8E9B082E997980CC91F327736 P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 @@ -85,8 +81,7 @@ services: environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120A66522370D60B9C09E79ADE2E9BB1EF2E78733A944B999B3A6AEE687CE476D61 - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 5eed4855fad183c451aac39dfc50831607e4cf408c98e2b977f3ce4a2df42ce2a66522370d60b9c09e79ade2e9bb1ef2e78733a944b999b3a6aee687ce476d61 + PRIVATE_KEY: 8026405EED4855FAD183C451AAC39DFC50831607E4CF408C98E2B977F3CE4A2DF42CE2A66522370D60B9C09E79ADE2E9BB1EF2E78733A944B999B3A6AEE687CE476D61 P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 diff --git a/configs/swarm/docker-compose.single.yml b/configs/swarm/docker-compose.single.yml index 03fb880fcea..8d307182477 100644 --- a/configs/swarm/docker-compose.single.yml +++ b/configs/swarm/docker-compose.single.yml @@ -9,13 +9,11 @@ services: environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb + PRIVATE_KEY: 8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - GENESIS_PRIVATE_KEY_ALGORITHM: ed25519 - GENESIS_PRIVATE_KEY_PAYLOAD: 82b3bde54aebeca4146257da0de8d59d8e46d5fe34887dcd8072866792fcb3ad4164bf554923ece1fd412d241036d863a6ae430476c898248b8237d77534cfc4 + GENESIS_PRIVATE_KEY: 80264082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD4164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 GENESIS_FILE: /config/genesis.json ports: - 1337:1337 diff --git a/configs/swarm/docker-compose.yml b/configs/swarm/docker-compose.yml index 6d13b8b9faa..241bbe16970 100644 --- a/configs/swarm/docker-compose.yml +++ b/configs/swarm/docker-compose.yml @@ -9,13 +9,11 @@ services: environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 8f4c15e5d664da3f13778801d23d4e89b76e94c1b94b389544168b6cb894f84f8ba62848cf767d72e7f7f4b9d2d7ba07fee33760f79abe5597a51520e292a0cb + PRIVATE_KEY: 8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - GENESIS_PRIVATE_KEY_ALGORITHM: ed25519 - GENESIS_PRIVATE_KEY_PAYLOAD: 82b3bde54aebeca4146257da0de8d59d8e46d5fe34887dcd8072866792fcb3ad4164bf554923ece1fd412d241036d863a6ae430476c898248b8237d77534cfc4 + GENESIS_PRIVATE_KEY: 80264082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD4164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 GENESIS_FILE: /config/genesis.json SUMERAGI_TRUSTED_PEERS: '[{"address":"iroha1:1338","public_key":"ed0120815BBDC9775D28C3633269B25F22D048E2AA2E36017CBE5AD85F15220BEB6F6F"},{"address":"iroha3:1340","public_key":"ed0120A66522370D60B9C09E79ADE2E9BB1EF2E78733A944B999B3A6AEE687CE476D61"},{"address":"iroha2:1339","public_key":"ed0120F417E0371E6ADB32FD66749477402B1AB67F84A8E9B082E997980CC91F327736"}]' ports: @@ -37,8 +35,7 @@ services: environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120815BBDC9775D28C3633269B25F22D048E2AA2E36017CBE5AD85F15220BEB6F6F - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: c02ffad5e455e7ec620d74de5769681e4d8385906bce5a437eb67452a9efbbc2815bbdc9775d28c3633269b25f22d048e2aa2e36017cbe5ad85f15220beb6f6f + PRIVATE_KEY: 802640C02FFAD5E455E7EC620D74DE5769681E4D8385906BCE5A437EB67452A9EFBBC2815BBDC9775D28C3633269B25F22D048E2AA2E36017CBE5AD85F15220BEB6F6F P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 @@ -61,8 +58,7 @@ services: environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120F417E0371E6ADB32FD66749477402B1AB67F84A8E9B082E997980CC91F327736 - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 29c5ed1409cb10fd791bc4ff8a6cb5e22a5fae7e36f448ef3ea2988b1319a88bf417e0371e6adb32fd66749477402b1ab67f84a8e9b082e997980cc91f327736 + PRIVATE_KEY: 80264029C5ED1409CB10FD791BC4FF8A6CB5E22A5FAE7E36F448EF3EA2988B1319A88BF417E0371E6ADB32FD66749477402B1AB67F84A8E9B082E997980CC91F327736 P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 @@ -85,8 +81,7 @@ services: environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120A66522370D60B9C09E79ADE2E9BB1EF2E78733A944B999B3A6AEE687CE476D61 - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 5eed4855fad183c451aac39dfc50831607e4cf408c98e2b977f3ce4a2df42ce2a66522370d60b9c09e79ade2e9bb1ef2e78733a944b999b3a6aee687ce476d61 + PRIVATE_KEY: 8026405EED4855FAD183C451AAC39DFC50831607E4CF408C98E2B977F3CE4A2DF42CE2A66522370D60B9C09E79ADE2E9BB1EF2E78733A944B999B3A6AEE687CE476D61 P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm index 55348c7b4cb483198f8426b9cce3bddb0050e6f1..9a8965b42ffac44c5e47cf11d88a9702c48963e0 100644 GIT binary patch delta 76608 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�_WlorMm! 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 delta 76711 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�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 Result { let bytes = hex_decode(key)?; - multihash::Multihash::try_from(bytes).map(Into::into) + let (algorithm, payload) = multihash::decode_public_key(&bytes)?; + PublicKey::from_bytes(algorithm, &payload).map(|key| *key.0) } } #[cfg(not(feature = "ffi_import"))] impl PublicKeyInner { fn normalize(&self) -> String { - let multihash: &multihash::Multihash = &self.clone().into(); - let bytes = Vec::try_from(multihash).expect("Failed to convert multihash to bytes."); + let (algorithm, payload) = self.to_raw(); + let bytes = multihash::encode_public_key(algorithm, &payload) + .expect("Failed to convert multihash to bytes."); - let mut bytes_iter = bytes.into_iter(); - let fn_code = hex::encode(bytes_iter.by_ref().take(2).collect::>()); - let dig_size = hex::encode(bytes_iter.by_ref().take(1).collect::>()); - let key = hex::encode_upper(bytes_iter.by_ref().collect::>()); - - format!("{fn_code}{dig_size}{key}") + multihash::multihash_to_hex_string(&bytes) } } @@ -595,10 +592,9 @@ enum PrivateKeyInner { ffi::ffi_item! { /// Private Key used in signatures. - #[derive(Clone, Deserialize)] + #[derive(Clone, DeserializeFromStr)] #[cfg_attr(all(feature = "ffi_export", not(feature = "ffi_import")), ffi_type(opaque))] #[allow(missing_docs, variant_size_differences)] - #[serde(try_from = "PrivateKeySerialized")] pub struct PrivateKey(Box>); } @@ -690,6 +686,16 @@ impl PrivateKey { } } +impl FromStr for PrivateKey { + type Err = ParseError; + + fn from_str(key: &str) -> Result { + let bytes = hex_decode(key)?; + let (algorithm, payload) = multihash::decode_private_key(&bytes)?; + PrivateKey::from_bytes(algorithm, &payload) + } +} + impl ZeroizeOnDrop for PrivateKeyInner {} impl Drop for PrivateKeyInner { @@ -739,72 +745,44 @@ impl Serialize for PrivateKey { /// Use when you need to format/serialize private key (e.g in kagami) #[derive(Eq, PartialEq)] +#[cfg_attr( + not(feature = "ffi_import"), + derive(DeserializeFromStr, SerializeDisplay) +)] pub struct ExposedPrivateKey(pub PrivateKey); -#[cfg(not(feature = "ffi_import"))] -impl fmt::Debug for ExposedPrivateKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple(self.0.algorithm().as_static_str()) - .field(&hex::encode_upper(self.0.payload())) - .finish() - } -} - -#[cfg(not(feature = "ffi_import"))] -impl fmt::Display for ExposedPrivateKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&hex::encode_upper(self.0.payload())) - } -} - -impl Serialize for ExposedPrivateKey { - fn serialize(&self, serializer: S) -> Result { - let key_serialized: PrivateKeySerialized = self.0.clone().into(); - key_serialized.serialize(serializer) - } -} +impl FromStr for ExposedPrivateKey { + type Err = ParseError; -impl<'de> Deserialize<'de> for ExposedPrivateKey { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let key_serialized = PrivateKeySerialized::deserialize(deserializer)?; - let private_key = key_serialized - .try_into() - .map_err(serde::de::Error::custom)?; + fn from_str(key: &str) -> Result { + let private_key = PrivateKey::from_str(key)?; Ok(ExposedPrivateKey(private_key)) } } -#[serde_with::serde_as] -#[derive(Serialize, Deserialize)] -struct PrivateKeySerialized { - algorithm: Algorithm, - #[serde_as(as = "serde_with::hex::Hex")] - payload: Vec, -} - -impl TryFrom for PrivateKey { - type Error = ParseError; +impl ExposedPrivateKey { + fn normalize(&self) -> String { + let (algorithm, payload) = self.0.to_bytes(); + let bytes = multihash::encode_private_key(algorithm, &payload) + .expect("Failed to convert multihash to bytes."); - fn try_from(value: PrivateKeySerialized) -> Result { - Self::from_bytes(value.algorithm, &value.payload) + multihash::multihash_to_hex_string(&bytes) } } -impl From for PrivateKeySerialized { - fn from(value: PrivateKey) -> Self { - Self { - algorithm: value.algorithm(), - payload: value.payload(), - } +#[cfg(not(feature = "ffi_import"))] +impl fmt::Debug for ExposedPrivateKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple(self.0.algorithm().as_static_str()) + .field(&self.normalize()) + .finish() } } -impl Drop for PrivateKeySerialized { - fn drop(&mut self) { - self.payload.zeroize(); +#[cfg(not(feature = "ffi_import"))] +impl fmt::Display for ExposedPrivateKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.normalize()) } } @@ -1183,10 +1161,7 @@ mod tests { assert_test_json_serde!( json!({ "public_key": "ed01201509A611AD6D97B01D871E58ED00C8FD7C3917B6CA61A8C2833A19E000AAC2E4", - "private_key": { - "algorithm": "ed25519", - "payload": "3A7991AF1ABB77F3FD27CC148404A6AE4439D095A63591B77C788D53F708A02A1509A611AD6D97B01D871E58ED00C8FD7C3917B6CA61A8C2833A19E000AAC2E4" - } + "private_key": "8026403A7991AF1ABB77F3FD27CC148404A6AE4439D095A63591B77C788D53F708A02A1509A611AD6D97B01D871E58ED00C8FD7C3917B6CA61A8C2833A19E000AAC2E4" }), TestJson { public_key: PublicKey::from_hex( @@ -1207,10 +1182,7 @@ mod tests { assert_test_json_serde!( json!({ "public_key": "e701210312273E8810581E58948D3FB8F9E8AD53AAA21492EBB8703915BBB565A21B7FCC", - "private_key": { - "algorithm": "secp256k1", - "payload": "4DF4FCA10762D4B529FE40A2188A60CA4469D2C50A825B5F33ADC2CB78C69445" - } + "private_key": "8126204DF4FCA10762D4B529FE40A2188A60CA4469D2C50A825B5F33ADC2CB78C69445" }), TestJson { public_key: PublicKey::from_hex( @@ -1235,10 +1207,7 @@ mod tests { assert_test_json_serde!( json!({ "public_key": "ea01309060D021340617E9554CCBC2CF3CC3DB922A9BA323ABDF7C271FCC6EF69BE7A8DEBCA7D9E96C0F0089ABA22CDAADE4A2", - "private_key": { - "algorithm": "bls_normal", - "payload": "1CA347641228C3B79AA43839DEDC85FA51C0E8B9B6A00F6B0D6B0423E902973F" - } + "private_key": "8926201CA347641228C3B79AA43839DEDC85FA51C0E8B9B6A00F6B0D6B0423E902973F" }), TestJson { public_key: PublicKey::from_hex( @@ -1254,10 +1223,7 @@ mod tests { assert_test_json_serde!( json!({ "public_key": "eb01609051D4A9C69402423413EBBA4C00BC82A0102AA2B783057BD7BCEE4DD17B37DE5D719EE84BE43783F2AE47A673A74B8315DD3E595ED1FBDFAC17DA1D7A36F642B423ED18275FAFD671B1D331439D22F12FB6EB436A47E8656F182A78DF29D310", - "private_key": { - "algorithm": "bls_small", - "payload": "8CB95072914CDD8E4CF682FDBE1189CDF4FC54D445E760B3446F896DBDBF5B2B" - } + "private_key": "8a26208CB95072914CDD8E4CF682FDBE1189CDF4FC54D445E760B3446F896DBDBF5B2B" }), TestJson { public_key: PublicKey::from_hex( diff --git a/crypto/src/multihash.rs b/crypto/src/multihash.rs index 7e6dbdc81b0..747fd1b5c98 100644 --- a/crypto/src/multihash.rs +++ b/crypto/src/multihash.rs @@ -2,192 +2,170 @@ #[cfg(not(feature = "std"))] use alloc::{ + format, string::{String, ToString as _}, vec, vec::Vec, }; use derive_more::Display; -use iroha_primitives::const_vec::ConstVec; - -use crate::{varint, Algorithm, NoSuchAlgorithm, ParseError, PublicKey, PublicKeyInner}; - -/// ed25519 public string -pub const ED_25519_PUB_STR: &str = "ed25519-pub"; -/// secp256k1 public string -pub const SECP_256_K1_PUB_STR: &str = "secp256k1-pub"; -/// bls12 381 g1 public string -pub const BLS12_381_G1_PUB: &str = "bls12_381-g1-pub"; -/// bls12 381 g2 public string -pub const BLS12_381_G2_PUB: &str = "bls12_381-g2-pub"; - -/// Type of digest function. -/// The corresponding byte codes are taken from [official multihash table](https://github.com/multiformats/multicodec/blob/master/table.csv) -#[allow(clippy::enum_variant_names)] -#[repr(u64)] -#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Default)] -pub enum DigestFunction { - /// `Ed25519` - #[display(fmt = "{ED_25519_PUB_STR}")] - #[default] - Ed25519Pub = 0xed, - /// `Secp256k1` - #[display(fmt = "{SECP_256_K1_PUB_STR}")] - Secp256k1Pub = 0xe7, - /// `Bls12381G1` - #[display(fmt = "{BLS12_381_G1_PUB}")] - Bls12381G1Pub = 0xea, - /// `Bls12381G2` - #[display(fmt = "{BLS12_381_G2_PUB}")] - Bls12381G2Pub = 0xeb, -} -impl From for Algorithm { - fn from(f: DigestFunction) -> Self { - match f { - DigestFunction::Ed25519Pub => Self::Ed25519, - DigestFunction::Secp256k1Pub => Self::Secp256k1, - DigestFunction::Bls12381G1Pub => Self::BlsNormal, - DigestFunction::Bls12381G2Pub => Self::BlsSmall, - } - } +use crate::{varint, Algorithm, ParseError}; + +pub fn decode_public_key(bytes: &[u8]) -> Result<(Algorithm, Vec), ParseError> { + let (digest_function, payload) = decode_multihash(bytes)?; + let algorithm = digest_function_public::decode(digest_function)?; + Ok((algorithm, payload)) } -impl From for DigestFunction { - fn from(a: Algorithm) -> Self { - match a { - Algorithm::Ed25519 => Self::Ed25519Pub, - Algorithm::Secp256k1 => Self::Secp256k1Pub, - Algorithm::BlsNormal => Self::Bls12381G1Pub, - Algorithm::BlsSmall => Self::Bls12381G2Pub, - } - } +pub fn encode_public_key( + algorithm: Algorithm, + payload: &[u8], +) -> Result, MultihashConvertError> { + let digest_function = digest_function_public::encode(algorithm); + encode_multihash(digest_function, payload) } -impl core::str::FromStr for DigestFunction { - type Err = NoSuchAlgorithm; +pub fn decode_private_key(bytes: &[u8]) -> Result<(Algorithm, Vec), ParseError> { + let (digest_function, payload) = decode_multihash(bytes)?; + let algorithm = digest_function_private::decode(digest_function)?; + Ok((algorithm, payload)) +} - fn from_str(source: &str) -> Result { - match source { - ED_25519_PUB_STR => Ok(DigestFunction::Ed25519Pub), - SECP_256_K1_PUB_STR => Ok(DigestFunction::Secp256k1Pub), - BLS12_381_G1_PUB => Ok(DigestFunction::Bls12381G1Pub), - BLS12_381_G2_PUB => Ok(DigestFunction::Bls12381G2Pub), - _ => Err(Self::Err {}), - } - } +pub fn encode_private_key( + algorithm: Algorithm, + payload: &[u8], +) -> Result, MultihashConvertError> { + let digest_function = digest_function_private::encode(algorithm); + encode_multihash(digest_function, payload) } -impl TryFrom for DigestFunction { - type Error = NoSuchAlgorithm; - - fn try_from(variant: u64) -> Result { - match variant { - variant if variant == DigestFunction::Ed25519Pub as u64 => { - Ok(DigestFunction::Ed25519Pub) - } - variant if variant == DigestFunction::Secp256k1Pub as u64 => { - Ok(DigestFunction::Secp256k1Pub) - } - variant if variant == DigestFunction::Bls12381G1Pub as u64 => { - Ok(DigestFunction::Bls12381G1Pub) - } - variant if variant == DigestFunction::Bls12381G2Pub as u64 => { - Ok(DigestFunction::Bls12381G2Pub) - } - _ => Err(Self::Error {}), - } - } +pub fn multihash_to_hex_string(bytes: &[u8]) -> String { + let mut bytes_iter = bytes.iter().copied(); + let fn_code = hex::encode(bytes_iter.by_ref().take(2).collect::>()); + let dig_size = hex::encode(bytes_iter.by_ref().take(1).collect::>()); + let key = hex::encode_upper(bytes_iter.by_ref().collect::>()); + + format!("{fn_code}{dig_size}{key}") } -impl From for u64 { - fn from(digest_function: DigestFunction) -> Self { - digest_function as u64 +/// Value of byte code corresponding to algorithm. +/// See [official multihash table](https://github.com/multiformats/multicodec/blob/master/table.csv) +type DigestFunction = u64; + +mod digest_function_public { + #[cfg(not(feature = "std"))] + use alloc::string::String; + + use crate::{error::ParseError, multihash::DigestFunction, Algorithm}; + + const ED_25519: DigestFunction = 0xed; + const SECP_256_K1: DigestFunction = 0xe7; + const BLS12_381_G1: DigestFunction = 0xea; + const BLS12_381_G2: DigestFunction = 0xeb; + + pub fn decode(digest_function: DigestFunction) -> Result { + let algorithm = match digest_function { + ED_25519 => Algorithm::Ed25519, + SECP_256_K1 => Algorithm::Secp256k1, + BLS12_381_G1 => Algorithm::BlsNormal, + BLS12_381_G2 => Algorithm::BlsSmall, + _ => return Err(ParseError(String::from("No such algorithm"))), + }; + Ok(algorithm) } -} -/// Multihash. -/// -/// Offers a middleware representation of [`PublicKey`] which can be converted -/// to/from bytes or string. -#[derive(Debug, PartialEq, Eq)] -pub struct Multihash(PublicKeyInner); - -impl TryFrom> for Multihash { - type Error = ParseError; - - fn try_from(bytes: Vec) -> Result { - let idx = bytes - .iter() - .enumerate() - .find(|&(_, &byte)| (byte & 0b1000_0000) == 0) - .ok_or_else(|| { - ParseError(String::from( - "Failed to find last byte(byte smaller than 128)", - )) - })? - .0; - - let (digest_function, bytes) = bytes.split_at(idx + 1); - let mut bytes = bytes.iter().copied(); - - let digest_function: u64 = varint::VarUint::new(digest_function) - .map_err(|err| ParseError(err.to_string()))? - .try_into() - .map_err(|err: varint::ConvertError| ParseError(err.to_string()))?; - let digest_function = - DigestFunction::try_from(digest_function).map_err(|err| ParseError(err.to_string()))?; - let algorithm = Algorithm::from(digest_function); - - let digest_size = bytes - .next() - .ok_or_else(|| ParseError(String::from("Digest size not found")))?; - - let payload: Vec = bytes.collect(); - if payload.len() != digest_size as usize { - return Err(ParseError(String::from( - "Digest size not equal to actual length", - ))); + pub fn encode(algorithm: Algorithm) -> u64 { + match algorithm { + Algorithm::Ed25519 => ED_25519, + Algorithm::Secp256k1 => SECP_256_K1, + Algorithm::BlsNormal => BLS12_381_G1, + Algorithm::BlsSmall => BLS12_381_G2, } - let payload = ConstVec::new(payload); - - Ok(Self::from(*PublicKey::from_bytes(algorithm, &payload)?.0)) } } -impl TryFrom<&Multihash> for Vec { - type Error = MultihashConvertError; - - fn try_from(multihash: &Multihash) -> Result { - let mut bytes = vec![]; - - let (algorithm, payload) = multihash.0.to_raw(); - let digest_function: DigestFunction = algorithm.into(); - let digest_function: u64 = digest_function.into(); - let digest_function: varint::VarUint = digest_function.into(); - let mut digest_function = digest_function.into(); - bytes.append(&mut digest_function); - bytes.push(payload.len().try_into().map_err(|_e| { - MultihashConvertError::new(String::from("Digest size can't fit into u8")) - })?); - bytes.extend_from_slice(payload.as_ref()); +mod digest_function_private { + #[cfg(not(feature = "std"))] + use alloc::string::String; + + use crate::{error::ParseError, multihash::DigestFunction, Algorithm}; + + const ED_25519: DigestFunction = 0x1300; + const SECP_256_K1: DigestFunction = 0x1301; + const BLS12_381_G1: DigestFunction = 0x1309; + const BLS12_381_G2: DigestFunction = 0x130a; + + pub fn decode(digest_function: DigestFunction) -> Result { + let algorithm = match digest_function { + ED_25519 => Algorithm::Ed25519, + SECP_256_K1 => Algorithm::Secp256k1, + BLS12_381_G1 => Algorithm::BlsNormal, + BLS12_381_G2 => Algorithm::BlsSmall, + _ => return Err(ParseError(String::from("No such algorithm"))), + }; + Ok(algorithm) + } - Ok(bytes) + pub fn encode(algorithm: Algorithm) -> u64 { + match algorithm { + Algorithm::Ed25519 => ED_25519, + Algorithm::Secp256k1 => SECP_256_K1, + Algorithm::BlsNormal => BLS12_381_G1, + Algorithm::BlsSmall => BLS12_381_G2, + } } } -impl From for PublicKeyInner { - #[inline] - fn from(multihash: Multihash) -> Self { - multihash.0 +fn decode_multihash(bytes: &[u8]) -> Result<(DigestFunction, Vec), ParseError> { + let idx = bytes + .iter() + .enumerate() + .find(|&(_, &byte)| (byte & 0b1000_0000) == 0) + .ok_or_else(|| { + ParseError(String::from( + "Failed to find last byte(byte smaller than 128)", + )) + })? + .0; + + let (digest_function, bytes) = bytes.split_at(idx + 1); + let mut bytes = bytes.iter().copied(); + + let digest_function: u64 = varint::VarUint::new(digest_function) + .map_err(|err| ParseError(err.to_string()))? + .try_into() + .map_err(|err: varint::ConvertError| ParseError(err.to_string()))?; + + let digest_size = bytes + .next() + .ok_or_else(|| ParseError(String::from("Digest size not found")))?; + + let payload: Vec = bytes.collect(); + if payload.len() != digest_size as usize { + return Err(ParseError(String::from( + "Digest size not equal to actual length", + ))); } + Ok((digest_function, payload)) } -impl From for Multihash { - #[inline] - fn from(public_key: PublicKeyInner) -> Self { - Self(public_key) - } +fn encode_multihash( + digest_function: DigestFunction, + payload: &[u8], +) -> Result, MultihashConvertError> { + let mut bytes = vec![]; + + let digest_function: varint::VarUint = digest_function.into(); + let mut digest_function = digest_function.into(); + bytes.append(&mut digest_function); + bytes.push( + payload.len().try_into().map_err(|_e| { + MultihashConvertError::new(String::from("Digest size can't fit into u8")) + })?, + ); + bytes.extend_from_slice(payload.as_ref()); + Ok(bytes) } /// Error which occurs when converting to/from `Multihash` @@ -205,58 +183,55 @@ impl MultihashConvertError { #[cfg(feature = "std")] impl std::error::Error for MultihashConvertError {} -impl From for MultihashConvertError { - fn from(source: NoSuchAlgorithm) -> Self { - Self { - reason: source.to_string(), - } - } -} - #[cfg(test)] mod tests { use super::*; use crate::hex_decode; #[test] - fn multihash_to_bytes() { - let multihash = Multihash( - *PublicKey::from_bytes( - Algorithm::Ed25519, - &hex_decode("1509A611AD6D97B01D871E58ED00C8FD7C3917B6CA61A8C2833A19E000AAC2E4") - .unwrap(), - ) - .unwrap() - .0, - ); - let bytes = Vec::try_from(&multihash).expect("Failed to serialize multihash"); - assert_eq!( + fn test_encode_public_key() { + let algorithm = Algorithm::Ed25519; + let payload = + hex_decode("1509A611AD6D97B01D871E58ED00C8FD7C3917B6CA61A8C2833A19E000AAC2E4").unwrap(); + let multihash = hex_decode("ed01201509A611AD6D97B01D871E58ED00C8FD7C3917B6CA61A8C2833A19E000AAC2E4") - .unwrap(), - bytes - ); + .unwrap(); + assert_eq!(encode_public_key(algorithm, &payload).unwrap(), multihash); } #[test] - fn multihash_from_bytes() { - let multihash = Multihash( - *PublicKey::from_bytes( - Algorithm::Ed25519, - &hex_decode("1509A611AD6D97B01D871E58ED00C8FD7C3917B6CA61A8C2833A19E000AAC2E4") - .unwrap(), - ) - .unwrap() - .0, - ); - let bytes = + fn test_decode_public_key() { + let algorithm = Algorithm::Ed25519; + let payload = + hex_decode("1509A611AD6D97B01D871E58ED00C8FD7C3917B6CA61A8C2833A19E000AAC2E4").unwrap(); + let multihash = hex_decode("ed01201509A611AD6D97B01D871E58ED00C8FD7C3917B6CA61A8C2833A19E000AAC2E4") .unwrap(); - let multihash_decoded: Multihash = bytes.try_into().unwrap(); - assert_eq!(multihash, multihash_decoded); + assert_eq!(decode_public_key(&multihash).unwrap(), (algorithm, payload)); } #[test] - fn digest_function_display() { - assert_eq!(DigestFunction::Ed25519Pub.to_string(), ED_25519_PUB_STR); + fn test_encode_private_key() { + let algorithm = Algorithm::Ed25519; + let payload = + hex_decode("8F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB").unwrap(); + let multihash = + hex_decode("8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB") + .unwrap(); + assert_eq!(encode_private_key(algorithm, &payload).unwrap(), multihash); + } + + #[test] + fn test_decode_private_key() { + let algorithm = Algorithm::Ed25519; + let payload = + hex_decode("8F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB").unwrap(); + let multihash = + hex_decode("8026408F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F8BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB") + .unwrap(); + assert_eq!( + decode_private_key(&multihash).unwrap(), + (algorithm, payload) + ); } } diff --git a/tools/kagami/src/crypto.rs b/tools/kagami/src/crypto.rs index 7e7a86bb84e..405b4095539 100644 --- a/tools/kagami/src/crypto.rs +++ b/tools/kagami/src/crypto.rs @@ -72,7 +72,6 @@ impl RunArgs for Args { } else if compact { writeln!(writer, "{}", &key_pair.public_key())?; writeln!(writer, "{}", &exposed_private_key)?; - writeln!(writer, "{}", &key_pair.public_key().algorithm())?; } else { writeln!( writer, @@ -81,9 +80,8 @@ impl RunArgs for Args { )?; writeln!( writer, - "Private key ({}): \"{}\"", - &key_pair.public_key().algorithm(), - exposed_private_key + "Private key (multihash): \"{}\"", + &exposed_private_key )?; } Ok(()) diff --git a/tools/swarm/src/compose.rs b/tools/swarm/src/compose.rs index a33237f34b9..cb4a77d8368 100644 --- a/tools/swarm/src/compose.rs +++ b/tools/swarm/src/compose.rs @@ -8,7 +8,7 @@ use std::{ }; use color_eyre::eyre::{eyre, Context, ContextCompat}; -use iroha_crypto::{Algorithm, KeyPair, PrivateKey, PublicKey}; +use iroha_crypto::{Algorithm, ExposedPrivateKey, KeyPair, PrivateKey, PublicKey}; use iroha_data_model::{prelude::PeerId, ChainId}; use iroha_primitives::addr::{socket_addr, SocketAddr}; use peer_generator::Peer; @@ -298,15 +298,11 @@ pub enum ServiceSource { struct FullPeerEnv { chain_id: ChainId, public_key: PublicKey, - private_key_algorithm: Algorithm, - #[serde_as(as = "serde_with::hex::Hex")] - private_key_payload: Vec, + private_key: ExposedPrivateKey, p2p_address: SocketAddr, api_address: SocketAddr, genesis_public_key: PublicKey, - genesis_private_key_algorithm: Option, - #[serde_as(as = "Option")] - genesis_private_key_payload: Option>, + genesis_private_key: Option, genesis_file: Option, #[serde_as(as = "Option")] sumeragi_trusted_peers: Option>, @@ -325,30 +321,19 @@ struct CompactPeerEnv { impl From for FullPeerEnv { fn from(value: CompactPeerEnv) -> Self { - let (genesis_private_key_algorithm, genesis_private_key_payload, genesis_file) = value - .genesis_private_key - .map_or((None, None, None), |private_key| { - let (algorithm, payload) = private_key.to_bytes(); - ( - Some(algorithm), - Some(payload), - Some(PATH_TO_GENESIS.to_string()), - ) - }); - - let (private_key_algorithm, private_key_payload) = { - let (algorithm, payload) = value.key_pair.private_key().clone().to_bytes(); - (algorithm, payload) + let genesis_private_key = value.genesis_private_key.map(ExposedPrivateKey); + let genesis_file = if genesis_private_key.is_some() { + Some(PATH_TO_GENESIS.to_string()) + } else { + None }; Self { chain_id: value.chain_id, public_key: value.key_pair.public_key().clone(), - private_key_algorithm, - private_key_payload, + private_key: ExposedPrivateKey(value.key_pair.private_key().clone()), genesis_public_key: value.genesis_public_key, - genesis_private_key_algorithm, - genesis_private_key_payload, + genesis_private_key, genesis_file, p2p_address: value.p2p_addr, api_address: value.api_addr, @@ -690,13 +675,11 @@ mod tests { environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012039E5BF092186FACC358770792A493CA98A83740643A3D41389483CF334F748C8 - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: db9d90d20f969177bd5882f9fe211d14d1399d5440d04e3468783d169bbc4a8e39e5bf092186facc358770792a493ca98a83740643a3d41389483cf334f748c8 + PRIVATE_KEY: 802640DB9D90D20F969177BD5882F9FE211D14D1399D5440D04E3468783D169BBC4A8E39E5BF092186FACC358770792A493CA98A83740643A3D41389483CF334F748C8 P2P_ADDRESS: iroha1:1339 API_ADDRESS: iroha1:1338 GENESIS_PUBLIC_KEY: ed012039E5BF092186FACC358770792A493CA98A83740643A3D41389483CF334F748C8 - GENESIS_PRIVATE_KEY_ALGORITHM: ed25519 - GENESIS_PRIVATE_KEY_PAYLOAD: db9d90d20f969177bd5882f9fe211d14d1399d5440d04e3468783d169bbc4a8e39e5bf092186facc358770792a493ca98a83740643a3d41389483cf334f748c8 + GENESIS_PRIVATE_KEY: 802640DB9D90D20F969177BD5882F9FE211D14D1399D5440D04E3468783D169BBC4A8E39E5BF092186FACC358770792A493CA98A83740643A3D41389483CF334F748C8 GENESIS_FILE: /config/genesis.json ports: - 1337:1337 @@ -732,8 +715,7 @@ mod tests { let expected = expect_test::expect![[r#" CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120415388A90FA238196737746A70565D041CFB32EAA0C89FF8CB244C7F832A6EBD - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 6bf163fd75192b81a78cb20c5f8cb917f591ac6635f2577e6ca305c27a456a5d415388a90fa238196737746a70565d041cfb32eaa0c89ff8cb244c7f832a6ebd + PRIVATE_KEY: 8026406BF163FD75192B81A78CB20C5F8CB917F591AC6635F2577E6CA305C27A456A5D415388A90FA238196737746A70565D041CFB32EAA0C89FF8CB244C7F832A6EBD P2P_ADDRESS: iroha0:1337 API_ADDRESS: iroha0:1337 GENESIS_PUBLIC_KEY: ed0120415388A90FA238196737746A70565D041CFB32EAA0C89FF8CB244C7F832A6EBD @@ -774,13 +756,11 @@ mod tests { environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120F0321EB4139163C35F88BF78520FF7071499D7F4E79854550028A196C7B49E13 - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 5f8d1291bf6b762ee748a87182345d135fd167062857aa4f20ba39f25e74c4b0f0321eb4139163c35f88bf78520ff7071499d7f4e79854550028a196c7b49e13 + PRIVATE_KEY: 8026405F8D1291BF6B762EE748A87182345D135FD167062857AA4F20BA39F25E74C4B0F0321EB4139163C35F88BF78520FF7071499D7F4E79854550028A196C7B49E13 P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01203420F48A9EEB12513B8EB7DAF71979CE80A1013F5F341C10DCDA4F6AA19F97A9 - GENESIS_PRIVATE_KEY_ALGORITHM: ed25519 - GENESIS_PRIVATE_KEY_PAYLOAD: 5a6d5f06a90d29ad906e2f6ea8b41b4ef187849d0d397081a4a15ffcbe71e7c73420f48a9eeb12513b8eb7daf71979ce80a1013f5f341c10dcda4f6aa19f97a9 + GENESIS_PRIVATE_KEY: 8026405A6D5F06A90D29AD906E2F6EA8B41B4EF187849D0D397081A4A15FFCBE71E7C73420F48A9EEB12513B8EB7DAF71979CE80A1013F5F341C10DCDA4F6AA19F97A9 GENESIS_FILE: /config/genesis.json SUMERAGI_TRUSTED_PEERS: '[{"address":"iroha2:1339","public_key":"ed0120312C1B7B5DE23D366ADCF23CD6DB92CE18B2AA283C7D9F5033B969C2DC2B92F4"},{"address":"iroha3:1340","public_key":"ed0120854457B2E3D6082181DA73DC01C1E6F93A72D0C45268DC8845755287E98A5DEE"},{"address":"iroha1:1338","public_key":"ed0120A88554AA5C86D28D0EEBEC497235664433E807881CD31E12A1AF6C4D8B0F026C"}]' ports: @@ -802,8 +782,7 @@ mod tests { environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120A88554AA5C86D28D0EEBEC497235664433E807881CD31E12A1AF6C4D8B0F026C - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: 8d34d2c6a699c61e7a9d5aabbbd07629029dfb4f9a0800d65aa6570113edb465a88554aa5c86d28d0eebec497235664433e807881cd31e12a1af6c4d8b0f026c + PRIVATE_KEY: 8026408D34D2C6A699C61E7A9D5AABBBD07629029DFB4F9A0800D65AA6570113EDB465A88554AA5C86D28D0EEBEC497235664433E807881CD31E12A1AF6C4D8B0F026C P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed01203420F48A9EEB12513B8EB7DAF71979CE80A1013F5F341C10DCDA4F6AA19F97A9 @@ -826,8 +805,7 @@ mod tests { environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120312C1B7B5DE23D366ADCF23CD6DB92CE18B2AA283C7D9F5033B969C2DC2B92F4 - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: cf4515a82289f312868027568c0da0ee3f0fde7fef1b69deb47b19fde7cbc169312c1b7b5de23d366adcf23cd6db92ce18b2aa283c7d9f5033b969c2dc2b92f4 + PRIVATE_KEY: 802640CF4515A82289F312868027568C0DA0EE3F0FDE7FEF1B69DEB47B19FDE7CBC169312C1B7B5DE23D366ADCF23CD6DB92CE18B2AA283C7D9F5033B969C2DC2B92F4 P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed01203420F48A9EEB12513B8EB7DAF71979CE80A1013F5F341C10DCDA4F6AA19F97A9 @@ -850,8 +828,7 @@ mod tests { environment: CHAIN_ID: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120854457B2E3D6082181DA73DC01C1E6F93A72D0C45268DC8845755287E98A5DEE - PRIVATE_KEY_ALGORITHM: ed25519 - PRIVATE_KEY_PAYLOAD: ab0e99c2b845b4ac7b3e88d25a860793c7eb600a25c66c75cba0bae91e955aa6854457b2e3d6082181da73dc01c1e6f93a72d0c45268dc8845755287e98a5dee + PRIVATE_KEY: 802640AB0E99C2B845B4AC7B3E88D25A860793C7EB600A25C66C75CBA0BAE91E955AA6854457B2E3D6082181DA73DC01C1E6F93A72D0C45268DC8845755287E98A5DEE P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed01203420F48A9EEB12513B8EB7DAF71979CE80A1013F5F341C10DCDA4F6AA19F97A9