diff --git a/Cargo.lock b/Cargo.lock index 660280e5041..97070192cb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1847,17 +1847,6 @@ dependencies = [ "ursa", ] -[[package]] -name = "iroha_crypto_cli" -version = "2.0.0-pre-rc.3" -dependencies = [ - "clap 2.34.0", - "color-eyre", - "hex", - "iroha_crypto", - "serde_json", -] - [[package]] name = "iroha_data_model" version = "2.0.0-pre-rc.3" @@ -1934,19 +1923,6 @@ dependencies = [ "syn", ] -[[package]] -name = "iroha_gen" -version = "2.0.0-pre-rc.3" -dependencies = [ - "color-eyre", - "iroha", - "iroha_config", - "iroha_core", - "iroha_data_model", - "iroha_schema_bin", - "serde_json", -] - [[package]] name = "iroha_logger" version = "2.0.0-pre-rc.3" @@ -2163,6 +2139,22 @@ dependencies = [ "sha2", ] +[[package]] +name = "kagami" +version = "2.0.0-pre-rc.3" +dependencies = [ + "clap 2.34.0", + "color-eyre", + "hex", + "iroha", + "iroha_config", + "iroha_core", + "iroha_crypto", + "iroha_data_model", + "iroha_schema_bin", + "serde_json", +] + [[package]] name = "keccak" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index c33c765262f..7013bc63c2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,10 +11,9 @@ members = [ "core", "core/test_network", "crypto", - "tools/crypto_cli", "tools/kura_inspector", "tools/parity_scale_decoder", - "tools/generator", + "tools/kagami", "data_model", "data_model/primitives", "futures", diff --git a/client/tests/integration/roles.rs b/client/tests/integration/roles.rs index 8fbd54d9a3c..c300f65b6a6 100644 --- a/client/tests/integration/roles.rs +++ b/client/tests/integration/roles.rs @@ -6,7 +6,10 @@ use eyre::{eyre, Result}; use iroha_client::client::{self, Client}; use iroha_core::{prelude::AllowAll, smartcontracts::permissions::ValidatorBuilder}; use iroha_data_model::{permissions::Permissions, prelude::*}; -use iroha_permissions_validators::public_blockchain::transfer; +use iroha_permissions_validators::public_blockchain::{ + key_value::{CAN_REMOVE_KEY_VALUE_IN_USER_METADATA, CAN_SET_KEY_VALUE_IN_USER_METADATA}, + transfer, +}; use test_network::{Peer as TestPeer, *}; use tokio::runtime::Runtime; @@ -126,3 +129,30 @@ fn register_role_with_empty_token_params() -> Result<()> { // TODO: When we have more sane default permissions, see if we can // test more about whether or not roles actually work. + +#[test] +fn register_and_grant_metadata_role_to_account() -> Result<()> { + let (_rt, _peer, mut test_client) = ::start_test_with_runtime(); + wait_for_genesis_committed(&vec![test_client.clone()], 0); + + let bob_id = ::Id::from_str("bob@wonderland")?; + let register_bob = RegisterBox::new(Account::new(bob_id.clone(), [])); + test_client.submit_blocking(register_bob)?; + + let role_id = iroha_data_model::role::Id::new("USER_METADATA_ACCESS".parse::()?); + let mut permissions = Permissions::new(); + let mut params = BTreeMap::new(); + params.insert(Name::from_str("account_id")?, bob_id.into()); + permissions.insert(PermissionToken { + name: CAN_SET_KEY_VALUE_IN_USER_METADATA.clone(), + params: params.clone(), + }); + permissions.insert(PermissionToken { + name: CAN_REMOVE_KEY_VALUE_IN_USER_METADATA.clone(), + params, + }); + let register_role = RegisterBox::new(Role::new(role_id, permissions)); + + test_client.submit(register_role)?; + Ok(()) +} diff --git a/config/derive/src/lib.rs b/config/derive/src/lib.rs index 0c1a9dd7b10..72588f03ea2 100644 --- a/config/derive/src/lib.rs +++ b/config/derive/src/lib.rs @@ -22,7 +22,7 @@ mod attrs { pub const INNER: &str = "inner"; } -fn get_type_argument<'a, 'b>(s: &'a str, ty: &'b Type) -> Option<&'b GenericArgument> { +fn get_type_argument<'st, 'ty>(s: &'st str, ty: &'ty Type) -> Option<&'ty GenericArgument> { let path = if let Type::Path(r#type) = ty { r#type } else { diff --git a/config/src/lib.rs b/config/src/lib.rs index 1ce41d754e3..d37a15e1b8a 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -172,9 +172,9 @@ pub trait Configurable: Serialize + DeserializeOwned { /// Gets inner field of arbitrary inner depth and returns as json-value /// # Errors /// Fails if field was unknown - fn get_recursive<'a, T>(&self, inner_field: T) -> Result + fn get_recursive<'fld, T>(&self, inner_field: T) -> Result where - T: AsRef<[&'a str]> + Send + 'a; + T: AsRef<[&'fld str]> + Send + 'fld; /// Fails if fails to deserialize from environment /// # Errors @@ -184,8 +184,8 @@ pub trait Configurable: Serialize + DeserializeOwned { /// Gets docs of inner field of arbitrary depth /// # Errors /// Fails if field was unknown - fn get_doc_recursive<'a>( - field: impl AsRef<[&'a str]>, + fn get_doc_recursive<'fld>( + field: impl AsRef<[&'fld str]>, ) -> Result, Self::Error>; /// Gets docs of field diff --git a/config/src/runtime_upgrades.rs b/config/src/runtime_upgrades.rs index 08b662bc4ad..1b3c2faf02d 100644 --- a/config/src/runtime_upgrades.rs +++ b/config/src/runtime_upgrades.rs @@ -30,7 +30,8 @@ pub enum ReloadError { Other, } -type PoisonErr<'a, T> = PoisonError + Send + Sync)>>>>; +type PoisonErr<'mutex, T> = + PoisonError + Send + Sync)>>>>; impl From> for ReloadError { fn from(_: PoisonErr<'_, T>) -> Self { diff --git a/core/src/block.rs b/core/src/block.rs index fbec7f30214..950a5830329 100644 --- a/core/src/block.rs +++ b/core/src/block.rs @@ -98,14 +98,14 @@ impl Chain { } /// Chain iterator -pub struct ChainIterator<'a> { - chain: &'a Chain, +pub struct ChainIterator<'ch> { + chain: &'ch Chain, pos_front: u64, pos_back: u64, } -impl<'a> ChainIterator<'a> { - fn new(chain: &'a Chain) -> Self { +impl<'ch> ChainIterator<'ch> { + fn new(chain: &'ch Chain) -> Self { ChainIterator { chain, pos_front: 1, @@ -118,8 +118,8 @@ impl<'a> ChainIterator<'a> { } } -impl<'a> Iterator for ChainIterator<'a> { - type Item = MapRef<'a, u64, VersionedCommittedBlock>; +impl<'ch> Iterator for ChainIterator<'ch> { + type Item = MapRef<'ch, u64, VersionedCommittedBlock>; fn next(&mut self) -> Option { if !self.is_exhausted() { let val = self.chain.blocks.get(&self.pos_front); @@ -152,7 +152,7 @@ impl<'a> Iterator for ChainIterator<'a> { } } -impl<'a> DoubleEndedIterator for ChainIterator<'a> { +impl<'de> DoubleEndedIterator for ChainIterator<'de> { fn next_back(&mut self) -> Option { if !self.is_exhausted() { let val = self.chain.blocks.get(&self.pos_back); diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 41cc4271824..36846620a05 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -8,7 +8,7 @@ use std::{collections::HashSet, fmt::Debug, fs::File, io::BufReader, ops::Deref, use eyre::{eyre, Result, WrapErr}; use iroha_actor::Addr; use iroha_crypto::{KeyPair, PublicKey}; -use iroha_data_model::{asset::AssetDefinition, domain::NewDomain, prelude::*}; +use iroha_data_model::{asset::AssetDefinition, prelude::*}; use iroha_schema::prelude::*; use serde::{Deserialize, Serialize}; use small::SmallVec; @@ -398,7 +398,7 @@ impl RawGenesisBlockBuilder { /// be used to create assets and accounts. pub fn domain(mut self, domain_name: Name) -> RawGenesisDomainBuilder { let domain_id = DomainId::new(domain_name); - let new_domain = NewDomain::new(domain_id.clone()); + let new_domain = Domain::new(domain_id.clone()); self.transaction .isi .push(Instruction::from(RegisterBox::new(new_domain))); @@ -505,7 +505,7 @@ mod tests { let domain_id: DomainId = "wonderland".parse().unwrap(); assert_eq!( finished_genesis_block.transactions[0].isi[0], - Instruction::from(RegisterBox::new(NewDomain::new(domain_id.clone()))) + Instruction::from(RegisterBox::new(Domain::new(domain_id.clone()))) ); assert_eq!( finished_genesis_block.transactions[0].isi[1], @@ -521,7 +521,7 @@ mod tests { let domain_id: DomainId = "tulgey_wood".parse().unwrap(); assert_eq!( finished_genesis_block.transactions[0].isi[3], - Instruction::from(RegisterBox::new(NewDomain::new(domain_id.clone()))) + Instruction::from(RegisterBox::new(Domain::new(domain_id.clone()))) ); assert_eq!( finished_genesis_block.transactions[0].isi[4], @@ -532,7 +532,7 @@ mod tests { let domain_id: DomainId = "meadow".parse().unwrap(); assert_eq!( finished_genesis_block.transactions[0].isi[5], - Instruction::from(RegisterBox::new(NewDomain::new(domain_id.clone()))) + Instruction::from(RegisterBox::new(Domain::new(domain_id.clone()))) ); assert_eq!( finished_genesis_block.transactions[0].isi[6], diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index f0193dafef4..5c0009abf9a 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -68,7 +68,7 @@ impl From for Error { } } -struct Validator<'a, W: WorldTrait> { +struct Validator<'va, W: WorldTrait> { /// Number of instructions in the smartcontract instruction_count: u64, /// Max allowed number of instructions in the smartcontract @@ -78,7 +78,7 @@ struct Validator<'a, W: WorldTrait> { /// If this particular query is allowed is_query_allowed: Arc>, /// Current [`WorldStateview`] - wsv: &'a WorldStateView, + wsv: &'va WorldStateView, } impl Validator<'_, W> { @@ -125,16 +125,16 @@ impl Validator<'_, W> { } } -struct State<'a, W: WorldTrait> { +struct State<'wrld, W: WorldTrait> { account_id: AccountId, /// Ensures smartcontract adheres to limits - validator: Option>, + validator: Option>, store_limits: StoreLimits, - wsv: &'a WorldStateView, + wsv: &'wrld WorldStateView, } -impl<'a, W: WorldTrait> State<'a, W> { - fn new(wsv: &'a WorldStateView, account_id: AccountId, config: Configuration) -> Self { +impl<'wrld, W: WorldTrait> State<'wrld, W> { + fn new(wsv: &'wrld WorldStateView, account_id: AccountId, config: Configuration) -> Self { Self { wsv, account_id, @@ -171,13 +171,13 @@ impl<'a, W: WorldTrait> State<'a, W> { } /// `WebAssembly` virtual machine -pub struct Runtime<'a, W: WorldTrait> { +pub struct Runtime<'wrld, W: WorldTrait> { engine: Engine, - linker: Linker>, + linker: Linker>, config: Configuration, } -impl<'a, W: WorldTrait> Runtime<'a, W> { +impl<'wrld, W: WorldTrait> Runtime<'wrld, W> { /// `Runtime` constructor with default configuration. /// /// # Errors @@ -344,7 +344,7 @@ impl<'a, W: WorldTrait> Runtime<'a, W> { Ok(()) } - fn create_linker(engine: &Engine) -> Result>, Error> { + fn create_linker(engine: &Engine) -> Result>, Error> { let mut linker = Linker::new(engine); linker diff --git a/core/src/sumeragi/message.rs b/core/src/sumeragi/message.rs index b41983bfe58..61455e8fd03 100644 --- a/core/src/sumeragi/message.rs +++ b/core/src/sumeragi/message.rs @@ -145,9 +145,9 @@ impl VersionedMessage { /// Send this message over the network to multiple `peers`. /// # Errors /// Fails if network sending fails - pub async fn send_to_multiple<'a, I>(self, broker: &Broker, peers: I) + pub async fn send_to_multiple<'itm, I>(self, broker: &Broker, peers: I) where - I: IntoIterator + Send, + I: IntoIterator + Send, { let futures = peers .into_iter() diff --git a/core/src/sumeragi/network_topology.rs b/core/src/sumeragi/network_topology.rs index e03864c49fa..415d3931be3 100644 --- a/core/src/sumeragi/network_topology.rs +++ b/core/src/sumeragi/network_topology.rs @@ -366,10 +366,10 @@ impl Topology { } /// Returns signatures of the peers with the specified `roles` from all `signatures`. - pub fn filter_signatures_by_roles<'a>( - &'a self, - roles: &'a [Role], - signatures: impl IntoIterator> + 'a, + pub fn filter_signatures_by_roles<'slf>( + &'slf self, + roles: &'slf [Role], + signatures: impl IntoIterator> + 'slf, ) -> Vec> { let roles: HashSet = roles.iter().copied().collect(); let public_keys: HashSet<_> = roles @@ -481,8 +481,8 @@ mod tests { fn correct_number_of_peers_genesis() { let peers = topology_test_peers(); // set_a.len() = 2, is wrong as it is not possible to get integer f in: 2f + 1 = 2 - let set_a: HashSet<_> = topology_test_peers().iter().cloned().take(3).collect(); - let set_b: HashSet<_> = topology_test_peers().iter().cloned().skip(3).collect(); + let set_a: HashSet<_> = topology_test_peers().iter().take(3).cloned().collect(); + let set_b: HashSet<_> = topology_test_peers().iter().skip(3).cloned().collect(); let _network_topology = GenesisBuilder::new() .with_leader(peers.iter().next().unwrap().clone()) .with_set_a(set_a) diff --git a/core/src/triggers.rs b/core/src/triggers.rs index 0f4bd3db443..fb217baf21f 100644 --- a/core/src/triggers.rs +++ b/core/src/triggers.rs @@ -105,9 +105,9 @@ impl TriggerSet { /// /// Users should not try to modify [`TriggerSet`] before dropping actions, /// returned by the current function - pub fn find_matching<'e, E>(&self, events: E) -> Vec + pub fn find_matching<'evnt, E>(&self, events: E) -> Vec where - E: IntoIterator, + E: IntoIterator, { let mut result = Vec::new(); diff --git a/crypto/src/signature.rs b/crypto/src/signature.rs index f39fc596155..22ee049ba5d 100644 --- a/crypto/src/signature.rs +++ b/crypto/src/signature.rs @@ -305,9 +305,9 @@ impl IntoIterator for SignaturesOf { } } -impl<'a, T> IntoIterator for &'a SignaturesOf { - type Item = &'a SignatureOf; - type IntoIter = btree_map::Values<'a, PublicKey, SignatureOf>; +impl<'sig, T> IntoIterator for &'sig SignaturesOf { + type Item = &'sig SignatureOf; + type IntoIter = btree_map::Values<'sig, PublicKey, SignatureOf>; fn into_iter(self) -> Self::IntoIter { self.signatures.values() } @@ -363,7 +363,7 @@ impl SignaturesOf { /// # Warning: /// /// This method uses [`core::mem::transmute`] internally - #[allow(unsafe_code)] + #[allow(unsafe_code, clippy::transmute_undefined_repr)] pub fn transmute(self) -> SignaturesOf { // SAFETY: Safe because we are transmuting to a pointer of // type `` which is related to type ``. diff --git a/data_model/src/domain.rs b/data_model/src/domain.rs index 7f4ba484825..ea8768a113b 100644 --- a/data_model/src/domain.rs +++ b/data_model/src/domain.rs @@ -74,7 +74,7 @@ pub struct NewDomain { /// The (IPFS) link to the logo of this domain. logo: Option, /// metadata associated to the domain builder. - pub metadata: Metadata, + metadata: Metadata, } impl PartialOrd for NewDomain { @@ -94,7 +94,7 @@ impl Ord for NewDomain { impl NewDomain { /// Create a [`NewDomain`], reserved for internal use. #[must_use] - pub fn new(id: ::Id) -> Self { + fn new(id: ::Id) -> Self { Self { id, logo: None, diff --git a/data_model/src/merkle.rs b/data_model/src/merkle.rs index 4bb58e75b1f..de3ec6f975e 100644 --- a/data_model/src/merkle.rs +++ b/data_model/src/merkle.rs @@ -48,8 +48,8 @@ pub enum Node { #[derive(Debug)] /// BFS iterator over the Merkle tree -pub struct BreadthFirstIter<'a, T> { - queue: Vec<&'a Node>, +pub struct BreadthFirstIter<'itm, T> { + queue: Vec<&'itm Node>, } #[cfg(feature = "std")] @@ -184,8 +184,8 @@ impl Node { } } -impl<'a, T> BreadthFirstIter<'a, T> { - fn new(root_node: &'a Node) -> Self { +impl<'itm, T> BreadthFirstIter<'itm, T> { + fn new(root_node: &'itm Node) -> Self { BreadthFirstIter { queue: vec![root_node], } @@ -196,8 +196,8 @@ impl<'a, T> BreadthFirstIter<'a, T> { /// `'a` lifetime specified for `Node`. Because `Node` is recursive data structure with self /// composition in case of `Node::Subtree` we use `Box` to know size of each `Node` object in /// memory. -impl<'a, T> Iterator for BreadthFirstIter<'a, T> { - type Item = &'a Node; +impl<'itm, T> Iterator for BreadthFirstIter<'itm, T> { + type Item = &'itm Node; fn next(&mut self) -> Option { match &self.queue.pop() { @@ -213,9 +213,9 @@ impl<'a, T> Iterator for BreadthFirstIter<'a, T> { } } -impl<'a, T> IntoIterator for &'a MerkleTree { - type Item = &'a Node; - type IntoIter = BreadthFirstIter<'a, T>; +impl<'itm, T> IntoIterator for &'itm MerkleTree { + type Item = &'itm Node; + type IntoIter = BreadthFirstIter<'itm, T>; fn into_iter(self) -> Self::IntoIter { BreadthFirstIter::new(&self.root_node) diff --git a/schema/derive/src/lib.rs b/schema/derive/src/lib.rs index a5c04de7682..c380a073941 100644 --- a/schema/derive/src/lib.rs +++ b/schema/derive/src/lib.rs @@ -299,10 +299,10 @@ fn variant_index(v: &Variant, i: usize) -> TokenStream2 { } /// Finds specific attribute with codec ident satisfying predicate -fn find_meta_item<'a, F, R, I, M>(mut itr: I, mut pred: F) -> Option +fn find_meta_item<'attr, F, R, I, M>(mut itr: I, mut pred: F) -> Option where F: FnMut(M) -> Option + Clone, - I: Iterator, + I: Iterator, M: Parse, { itr.find_map(|attr| { diff --git a/scripts/check.sh b/scripts/check.sh index 0d402180e74..76acfa5c391 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -5,13 +5,13 @@ TMPFILE=$(mktemp) case $1 in "docs") - cargo run --bin iroha_gen -- --docs >"$TMPFILE" + cargo run --bin kagami -- --docs >"$TMPFILE" diff "$TMPFILE" docs/source/references/config.md || { echo 'Please re-generate docs with git hook in ./hooks directory' exit 1 };; "genesis") - cargo run --bin iroha_gen -- --genesis >"$TMPFILE" + cargo run --bin kagami -- --genesis >"$TMPFILE" diff "$TMPFILE" configs/peer/genesis.json || { echo 'Please re-generate the genesis with `cargo run --bin iroha_gen -- --genesis`' exit 1 diff --git a/tools/crypto_cli/Cargo.toml b/tools/crypto_cli/Cargo.toml deleted file mode 100644 index 729e63d2dfd..00000000000 --- a/tools/crypto_cli/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "iroha_crypto_cli" -version = "2.0.0-pre-rc.3" -authors = ["Iroha 2 team "] -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -iroha_crypto = { version = "=2.0.0-pre-rc.3", path = "../../crypto" } - -clap = "2.33.0" -color-eyre = "0.5.11" -hex = "0.4.0" -serde_json = "1.0" diff --git a/tools/crypto_cli/README.md b/tools/crypto_cli/README.md deleted file mode 100644 index f85e49fa7be..00000000000 --- a/tools/crypto_cli/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Iroha Crypto CLI - -## Description - -Tool for generating public/private key pairs for use in Iroha networks. - -All keys are represented in the [multihash format](https://github.com/multiformats/multihash). - -## Usage - -Assuming that the command is run either from the root of the cloned repository or the directory containing this document, use - - -```bash -cargo run --bin iroha_crypto_cli -``` - -**NOTE:** arguments before the `--` terminator are interpreted as arguments given to `cargo run`, rather than `iroha_crypto_cli` to pass the argument `--help` use the following syntax. - -```bash -cargo run --bin iroha_crypto_cli -- --help -``` - -### Contributing - -Check out [this document](https://github.com/hyperledger/iroha/blob/iroha2-dev/CONTRIBUTING.md) - -## [Need help?](https://github.com/hyperledger/iroha/blob/iroha2-dev/CONTRIBUTING.md#contact) - -## License - -Iroha codebase is licensed under the Apache License, -Version 2.0 (the "License"); you may not use this file except -in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Iroha documentation files are made available under the Creative Commons -Attribution 4.0 International License (CC-BY-4.0), available at -http://creativecommons.org/licenses/by/4.0/ diff --git a/tools/crypto_cli/src/main.rs b/tools/crypto_cli/src/main.rs deleted file mode 100644 index 15d42b9bdc8..00000000000 --- a/tools/crypto_cli/src/main.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! `iroha_crypto_cli` is a command line tool used to generate keys for Iroha peers and clients. - -use clap::{App, Arg, ArgGroup}; -use color_eyre::{ - eyre::{self, eyre, WrapErr}, - Report, Result, -}; -use iroha_crypto::{Algorithm, KeyGenConfiguration, KeyPair, PrivateKey}; - -fn main() -> Result<(), Report> { - color_eyre::install()?; - let default_algorithm = Algorithm::default().to_string(); - let matches = App::new("iroha_crypto_cli") - .version("0.1") - .author("Soramitsu") - .about("iroha_crypto_cli is a command line tool used to generate keys for Iroha peers and clients.") - .arg( - Arg::with_name("seed") - .long("seed") - .value_name("seed") - .help("Sets a seed for random number generator. Should be used separately from `private_key`.") - .required(false) - .takes_value(true) - ) - .arg( - Arg::with_name("private_key") - .long("private_key") - .value_name("private_key") - .help("Sets a private key. Should be used separately from `seed`.") - .required(false) - .takes_value(true) - ) - .arg( - Arg::with_name("algorithm") - .long("algorithm") - .value_name("algorithm") - .help("Function used to generate the key pair.") - .takes_value(true) - .possible_value(iroha_crypto::ED_25519) - .possible_value(iroha_crypto::SECP_256_K1) - .possible_value(iroha_crypto::BLS_NORMAL) - .possible_value(iroha_crypto::BLS_SMALL) - .default_value(&default_algorithm) - ) - .arg( - Arg::with_name("json") - .long("json") - .help("If specified the output will be formatted as json.") - .takes_value(false) - .multiple(false) - ) - .group( - ArgGroup::with_name("key_gen_options") - .args(&["seed", "private_key"]) - .required(false) - .multiple(false) - ) - .get_matches(); - let seed_option = matches.value_of("seed"); - let private_key_option = matches.value_of("private_key"); - let algorithm = matches - .value_of("algorithm") - .ok_or_else(|| eyre!("Failed to get algorithm name."))? - .parse::() - .wrap_err("Failed to parse algorithm.")?; - let key_gen_configuration = KeyGenConfiguration::default().with_algorithm(algorithm); - let keypair: KeyPair = seed_option.map_or_else( - || -> eyre::Result<_> { - private_key_option.map_or_else( - || { - KeyPair::generate_with_configuration(key_gen_configuration.clone()) - .wrap_err("failed to generate key pair") - }, - |private_key| { - KeyPair::generate_with_configuration( - key_gen_configuration.clone().use_private_key(PrivateKey { - digest_function: algorithm.to_string(), - payload: hex::decode(private_key) - .wrap_err("Failed to decode private key.")?, - }), - ) - .wrap_err("Failed to generate key pair") - }, - ) - }, - |seed| -> eyre::Result<_> { - KeyPair::generate_with_configuration( - key_gen_configuration - .clone() - .use_seed(seed.as_bytes().into()), - ) - .wrap_err("Failed to generate key pair") - }, - )?; - - #[allow(clippy::print_stdout)] - if matches.is_present("json") { - let json = - serde_json::to_string_pretty(&keypair).wrap_err("Failed to serialize to json.")?; - println!("{}", json); - } else { - println!("Public key (multihash): {}", &keypair.public_key); - println!("Private key: {}", &keypair.private_key); - println!("Digest function: {}", &keypair.public_key.digest_function); - } - - Ok(()) -} diff --git a/tools/generator/src/main.rs b/tools/generator/src/main.rs deleted file mode 100644 index 3ce17232fcf..00000000000 --- a/tools/generator/src/main.rs +++ /dev/null @@ -1,172 +0,0 @@ -//! CLI for generating iroha sample configuration and genesis, as well -//! as their documentation. - -#![allow(clippy::restriction)] - -use std::io::{stdout, BufWriter, Write}; - -use color_eyre::eyre::WrapErr as _; -use iroha::config::Configuration; - -// TODO: if we merge #2077 first, we should change this to sync up with the default in docs. -static DEFAULT_PUBLIC_KEY: &str = - "ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"; - -fn main() -> color_eyre::Result<()> { - use docs::PrintDocs as _; - color_eyre::install().unwrap(); - let mut output = BufWriter::new(stdout()); - if std::env::args().any(|a| cli::is_genesis(&a)) { - writeln!( - output, - "{}", - serde_json::to_string_pretty(&genesis::generate_default()?)? - )?; - Ok(()) - } else if std::env::args().any(|a| cli::is_schema(&a)) { - let schemas = iroha_schema_bin::build_schemas(); - writeln!(output, "{}", serde_json::to_string_pretty(&schemas)?)?; - Ok(()) - } else if std::env::args().any(|a| cli::is_docs(&a)) { - Configuration::get_markdown(&mut BufWriter::new(stdout())) - .wrap_err("Failed to generate documentation") - } else { - cli::print_help(); - Ok(()) - } -} - -mod cli { - pub fn print_help() { - println!("Tool for generating iroha-related data."); - println!(); - println!("pass `--docs` or `-d` to generate sample config and its documentation."); - println!("pass `--schema` or `-s` to generate the schema."); - println!("pass `--genesis` or `-g` to generate the genesis block."); - } - - pub fn is_docs(arg: &str) -> bool { - ["--docs", "-d"].contains(&arg) - } - - pub fn is_schema(arg: &str) -> bool { - ["--schema", "-s"].contains(&arg) - } - - pub fn is_genesis(arg: &str) -> bool { - ["--genesis", "-g"].contains(&arg) - } -} - -mod genesis { - use iroha_core::{ - genesis::{RawGenesisBlock, RawGenesisBlockBuilder}, - tx::{AssetDefinition, MintBox}, - }; - - pub fn generate_default() -> color_eyre::Result { - let asset_definition = AssetDefinition::quantity("rose#wonderland".parse()?).build(); - let mut result = RawGenesisBlockBuilder::new() - .domain("wonderland".parse()?) - .with_account("alice".parse()?, crate::DEFAULT_PUBLIC_KEY.parse()?) - .with_asset(asset_definition.clone()) - .finish_domain() - .build(); - let mint = MintBox::new( - iroha_data_model::prelude::Value::U32(13_u32), - iroha_data_model::IdBox::AssetId(iroha_data_model::prelude::AssetId::new( - asset_definition.id().clone(), // Probably redundant clone - "alice@wonderland".parse()?, - )), - ); - result.transactions[0].isi.push(mint.into()); - Ok(result) - } -} - -mod docs { - use std::{fmt::Debug, io::Write}; - - use iroha_config::Configurable; - use serde_json::Value; - - impl + Send + Sync + Default> PrintDocs for C {} - - pub trait PrintDocs: Configurable + Send + Sync + Default - where - Self::Error: Debug, - { - fn get_markdown(writer: &mut W) -> color_eyre::Result<()> { - let docs = match Self::get_docs() { - Value::Object(obj) => obj, - _ => unreachable!("As top level structure is always object"), - }; - let mut vec = Vec::new(); - let defaults = serde_json::to_string_pretty(&Self::default())?; - - writeln!(writer, "# Iroha Configuration reference\n")?; - writeln!(writer, "In this document we provide a reference and detailed descriptions of Iroha's configuration options.\n")?; - writeln!(writer, "## Default configuration\n")?; - writeln!( - writer, - "The following is the default configuration used by Iroha.\n" - )?; - writeln!(writer, "```json\n{}\n```\n", defaults)?; - Self::get_markdown_with_depth(writer, &docs, &mut vec, 2)?; - Ok(()) - } - - fn get_markdown_with_depth( - writer: &mut W, - docs: &serde_json::Map, - field: &mut Vec, - depth: usize, - ) -> color_eyre::Result<()> { - let current_field = { - let mut docs = docs; - for f in &*field { - docs = match &docs[f] { - Value::Object(obj) => obj, - _ => unreachable!(), - }; - } - docs - }; - - for (f, value) in current_field { - field.push(f.clone()); - let get_field = field.iter().map(AsRef::as_ref).collect::>(); - let (doc, inner) = match value { - Value::Object(_) => { - let doc = Self::get_doc_recursive(&get_field) - .expect("Should be there, as already in docs"); - (doc.unwrap_or_default().to_owned(), true) - } - Value::String(s) => (s.clone(), false), - _ => unreachable!("Only strings and objects in docs"), - }; - let doc = doc.strip_prefix(' ').unwrap_or(&doc); - let defaults = Self::default() - .get_recursive(get_field) - .expect("Failed to get defaults."); - let defaults = serde_json::to_string_pretty(&defaults)?; - let field_str = field - .join(".") - .chars() - .filter(|&chr| chr != ' ') - .collect::(); - - write!(writer, "{} `{}`\n\n", "#".repeat(depth), field_str)?; - write!(writer, "{}\n\n", doc)?; - write!(writer, "```json\n{}\n```\n\n", defaults)?; - - if inner { - Self::get_markdown_with_depth(writer, docs, field, depth + 1)?; - } - - field.pop(); - } - Ok(()) - } - } -} diff --git a/tools/generator/Cargo.toml b/tools/kagami/Cargo.toml similarity index 72% rename from tools/generator/Cargo.toml rename to tools/kagami/Cargo.toml index c0da4eea7d2..7d94a136ac0 100644 --- a/tools/generator/Cargo.toml +++ b/tools/kagami/Cargo.toml @@ -1,12 +1,16 @@ [package] -name = "iroha_gen" +name = "kagami" version = "2.0.0-pre-rc.3" authors = ["Iroha 2 team "] edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -# Explanation: You want the option to remove configuration docs if you distribute e.g. a `deb`, but want the person who just cloned the repo to be able to see at a glance what kinds of features are accessible to them, what they do and how to use them. #1975 should be fixed soon. +# Explanation: You want the option to remove configuration docs if you +# distribute e.g. a `deb`, but want the person who just cloned the +# repo to be able to see at a glance what kinds of features are +# accessible to them, what they do and how to use them. #1975 should +# be fixed soon. [features] roles = ["iroha_core/roles"] dex = ["iroha_core/dex"] @@ -17,10 +21,13 @@ default = ["roles", "dex", "telemetry", "dev-telemetry"] [dependencies] iroha_core = { version = "=2.0.0-pre-rc.3", path = "../../core" } +iroha_crypto = { version = "=2.0.0-pre-rc.3", path = "../../crypto" } iroha_config = { version = "=2.0.0-pre-rc.3", path = "../../config" } iroha_data_model = { version = "=2.0.0-pre-rc.3", path = "../../data_model" } iroha_schema_bin = { version = "=2.0.0-pre-rc.3", path = "../../schema/bin" } iroha = { path = "../../cli" } color-eyre = "0.5.11" +hex = "0.4.0" +clap = "2.33.0" serde_json = "1" diff --git a/tools/kagami/README.md b/tools/kagami/README.md new file mode 100644 index 00000000000..2b5086c4723 --- /dev/null +++ b/tools/kagami/README.md @@ -0,0 +1,102 @@ +# Kagami + +This tool is used to generate and validate the automatically generated data files shipped with Iroha. + +### Building + +Use + +```bash +cargo build --bin kagami +``` + +anywhere in this repository. This will place `kagami` inside the `target/debug/` directory (from the root of the repository). + +### Usage + +```bash +Kagami 0.1 +Iroha development team. +Generator for data used in Iroha. + +USAGE: +kagami [FLAGS] [OPTIONS] + +FLAGS: +-d, --docs If specified, print configuration docs +-g, --genesis If specified, print the Genesis +-h, --help Prints help information +--json If specified the output will be formatted as json. +-s, --schema If specified, print Schema +-V, --version Prints version information + +OPTIONS: +--algorithm Function used to generate the key pair. [default: ed25519] [possible values: +ed25519, secp256k1, bls_normal, bls_small] +--private_key Sets a private key. Should be used separately from `seed`. +--seed Sets a seed for random number generator. Should be used separately from +`private_key`. +``` + +#### Key generation + +With a few examples. + +By default, will generate a key pair. + +```bash +$ ./kagami +``` + +```bash +Kagami. To see help run with `--help`. +No flags specified, generating key-pair. +Public key (multihash): ed0120232adec551bfa1856279ebccc3c3a09783c516478f4cbb2f42f342614bec7601 +Private key: a1e2c094496dd53ea103f1423b90ccb7d65ff25ab46f5fa1643c14e6010f7f75232adec551bfa1856279ebccc3c3a09783c516478f4cbb2f42f342614bec7601 +Digest function: ed25519 +``` + +To generate a key pair from a given seed, run + +```bash +$ ./kagami --seed +``` + +To generate a key with the `secp256k1` algorithm, which corresponds to the private key `8e170e7abe3cc71afeb2459b2d055641159dca4825e0536234e120ced756fabda2bfcb42761216a95a5bf2574219c602a9e7d410420af8b020c9e9e40ffb3690`, run + +```bash +$ ./kagami --algorithm --private-key 8e170e7abe3cc71afeb2459b2d055641159dca4825e0536234e120ced756fabda2bfcb42761216a95a5bf2574219c602a9e7d410420af8b020c9e9e40ffb3690 +``` + +```bash +Kagami. To see help run with `--help`. +No flags specified, generating key-pair. +Public key (multihash): ed0120a2bfcb42761216a95a5bf2574219c602a9e7d410420af8b020c9e9e40ffb3690 +Private key: 8e170e7abe3cc71afeb2459b2d055641159dca4825e0536234e120ced756fabda2bfcb42761216a95a5bf2574219c602a9e7d410420af8b020c9e9e40ffb3690 +Digest function: ed25519 +``` + + +#### Genesis + +```bash +kagami -g +``` + +Should produce a genesis block in JSON format. You might want to use shell redirections e.g. `kagami -g >genesis.json`. + +#### Schema + +```bash +kagami -s +``` + +Should generate the schema in JSON format. You might want to use shell redirections e.g. `kagami -g >genesis.json`. + +#### Peer configuration reference + +```bash +kagami --docs +``` + +Should generate the documentation in Markdown format. Should be identical to the [reference configuration](../../docs/source/references/config.md). diff --git a/tools/kagami/src/main.rs b/tools/kagami/src/main.rs new file mode 100644 index 00000000000..3c2b7cc09b0 --- /dev/null +++ b/tools/kagami/src/main.rs @@ -0,0 +1,297 @@ +//! CLI for generating iroha sample configuration, genesis and +//! cryptographic key pairs. To be used with all compliant Iroha +//! installations. + +use std::io::{stdout, BufWriter, Write}; + +use clap::{App, Arg, ArgGroup}; +use color_eyre::eyre::WrapErr as _; +use docs::PrintDocs as _; +use iroha::config::Configuration; + +// The reason for hard-coding this default is to ensure that the +// algorithm is matched to the public key. If you need to change +// either, you should definitely change both. +static DEFAULT_PUBLIC_KEY: &str = + "ed01207233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"; +static DEFAULT_ALGORITHM: &str = iroha_crypto::ED_25519; + +fn main() -> color_eyre::Result<()> { + color_eyre::install()?; + let matches = arg_parse(); + let keypair = crypto::key_pair(&matches)?; + let mut output = BufWriter::new(stdout()); + + if matches.is_present("genesis") { + writeln!( + output, + "{}", + serde_json::to_string_pretty(&genesis::generate_default()?)? + )?; + } else if matches.is_present("docs") { + Configuration::get_markdown(&mut BufWriter::new(stdout())) + .wrap_err("Failed to generate documentation")?; + } else if matches.is_present("schema") { + let schemas = iroha_schema_bin::build_schemas(); + writeln!(output, "{}", serde_json::to_string_pretty(&schemas)?)?; + } else { + #[allow(clippy::print_stdout)] + if matches.is_present("json") { + let json = + serde_json::to_string_pretty(&keypair).wrap_err("Failed to serialize to json.")?; + writeln!(output, "{}", json)?; + } else { + writeln!(output, "Kagami. To see help run with `--help`.")?; + writeln!(output, "No flags specified, generating key-pair.")?; + writeln!(output, "Public key (multihash): {}", &keypair.public_key)?; + writeln!(output, "Private key: {}", &keypair.private_key)?; + writeln!( + output, + "Digest function: {}", + &keypair.public_key.digest_function + )?; + } + } + Ok(()) +} + +// TODO: Refactor to use the `StructOpt` syntax just like all other tools. +fn arg_parse() -> clap::ArgMatches<'static> { + let matches = App::new("Kagami") + .version("0.1") + .author("Iroha development team.") + .about("Generator for data used in Iroha.") + .arg( + Arg::with_name("seed") + .long("seed") + .value_name("seed") + .help("Sets a seed for random number generator. Should be used separately from `private_key`.") + .required(false) + .takes_value(true) + ) + .arg( + Arg::with_name("private-key") + .long("private-key") + .value_name("private_key") + .help("Sets a private key. Should be used separately from `seed`.") + .required(false) + .takes_value(true) + ) + .arg( + Arg::with_name("algorithm") + .long("algorithm") + .value_name("algorithm") + .help("Function used to generate the key pair.") + .takes_value(true) + .possible_value(iroha_crypto::ED_25519) + .possible_value(iroha_crypto::SECP_256_K1) + .possible_value(iroha_crypto::BLS_NORMAL) + .possible_value(iroha_crypto::BLS_SMALL) + .default_value(DEFAULT_ALGORITHM) + ) + .arg( + Arg::with_name("json") + .long("json") + .help("If specified the output will be formatted as json.") + .takes_value(false) + .multiple(false) + ) + .arg( + Arg::with_name("genesis") + .long("genesis") + .short("g") + .help("If specified, print the Genesis") + .takes_value(false) + .multiple(false) + ) + .arg( + Arg::with_name("schema") + .long("schema") + .short("s") + .help("If specified, print Schema") + .takes_value(false) + .multiple(false) + ) + .arg( + Arg::with_name("docs") + .long("docs") + .short("d") + .help("If specified, print configuration docs") + .takes_value(false) + .multiple(false) + ) + .group( + ArgGroup::with_name("other_gen_options") + .args(&["docs", "schema", "genesis"]) + .required(false) + .multiple(false) + ) + .group( + ArgGroup::with_name("key_gen_options") + .args(&["seed", "private-key"]) + .required(false) + .multiple(false) + ) + .get_matches(); + matches +} + +mod crypto { + + use color_eyre::eyre::{eyre, WrapErr as _}; + use iroha_crypto::{Algorithm, KeyGenConfiguration, KeyPair, PrivateKey}; + + pub fn key_pair(matches: &clap::ArgMatches) -> color_eyre::Result { + let seed_option = matches.value_of("seed"); + let private_key_option = matches.value_of("private-key"); + let algorithm = matches + .value_of("algorithm") + .ok_or_else(|| eyre!("Failed to get algorithm name."))? + .parse::() + .wrap_err("Failed to parse algorithm.")?; + let key_gen_configuration = KeyGenConfiguration::default().with_algorithm(algorithm); + let keypair: KeyPair = seed_option.map_or_else( + || -> color_eyre::Result<_> { + private_key_option.map_or_else( + || { + KeyPair::generate_with_configuration(key_gen_configuration.clone()) + .wrap_err("failed to generate key pair") + }, + |private_key| { + KeyPair::generate_with_configuration( + key_gen_configuration.clone().use_private_key(PrivateKey { + digest_function: algorithm.to_string(), + payload: hex::decode(private_key) + .wrap_err("Failed to decode private key.")?, + }), + ) + .wrap_err("Failed to generate key pair") + }, + ) + }, + |seed| -> color_eyre::Result<_> { + KeyPair::generate_with_configuration( + key_gen_configuration + .clone() + .use_seed(seed.as_bytes().into()), + ) + .wrap_err("Failed to generate key pair") + }, + )?; + Ok(keypair) + } +} + +mod genesis { + use iroha_core::{ + genesis::{RawGenesisBlock, RawGenesisBlockBuilder}, + tx::{AssetDefinition, MintBox}, + }; + + pub fn generate_default() -> color_eyre::Result { + let asset_definition = AssetDefinition::quantity("rose#wonderland".parse()?).build(); + let mut result = RawGenesisBlockBuilder::new() + .domain("wonderland".parse()?) + .with_account("alice".parse()?, crate::DEFAULT_PUBLIC_KEY.parse()?) + .with_asset(asset_definition.clone()) + .finish_domain() + .build(); + let mint = MintBox::new( + iroha_data_model::prelude::Value::U32(13_u32), + iroha_data_model::IdBox::AssetId(iroha_data_model::prelude::AssetId::new( + asset_definition.id().clone(), // Probably redundant clone + "alice@wonderland".parse()?, + )), + ); + result.transactions[0].isi.push(mint.into()); + Ok(result) + } +} + +mod docs { + #![allow(clippy::panic_in_result_fn, clippy::expect_used)] + use std::{fmt::Debug, io::Write}; + + use iroha_config::Configurable; + use serde_json::Value; + + impl + Send + Sync + Default> PrintDocs for C {} + + pub trait PrintDocs: Configurable + Send + Sync + Default + where + Self::Error: Debug, + { + fn get_markdown(writer: &mut W) -> color_eyre::Result<()> { + let docs = match Self::get_docs() { + Value::Object(obj) => obj, + _ => unreachable!("As top level structure is always object"), + }; + let mut vec = Vec::new(); + let defaults = serde_json::to_string_pretty(&Self::default())?; + + writeln!(writer, "# Iroha Configuration reference\n")?; + writeln!(writer, "In this document we provide a reference and detailed descriptions of Iroha's configuration options.\n")?; + writeln!(writer, "## Default configuration\n")?; + writeln!( + writer, + "The following is the default configuration used by Iroha.\n" + )?; + writeln!(writer, "```json\n{}\n```\n", defaults)?; + Self::get_markdown_with_depth(writer, &docs, &mut vec, 2)?; + Ok(()) + } + + fn get_markdown_with_depth( + writer: &mut W, + docs: &serde_json::Map, + field: &mut Vec, + depth: usize, + ) -> color_eyre::Result<()> { + let current_field = { + let mut docs = docs; + for f in &*field { + docs = match &docs[f] { + Value::Object(obj) => obj, + _ => unreachable!(), + }; + } + docs + }; + + for (f, value) in current_field { + field.push(f.clone()); + let get_field = field.iter().map(AsRef::as_ref).collect::>(); + let (doc, inner) = match value { + Value::Object(_) => { + let doc = Self::get_doc_recursive(&get_field) + .expect("Should be there, as already in docs"); + (doc.unwrap_or_default().to_owned(), true) + } + Value::String(s) => (s.clone(), false), + _ => unreachable!("Only strings and objects in docs"), + }; + let doc = doc.strip_prefix(' ').unwrap_or(&doc); + let defaults = Self::default() + .get_recursive(get_field) + .expect("Failed to get defaults."); + let defaults = serde_json::to_string_pretty(&defaults)?; + let field_str = field + .join(".") + .chars() + .filter(|&chr| chr != ' ') + .collect::(); + + write!(writer, "{} `{}`\n\n", "#".repeat(depth), field_str)?; + write!(writer, "{}\n\n", doc)?; + write!(writer, "```json\n{}\n```\n\n", defaults)?; + + if inner { + Self::get_markdown_with_depth(writer, docs, field, depth + 1)?; + } + + field.pop(); + } + Ok(()) + } + } +} diff --git a/version/src/lib.rs b/version/src/lib.rs index d03895eef0f..576c9bcf3c4 100644 --- a/version/src/lib.rs +++ b/version/src/lib.rs @@ -217,7 +217,7 @@ pub mod json { use super::{error::Result, Version}; /// [`Serialize`] versioned analog, specifically for JSON. - pub trait DeserializeVersioned<'a>: Deserialize<'a> + Version { + pub trait DeserializeVersioned<'de>: Deserialize<'de> + Version { /// Use this function for versioned objects instead of [`serde_json::from_str`]. /// /// # Errors