From 5d26731e86522baaab967ad9d4df1b4e72d99231 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 2 Nov 2020 20:41:21 +0100 Subject: [PATCH 01/60] Fix URIs --- metadata/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index 28507415..829f74b3 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -33,9 +33,9 @@ //! .version(Version::new(2, 1, 0)) //! .authors(vec!["Parity Technologies ".to_string()]) //! .description("increment a value".to_string()) -//! .documentation(Url::parse("http:docs.rs/").unwrap()) -//! .repository(Url::parse("http:github.com/paritytech/ink/").unwrap()) -//! .homepage(Url::parse("http:example.com/").unwrap()) +//! .documentation(Url::parse("http://docs.rs/").unwrap()) +//! .repository(Url::parse("http://github.com/paritytech/ink/").unwrap()) +//! .homepage(Url::parse("http://example.com/").unwrap()) //! .license("Apache-2.0".to_string()) //! .build() //! .unwrap(); -- GitLab From 806929f81096aafab6bebeb22bf7b9fb8c67ea3c Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 2 Nov 2020 20:52:58 +0100 Subject: [PATCH 02/60] Make `generate-metadata` output consistent with `build` --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index d6698c2b..ad22e566 100644 --- a/src/main.rs +++ b/src/main.rs @@ -274,8 +274,8 @@ fn exec(cmd: Command) -> Result { unstable_options.try_into()?, )?; Ok(format!( - "Your metadata file is ready.\nYou can find it here:\n{}", - metadata_file.display() + "\nYour metadata file is ready.\nYou can find it here:\n{}", + metadata_file.display().to_string().bold() )) } Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")), -- GitLab From 7161a6dd7aed975a5fc1f2b04913e4dd8dc02ce6 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 2 Nov 2020 20:41:27 +0100 Subject: [PATCH 03/60] Add `cargo contract pack` --- metadata/lib.rs | 53 +++++++++++++++++++++++++++++++---- src/cmd/metadata.rs | 67 ++++++++++++++++++++++++++++++++------------- src/main.rs | 29 ++++++++++++++++++++ 3 files changed, 125 insertions(+), 24 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index 829f74b3..59953a3d 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -27,7 +27,8 @@ //! //! let language = SourceLanguage::new(Language::Ink, Version::new(2, 1, 0)); //! let compiler = SourceCompiler::new(Compiler::RustC, Version::parse("1.46.0-nightly").unwrap()); -//! let source = Source::new([0u8; 32], language, compiler); +//! let wasm = SourceWasm::new(vec![0u8]); +//! let source = Source::new(Some(wasm), [0u8; 32], language, compiler); //! let contract = Contract::builder() //! .name("incrementer".to_string()) //! .version(Version::new(2, 1, 0)) @@ -100,16 +101,56 @@ pub struct Source { hash: [u8; 32], language: SourceLanguage, compiler: SourceCompiler, + #[serde(skip_serializing_if = "Option::is_none")] + wasm: Option, } impl Source { /// Constructs a new InkProjectSource. - pub fn new(hash: [u8; 32], language: SourceLanguage, compiler: SourceCompiler) -> Self { + pub fn new( + wasm: Option, + hash: [u8; 32], + language: SourceLanguage, + compiler: SourceCompiler, + ) -> Self { Source { hash, language, compiler, + wasm, + } + } +} + +/// The bytes of the compiled Wasm smart contract. +#[derive(Debug)] +pub struct SourceWasm { + wasm: Vec, +} + +impl SourceWasm { + /// Constructs a new `SourceWasm`. + pub fn new(wasm: Vec) -> Self { + SourceWasm { wasm } + } +} + +impl Serialize for SourceWasm { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serialize_as_byte_str(&self.wasm[..], serializer) + } +} + +impl Display for SourceWasm { + fn fmt(&self, f: &mut Formatter<'_>) -> DisplayResult { + write!(f, "0x").expect("failed writing to string"); + for byte in &self.wasm { + write!(f, "{:02x}", byte).expect("failed writing to string"); } + write!(f, "") } } @@ -463,7 +504,8 @@ mod tests { let language = SourceLanguage::new(Language::Ink, Version::new(2, 1, 0)); let compiler = SourceCompiler::new(Compiler::RustC, Version::parse("1.46.0-nightly").unwrap()); - let source = Source::new([0u8; 32], language, compiler); + let wasm = SourceWasm::new(vec![0u8, 1u8, 2u8]); + let source = Source::new(Some(wasm), [0u8; 32], language, compiler); let contract = Contract::builder() .name("incrementer".to_string()) .version(Version::new(2, 1, 0)) @@ -507,7 +549,8 @@ mod tests { "source": { "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "language": "ink! 2.1.0", - "compiler": "rustc 1.46.0-nightly" + "compiler": "rustc 1.46.0-nightly", + "wasm": "0x000102" }, "contract": { "name": "incrementer", @@ -544,7 +587,7 @@ mod tests { let language = SourceLanguage::new(Language::Ink, Version::new(2, 1, 0)); let compiler = SourceCompiler::new(Compiler::RustC, Version::parse("1.46.0-nightly").unwrap()); - let source = Source::new([0u8; 32], language, compiler); + let source = Source::new(None, [0u8; 32], language, compiler); let contract = Contract::builder() .name("incrementer".to_string()) .version(Version::new(2, 1, 0)) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 15393910..44b29920 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -21,8 +21,10 @@ use crate::{ UnstableFlags, Verbosity, }; use anyhow::Result; +use blake2::digest::{Update as _, VariableOutput as _}; use contract_metadata::{ - Compiler, Contract, ContractMetadata, Language, Source, SourceCompiler, SourceLanguage, User, + Compiler, Contract, ContractMetadata, Language, Source, SourceCompiler, SourceLanguage, + SourceWasm, User, }; use semver::Version; use std::{fs, path::PathBuf}; @@ -34,6 +36,7 @@ const METADATA_FILE: &str = "metadata.json"; struct GenerateMetadataCommand { crate_metadata: CrateMetadata, verbosity: Option, + include_wasm: bool, unstable_options: UnstableFlags, } @@ -112,7 +115,16 @@ impl GenerateMetadataCommand { let source = { let lang = SourceLanguage::new(Language::Ink, ink_version.clone()); let compiler = SourceCompiler::new(Compiler::RustC, rust_version); - Source::new(hash, lang, compiler) + let maybe_wasm = match self.include_wasm { + true => { + let wasm = fs::read(&self.crate_metadata.dest_wasm)?; + // The Wasm which we read must have the same hash as `source.hash` + debug_assert_eq!(blake2_hash(wasm.clone().as_slice()), hash); + Some(SourceWasm::new(wasm)) + } + false => None, + }; + Source::new(maybe_wasm, hash, lang, compiler) }; // Required contract fields @@ -161,28 +173,33 @@ impl GenerateMetadataCommand { )?; let wasm = fs::read(&self.crate_metadata.dest_wasm)?; - - use ::blake2::digest::{Update as _, VariableOutput as _}; - let mut output = [0u8; 32]; - let mut blake2 = blake2::VarBlake2b::new_keyed(&[], 32); - blake2.update(wasm); - blake2.finalize_variable(|result| output.copy_from_slice(result)); - Ok(output) + Ok(blake2_hash(wasm.as_slice())) } } +/// Returns the blake2 hash of the submitted slice. +fn blake2_hash(code: &[u8]) -> [u8; 32] { + let mut output = [0u8; 32]; + let mut blake2 = blake2::VarBlake2b::new_keyed(&[], 32); + blake2.update(code); + blake2.finalize_variable(|result| output.copy_from_slice(result)); + output +} + /// Generates a file with metadata describing the ABI of the smart-contract. /// /// It does so by generating and invoking a temporary workspace member. pub(crate) fn execute( manifest_path: ManifestPath, verbosity: Option, + include_wasm: bool, unstable_options: UnstableFlags, ) -> Result { let crate_metadata = CrateMetadata::collect(&manifest_path)?; GenerateMetadataCommand { crate_metadata, verbosity, + include_wasm, unstable_options, } .exec() @@ -287,9 +304,13 @@ mod tests { test_manifest.write()?; let crate_metadata = CrateMetadata::collect(&test_manifest.manifest_path)?; - let metadata_file = - cmd::metadata::execute(test_manifest.manifest_path, None, UnstableFlags::default()) - .expect("generate metadata failed"); + let metadata_file = cmd::metadata::execute( + test_manifest.manifest_path, + None, + true, + UnstableFlags::default(), + ) + .expect("generate metadata failed"); let metadata_json: Map = serde_json::from_slice(&fs::read(&metadata_file)?)?; @@ -302,6 +323,7 @@ mod tests { let hash = source.get("hash").expect("source.hash not found"); let language = source.get("language").expect("source.language not found"); let compiler = source.get("compiler").expect("source.compiler not found"); + let wasm = source.get("wasm").expect("source.wasm not found"); let contract = metadata_json.get("contract").expect("contract not found"); let name = contract.get("name").expect("contract.name not found"); @@ -331,17 +353,14 @@ mod tests { let user = metadata_json.get("user").expect("user section not found"); // calculate wasm hash - let wasm = fs::read(&crate_metadata.dest_wasm)?; + let fs_wasm = fs::read(&crate_metadata.dest_wasm)?; let mut output = [0u8; 32]; let mut blake2 = blake2::VarBlake2b::new_keyed(&[], 32); - blake2.update(wasm); + blake2.update(fs_wasm.clone()); blake2.finalize_variable(|result| output.copy_from_slice(result)); + let expected_hash = build_byte_str(&output); + let expected_wasm = build_byte_str(&fs_wasm); - let mut expected_hash = String::new(); - write!(expected_hash, "0x").expect("failed writing to string"); - for byte in &output { - write!(expected_hash, "{:02x}", byte).expect("failed writing to string"); - } let expected_language = SourceLanguage::new(Language::Ink, crate_metadata.ink_version).to_string(); let expected_rustc_version = @@ -359,6 +378,7 @@ mod tests { ); assert_eq!(expected_hash, hash.as_str().unwrap()); + assert_eq!(expected_wasm, wasm.as_str().unwrap()); assert_eq!(expected_language, language.as_str().unwrap()); assert_eq!(expected_compiler, compiler.as_str().unwrap()); assert_eq!(crate_metadata.package_name, name.as_str().unwrap()); @@ -377,4 +397,13 @@ mod tests { Ok(()) }) } + + fn build_byte_str(bytes: &[u8]) -> String { + let mut str = String::new(); + write!(str, "0x").expect("failed writing to string"); + for byte in bytes { + write!(str, "{:02x}", byte).expect("failed writing to string"); + } + str + } } diff --git a/src/main.rs b/src/main.rs index ad22e566..d3fc18ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -173,6 +173,17 @@ enum Command { #[structopt(flatten)] unstable_options: UnstableOptions, }, + /// Compiles the contract, generates metadata, packs both together in one file + #[structopt(name = "pack")] + Pack { + /// Path to the Cargo.toml of the contract to build and pack + #[structopt(long, parse(from_os_str))] + manifest_path: Option, + #[structopt(flatten)] + verbosity: VerbosityFlags, + #[structopt(flatten)] + unstable_options: UnstableOptions, + }, /// Generate contract metadata artifacts #[structopt(name = "generate-metadata")] GenerateMetadata { @@ -262,6 +273,23 @@ fn exec(cmd: Command) -> Result { dest_wasm.display().to_string().bold() )) } + Command::Pack { + manifest_path, + verbosity, + unstable_options, + } => { + let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; + let pack_file = cmd::metadata::execute( + manifest_path, + verbosity.try_into()?, + true, + unstable_options.try_into()?, + )?; + Ok(format!( + "\nYour packed contract is ready. You can find it here:\n{}", + pack_file.display().to_string().bold() + )) + } Command::GenerateMetadata { manifest_path, verbosity, @@ -271,6 +299,7 @@ fn exec(cmd: Command) -> Result { let metadata_file = cmd::metadata::execute( manifest_path, verbosity.try_into()?, + false, unstable_options.try_into()?, )?; Ok(format!( -- GitLab From 5e3f520afda74681e7cc813e8f555d8da638d125 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 3 Nov 2020 17:55:25 +0100 Subject: [PATCH 04/60] Return error instead of panicking --- src/cmd/metadata.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 44b29920..8aef4523 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -309,8 +309,7 @@ mod tests { None, true, UnstableFlags::default(), - ) - .expect("generate metadata failed"); + )?; let metadata_json: Map = serde_json::from_slice(&fs::read(&metadata_file)?)?; -- GitLab From e7fbabadcdf7d7aef464dac65594499cb0144bf4 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 3 Nov 2020 18:02:00 +0100 Subject: [PATCH 05/60] Use blake2_hash() --- src/cmd/metadata.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 8aef4523..3c511e5f 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -353,11 +353,7 @@ mod tests { // calculate wasm hash let fs_wasm = fs::read(&crate_metadata.dest_wasm)?; - let mut output = [0u8; 32]; - let mut blake2 = blake2::VarBlake2b::new_keyed(&[], 32); - blake2.update(fs_wasm.clone()); - blake2.finalize_variable(|result| output.copy_from_slice(result)); - let expected_hash = build_byte_str(&output); + let expected_hash = blake2_hash(&fs_wasm[..]); let expected_wasm = build_byte_str(&fs_wasm); let expected_language = -- GitLab From 61f7261e41ffb641ce4f52b3016a6e92554a7c96 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 3 Nov 2020 18:03:24 +0100 Subject: [PATCH 06/60] Replace match with if --- src/cmd/metadata.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 3c511e5f..ac1e0585 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -115,14 +115,13 @@ impl GenerateMetadataCommand { let source = { let lang = SourceLanguage::new(Language::Ink, ink_version.clone()); let compiler = SourceCompiler::new(Compiler::RustC, rust_version); - let maybe_wasm = match self.include_wasm { - true => { - let wasm = fs::read(&self.crate_metadata.dest_wasm)?; - // The Wasm which we read must have the same hash as `source.hash` - debug_assert_eq!(blake2_hash(wasm.clone().as_slice()), hash); - Some(SourceWasm::new(wasm)) - } - false => None, + let maybe_wasm = if self.include_wasm { + let wasm = fs::read(&self.crate_metadata.dest_wasm)?; + // The Wasm which we read must have the same hash as `source.hash` + debug_assert_eq!(blake2_hash(wasm.clone().as_slice()), hash); + Some(SourceWasm::new(wasm)) + } else { + None }; Source::new(maybe_wasm, hash, lang, compiler) }; -- GitLab From 6cc0a67ef092703f91f870c7bc23a93431c8b6eb Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 3 Nov 2020 18:20:11 +0100 Subject: [PATCH 07/60] Pass reference instead of ownership --- src/cmd/metadata.rs | 4 ++-- src/main.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index ac1e0585..1603fa08 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -189,12 +189,12 @@ fn blake2_hash(code: &[u8]) -> [u8; 32] { /// /// It does so by generating and invoking a temporary workspace member. pub(crate) fn execute( - manifest_path: ManifestPath, + manifest_path: &ManifestPath, verbosity: Option, include_wasm: bool, unstable_options: UnstableFlags, ) -> Result { - let crate_metadata = CrateMetadata::collect(&manifest_path)?; + let crate_metadata = CrateMetadata::collect(manifest_path)?; GenerateMetadataCommand { crate_metadata, verbosity, diff --git a/src/main.rs b/src/main.rs index d3fc18ba..f316c80d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -297,7 +297,7 @@ fn exec(cmd: Command) -> Result { } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; let metadata_file = cmd::metadata::execute( - manifest_path, + &manifest_path, verbosity.try_into()?, false, unstable_options.try_into()?, -- GitLab From d9eb49e75a1bb110e896dc6daa7b7183f9bceed7 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 3 Nov 2020 18:20:59 +0100 Subject: [PATCH 08/60] Generate metadata.json and .pack --- src/cmd/metadata.rs | 7 ++++++- src/main.rs | 12 ++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 1603fa08..e61d347b 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -46,7 +46,12 @@ impl GenerateMetadataCommand { println!(" Generating metadata"); let cargo_meta = &self.crate_metadata.cargo_meta; - let out_path = cargo_meta.target_directory.join(METADATA_FILE); + let out_path = if self.include_wasm { + let fname = format!("{}.pack", self.crate_metadata.package_name); + cargo_meta.target_directory.join(fname) + } else { + cargo_meta.target_directory.join(METADATA_FILE) + }; let target_dir = cargo_meta.target_directory.clone(); // build the extended contract project metadata diff --git a/src/main.rs b/src/main.rs index f316c80d..2d338b38 100644 --- a/src/main.rs +++ b/src/main.rs @@ -279,14 +279,22 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; + let metadata_file = cmd::metadata::execute( + &manifest_path, + verbosity.try_into()?, + false, + unstable_options.try_into()?, + )?; let pack_file = cmd::metadata::execute( - manifest_path, + &manifest_path, verbosity.try_into()?, true, unstable_options.try_into()?, )?; Ok(format!( - "\nYour packed contract is ready. You can find it here:\n{}", + "\nYour metadata file is ready.\nYou can find it here:\n{} + \nYour packed contract is ready. You can find it here:\n{}", + metadata_file.display().to_string().bold(), pack_file.display().to_string().bold() )) } -- GitLab From 4d1edfa280e4515b1728c8365ef143b0a26b5da7 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 3 Nov 2020 18:30:46 +0100 Subject: [PATCH 09/60] Output .wasm, .json, .pack --- src/cmd/metadata.rs | 20 ++++++++++---------- src/main.rs | 10 ++++++---- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index e61d347b..5cd1ae0d 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -41,7 +41,7 @@ struct GenerateMetadataCommand { } impl GenerateMetadataCommand { - pub fn exec(&self) -> Result { + pub fn exec(&self) -> Result<(PathBuf, PathBuf)> { util::assert_channel()?; println!(" Generating metadata"); @@ -55,7 +55,7 @@ impl GenerateMetadataCommand { let target_dir = cargo_meta.target_directory.clone(); // build the extended contract project metadata - let (source_meta, contract_meta, user_meta) = self.extended_metadata()?; + let (dest_wasm, source_meta, contract_meta, user_meta) = self.extended_metadata()?; let generate_metadata = |manifest_path: &ManifestPath| -> Result<()> { let target_dir_arg = format!("--target-dir={}", target_dir.to_string_lossy()); @@ -94,11 +94,11 @@ impl GenerateMetadataCommand { .using_temp(generate_metadata)?; } - Ok(out_path) + Ok((out_path, dest_wasm)) } /// Generate the extended contract project metadata - fn extended_metadata(&self) -> Result<(Source, Contract, Option)> { + fn extended_metadata(&self) -> Result<(PathBuf, Source, Contract, Option)> { let contract_package = &self.crate_metadata.root_package; let ink_version = &self.crate_metadata.ink_version; let rust_version = Version::parse(&rustc_version::version()?.to_string())?; @@ -115,7 +115,7 @@ impl GenerateMetadataCommand { .transpose()?; let homepage = self.crate_metadata.homepage.clone(); let license = contract_package.license.clone(); - let hash = self.wasm_hash()?; + let (dest_wasm, hash) = self.wasm_hash()?; let source = { let lang = SourceLanguage::new(Language::Ink, ink_version.clone()); @@ -165,19 +165,19 @@ impl GenerateMetadataCommand { // user defined metadata let user = self.crate_metadata.user.clone().map(User::new); - Ok((source, contract, user)) + Ok((dest_wasm, source, contract, user)) } /// Compile the contract and then hash the resulting wasm - fn wasm_hash(&self) -> Result<[u8; 32]> { - super::build::execute_with_metadata( + fn wasm_hash(&self) -> Result<(PathBuf, [u8; 32])> { + let dest_wasm = super::build::execute_with_metadata( &self.crate_metadata, self.verbosity, self.unstable_options.clone(), )?; let wasm = fs::read(&self.crate_metadata.dest_wasm)?; - Ok(blake2_hash(wasm.as_slice())) + Ok((dest_wasm, blake2_hash(wasm.as_slice()))) } } @@ -198,7 +198,7 @@ pub(crate) fn execute( verbosity: Option, include_wasm: bool, unstable_options: UnstableFlags, -) -> Result { +) -> Result<(PathBuf, PathBuf)> { let crate_metadata = CrateMetadata::collect(manifest_path)?; GenerateMetadataCommand { crate_metadata, diff --git a/src/main.rs b/src/main.rs index 2d338b38..f2b36bd4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -279,21 +279,23 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let metadata_file = cmd::metadata::execute( + let (metadata_file, _dest_wasm) = cmd::metadata::execute( &manifest_path, verbosity.try_into()?, false, unstable_options.try_into()?, )?; - let pack_file = cmd::metadata::execute( + let (pack_file, dest_wasm) = cmd::metadata::execute( &manifest_path, verbosity.try_into()?, true, unstable_options.try_into()?, )?; Ok(format!( - "\nYour metadata file is ready.\nYou can find it here:\n{} + "\nYour contract is ready. You can find it here:\n{} + \nYour metadata file is ready. You can find it here:\n{} \nYour packed contract is ready. You can find it here:\n{}", + dest_wasm.display().to_string().bold(), metadata_file.display().to_string().bold(), pack_file.display().to_string().bold() )) @@ -304,7 +306,7 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let metadata_file = cmd::metadata::execute( + let (metadata_file, _dest_wasm) = cmd::metadata::execute( &manifest_path, verbosity.try_into()?, false, -- GitLab From 0eb1949d52b81de8f830942eb9f597459a7cfd15 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 3 Nov 2020 18:41:14 +0100 Subject: [PATCH 10/60] Return result object instead of tuple --- src/cmd/metadata.rs | 17 ++++++++++++++--- src/main.rs | 14 +++++++------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 5cd1ae0d..99ae39ed 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -32,6 +32,14 @@ use url::Url; const METADATA_FILE: &str = "metadata.json"; +/// Result of the metadata generation process. +pub struct GenerateMetadataResult { + /// Path to the resulting metadata file. + pub metadata_file: PathBuf, + /// Path to the resulting Wasm file. + pub wasm_file: PathBuf, +} + /// Executes the metadata generation process struct GenerateMetadataCommand { crate_metadata: CrateMetadata, @@ -41,7 +49,7 @@ struct GenerateMetadataCommand { } impl GenerateMetadataCommand { - pub fn exec(&self) -> Result<(PathBuf, PathBuf)> { + pub fn exec(&self) -> Result { util::assert_channel()?; println!(" Generating metadata"); @@ -94,7 +102,10 @@ impl GenerateMetadataCommand { .using_temp(generate_metadata)?; } - Ok((out_path, dest_wasm)) + Ok(GenerateMetadataResult { + metadata_file: out_path, + wasm_file: dest_wasm, + }) } /// Generate the extended contract project metadata @@ -198,7 +209,7 @@ pub(crate) fn execute( verbosity: Option, include_wasm: bool, unstable_options: UnstableFlags, -) -> Result<(PathBuf, PathBuf)> { +) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; GenerateMetadataCommand { crate_metadata, diff --git a/src/main.rs b/src/main.rs index f2b36bd4..4d55c8f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -279,13 +279,13 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let (metadata_file, _dest_wasm) = cmd::metadata::execute( + let metadata_result = cmd::metadata::execute( &manifest_path, verbosity.try_into()?, false, unstable_options.try_into()?, )?; - let (pack_file, dest_wasm) = cmd::metadata::execute( + let pack_result = cmd::metadata::execute( &manifest_path, verbosity.try_into()?, true, @@ -295,9 +295,9 @@ fn exec(cmd: Command) -> Result { "\nYour contract is ready. You can find it here:\n{} \nYour metadata file is ready. You can find it here:\n{} \nYour packed contract is ready. You can find it here:\n{}", - dest_wasm.display().to_string().bold(), - metadata_file.display().to_string().bold(), - pack_file.display().to_string().bold() + pack_result.wasm_file.display().to_string().bold(), + metadata_result.metadata_file.display().to_string().bold(), + pack_result.metadata_file.display().to_string().bold() )) } Command::GenerateMetadata { @@ -306,7 +306,7 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let (metadata_file, _dest_wasm) = cmd::metadata::execute( + let res = cmd::metadata::execute( &manifest_path, verbosity.try_into()?, false, @@ -314,7 +314,7 @@ fn exec(cmd: Command) -> Result { )?; Ok(format!( "\nYour metadata file is ready.\nYou can find it here:\n{}", - metadata_file.display().to_string().bold() + res.metadata_file.display().to_string().bold(), )) } Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")), -- GitLab From 3b3206efb6fb1d445e690565ce8119813926829a Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 3 Nov 2020 18:58:41 +0100 Subject: [PATCH 11/60] Get it to run with '--features test-ci-only' --- src/cmd/metadata.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 99ae39ed..7fda3cc5 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -223,10 +223,10 @@ pub(crate) fn execute( #[cfg(feature = "test-ci-only")] #[cfg(test)] mod tests { + use crate::cmd::metadata::blake2_hash; use crate::{ cmd, crate_metadata::CrateMetadata, util::tests::with_tmp_dir, ManifestPath, UnstableFlags, }; - use blake2::digest::{Update as _, VariableOutput as _}; use contract_metadata::*; use serde_json::{Map, Value}; use std::{fmt::Write, fs}; @@ -320,11 +320,12 @@ mod tests { let crate_metadata = CrateMetadata::collect(&test_manifest.manifest_path)?; let metadata_file = cmd::metadata::execute( - test_manifest.manifest_path, + &test_manifest.manifest_path, None, true, UnstableFlags::default(), - )?; + )? + .metadata_file; let metadata_json: Map = serde_json::from_slice(&fs::read(&metadata_file)?)?; @@ -387,7 +388,7 @@ mod tests { ), ); - assert_eq!(expected_hash, hash.as_str().unwrap()); + assert_eq!(build_byte_str(&expected_hash[..]), hash.as_str().unwrap()); assert_eq!(expected_wasm, wasm.as_str().unwrap()); assert_eq!(expected_language, language.as_str().unwrap()); assert_eq!(expected_compiler, compiler.as_str().unwrap()); -- GitLab From f5450d6589629eb4adeea51c56fb969321e647e1 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 4 Nov 2020 14:01:39 +0100 Subject: [PATCH 12/60] Rename .pack to .contract --- src/cmd/metadata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 7fda3cc5..75f7c332 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -55,7 +55,7 @@ impl GenerateMetadataCommand { let cargo_meta = &self.crate_metadata.cargo_meta; let out_path = if self.include_wasm { - let fname = format!("{}.pack", self.crate_metadata.package_name); + let fname = format!("{}.contract", self.crate_metadata.package_name); cargo_meta.target_directory.join(fname) } else { cargo_meta.target_directory.join(METADATA_FILE) -- GitLab From c71639ff84963b4079a09165b881ebb4f54c922f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Wed, 4 Nov 2020 14:02:14 +0100 Subject: [PATCH 13/60] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Theißen --- src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4d55c8f6..0599ab8e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -292,9 +292,9 @@ fn exec(cmd: Command) -> Result { unstable_options.try_into()?, )?; Ok(format!( - "\nYour contract is ready. You can find it here:\n{} - \nYour metadata file is ready. You can find it here:\n{} - \nYour packed contract is ready. You can find it here:\n{}", + "\nYour contract's code is ready. You can find it here:\n{} + \nYour contract's metadata is ready. You can find it here:\n{} + \nYour contract bundle (code + metadata) is ready. You can find it here:\n{}", pack_result.wasm_file.display().to_string().bold(), metadata_result.metadata_file.display().to_string().bold(), pack_result.metadata_file.display().to_string().bold() @@ -313,7 +313,7 @@ fn exec(cmd: Command) -> Result { unstable_options.try_into()?, )?; Ok(format!( - "\nYour metadata file is ready.\nYou can find it here:\n{}", + "\nYour metadata is ready.\nYou can find it here:\n{}", res.metadata_file.display().to_string().bold(), )) } -- GitLab From 2aa7c9645706491cdebb3905a3c8287eb630206c Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 4 Nov 2020 16:20:25 +0100 Subject: [PATCH 14/60] Introduce '--skip-packing' and '--skip-metadata' --- src/main.rs | 85 ++++++++++++++++++----------------------------------- 1 file changed, 29 insertions(+), 56 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0599ab8e..ecadda91 100644 --- a/src/main.rs +++ b/src/main.rs @@ -162,34 +162,18 @@ enum Command { #[structopt(short, long, parse(from_os_str))] target_dir: Option, }, - /// Compiles the smart contract + /// Compiles the contract, generates metadata, packs both together in one .contract file #[structopt(name = "build")] Build { /// Path to the Cargo.toml of the contract to build #[structopt(long, parse(from_os_str))] manifest_path: Option, - #[structopt(flatten)] - verbosity: VerbosityFlags, - #[structopt(flatten)] - unstable_options: UnstableOptions, - }, - /// Compiles the contract, generates metadata, packs both together in one file - #[structopt(name = "pack")] - Pack { - /// Path to the Cargo.toml of the contract to build and pack - #[structopt(long, parse(from_os_str))] - manifest_path: Option, - #[structopt(flatten)] - verbosity: VerbosityFlags, - #[structopt(flatten)] - unstable_options: UnstableOptions, - }, - /// Generate contract metadata artifacts - #[structopt(name = "generate-metadata")] - GenerateMetadata { - /// Path to the Cargo.toml of the contract for which to generate metadata - #[structopt(long, parse(from_os_str))] - manifest_path: Option, + /// Only the Wasm and the metadata are generated, no packed .contract file is created + #[structopt(long = "skip-packing", conflicts_with = "skip-metadata")] + skip_packing: bool, + /// Only the Wasm is created, generation of metadata and a packed .contract file is skipped + #[structopt(long = "skip-metadata", conflicts_with = "skip-packing")] + skip_metadata: bool, #[structopt(flatten)] verbosity: VerbosityFlags, #[structopt(flatten)] @@ -260,24 +244,22 @@ fn exec(cmd: Command) -> Result { Command::Build { manifest_path, verbosity, + skip_packing, + skip_metadata, unstable_options, } => { - let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let dest_wasm = cmd::build::execute( - &manifest_path, - verbosity.try_into()?, - unstable_options.try_into()?, - )?; - Ok(format!( - "\nYour contract is ready. You can find it here:\n{}", - dest_wasm.display().to_string().bold() - )) - } - Command::Pack { - manifest_path, - verbosity, - unstable_options, - } => { + if *(skip_metadata) { + let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; + let dest_wasm = cmd::build::execute( + &manifest_path, + verbosity.try_into()?, + unstable_options.try_into()?, + )?; + return Ok(format!( + "\nYour contract is ready. You can find it here:\n{}", + dest_wasm.display().to_string().bold() + )); + } let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; let metadata_result = cmd::metadata::execute( &manifest_path, @@ -285,6 +267,14 @@ fn exec(cmd: Command) -> Result { false, unstable_options.try_into()?, )?; + if *(skip_packing) { + return Ok(format!( + "\nYour contract's code is ready. You can find it here:\n{} + \nYour contract's metadata is ready. You can find it here:\n{}", + metadata_result.wasm_file.display().to_string().bold(), + metadata_result.metadata_file.display().to_string().bold(), + )); + } let pack_result = cmd::metadata::execute( &manifest_path, verbosity.try_into()?, @@ -300,23 +290,6 @@ fn exec(cmd: Command) -> Result { pack_result.metadata_file.display().to_string().bold() )) } - Command::GenerateMetadata { - manifest_path, - verbosity, - unstable_options, - } => { - let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let res = cmd::metadata::execute( - &manifest_path, - verbosity.try_into()?, - false, - unstable_options.try_into()?, - )?; - Ok(format!( - "\nYour metadata is ready.\nYou can find it here:\n{}", - res.metadata_file.display().to_string().bold(), - )) - } Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")), #[cfg(feature = "extrinsics")] Command::Deploy { -- GitLab From b40a82e787f6716bcc5ad4e1a3d3021ae98b1758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Thu, 5 Nov 2020 10:49:57 +0100 Subject: [PATCH 15/60] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Theißen --- src/main.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main.rs b/src/main.rs index ecadda91..ead760a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -162,17 +162,17 @@ enum Command { #[structopt(short, long, parse(from_os_str))] target_dir: Option, }, - /// Compiles the contract, generates metadata, packs both together in one .contract file + /// Compiles the contract, generates metadata, bundles both together in one .contract file #[structopt(name = "build")] Build { /// Path to the Cargo.toml of the contract to build #[structopt(long, parse(from_os_str))] manifest_path: Option, - /// Only the Wasm and the metadata are generated, no packed .contract file is created - #[structopt(long = "skip-packing", conflicts_with = "skip-metadata")] - skip_packing: bool, + /// Only the Wasm and the metadata are generated, no bundled .contract file is created + #[structopt(long = "skip-bundle", conflicts_with = "skip-metadata")] + skip_bundle: bool, /// Only the Wasm is created, generation of metadata and a packed .contract file is skipped - #[structopt(long = "skip-metadata", conflicts_with = "skip-packing")] + #[structopt(long = "skip-metadata", conflicts_with = "skip-bundle")] skip_metadata: bool, #[structopt(flatten)] verbosity: VerbosityFlags, @@ -244,7 +244,7 @@ fn exec(cmd: Command) -> Result { Command::Build { manifest_path, verbosity, - skip_packing, + skip_bundle, skip_metadata, unstable_options, } => { @@ -256,7 +256,7 @@ fn exec(cmd: Command) -> Result { unstable_options.try_into()?, )?; return Ok(format!( - "\nYour contract is ready. You can find it here:\n{}", + "\nYour contract's code is ready. You can find it here:\n{}", dest_wasm.display().to_string().bold() )); } @@ -267,7 +267,7 @@ fn exec(cmd: Command) -> Result { false, unstable_options.try_into()?, )?; - if *(skip_packing) { + if *(skip_bundle) { return Ok(format!( "\nYour contract's code is ready. You can find it here:\n{} \nYour contract's metadata is ready. You can find it here:\n{}", @@ -275,7 +275,7 @@ fn exec(cmd: Command) -> Result { metadata_result.metadata_file.display().to_string().bold(), )); } - let pack_result = cmd::metadata::execute( + let bundle_result = cmd::metadata::execute( &manifest_path, verbosity.try_into()?, true, @@ -285,9 +285,9 @@ fn exec(cmd: Command) -> Result { "\nYour contract's code is ready. You can find it here:\n{} \nYour contract's metadata is ready. You can find it here:\n{} \nYour contract bundle (code + metadata) is ready. You can find it here:\n{}", - pack_result.wasm_file.display().to_string().bold(), + bundle_result.wasm_file.display().to_string().bold(), metadata_result.metadata_file.display().to_string().bold(), - pack_result.metadata_file.display().to_string().bold() + bundle_result.metadata_file.display().to_string().bold() )) } Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")), -- GitLab From bd6477f4d7f30e967850ed124a32b15902af065c Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 13:18:00 +0100 Subject: [PATCH 16/60] Short help message --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index ead760a3..cddd84c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -162,7 +162,7 @@ enum Command { #[structopt(short, long, parse(from_os_str))] target_dir: Option, }, - /// Compiles the contract, generates metadata, bundles both together in one .contract file + /// Compiles the contract, generates metadata, bundles both together in a '.contract' file #[structopt(name = "build")] Build { /// Path to the Cargo.toml of the contract to build -- GitLab From 294d206e7dc313bd44326ca59c647e5d9618a6f6 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 13:19:26 +0100 Subject: [PATCH 17/60] Output deprecated error for 'generate-metadata' --- src/main.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main.rs b/src/main.rs index cddd84c2..c49a31c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -179,6 +179,17 @@ enum Command { #[structopt(flatten)] unstable_options: UnstableOptions, }, + /// Command has been deprecated, use 'cargo contract build' instead + #[structopt(name = "generate-metadata")] + GenerateMetadata { + /// Path to the Cargo.toml of the contract to build + #[structopt(long, parse(from_os_str))] + manifest_path: Option, + #[structopt(flatten)] + verbosity: VerbosityFlags, + #[structopt(flatten)] + unstable_options: UnstableOptions, + }, /// Test the smart contract off-chain #[structopt(name = "test")] Test {}, @@ -290,6 +301,13 @@ fn exec(cmd: Command) -> Result { bundle_result.metadata_file.display().to_string().bold() )) } + Command::GenerateMetadata { + manifest_path: _, + verbosity: _, + unstable_options: _, + } => Err(anyhow::anyhow!(format!( + "Command deprecated, use 'cargo contract build' instead" + ))), Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")), #[cfg(feature = "extrinsics")] Command::Deploy { -- GitLab From bb6f5e5258b19b3c080cf72e352a561357e6081d Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 13:21:35 +0100 Subject: [PATCH 18/60] =?UTF-8?q?Rename=20pack=20=E2=9E=9C=20bundle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index c49a31c4..02f14747 100644 --- a/src/main.rs +++ b/src/main.rs @@ -171,7 +171,7 @@ enum Command { /// Only the Wasm and the metadata are generated, no bundled .contract file is created #[structopt(long = "skip-bundle", conflicts_with = "skip-metadata")] skip_bundle: bool, - /// Only the Wasm is created, generation of metadata and a packed .contract file is skipped + /// Only the Wasm is created, generation of metadata and a bundled .contract file is skipped #[structopt(long = "skip-metadata", conflicts_with = "skip-bundle")] skip_metadata: bool, #[structopt(flatten)] -- GitLab From 8b7f7128d8c942684d7e95c83673a43a7e26999e Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 13:25:00 +0100 Subject: [PATCH 19/60] Add 'cargo contract check' command --- src/main.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/main.rs b/src/main.rs index 02f14747..bf0d6df1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -190,6 +190,17 @@ enum Command { #[structopt(flatten)] unstable_options: UnstableOptions, }, + /// Check that the Wasm builds; does not optimize, generate metadata, or bundle + #[structopt(name = "check")] + Check { + /// Path to the Cargo.toml of the contract to build + #[structopt(long, parse(from_os_str))] + manifest_path: Option, + #[structopt(flatten)] + verbosity: VerbosityFlags, + #[structopt(flatten)] + unstable_options: UnstableOptions, + }, /// Test the smart contract off-chain #[structopt(name = "test")] Test {}, @@ -301,6 +312,22 @@ fn exec(cmd: Command) -> Result { bundle_result.metadata_file.display().to_string().bold() )) } + Command::Check { + manifest_path, + verbosity, + unstable_options, + } => { + let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; + let dest_wasm = cmd::build::execute( + &manifest_path, + verbosity.try_into()?, + unstable_options.try_into()?, + )?; + Ok(format!( + "\nYour contract's code was built successfully. You can find it here:\n{}", + dest_wasm.display().to_string().bold() + )) + } Command::GenerateMetadata { manifest_path: _, verbosity: _, -- GitLab From e89b6df33629ea34a630e23dd42e8ee0903bb0f6 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 13:32:10 +0100 Subject: [PATCH 20/60] Optimize resulting Wasm file, except on 'check' --- src/cmd/build.rs | 23 ++++++++++++++++------- src/cmd/metadata.rs | 1 + src/main.rs | 2 ++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 9c8cfec2..edcdd16e 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -241,9 +241,15 @@ pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Option, unstable_options: UnstableFlags, + optimize_contract: bool, ) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; - execute_with_metadata(&crate_metadata, verbosity, unstable_options) + execute_with_metadata( + &crate_metadata, + verbosity, + unstable_options, + optimize_contract, + ) } /// Executes build of the smart-contract which produces a wasm binary that is ready for deploying. @@ -257,6 +263,7 @@ pub(crate) fn execute_with_metadata( crate_metadata: &CrateMetadata, verbosity: Option, unstable_options: UnstableFlags, + optimize_contract: bool, ) -> Result { println!( " {} {}", @@ -270,12 +277,14 @@ pub(crate) fn execute_with_metadata( "Post processing wasm file".bright_green().bold() ); post_process_wasm(&crate_metadata)?; - println!( - " {} {}", - "[3/3]".bold(), - "Optimizing wasm file".bright_green().bold() - ); - optimize_wasm(&crate_metadata)?; + if optimize_contract { + println!( + " {} {}", + "[3/3]".bold(), + "Optimizing wasm file".bright_green().bold() + ); + optimize_wasm(&crate_metadata)?; + } Ok(crate_metadata.dest_wasm.clone()) } diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 75f7c332..5f1eaca0 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -185,6 +185,7 @@ impl GenerateMetadataCommand { &self.crate_metadata, self.verbosity, self.unstable_options.clone(), + true, )?; let wasm = fs::read(&self.crate_metadata.dest_wasm)?; diff --git a/src/main.rs b/src/main.rs index bf0d6df1..baaf81dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -276,6 +276,7 @@ fn exec(cmd: Command) -> Result { &manifest_path, verbosity.try_into()?, unstable_options.try_into()?, + true, )?; return Ok(format!( "\nYour contract's code is ready. You can find it here:\n{}", @@ -322,6 +323,7 @@ fn exec(cmd: Command) -> Result { &manifest_path, verbosity.try_into()?, unstable_options.try_into()?, + false, )?; Ok(format!( "\nYour contract's code was built successfully. You can find it here:\n{}", -- GitLab From 08507790d5f5b00c8fc4919c41dd86d7e95282c2 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 13:40:33 +0100 Subject: [PATCH 21/60] Do not make unoptimized file easily mistake for optimized one --- src/cmd/build.rs | 5 ++++- src/main.rs | 7 ++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index edcdd16e..dbc68029 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -243,7 +243,10 @@ pub(crate) fn execute( unstable_options: UnstableFlags, optimize_contract: bool, ) -> Result { - let crate_metadata = CrateMetadata::collect(manifest_path)?; + let mut crate_metadata = CrateMetadata::collect(manifest_path)?; + if !optimize_contract { + crate_metadata.dest_wasm.set_extension("wasm.unoptimized"); + } execute_with_metadata( &crate_metadata, verbosity, diff --git a/src/main.rs b/src/main.rs index baaf81dd..8da1b08f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -319,16 +319,13 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let dest_wasm = cmd::build::execute( + let _dest_unoptimized_wasm = cmd::build::execute( &manifest_path, verbosity.try_into()?, unstable_options.try_into()?, false, )?; - Ok(format!( - "\nYour contract's code was built successfully. You can find it here:\n{}", - dest_wasm.display().to_string().bold() - )) + Ok(format!("\nYour contract's code was built successfully.")) } Command::GenerateMetadata { manifest_path: _, -- GitLab From 4dc41b7f2ab6b3d5aa0ae90bddb212467b291922 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 13:44:42 +0100 Subject: [PATCH 22/60] Get it to run with --- src/cmd/build.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index dbc68029..6ec28db9 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -302,7 +302,8 @@ mod tests { cmd::new::execute("new_project", Some(path)).expect("new project creation failed"); let manifest_path = ManifestPath::new(&path.join("new_project").join("Cargo.toml")).unwrap(); - super::execute(&manifest_path, None, UnstableFlags::default()).expect("build failed"); + super::execute(&manifest_path, None, UnstableFlags::default(), true) + .expect("build failed"); Ok(()) }) } -- GitLab From 85efad844968403a3fe9d5089eee8748cd2f7b43 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 13:46:56 +0100 Subject: [PATCH 23/60] Update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c3d97847..5025e885 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,8 @@ OPTIONS: SUBCOMMANDS: new Setup and create a new smart contract project - build Compiles the smart contract - generate-metadata Generate contract metadata artifacts + build Compiles the contract, generates metadata, bundles both together in a '.contract' file + check Check that the Wasm builds; does not optimize, generate metadata, or bundle test Test the smart contract off-chain deploy Upload the smart contract code to the chain instantiate Instantiate a deployed smart contract -- GitLab From 44d3a8517f76fde40f1d95e47d873cf7313c4ac1 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 14:32:56 +0100 Subject: [PATCH 24/60] Make unoptimized wasm not show up in target folder --- src/cmd/build.rs | 26 ++++++++++++-------------- src/cmd/metadata.rs | 3 ++- src/main.rs | 6 ++++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 6ec28db9..54f00aee 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -242,11 +242,8 @@ pub(crate) fn execute( verbosity: Option, unstable_options: UnstableFlags, optimize_contract: bool, -) -> Result { - let mut crate_metadata = CrateMetadata::collect(manifest_path)?; - if !optimize_contract { - crate_metadata.dest_wasm.set_extension("wasm.unoptimized"); - } +) -> Result> { + let crate_metadata = CrateMetadata::collect(manifest_path)?; execute_with_metadata( &crate_metadata, verbosity, @@ -267,7 +264,7 @@ pub(crate) fn execute_with_metadata( verbosity: Option, unstable_options: UnstableFlags, optimize_contract: bool, -) -> Result { +) -> Result> { println!( " {} {}", "[1/3]".bold(), @@ -280,15 +277,16 @@ pub(crate) fn execute_with_metadata( "Post processing wasm file".bright_green().bold() ); post_process_wasm(&crate_metadata)?; - if optimize_contract { - println!( - " {} {}", - "[3/3]".bold(), - "Optimizing wasm file".bright_green().bold() - ); - optimize_wasm(&crate_metadata)?; + if !optimize_contract { + return Ok(None); } - Ok(crate_metadata.dest_wasm.clone()) + println!( + " {} {}", + "[3/3]".bold(), + "Optimizing wasm file".bright_green().bold() + ); + optimize_wasm(&crate_metadata)?; + Ok(Some(crate_metadata.dest_wasm.clone())) } #[cfg(feature = "test-ci-only")] diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 5f1eaca0..f52f5715 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -186,7 +186,8 @@ impl GenerateMetadataCommand { self.verbosity, self.unstable_options.clone(), true, - )?; + )? + .expect("dest_wasm must exist"); let wasm = fs::read(&self.crate_metadata.dest_wasm)?; Ok((dest_wasm, blake2_hash(wasm.as_slice()))) diff --git a/src/main.rs b/src/main.rs index 8da1b08f..0938e894 100644 --- a/src/main.rs +++ b/src/main.rs @@ -277,7 +277,8 @@ fn exec(cmd: Command) -> Result { verbosity.try_into()?, unstable_options.try_into()?, true, - )?; + )? + .expect("dest_wasm must exist"); return Ok(format!( "\nYour contract's code is ready. You can find it here:\n{}", dest_wasm.display().to_string().bold() @@ -319,12 +320,13 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let _dest_unoptimized_wasm = cmd::build::execute( + let maybe_dest_wasm = cmd::build::execute( &manifest_path, verbosity.try_into()?, unstable_options.try_into()?, false, )?; + assert!(maybe_dest_wasm.is_none(), "no dest_wasm should exist"); Ok(format!("\nYour contract's code was built successfully.")) } Command::GenerateMetadata { -- GitLab From 63a7131dd7f6cfddcec7a4920e842613312ce436 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 14:43:20 +0100 Subject: [PATCH 25/60] Update comments --- README.md | 2 +- src/main.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 5025e885..3550f866 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ OPTIONS: SUBCOMMANDS: new Setup and create a new smart contract project build Compiles the contract, generates metadata, bundles both together in a '.contract' file - check Check that the Wasm builds; does not optimize, generate metadata, or bundle + check Check that the code builds as Wasm; does not output any build artifact to the top level `target/` directory test Test the smart contract off-chain deploy Upload the smart contract code to the chain instantiate Instantiate a deployed smart contract diff --git a/src/main.rs b/src/main.rs index 0938e894..8e01c455 100644 --- a/src/main.rs +++ b/src/main.rs @@ -162,16 +162,16 @@ enum Command { #[structopt(short, long, parse(from_os_str))] target_dir: Option, }, - /// Compiles the contract, generates metadata, bundles both together in a '.contract' file + /// Compiles the contract, generates metadata, bundles both together in a `.contract` file #[structopt(name = "build")] Build { /// Path to the Cargo.toml of the contract to build #[structopt(long, parse(from_os_str))] manifest_path: Option, - /// Only the Wasm and the metadata are generated, no bundled .contract file is created + /// Only the Wasm and the metadata are generated, no bundled `.contract` file is created #[structopt(long = "skip-bundle", conflicts_with = "skip-metadata")] skip_bundle: bool, - /// Only the Wasm is created, generation of metadata and a bundled .contract file is skipped + /// Only the Wasm is created, generation of metadata and a bundled `.contract` file is skipped #[structopt(long = "skip-metadata", conflicts_with = "skip-bundle")] skip_metadata: bool, #[structopt(flatten)] @@ -179,7 +179,7 @@ enum Command { #[structopt(flatten)] unstable_options: UnstableOptions, }, - /// Command has been deprecated, use 'cargo contract build' instead + /// Command has been deprecated, use `cargo contract build` instead #[structopt(name = "generate-metadata")] GenerateMetadata { /// Path to the Cargo.toml of the contract to build @@ -190,7 +190,7 @@ enum Command { #[structopt(flatten)] unstable_options: UnstableOptions, }, - /// Check that the Wasm builds; does not optimize, generate metadata, or bundle + /// Check that the code builds as Wasm; does not output any build artifact to the top level `target/` directory #[structopt(name = "check")] Check { /// Path to the Cargo.toml of the contract to build @@ -210,7 +210,7 @@ enum Command { Deploy { #[structopt(flatten)] extrinsic_opts: ExtrinsicOpts, - /// Path to wasm contract code, defaults to ./target/-pruned.wasm + /// Path to wasm contract code, defaults to `./target/-pruned.wasm` #[structopt(parse(from_os_str))] wasm_path: Option, }, @@ -334,7 +334,7 @@ fn exec(cmd: Command) -> Result { verbosity: _, unstable_options: _, } => Err(anyhow::anyhow!(format!( - "Command deprecated, use 'cargo contract build' instead" + "Command deprecated, use `cargo contract build` instead" ))), Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")), #[cfg(feature = "extrinsics")] -- GitLab From 54a710514117b89d4f0787fa3c4cc35d999e9c34 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 5 Nov 2020 14:45:20 +0100 Subject: [PATCH 26/60] Remove 'generate-metadata' variants --- src/main.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8e01c455..cf20f8bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -181,15 +181,7 @@ enum Command { }, /// Command has been deprecated, use `cargo contract build` instead #[structopt(name = "generate-metadata")] - GenerateMetadata { - /// Path to the Cargo.toml of the contract to build - #[structopt(long, parse(from_os_str))] - manifest_path: Option, - #[structopt(flatten)] - verbosity: VerbosityFlags, - #[structopt(flatten)] - unstable_options: UnstableOptions, - }, + GenerateMetadata {}, /// Check that the code builds as Wasm; does not output any build artifact to the top level `target/` directory #[structopt(name = "check")] Check { @@ -329,11 +321,7 @@ fn exec(cmd: Command) -> Result { assert!(maybe_dest_wasm.is_none(), "no dest_wasm should exist"); Ok(format!("\nYour contract's code was built successfully.")) } - Command::GenerateMetadata { - manifest_path: _, - verbosity: _, - unstable_options: _, - } => Err(anyhow::anyhow!(format!( + Command::GenerateMetadata {} => Err(anyhow::anyhow!(format!( "Command deprecated, use `cargo contract build` instead" ))), Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")), -- GitLab From 73d8e9471913f0afde3e5559a6d5c4af2bdfab70 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 08:53:04 +0100 Subject: [PATCH 27/60] Move dispatch logic into metadata --- src/cmd/metadata.rs | 40 ++++++++++++++++++++++++++++++---------- src/main.rs | 40 +++++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index f52f5715..928171b4 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -38,6 +38,8 @@ pub struct GenerateMetadataResult { pub metadata_file: PathBuf, /// Path to the resulting Wasm file. pub wasm_file: PathBuf, + /// Path to the bundled file. + pub bundle_file: Option, } /// Executes the metadata generation process @@ -105,6 +107,7 @@ impl GenerateMetadataCommand { Ok(GenerateMetadataResult { metadata_file: out_path, wasm_file: dest_wasm, + bundle_file: None, }) } @@ -209,17 +212,33 @@ fn blake2_hash(code: &[u8]) -> [u8; 32] { pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Option, - include_wasm: bool, + skip_bundle: bool, unstable_options: UnstableFlags, ) -> Result { + let bundle_file = if skip_bundle { + None + } else { + let crate_metadata = CrateMetadata::collect(manifest_path)?; + let res = GenerateMetadataCommand { + crate_metadata, + verbosity, + include_wasm: true, + unstable_options: unstable_options.clone(), + } + .exec()?; + Some(res.metadata_file) + }; + let crate_metadata = CrateMetadata::collect(manifest_path)?; - GenerateMetadataCommand { + let mut res = GenerateMetadataCommand { crate_metadata, verbosity, - include_wasm, + include_wasm: false, unstable_options, } - .exec() + .exec()?; + res.bundle_file = bundle_file; + Ok(res) } #[cfg(feature = "test-ci-only")] @@ -321,19 +340,20 @@ mod tests { test_manifest.write()?; let crate_metadata = CrateMetadata::collect(&test_manifest.manifest_path)?; - let metadata_file = cmd::metadata::execute( + let bundle_file = cmd::metadata::execute( &test_manifest.manifest_path, None, - true, + false, UnstableFlags::default(), )? - .metadata_file; + .bundle_file + .expect("bundle file not found"); let metadata_json: Map = - serde_json::from_slice(&fs::read(&metadata_file)?)?; + serde_json::from_slice(&fs::read(&bundle_file)?)?; assert!( - metadata_file.exists(), - format!("Missing metadata file '{}'", metadata_file.display()) + bundle_file.exists(), + format!("Missing metadata file '{}'", bundle_file.display()) ); let source = metadata_json.get("source").expect("source not found"); diff --git a/src/main.rs b/src/main.rs index cf20f8bd..f6d8f09d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -262,8 +262,8 @@ fn exec(cmd: Command) -> Result { skip_metadata, unstable_options, } => { + let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; if *(skip_metadata) { - let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; let dest_wasm = cmd::build::execute( &manifest_path, verbosity.try_into()?, @@ -276,34 +276,32 @@ fn exec(cmd: Command) -> Result { dest_wasm.display().to_string().bold() )); } - let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; + let metadata_result = cmd::metadata::execute( &manifest_path, verbosity.try_into()?, - false, - unstable_options.try_into()?, - )?; - if *(skip_bundle) { - return Ok(format!( - "\nYour contract's code is ready. You can find it here:\n{} - \nYour contract's metadata is ready. You can find it here:\n{}", - metadata_result.wasm_file.display().to_string().bold(), - metadata_result.metadata_file.display().to_string().bold(), - )); - } - let bundle_result = cmd::metadata::execute( - &manifest_path, - verbosity.try_into()?, - true, + *skip_bundle, unstable_options.try_into()?, )?; + let maybe_bundle = if !*(skip_bundle) { + format!( + "\nYour contract bundle (code + metadata) is ready. You can find it here:\n{}", + metadata_result + .bundle_file + .expect("bundle file must exist") + .display() + .to_string() + .bold() + ) + } else { + "".to_string() + }; Ok(format!( "\nYour contract's code is ready. You can find it here:\n{} - \nYour contract's metadata is ready. You can find it here:\n{} - \nYour contract bundle (code + metadata) is ready. You can find it here:\n{}", - bundle_result.wasm_file.display().to_string().bold(), + \nYour contract's metadata is ready. You can find it here:\n{}{}", + metadata_result.wasm_file.display().to_string().bold(), metadata_result.metadata_file.display().to_string().bold(), - bundle_result.metadata_file.display().to_string().bold() + maybe_bundle, )) } Command::Check { -- GitLab From 134c07a60e98fe128d9851837574520ceda05873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Fri, 6 Nov 2020 09:03:06 +0100 Subject: [PATCH 28/60] Update src/main.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Theißen --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index f6d8f09d..1382fe0a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -319,9 +319,9 @@ fn exec(cmd: Command) -> Result { assert!(maybe_dest_wasm.is_none(), "no dest_wasm should exist"); Ok(format!("\nYour contract's code was built successfully.")) } - Command::GenerateMetadata {} => Err(anyhow::anyhow!(format!( + Command::GenerateMetadata {} => Err(anyhow::anyhow!( "Command deprecated, use `cargo contract build` instead" - ))), + )), Command::Test {} => Err(anyhow::anyhow!("Command unimplemented")), #[cfg(feature = "extrinsics")] Command::Deploy { -- GitLab From 1e7dabb5c3816b06dd6166988ce44d596fdc3d29 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 14:40:14 +0100 Subject: [PATCH 29/60] Move logic into build.rs --- metadata/lib.rs | 4 +++ src/cmd/build.rs | 50 +++++++++++++++++++++++++++------ src/cmd/metadata.rs | 60 +++++++++++++++++++-------------------- src/main.rs | 68 +++++++++++++++++++++------------------------ 4 files changed, 106 insertions(+), 76 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index 59953a3d..088901f5 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -93,6 +93,10 @@ impl ContractMetadata { abi, } } + + pub fn remove_wasm(&mut self) { + self.source.wasm = None; + } } #[derive(Debug, Serialize)] diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 54f00aee..e0da5347 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -33,6 +33,16 @@ use parity_wasm::elements::{External, MemoryType, Module, Section}; /// This is the maximum number of pages available for a contract to allocate. const MAX_MEMORY_PAGES: u32 = 16; +/// Result of the metadata generation process. +pub struct BuildResult { + /// Path to the resulting metadata file. + pub dest_metadata: Option, + /// Path to the resulting Wasm file. + pub dest_wasm: Option, + /// Path to the bundled file. + pub dest_bundle: Option, +} + /// Builds the project in the specified directory, defaults to the current directory. /// /// Uses [`cargo-xbuild`](https://github.com/rust-osdev/cargo-xbuild) for maximum optimization of @@ -240,16 +250,40 @@ fn optimize_wasm(crate_metadata: &CrateMetadata) -> Result<()> { pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Option, - unstable_options: UnstableFlags, optimize_contract: bool, -) -> Result> { + skip_bundle: bool, + skip_metadata: bool, + unstable_options: UnstableFlags, +) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; - execute_with_metadata( - &crate_metadata, + if skip_metadata { + let dest_wasm = execute_with_metadata( + &crate_metadata, + verbosity, + optimize_contract, + unstable_options, + )?; + let res = BuildResult { + dest_wasm: dest_wasm, + dest_metadata: None, + dest_bundle: None, + }; + return Ok(res); + } + + let metadata_result = super::metadata::execute( + &manifest_path, verbosity, - unstable_options, + !skip_bundle, optimize_contract, - ) + unstable_options, + )?; + let res = BuildResult { + dest_wasm: Some(metadata_result.wasm_file), + dest_metadata: Some(metadata_result.metadata_file), + dest_bundle: metadata_result.bundle_file, + }; + Ok(res) } /// Executes build of the smart-contract which produces a wasm binary that is ready for deploying. @@ -262,8 +296,8 @@ pub(crate) fn execute( pub(crate) fn execute_with_metadata( crate_metadata: &CrateMetadata, verbosity: Option, - unstable_options: UnstableFlags, optimize_contract: bool, + unstable_options: UnstableFlags, ) -> Result> { println!( " {} {}", @@ -300,7 +334,7 @@ mod tests { cmd::new::execute("new_project", Some(path)).expect("new project creation failed"); let manifest_path = ManifestPath::new(&path.join("new_project").join("Cargo.toml")).unwrap(); - super::execute(&manifest_path, None, UnstableFlags::default(), true) + super::execute(&manifest_path, None, UnstableFlags::default(), true, true) .expect("build failed"); Ok(()) }) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 928171b4..c84b4f52 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -46,7 +46,8 @@ pub struct GenerateMetadataResult { struct GenerateMetadataCommand { crate_metadata: CrateMetadata, verbosity: Option, - include_wasm: bool, + create_bundle: bool, + optimize_contract: bool, unstable_options: UnstableFlags, } @@ -56,12 +57,11 @@ impl GenerateMetadataCommand { println!(" Generating metadata"); let cargo_meta = &self.crate_metadata.cargo_meta; - let out_path = if self.include_wasm { - let fname = format!("{}.contract", self.crate_metadata.package_name); - cargo_meta.target_directory.join(fname) - } else { - cargo_meta.target_directory.join(METADATA_FILE) - }; + let out_path_wasm = cargo_meta.target_directory.join(METADATA_FILE); + + let fname_bundle = format!("{}.contract", self.crate_metadata.package_name); + let out_path_bundle = cargo_meta.target_directory.join(fname_bundle); + let target_dir = cargo_meta.target_directory.clone(); // build the extended contract project metadata @@ -84,9 +84,15 @@ impl GenerateMetadataCommand { let ink_meta: serde_json::Map = serde_json::from_slice(&stdout)?; - let metadata = ContractMetadata::new(source_meta, contract_meta, user_meta, ink_meta); + let mut metadata = + ContractMetadata::new(source_meta, contract_meta, user_meta, ink_meta); + if self.create_bundle { + let contents = serde_json::to_string_pretty(&metadata)?; + fs::write(&out_path_bundle, contents)?; + } + metadata.remove_wasm(); let contents = serde_json::to_string_pretty(&metadata)?; - fs::write(&out_path, contents)?; + fs::write(&out_path_wasm, contents)?; Ok(()) }; @@ -104,10 +110,15 @@ impl GenerateMetadataCommand { .using_temp(generate_metadata)?; } + let bundle_file = if self.create_bundle { + Some(out_path_bundle) + } else { + None + }; Ok(GenerateMetadataResult { - metadata_file: out_path, + metadata_file: out_path_wasm, wasm_file: dest_wasm, - bundle_file: None, + bundle_file, }) } @@ -134,7 +145,7 @@ impl GenerateMetadataCommand { let source = { let lang = SourceLanguage::new(Language::Ink, ink_version.clone()); let compiler = SourceCompiler::new(Compiler::RustC, rust_version); - let maybe_wasm = if self.include_wasm { + let maybe_wasm = if self.create_bundle { let wasm = fs::read(&self.crate_metadata.dest_wasm)?; // The Wasm which we read must have the same hash as `source.hash` debug_assert_eq!(blake2_hash(wasm.clone().as_slice()), hash); @@ -187,8 +198,8 @@ impl GenerateMetadataCommand { let dest_wasm = super::build::execute_with_metadata( &self.crate_metadata, self.verbosity, + self.optimize_contract, self.unstable_options.clone(), - true, )? .expect("dest_wasm must exist"); @@ -212,32 +223,19 @@ fn blake2_hash(code: &[u8]) -> [u8; 32] { pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Option, - skip_bundle: bool, + create_bundle: bool, + optimize_contract: bool, unstable_options: UnstableFlags, ) -> Result { - let bundle_file = if skip_bundle { - None - } else { - let crate_metadata = CrateMetadata::collect(manifest_path)?; - let res = GenerateMetadataCommand { - crate_metadata, - verbosity, - include_wasm: true, - unstable_options: unstable_options.clone(), - } - .exec()?; - Some(res.metadata_file) - }; - let crate_metadata = CrateMetadata::collect(manifest_path)?; - let mut res = GenerateMetadataCommand { + let res = GenerateMetadataCommand { crate_metadata, verbosity, - include_wasm: false, + create_bundle, + optimize_contract, unstable_options, } .exec()?; - res.bundle_file = bundle_file; Ok(res) } diff --git a/src/main.rs b/src/main.rs index 1382fe0a..ceb72509 100644 --- a/src/main.rs +++ b/src/main.rs @@ -263,46 +263,38 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - if *(skip_metadata) { - let dest_wasm = cmd::build::execute( - &manifest_path, - verbosity.try_into()?, - unstable_options.try_into()?, - true, - )? - .expect("dest_wasm must exist"); - return Ok(format!( - "\nYour contract's code is ready. You can find it here:\n{}", - dest_wasm.display().to_string().bold() - )); - } - - let metadata_result = cmd::metadata::execute( + let build_result = cmd::build::execute( &manifest_path, verbosity.try_into()?, + true, *skip_bundle, + *skip_metadata, unstable_options.try_into()?, )?; - let maybe_bundle = if !*(skip_bundle) { - format!( + + let mut out = "".to_string(); + if let Some(dest_bundle) = build_result.dest_bundle { + let bundle = format!( "\nYour contract bundle (code + metadata) is ready. You can find it here:\n{}", - metadata_result - .bundle_file - .expect("bundle file must exist") - .display() - .to_string() - .bold() - ) - } else { - "".to_string() - }; - Ok(format!( - "\nYour contract's code is ready. You can find it here:\n{} - \nYour contract's metadata is ready. You can find it here:\n{}{}", - metadata_result.wasm_file.display().to_string().bold(), - metadata_result.metadata_file.display().to_string().bold(), - maybe_bundle, - )) + dest_bundle.display().to_string().bold() + ); + out.push_str(&bundle); + } + if let Some(dest_wasm) = build_result.dest_wasm { + let wasm = format!( + "\nYour contract's code is ready. You can find it here:\n{}", + dest_wasm.display().to_string().bold() + ); + out.push_str(&wasm); + } + if let Some(dest_metadata) = build_result.dest_metadata { + let metadata = format!( + "\nYour contract's metadata is ready. You can find it here:\n{}", + dest_metadata.display().to_string().bold() + ); + out.push_str(&metadata); + } + Ok(out) } Command::Check { manifest_path, @@ -310,13 +302,15 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let maybe_dest_wasm = cmd::build::execute( + let res = cmd::build::execute( &manifest_path, verbosity.try_into()?, - unstable_options.try_into()?, false, + true, + true, + unstable_options.try_into()?, )?; - assert!(maybe_dest_wasm.is_none(), "no dest_wasm should exist"); + assert!(res.dest_wasm.is_none(), "no dest_wasm should exist"); Ok(format!("\nYour contract's code was built successfully.")) } Command::GenerateMetadata {} => Err(anyhow::anyhow!( -- GitLab From c7e2ffe0a9e3fce5682cc1736a679e31a174d040 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 15:29:16 +0100 Subject: [PATCH 30/60] Improve progress output --- metadata/lib.rs | 2 +- src/cmd/build.rs | 7 ++++++- src/cmd/metadata.rs | 25 ++++++++++++++++++++----- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index 088901f5..1637265d 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -94,7 +94,7 @@ impl ContractMetadata { } } - pub fn remove_wasm(&mut self) { + pub fn remove_source_wasm_attribute(&mut self) { self.source.wasm = None; } } diff --git a/src/cmd/build.rs b/src/cmd/build.rs index e0da5347..cc5b13c0 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -257,11 +257,13 @@ pub(crate) fn execute( ) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; if skip_metadata { + let total_steps = 3; let dest_wasm = execute_with_metadata( &crate_metadata, verbosity, optimize_contract, unstable_options, + total_steps, )?; let res = BuildResult { dest_wasm: dest_wasm, @@ -271,12 +273,14 @@ pub(crate) fn execute( return Ok(res); } + let total_steps = if skip_bundle { 4 } else { 5 }; let metadata_result = super::metadata::execute( &manifest_path, verbosity, !skip_bundle, optimize_contract, unstable_options, + total_steps, )?; let res = BuildResult { dest_wasm: Some(metadata_result.wasm_file), @@ -298,10 +302,11 @@ pub(crate) fn execute_with_metadata( verbosity: Option, optimize_contract: bool, unstable_options: UnstableFlags, + total_steps: usize, ) -> Result> { println!( " {} {}", - "[1/3]".bold(), + format!("[1/{}]", total_steps).bold(), "Building cargo project".bright_green().bold() ); build_cargo_project(&crate_metadata, verbosity, unstable_options)?; diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index c84b4f52..d95b1e54 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -22,6 +22,7 @@ use crate::{ }; use anyhow::Result; use blake2::digest::{Update as _, VariableOutput as _}; +use colored::Colorize; use contract_metadata::{ Compiler, Contract, ContractMetadata, Language, Source, SourceCompiler, SourceLanguage, SourceWasm, User, @@ -49,12 +50,12 @@ struct GenerateMetadataCommand { create_bundle: bool, optimize_contract: bool, unstable_options: UnstableFlags, + total_steps: usize, } impl GenerateMetadataCommand { pub fn exec(&self) -> Result { util::assert_channel()?; - println!(" Generating metadata"); let cargo_meta = &self.crate_metadata.cargo_meta; let out_path_wasm = cargo_meta.target_directory.join(METADATA_FILE); @@ -67,6 +68,11 @@ impl GenerateMetadataCommand { // build the extended contract project metadata let (dest_wasm, source_meta, contract_meta, user_meta) = self.extended_metadata()?; + println!( + " {} {}", + format!("[4/{}]", self.total_steps).bold(), + "Generating metadata".bright_green().bold() + ); let generate_metadata = |manifest_path: &ManifestPath| -> Result<()> { let target_dir_arg = format!("--target-dir={}", target_dir.to_string_lossy()); let stdout = util::invoke_cargo( @@ -86,13 +92,19 @@ impl GenerateMetadataCommand { serde_json::from_slice(&stdout)?; let mut metadata = ContractMetadata::new(source_meta, contract_meta, user_meta, ink_meta); + let contents = serde_json::to_string_pretty(&metadata)?; + fs::write(&out_path_bundle, contents)?; + if self.create_bundle { + println!( + " {} {}", + format!("[5/{}]", self.total_steps).bold(), + "Generating bundle".bright_green().bold() + ); + metadata.remove_source_wasm_attribute(); let contents = serde_json::to_string_pretty(&metadata)?; - fs::write(&out_path_bundle, contents)?; + fs::write(&out_path_wasm, contents)?; } - metadata.remove_wasm(); - let contents = serde_json::to_string_pretty(&metadata)?; - fs::write(&out_path_wasm, contents)?; Ok(()) }; @@ -200,6 +212,7 @@ impl GenerateMetadataCommand { self.verbosity, self.optimize_contract, self.unstable_options.clone(), + self.total_steps, )? .expect("dest_wasm must exist"); @@ -226,6 +239,7 @@ pub(crate) fn execute( create_bundle: bool, optimize_contract: bool, unstable_options: UnstableFlags, + total_steps: usize, ) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; let res = GenerateMetadataCommand { @@ -234,6 +248,7 @@ pub(crate) fn execute( create_bundle, optimize_contract, unstable_options, + total_steps, } .exec()?; Ok(res) -- GitLab From 82292463c133144397ffdb557e6907163b0824d9 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 15:31:15 +0100 Subject: [PATCH 31/60] Make clippy happy --- src/cmd/build.rs | 2 +- src/cmd/metadata.rs | 2 +- src/main.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index cc5b13c0..3eaa4cfe 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -266,7 +266,7 @@ pub(crate) fn execute( total_steps, )?; let res = BuildResult { - dest_wasm: dest_wasm, + dest_wasm, dest_metadata: None, dest_bundle: None, }; diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index d95b1e54..3c79b55c 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -160,7 +160,7 @@ impl GenerateMetadataCommand { let maybe_wasm = if self.create_bundle { let wasm = fs::read(&self.crate_metadata.dest_wasm)?; // The Wasm which we read must have the same hash as `source.hash` - debug_assert_eq!(blake2_hash(wasm.clone().as_slice()), hash); + debug_assert_eq!(blake2_hash(wasm.as_slice()), hash); Some(SourceWasm::new(wasm)) } else { None diff --git a/src/main.rs b/src/main.rs index ceb72509..4fbd9e1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -311,7 +311,7 @@ fn exec(cmd: Command) -> Result { unstable_options.try_into()?, )?; assert!(res.dest_wasm.is_none(), "no dest_wasm should exist"); - Ok(format!("\nYour contract's code was built successfully.")) + Ok("\nYour contract's code was built successfully.".to_string()) } Command::GenerateMetadata {} => Err(anyhow::anyhow!( "Command deprecated, use `cargo contract build` instead" -- GitLab From 3500946e90a8f5c917c875ae79b14be81601ec48 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 15:33:07 +0100 Subject: [PATCH 32/60] Fix progress output --- src/cmd/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 3eaa4cfe..22694f86 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -312,7 +312,7 @@ pub(crate) fn execute_with_metadata( build_cargo_project(&crate_metadata, verbosity, unstable_options)?; println!( " {} {}", - "[2/3]".bold(), + format!("[2/{}]", total_steps).bold(), "Post processing wasm file".bright_green().bold() ); post_process_wasm(&crate_metadata)?; @@ -321,7 +321,7 @@ pub(crate) fn execute_with_metadata( } println!( " {} {}", - "[3/3]".bold(), + format!("[3/{}]", total_steps).bold(), "Optimizing wasm file".bright_green().bold() ); optimize_wasm(&crate_metadata)?; -- GitLab From d2290c4d318b4d9df8376b3326e5bf188c8c2651 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 15:40:55 +0100 Subject: [PATCH 33/60] Make it work with `--features test-ci-only` --- src/cmd/build.rs | 2 +- src/cmd/metadata.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 22694f86..203d71e3 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -339,7 +339,7 @@ mod tests { cmd::new::execute("new_project", Some(path)).expect("new project creation failed"); let manifest_path = ManifestPath::new(&path.join("new_project").join("Cargo.toml")).unwrap(); - super::execute(&manifest_path, None, UnstableFlags::default(), true, true) + super::execute(&manifest_path, None, true, false, false, UnstableFlags::default()) .expect("build failed"); Ok(()) }) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 3c79b55c..1e040073 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -357,7 +357,9 @@ mod tests { &test_manifest.manifest_path, None, false, + false, UnstableFlags::default(), + 3, )? .bundle_file .expect("bundle file not found"); -- GitLab From f8246d39905d070b2ff846560304ae64f11a3a41 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 15:41:44 +0100 Subject: [PATCH 34/60] Apply cargo fmt --- src/cmd/build.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 203d71e3..45d6dbab 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -339,8 +339,15 @@ mod tests { cmd::new::execute("new_project", Some(path)).expect("new project creation failed"); let manifest_path = ManifestPath::new(&path.join("new_project").join("Cargo.toml")).unwrap(); - super::execute(&manifest_path, None, true, false, false, UnstableFlags::default()) - .expect("build failed"); + super::execute( + &manifest_path, + None, + true, + false, + false, + UnstableFlags::default(), + ) + .expect("build failed"); Ok(()) }) } -- GitLab From 939a19b2923886a41d7827bd872a55e472d118d7 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 16:00:23 +0100 Subject: [PATCH 35/60] Always use optimized Wasm for metadata hash --- src/cmd/build.rs | 1 - src/cmd/metadata.rs | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 45d6dbab..4d68f5e0 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -278,7 +278,6 @@ pub(crate) fn execute( &manifest_path, verbosity, !skip_bundle, - optimize_contract, unstable_options, total_steps, )?; diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 1e040073..99809494 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -48,7 +48,6 @@ struct GenerateMetadataCommand { crate_metadata: CrateMetadata, verbosity: Option, create_bundle: bool, - optimize_contract: bool, unstable_options: UnstableFlags, total_steps: usize, } @@ -210,7 +209,7 @@ impl GenerateMetadataCommand { let dest_wasm = super::build::execute_with_metadata( &self.crate_metadata, self.verbosity, - self.optimize_contract, + true, // for the hash we always use the optimized version of the contract self.unstable_options.clone(), self.total_steps, )? @@ -237,7 +236,6 @@ pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Option, create_bundle: bool, - optimize_contract: bool, unstable_options: UnstableFlags, total_steps: usize, ) -> Result { @@ -246,7 +244,6 @@ pub(crate) fn execute( crate_metadata, verbosity, create_bundle, - optimize_contract, unstable_options, total_steps, } -- GitLab From 007bb657b2e9b996990368343ad07817d0554477 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 16:01:43 +0100 Subject: [PATCH 36/60] Always use optimized Wasm for metadata hash --- src/cmd/metadata.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 99809494..c5538d3d 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -354,7 +354,6 @@ mod tests { &test_manifest.manifest_path, None, false, - false, UnstableFlags::default(), 3, )? -- GitLab From c99bd379fa841ae4343da5713cadfd61b181da97 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 16:21:59 +0100 Subject: [PATCH 37/60] Make it work with `--features test-ci-only` --- src/cmd/metadata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index c5538d3d..facba8a8 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -353,7 +353,7 @@ mod tests { let bundle_file = cmd::metadata::execute( &test_manifest.manifest_path, None, - false, + true, UnstableFlags::default(), 3, )? -- GitLab From c74e3aae5e23bb926a333b648ef4778336143ae9 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 16:54:25 +0100 Subject: [PATCH 38/60] Switch naming --- src/cmd/metadata.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index facba8a8..cda33f5a 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -92,7 +92,7 @@ impl GenerateMetadataCommand { let mut metadata = ContractMetadata::new(source_meta, contract_meta, user_meta, ink_meta); let contents = serde_json::to_string_pretty(&metadata)?; - fs::write(&out_path_bundle, contents)?; + fs::write(&out_path_wasm, contents)?; if self.create_bundle { println!( @@ -102,7 +102,7 @@ impl GenerateMetadataCommand { ); metadata.remove_source_wasm_attribute(); let contents = serde_json::to_string_pretty(&metadata)?; - fs::write(&out_path_wasm, contents)?; + fs::write(&out_path_bundle, contents)?; } Ok(()) }; -- GitLab From bc965c71aab064215dd92b47536969947dcbd1eb Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 17:02:00 +0100 Subject: [PATCH 39/60] Fix metadata/bundle output --- src/cmd/metadata.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index cda33f5a..a49704e6 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -67,11 +67,6 @@ impl GenerateMetadataCommand { // build the extended contract project metadata let (dest_wasm, source_meta, contract_meta, user_meta) = self.extended_metadata()?; - println!( - " {} {}", - format!("[4/{}]", self.total_steps).bold(), - "Generating metadata".bright_green().bold() - ); let generate_metadata = |manifest_path: &ManifestPath| -> Result<()> { let target_dir_arg = format!("--target-dir={}", target_dir.to_string_lossy()); let stdout = util::invoke_cargo( @@ -89,21 +84,29 @@ impl GenerateMetadataCommand { let ink_meta: serde_json::Map = serde_json::from_slice(&stdout)?; + let mut metadata = ContractMetadata::new(source_meta, contract_meta, user_meta, ink_meta); - let contents = serde_json::to_string_pretty(&metadata)?; - fs::write(&out_path_wasm, contents)?; - + let mut current_progress = 4; if self.create_bundle { println!( " {} {}", - format!("[5/{}]", self.total_steps).bold(), + format!("[{}/{}]", current_progress, self.total_steps).bold(), "Generating bundle".bright_green().bold() ); - metadata.remove_source_wasm_attribute(); let contents = serde_json::to_string_pretty(&metadata)?; fs::write(&out_path_bundle, contents)?; + current_progress += 1; } + + println!( + " {} {}", + format!("[{}/{}]", current_progress, self.total_steps).bold(), + "Generating metadata".bright_green().bold() + ); + metadata.remove_source_wasm_attribute(); + let contents = serde_json::to_string_pretty(&metadata)?; + fs::write(&out_path_wasm, contents)?; Ok(()) }; -- GitLab From da0c4ef5ebc1b9df5ef75318411d0c6e6d6008a3 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 18:39:20 +0100 Subject: [PATCH 40/60] Use enum `BuildArtifacts` instead of boolean flags --- src/cmd/build.rs | 71 ++++++++++++++++++++++++++++++++------------- src/cmd/metadata.rs | 29 +++++++++--------- src/main.rs | 32 ++++++++++++-------- 3 files changed, 84 insertions(+), 48 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 4d68f5e0..43b47264 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -19,6 +19,7 @@ use std::{ io::{Read, Write}, path::PathBuf, }; +use structopt::StructOpt; use crate::{ crate_metadata::CrateMetadata, @@ -33,6 +34,45 @@ use parity_wasm::elements::{External, MemoryType, Module, Section}; /// This is the maximum number of pages available for a contract to allocate. const MAX_MEMORY_PAGES: u32 = 16; +/// Describes which build artifacts to generate +#[derive(Copy, Clone, Eq, PartialEq, Debug, StructOpt)] +#[structopt(name = "build-artifacts")] +pub enum BuildArtifacts { + /// Generate the Wasm, the metadata and a bundled `.contract` file + #[structopt(name = "all")] + All, + /// Only the Wasm is created, generation of metadata and a bundled `.contract` file is skipped + #[structopt(name = "code-only")] + CodeOnly, + /// Only the Wasm and the metadata are generated, no bundled `.contract` file is created + #[structopt(name = "metadata-only")] + MetadataOnly, +} + +impl BuildArtifacts { + /// Returns the number of steps required to complete a build artifact. + /// Used as output on the cli. + pub fn steps(&self) -> usize { + match self { + BuildArtifacts::All => 5, + BuildArtifacts::MetadataOnly => 4, + BuildArtifacts::CodeOnly => 3, + } + } +} + +impl std::str::FromStr for BuildArtifacts { + type Err = String; + fn from_str(artifact: &str) -> Result { + match artifact { + "all" => Ok(BuildArtifacts::All), + "code-only" => Ok(BuildArtifacts::CodeOnly), + "metadata-only" => Ok(BuildArtifacts::MetadataOnly), + _ => Err("Could not parse build artifact".to_string()), + } + } +} + /// Result of the metadata generation process. pub struct BuildResult { /// Path to the resulting metadata file. @@ -251,19 +291,17 @@ pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Option, optimize_contract: bool, - skip_bundle: bool, - skip_metadata: bool, + build_artifact: BuildArtifacts, unstable_options: UnstableFlags, ) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; - if skip_metadata { - let total_steps = 3; + if build_artifact == BuildArtifacts::CodeOnly { let dest_wasm = execute_with_metadata( &crate_metadata, verbosity, optimize_contract, + build_artifact, unstable_options, - total_steps, )?; let res = BuildResult { dest_wasm, @@ -273,14 +311,8 @@ pub(crate) fn execute( return Ok(res); } - let total_steps = if skip_bundle { 4 } else { 5 }; - let metadata_result = super::metadata::execute( - &manifest_path, - verbosity, - !skip_bundle, - unstable_options, - total_steps, - )?; + let metadata_result = + super::metadata::execute(&manifest_path, verbosity, build_artifact, unstable_options)?; let res = BuildResult { dest_wasm: Some(metadata_result.wasm_file), dest_metadata: Some(metadata_result.metadata_file), @@ -300,18 +332,18 @@ pub(crate) fn execute_with_metadata( crate_metadata: &CrateMetadata, verbosity: Option, optimize_contract: bool, + build_artifact: BuildArtifacts, unstable_options: UnstableFlags, - total_steps: usize, ) -> Result> { println!( " {} {}", - format!("[1/{}]", total_steps).bold(), + format!("[1/{}]", build_artifact.steps()).bold(), "Building cargo project".bright_green().bold() ); build_cargo_project(&crate_metadata, verbosity, unstable_options)?; println!( " {} {}", - format!("[2/{}]", total_steps).bold(), + format!("[2/{}]", build_artifact.steps()).bold(), "Post processing wasm file".bright_green().bold() ); post_process_wasm(&crate_metadata)?; @@ -320,7 +352,7 @@ pub(crate) fn execute_with_metadata( } println!( " {} {}", - format!("[3/{}]", total_steps).bold(), + format!("[3/{}]", build_artifact.steps()).bold(), "Optimizing wasm file".bright_green().bold() ); optimize_wasm(&crate_metadata)?; @@ -330,7 +362,7 @@ pub(crate) fn execute_with_metadata( #[cfg(feature = "test-ci-only")] #[cfg(test)] mod tests { - use crate::{cmd, util::tests::with_tmp_dir, ManifestPath, UnstableFlags}; + use crate::{cmd, util::tests::with_tmp_dir, BuildArtifacts, ManifestPath, UnstableFlags}; #[test] fn build_template() { @@ -342,8 +374,7 @@ mod tests { &manifest_path, None, true, - false, - false, + BuildArtifacts::All, UnstableFlags::default(), ) .expect("build failed"); diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index a49704e6..fcc1175a 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -18,7 +18,7 @@ use crate::{ crate_metadata::CrateMetadata, util, workspace::{ManifestPath, Workspace}, - UnstableFlags, Verbosity, + BuildArtifacts, UnstableFlags, Verbosity, }; use anyhow::Result; use blake2::digest::{Update as _, VariableOutput as _}; @@ -47,9 +47,8 @@ pub struct GenerateMetadataResult { struct GenerateMetadataCommand { crate_metadata: CrateMetadata, verbosity: Option, - create_bundle: bool, + build_artifact: BuildArtifacts, unstable_options: UnstableFlags, - total_steps: usize, } impl GenerateMetadataCommand { @@ -88,10 +87,10 @@ impl GenerateMetadataCommand { let mut metadata = ContractMetadata::new(source_meta, contract_meta, user_meta, ink_meta); let mut current_progress = 4; - if self.create_bundle { + if self.build_artifact == BuildArtifacts::All { println!( " {} {}", - format!("[{}/{}]", current_progress, self.total_steps).bold(), + format!("[{}/{}]", current_progress, self.build_artifact.steps()).bold(), "Generating bundle".bright_green().bold() ); let contents = serde_json::to_string_pretty(&metadata)?; @@ -101,7 +100,7 @@ impl GenerateMetadataCommand { println!( " {} {}", - format!("[{}/{}]", current_progress, self.total_steps).bold(), + format!("[{}/{}]", current_progress, self.build_artifact.steps()).bold(), "Generating metadata".bright_green().bold() ); metadata.remove_source_wasm_attribute(); @@ -124,7 +123,7 @@ impl GenerateMetadataCommand { .using_temp(generate_metadata)?; } - let bundle_file = if self.create_bundle { + let bundle_file = if self.build_artifact == BuildArtifacts::All { Some(out_path_bundle) } else { None @@ -159,7 +158,7 @@ impl GenerateMetadataCommand { let source = { let lang = SourceLanguage::new(Language::Ink, ink_version.clone()); let compiler = SourceCompiler::new(Compiler::RustC, rust_version); - let maybe_wasm = if self.create_bundle { + let maybe_wasm = if self.build_artifact == BuildArtifacts::All { let wasm = fs::read(&self.crate_metadata.dest_wasm)?; // The Wasm which we read must have the same hash as `source.hash` debug_assert_eq!(blake2_hash(wasm.as_slice()), hash); @@ -213,8 +212,8 @@ impl GenerateMetadataCommand { &self.crate_metadata, self.verbosity, true, // for the hash we always use the optimized version of the contract + self.build_artifact, self.unstable_options.clone(), - self.total_steps, )? .expect("dest_wasm must exist"); @@ -238,17 +237,15 @@ fn blake2_hash(code: &[u8]) -> [u8; 32] { pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Option, - create_bundle: bool, + build_artifact: BuildArtifacts, unstable_options: UnstableFlags, - total_steps: usize, ) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; let res = GenerateMetadataCommand { crate_metadata, verbosity, - create_bundle, + build_artifact, unstable_options, - total_steps, } .exec()?; Ok(res) @@ -259,7 +256,8 @@ pub(crate) fn execute( mod tests { use crate::cmd::metadata::blake2_hash; use crate::{ - cmd, crate_metadata::CrateMetadata, util::tests::with_tmp_dir, ManifestPath, UnstableFlags, + cmd, cmd::build::BuildArtifacts, crate_metadata::CrateMetadata, util::tests::with_tmp_dir, + ManifestPath, UnstableFlags, }; use contract_metadata::*; use serde_json::{Map, Value}; @@ -356,9 +354,8 @@ mod tests { let bundle_file = cmd::metadata::execute( &test_manifest.manifest_path, None, - true, + BuildArtifacts::MetadataOnly, UnstableFlags::default(), - 3, )? .bundle_file .expect("bundle file not found"); diff --git a/src/main.rs b/src/main.rs index 4fbd9e1e..9fe49f27 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,6 +30,7 @@ use std::{ #[cfg(feature = "extrinsics")] use subxt::PairSigner; +use crate::cmd::build::BuildArtifacts; use anyhow::{Error, Result}; use colored::Colorize; use structopt::{clap, StructOpt}; @@ -168,12 +169,22 @@ enum Command { /// Path to the Cargo.toml of the contract to build #[structopt(long, parse(from_os_str))] manifest_path: Option, - /// Only the Wasm and the metadata are generated, no bundled `.contract` file is created - #[structopt(long = "skip-bundle", conflicts_with = "skip-metadata")] - skip_bundle: bool, - /// Only the Wasm is created, generation of metadata and a bundled `.contract` file is skipped - #[structopt(long = "skip-metadata", conflicts_with = "skip-bundle")] - skip_metadata: bool, + /// Which build artifacts to generate. + /// + /// - `all`: Generate the Wasm, the metadata and a bundled `.contract` file. + /// + /// - `code-only`: Only the Wasm is created, generation of metadata and a bundled + /// `.contract` file is skipped. + /// + /// - `metadata-only`: Only the Wasm and the metadata are generated, no bundled + /// `.contract` file is created. + #[structopt( + long = "generate", + default_value = "all", + value_name = "all | code-only | metadata-only", + verbatim_doc_comment + )] + build_artifact: BuildArtifacts, #[structopt(flatten)] verbosity: VerbosityFlags, #[structopt(flatten)] @@ -258,8 +269,7 @@ fn exec(cmd: Command) -> Result { Command::Build { manifest_path, verbosity, - skip_bundle, - skip_metadata, + build_artifact, unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; @@ -267,8 +277,7 @@ fn exec(cmd: Command) -> Result { &manifest_path, verbosity.try_into()?, true, - *skip_bundle, - *skip_metadata, + *build_artifact, unstable_options.try_into()?, )?; @@ -306,8 +315,7 @@ fn exec(cmd: Command) -> Result { &manifest_path, verbosity.try_into()?, false, - true, - true, + BuildArtifacts::CodeOnly, unstable_options.try_into()?, )?; assert!(res.dest_wasm.is_none(), "no dest_wasm should exist"); -- GitLab From c521d61febd0b92adec1a871a53218996832010b Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 18:48:29 +0100 Subject: [PATCH 41/60] Improve misleading fn name --- src/cmd/build.rs | 6 +++--- src/cmd/metadata.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 43b47264..9718df1b 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -296,7 +296,7 @@ pub(crate) fn execute( ) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; if build_artifact == BuildArtifacts::CodeOnly { - let dest_wasm = execute_with_metadata( + let dest_wasm = execute_with_crate_metadata( &crate_metadata, verbosity, optimize_contract, @@ -321,14 +321,14 @@ pub(crate) fn execute( Ok(res) } -/// Executes build of the smart-contract which produces a wasm binary that is ready for deploying. +/// Executes build of the smart-contract which produces a Wasm binary that is ready for deploying. /// /// It does so by invoking `cargo build` and then post processing the final binary. /// /// # Note /// /// Uses the supplied `CrateMetadata`. If an instance is not available use [`execute_build`] -pub(crate) fn execute_with_metadata( +pub(crate) fn execute_with_crate_metadata( crate_metadata: &CrateMetadata, verbosity: Option, optimize_contract: bool, diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index fcc1175a..d48f2fff 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -208,7 +208,7 @@ impl GenerateMetadataCommand { /// Compile the contract and then hash the resulting wasm fn wasm_hash(&self) -> Result<(PathBuf, [u8; 32])> { - let dest_wasm = super::build::execute_with_metadata( + let dest_wasm = super::build::execute_with_crate_metadata( &self.crate_metadata, self.verbosity, true, // for the hash we always use the optimized version of the contract -- GitLab From 8b2b3d2da6a18490e4c5dafdba0c0b61c2dafea6 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 6 Nov 2020 18:52:05 +0100 Subject: [PATCH 42/60] Make it work with `--features test-ci-only` --- src/cmd/metadata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index d48f2fff..9eb38f60 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -354,7 +354,7 @@ mod tests { let bundle_file = cmd::metadata::execute( &test_manifest.manifest_path, None, - BuildArtifacts::MetadataOnly, + BuildArtifacts::All, UnstableFlags::default(), )? .bundle_file -- GitLab From d08a6f1b2041d4b4ae9ae9c9ded1c6f8213d47ae Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 08:43:01 +0100 Subject: [PATCH 43/60] Make output more concise --- src/cmd/build.rs | 14 ++++++++++++++ src/main.rs | 17 ++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 9718df1b..170823e1 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -81,6 +81,18 @@ pub struct BuildResult { pub dest_wasm: Option, /// Path to the bundled file. pub dest_bundle: Option, + /// Path to the directory where output files are written to. + pub target_directory: PathBuf, +} + +impl BuildResult { + /// Returns the base name of the path. + pub fn display(path: &PathBuf) -> &str { + path.file_name() + .expect("file name must exist") + .to_str() + .expect("must be valid utf-8") + } } /// Builds the project in the specified directory, defaults to the current directory. @@ -307,6 +319,7 @@ pub(crate) fn execute( dest_wasm, dest_metadata: None, dest_bundle: None, + target_directory: crate_metadata.cargo_meta.target_directory, }; return Ok(res); } @@ -317,6 +330,7 @@ pub(crate) fn execute( dest_wasm: Some(metadata_result.wasm_file), dest_metadata: Some(metadata_result.metadata_file), dest_bundle: metadata_result.bundle_file, + target_directory: crate_metadata.cargo_meta.target_directory.clone(), }; Ok(res) } diff --git a/src/main.rs b/src/main.rs index 9fe49f27..39a75401 100644 --- a/src/main.rs +++ b/src/main.rs @@ -281,25 +281,28 @@ fn exec(cmd: Command) -> Result { unstable_options.try_into()?, )?; - let mut out = "".to_string(); + let mut out = format!( + "\nYour contract artifacts are ready. You can find them in:\n{}\n", + build_result.target_directory.display().to_string().bold() + ); if let Some(dest_bundle) = build_result.dest_bundle { let bundle = format!( - "\nYour contract bundle (code + metadata) is ready. You can find it here:\n{}", - dest_bundle.display().to_string().bold() + " - {} (code + metadata)\n", + cmd::build::BuildResult::display(&dest_bundle) ); out.push_str(&bundle); } if let Some(dest_wasm) = build_result.dest_wasm { let wasm = format!( - "\nYour contract's code is ready. You can find it here:\n{}", - dest_wasm.display().to_string().bold() + " - {} (the contract's code)\n", + cmd::build::BuildResult::display(&dest_wasm) ); out.push_str(&wasm); } if let Some(dest_metadata) = build_result.dest_metadata { let metadata = format!( - "\nYour contract's metadata is ready. You can find it here:\n{}", - dest_metadata.display().to_string().bold() + " - {} (the contract's metadata)", + cmd::build::BuildResult::display(&dest_metadata) ); out.push_str(&metadata); } -- GitLab From 9ed109b00238ba5229126ad7d280e73177278cda Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 09:12:50 +0100 Subject: [PATCH 44/60] Print optimization result at the end --- src/cmd/build.rs | 48 +++++++++++++++++++++++++++++++++++++-------- src/cmd/metadata.rs | 35 +++++++++++++++++++++++---------- src/main.rs | 5 ++++- 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 170823e1..192e6765 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -83,6 +83,8 @@ pub struct BuildResult { pub dest_bundle: Option, /// Path to the directory where output files are written to. pub target_directory: PathBuf, + /// If existent the result of the optimization. + pub optimization_result: Option, } impl BuildResult { @@ -93,6 +95,24 @@ impl BuildResult { .to_str() .expect("must be valid utf-8") } + + /// Returns a tuple of `(original_size, optimized_size)`. + /// + /// Panics if no optimization result is available. + pub fn display_optimization(res: &BuildResult) -> (f64, f64) { + let optimization = res + .optimization_result + .as_ref() + .expect("optimization result must exist"); + (optimization.original_size, optimization.optimized_size) + } +} + +pub struct OptimizationResult { + /// The original Wasm size. + pub original_size: f64, + /// The Wasm size after optimizations have been applied. + pub optimized_size: f64, } /// Builds the project in the specified directory, defaults to the current directory. @@ -254,7 +274,7 @@ fn post_process_wasm(crate_metadata: &CrateMetadata) -> Result<()> { /// /// The intention is to reduce the size of bloated wasm binaries as a result of missing /// optimizations (or bugs?) between Rust and Wasm. -fn optimize_wasm(crate_metadata: &CrateMetadata) -> Result<()> { +fn optimize_wasm(crate_metadata: &CrateMetadata) -> Result { let mut optimized = crate_metadata.dest_wasm.clone(); optimized.set_file_name(format!("{}-opt.wasm", crate_metadata.package_name)); @@ -281,14 +301,19 @@ fn optimize_wasm(crate_metadata: &CrateMetadata) -> Result<()> { let original_size = metadata(&crate_metadata.dest_wasm)?.len() as f64 / 1000.0; let optimized_size = metadata(&optimized)?.len() as f64 / 1000.0; + /* println!( " Original wasm size: {:.1}K, Optimized: {:.1}K", original_size, optimized_size ); + */ // overwrite existing destination wasm file with the optimised version std::fs::rename(&optimized, &crate_metadata.dest_wasm)?; - Ok(()) + Ok(OptimizationResult { + original_size, + optimized_size, + }) } /// Executes build of the smart-contract which produces a wasm binary that is ready for deploying. @@ -308,7 +333,7 @@ pub(crate) fn execute( ) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; if build_artifact == BuildArtifacts::CodeOnly { - let dest_wasm = execute_with_crate_metadata( + let (maybe_dest_wasm, maybe_optimization_result) = execute_with_crate_metadata( &crate_metadata, verbosity, optimize_contract, @@ -316,10 +341,11 @@ pub(crate) fn execute( unstable_options, )?; let res = BuildResult { - dest_wasm, + dest_wasm: maybe_dest_wasm, dest_metadata: None, dest_bundle: None, target_directory: crate_metadata.cargo_meta.target_directory, + optimization_result: maybe_optimization_result, }; return Ok(res); } @@ -331,6 +357,7 @@ pub(crate) fn execute( dest_metadata: Some(metadata_result.metadata_file), dest_bundle: metadata_result.bundle_file, target_directory: crate_metadata.cargo_meta.target_directory.clone(), + optimization_result: metadata_result.optimization_result, }; Ok(res) } @@ -342,13 +369,15 @@ pub(crate) fn execute( /// # Note /// /// Uses the supplied `CrateMetadata`. If an instance is not available use [`execute_build`] +/// +/// Returns a tuple of `(maybe_optimized_wasm_path, maybe_optimization_result)`. pub(crate) fn execute_with_crate_metadata( crate_metadata: &CrateMetadata, verbosity: Option, optimize_contract: bool, build_artifact: BuildArtifacts, unstable_options: UnstableFlags, -) -> Result> { +) -> Result<(Option, Option)> { println!( " {} {}", format!("[1/{}]", build_artifact.steps()).bold(), @@ -362,15 +391,18 @@ pub(crate) fn execute_with_crate_metadata( ); post_process_wasm(&crate_metadata)?; if !optimize_contract { - return Ok(None); + return Ok((None, None)); } println!( " {} {}", format!("[3/{}]", build_artifact.steps()).bold(), "Optimizing wasm file".bright_green().bold() ); - optimize_wasm(&crate_metadata)?; - Ok(Some(crate_metadata.dest_wasm.clone())) + let optimization_result = optimize_wasm(&crate_metadata)?; + Ok(( + Some(crate_metadata.dest_wasm.clone()), + Some(optimization_result), + )) } #[cfg(feature = "test-ci-only")] diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 9eb38f60..f7bde424 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -41,6 +41,8 @@ pub struct GenerateMetadataResult { pub wasm_file: PathBuf, /// Path to the bundled file. pub bundle_file: Option, + /// If existent the result of the optimization. + pub optimization_result: Option, } /// Executes the metadata generation process @@ -64,7 +66,8 @@ impl GenerateMetadataCommand { let target_dir = cargo_meta.target_directory.clone(); // build the extended contract project metadata - let (dest_wasm, source_meta, contract_meta, user_meta) = self.extended_metadata()?; + let (dest_wasm, source_meta, contract_meta, user_meta, optimization_result) = + self.extended_metadata()?; let generate_metadata = |manifest_path: &ManifestPath| -> Result<()> { let target_dir_arg = format!("--target-dir={}", target_dir.to_string_lossy()); @@ -132,11 +135,20 @@ impl GenerateMetadataCommand { metadata_file: out_path_wasm, wasm_file: dest_wasm, bundle_file, + optimization_result: Some(optimization_result), }) } /// Generate the extended contract project metadata - fn extended_metadata(&self) -> Result<(PathBuf, Source, Contract, Option)> { + fn extended_metadata( + &self, + ) -> Result<( + PathBuf, + Source, + Contract, + Option, + super::build::OptimizationResult, + )> { let contract_package = &self.crate_metadata.root_package; let ink_version = &self.crate_metadata.ink_version; let rust_version = Version::parse(&rustc_version::version()?.to_string())?; @@ -153,7 +165,7 @@ impl GenerateMetadataCommand { .transpose()?; let homepage = self.crate_metadata.homepage.clone(); let license = contract_package.license.clone(); - let (dest_wasm, hash) = self.wasm_hash()?; + let (dest_wasm, hash, optimization_res) = self.wasm_hash()?; let source = { let lang = SourceLanguage::new(Language::Ink, ink_version.clone()); @@ -203,22 +215,25 @@ impl GenerateMetadataCommand { // user defined metadata let user = self.crate_metadata.user.clone().map(User::new); - Ok((dest_wasm, source, contract, user)) + Ok((dest_wasm, source, contract, user, optimization_res)) } - /// Compile the contract and then hash the resulting wasm - fn wasm_hash(&self) -> Result<(PathBuf, [u8; 32])> { - let dest_wasm = super::build::execute_with_crate_metadata( + /// Compile the contract and then hash the resulting Wasm. + /// + /// Return a tuple of `(dest_wasm, hash, optimization_result)`. + fn wasm_hash(&self) -> Result<(PathBuf, [u8; 32], super::build::OptimizationResult)> { + let (maybe_dest_wasm, maybe_optimization_res) = super::build::execute_with_crate_metadata( &self.crate_metadata, self.verbosity, true, // for the hash we always use the optimized version of the contract self.build_artifact, self.unstable_options.clone(), - )? - .expect("dest_wasm must exist"); + )?; let wasm = fs::read(&self.crate_metadata.dest_wasm)?; - Ok((dest_wasm, blake2_hash(wasm.as_slice()))) + let dest_wasm = maybe_dest_wasm.expect("dest wasm must exist"); + let optimization_res = maybe_optimization_res.expect("optimization result must exist"); + Ok((dest_wasm, blake2_hash(wasm.as_slice()), optimization_res)) } } diff --git a/src/main.rs b/src/main.rs index 39a75401..c72fbacc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -282,7 +282,10 @@ fn exec(cmd: Command) -> Result { )?; let mut out = format!( - "\nYour contract artifacts are ready. You can find them in:\n{}\n", + "\nOriginal wasm size: {:.1}K, Optimized: {:.1}K\n\n\ + Your contract artifacts are ready. You can find them in:\n{}\n", + cmd::build::BuildResult::display_optimization(&build_result).0, + cmd::build::BuildResult::display_optimization(&build_result).1, build_result.target_directory.display().to_string().bold() ); if let Some(dest_bundle) = build_result.dest_bundle { -- GitLab From 693f98789b14a3c3ee17de07b985cc59bec3a017 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 09:22:50 +0100 Subject: [PATCH 45/60] Improve output --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index c72fbacc..88892e86 100644 --- a/src/main.rs +++ b/src/main.rs @@ -283,10 +283,10 @@ fn exec(cmd: Command) -> Result { let mut out = format!( "\nOriginal wasm size: {:.1}K, Optimized: {:.1}K\n\n\ - Your contract artifacts are ready. You can find them in:\n{}\n", + Your contract artifacts are ready. You can find them in:\n{}\n\n", cmd::build::BuildResult::display_optimization(&build_result).0, cmd::build::BuildResult::display_optimization(&build_result).1, - build_result.target_directory.display().to_string().bold() + build_result.target_directory.display().to_string() ); if let Some(dest_bundle) = build_result.dest_bundle { let bundle = format!( -- GitLab From 160b9922aa7dba4d7a5e2242d7c405a682cbdbda Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 11:37:28 +0100 Subject: [PATCH 46/60] Replace 5-tuple return value with struct --- src/cmd/metadata.rs | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index f7bde424..9d1fdb1e 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -53,6 +53,15 @@ struct GenerateMetadataCommand { unstable_options: UnstableFlags, } +/// Result of generating the extended contract project metadata +struct ExtendedMetadataResult { + dest_wasm: PathBuf, + source: Source, + contract: Contract, + user: Option, + optimization_result: super::build::OptimizationResult, +} + impl GenerateMetadataCommand { pub fn exec(&self) -> Result { util::assert_channel()?; @@ -66,8 +75,13 @@ impl GenerateMetadataCommand { let target_dir = cargo_meta.target_directory.clone(); // build the extended contract project metadata - let (dest_wasm, source_meta, contract_meta, user_meta, optimization_result) = - self.extended_metadata()?; + let ExtendedMetadataResult { + dest_wasm, + source, + contract, + user, + optimization_result, + } = self.extended_metadata()?; let generate_metadata = |manifest_path: &ManifestPath| -> Result<()> { let target_dir_arg = format!("--target-dir={}", target_dir.to_string_lossy()); @@ -87,8 +101,7 @@ impl GenerateMetadataCommand { let ink_meta: serde_json::Map = serde_json::from_slice(&stdout)?; - let mut metadata = - ContractMetadata::new(source_meta, contract_meta, user_meta, ink_meta); + let mut metadata = ContractMetadata::new(source, contract, user, ink_meta); let mut current_progress = 4; if self.build_artifact == BuildArtifacts::All { println!( @@ -140,15 +153,7 @@ impl GenerateMetadataCommand { } /// Generate the extended contract project metadata - fn extended_metadata( - &self, - ) -> Result<( - PathBuf, - Source, - Contract, - Option, - super::build::OptimizationResult, - )> { + fn extended_metadata(&self) -> Result { let contract_package = &self.crate_metadata.root_package; let ink_version = &self.crate_metadata.ink_version; let rust_version = Version::parse(&rustc_version::version()?.to_string())?; @@ -165,7 +170,7 @@ impl GenerateMetadataCommand { .transpose()?; let homepage = self.crate_metadata.homepage.clone(); let license = contract_package.license.clone(); - let (dest_wasm, hash, optimization_res) = self.wasm_hash()?; + let (dest_wasm, hash, optimization_result) = self.wasm_hash()?; let source = { let lang = SourceLanguage::new(Language::Ink, ink_version.clone()); @@ -215,7 +220,13 @@ impl GenerateMetadataCommand { // user defined metadata let user = self.crate_metadata.user.clone().map(User::new); - Ok((dest_wasm, source, contract, user, optimization_res)) + Ok(ExtendedMetadataResult { + dest_wasm, + source, + contract, + user, + optimization_result, + }) } /// Compile the contract and then hash the resulting Wasm. -- GitLab From c699312c35c9dcd420a12b552e4de84e325c2ac2 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 12:26:53 +0100 Subject: [PATCH 47/60] Include hash only for bundle in metadata --- metadata/lib.rs | 17 +++- src/cmd/build.rs | 107 ++--------------------- src/cmd/metadata.rs | 84 +++++++++--------- src/main.rs | 201 +++++++++++++++++++++++++++++++++++--------- 4 files changed, 228 insertions(+), 181 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index 1637265d..7039e6bc 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -101,8 +101,11 @@ impl ContractMetadata { #[derive(Debug, Serialize)] pub struct Source { - #[serde(serialize_with = "serialize_as_byte_str")] - hash: [u8; 32], + #[serde( + serialize_with = "serialize_as_byte_str_foo", + skip_serializing_if = "Option::is_none" + )] + hash: Option<[u8; 32]>, language: SourceLanguage, compiler: SourceCompiler, #[serde(skip_serializing_if = "Option::is_none")] @@ -113,7 +116,7 @@ impl Source { /// Constructs a new InkProjectSource. pub fn new( wasm: Option, - hash: [u8; 32], + hash: Option<[u8; 32]>, language: SourceLanguage, compiler: SourceCompiler, ) -> Self { @@ -433,6 +436,14 @@ impl ContractBuilder { } } +fn serialize_as_byte_str_foo(bytes: &Option<[u8; 32]>, serializer: S) -> Result +where + S: serde::Serializer, +{ + let bytes = bytes.expect("must_exist"); + serialize_as_byte_str(&bytes[..], serializer) +} + /// Serializes the given bytes as byte string. fn serialize_as_byte_str(bytes: &[u8], serializer: S) -> Result where diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 192e6765..e54c16c1 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -19,13 +19,12 @@ use std::{ io::{Read, Write}, path::PathBuf, }; -use structopt::StructOpt; use crate::{ crate_metadata::CrateMetadata, util, workspace::{ManifestPath, Profile, Workspace}, - UnstableFlags, Verbosity, + GenerateArtifacts, GenerationResult, OptimizationResult, UnstableFlags, Verbosity, }; use anyhow::{Context, Result}; use colored::Colorize; @@ -34,87 +33,6 @@ use parity_wasm::elements::{External, MemoryType, Module, Section}; /// This is the maximum number of pages available for a contract to allocate. const MAX_MEMORY_PAGES: u32 = 16; -/// Describes which build artifacts to generate -#[derive(Copy, Clone, Eq, PartialEq, Debug, StructOpt)] -#[structopt(name = "build-artifacts")] -pub enum BuildArtifacts { - /// Generate the Wasm, the metadata and a bundled `.contract` file - #[structopt(name = "all")] - All, - /// Only the Wasm is created, generation of metadata and a bundled `.contract` file is skipped - #[structopt(name = "code-only")] - CodeOnly, - /// Only the Wasm and the metadata are generated, no bundled `.contract` file is created - #[structopt(name = "metadata-only")] - MetadataOnly, -} - -impl BuildArtifacts { - /// Returns the number of steps required to complete a build artifact. - /// Used as output on the cli. - pub fn steps(&self) -> usize { - match self { - BuildArtifacts::All => 5, - BuildArtifacts::MetadataOnly => 4, - BuildArtifacts::CodeOnly => 3, - } - } -} - -impl std::str::FromStr for BuildArtifacts { - type Err = String; - fn from_str(artifact: &str) -> Result { - match artifact { - "all" => Ok(BuildArtifacts::All), - "code-only" => Ok(BuildArtifacts::CodeOnly), - "metadata-only" => Ok(BuildArtifacts::MetadataOnly), - _ => Err("Could not parse build artifact".to_string()), - } - } -} - -/// Result of the metadata generation process. -pub struct BuildResult { - /// Path to the resulting metadata file. - pub dest_metadata: Option, - /// Path to the resulting Wasm file. - pub dest_wasm: Option, - /// Path to the bundled file. - pub dest_bundle: Option, - /// Path to the directory where output files are written to. - pub target_directory: PathBuf, - /// If existent the result of the optimization. - pub optimization_result: Option, -} - -impl BuildResult { - /// Returns the base name of the path. - pub fn display(path: &PathBuf) -> &str { - path.file_name() - .expect("file name must exist") - .to_str() - .expect("must be valid utf-8") - } - - /// Returns a tuple of `(original_size, optimized_size)`. - /// - /// Panics if no optimization result is available. - pub fn display_optimization(res: &BuildResult) -> (f64, f64) { - let optimization = res - .optimization_result - .as_ref() - .expect("optimization result must exist"); - (optimization.original_size, optimization.optimized_size) - } -} - -pub struct OptimizationResult { - /// The original Wasm size. - pub original_size: f64, - /// The Wasm size after optimizations have been applied. - pub optimized_size: f64, -} - /// Builds the project in the specified directory, defaults to the current directory. /// /// Uses [`cargo-xbuild`](https://github.com/rust-osdev/cargo-xbuild) for maximum optimization of @@ -328,11 +246,11 @@ pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Option, optimize_contract: bool, - build_artifact: BuildArtifacts, + build_artifact: GenerateArtifacts, unstable_options: UnstableFlags, -) -> Result { +) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; - if build_artifact == BuildArtifacts::CodeOnly { + if build_artifact == GenerateArtifacts::CodeOnly { let (maybe_dest_wasm, maybe_optimization_result) = execute_with_crate_metadata( &crate_metadata, verbosity, @@ -340,7 +258,7 @@ pub(crate) fn execute( build_artifact, unstable_options, )?; - let res = BuildResult { + let res = GenerationResult { dest_wasm: maybe_dest_wasm, dest_metadata: None, dest_bundle: None, @@ -350,15 +268,8 @@ pub(crate) fn execute( return Ok(res); } - let metadata_result = + let res = super::metadata::execute(&manifest_path, verbosity, build_artifact, unstable_options)?; - let res = BuildResult { - dest_wasm: Some(metadata_result.wasm_file), - dest_metadata: Some(metadata_result.metadata_file), - dest_bundle: metadata_result.bundle_file, - target_directory: crate_metadata.cargo_meta.target_directory.clone(), - optimization_result: metadata_result.optimization_result, - }; Ok(res) } @@ -375,7 +286,7 @@ pub(crate) fn execute_with_crate_metadata( crate_metadata: &CrateMetadata, verbosity: Option, optimize_contract: bool, - build_artifact: BuildArtifacts, + build_artifact: GenerateArtifacts, unstable_options: UnstableFlags, ) -> Result<(Option, Option)> { println!( @@ -408,7 +319,7 @@ pub(crate) fn execute_with_crate_metadata( #[cfg(feature = "test-ci-only")] #[cfg(test)] mod tests { - use crate::{cmd, util::tests::with_tmp_dir, BuildArtifacts, ManifestPath, UnstableFlags}; + use crate::{cmd, util::tests::with_tmp_dir, GenerateArtifacts, ManifestPath, UnstableFlags}; #[test] fn build_template() { @@ -420,7 +331,7 @@ mod tests { &manifest_path, None, true, - BuildArtifacts::All, + GenerateArtifacts::All, UnstableFlags::default(), ) .expect("build failed"); diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 9d1fdb1e..33c2386f 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -18,8 +18,9 @@ use crate::{ crate_metadata::CrateMetadata, util, workspace::{ManifestPath, Workspace}, - BuildArtifacts, UnstableFlags, Verbosity, + GenerateArtifacts, GenerationResult, OptimizationResult, UnstableFlags, Verbosity, }; + use anyhow::Result; use blake2::digest::{Update as _, VariableOutput as _}; use colored::Colorize; @@ -33,37 +34,25 @@ use url::Url; const METADATA_FILE: &str = "metadata.json"; -/// Result of the metadata generation process. -pub struct GenerateMetadataResult { - /// Path to the resulting metadata file. - pub metadata_file: PathBuf, - /// Path to the resulting Wasm file. - pub wasm_file: PathBuf, - /// Path to the bundled file. - pub bundle_file: Option, - /// If existent the result of the optimization. - pub optimization_result: Option, -} - /// Executes the metadata generation process struct GenerateMetadataCommand { crate_metadata: CrateMetadata, verbosity: Option, - build_artifact: BuildArtifacts, + build_artifact: GenerateArtifacts, unstable_options: UnstableFlags, } /// Result of generating the extended contract project metadata struct ExtendedMetadataResult { - dest_wasm: PathBuf, + dest_wasm: Option, source: Source, contract: Contract, user: Option, - optimization_result: super::build::OptimizationResult, + optimization_result: Option, } impl GenerateMetadataCommand { - pub fn exec(&self) -> Result { + pub fn exec(&self) -> Result { util::assert_channel()?; let cargo_meta = &self.crate_metadata.cargo_meta; @@ -72,7 +61,7 @@ impl GenerateMetadataCommand { let fname_bundle = format!("{}.contract", self.crate_metadata.package_name); let out_path_bundle = cargo_meta.target_directory.join(fname_bundle); - let target_dir = cargo_meta.target_directory.clone(); + let target_directory = cargo_meta.target_directory.clone(); // build the extended contract project metadata let ExtendedMetadataResult { @@ -84,7 +73,7 @@ impl GenerateMetadataCommand { } = self.extended_metadata()?; let generate_metadata = |manifest_path: &ManifestPath| -> Result<()> { - let target_dir_arg = format!("--target-dir={}", target_dir.to_string_lossy()); + let target_dir_arg = format!("--target-dir={}", target_directory.to_string_lossy()); let stdout = util::invoke_cargo( "run", &[ @@ -103,7 +92,7 @@ impl GenerateMetadataCommand { let mut metadata = ContractMetadata::new(source, contract, user, ink_meta); let mut current_progress = 4; - if self.build_artifact == BuildArtifacts::All { + if self.build_artifact == GenerateArtifacts::All { println!( " {} {}", format!("[{}/{}]", current_progress, self.build_artifact.steps()).bold(), @@ -114,11 +103,19 @@ impl GenerateMetadataCommand { current_progress += 1; } - println!( - " {} {}", - format!("[{}/{}]", current_progress, self.build_artifact.steps()).bold(), - "Generating metadata".bright_green().bold() - ); + if self.build_artifact == GenerateArtifacts::MetadataOnly { + println!( + " {} {}", + format!("[{}/{}]", 1, self.build_artifact.steps()).bold(), + "Generating metadata".bright_green().bold() + ); + } else { + println!( + " {} {}", + format!("[{}/{}]", current_progress, self.build_artifact.steps()).bold(), + "Generating metadata".bright_green().bold() + ); + } metadata.remove_source_wasm_attribute(); let contents = serde_json::to_string_pretty(&metadata)?; fs::write(&out_path_wasm, contents)?; @@ -139,16 +136,17 @@ impl GenerateMetadataCommand { .using_temp(generate_metadata)?; } - let bundle_file = if self.build_artifact == BuildArtifacts::All { + let dest_bundle = if self.build_artifact == GenerateArtifacts::All { Some(out_path_bundle) } else { None }; - Ok(GenerateMetadataResult { - metadata_file: out_path_wasm, - wasm_file: dest_wasm, - bundle_file, - optimization_result: Some(optimization_result), + Ok(GenerationResult { + dest_metadata: Some(out_path_wasm), + dest_wasm, + dest_bundle, + optimization_result, + target_directory, }) } @@ -170,21 +168,29 @@ impl GenerateMetadataCommand { .transpose()?; let homepage = self.crate_metadata.homepage.clone(); let license = contract_package.license.clone(); - let (dest_wasm, hash, optimization_result) = self.wasm_hash()?; - + //{ + let (dest_wasm, hash, optimization_result) = + if self.build_artifact != GenerateArtifacts::MetadataOnly { + let (wasm, hash, optimization) = self.wasm_hash()?; + (Some(wasm), Some(hash), Some(optimization)) + } else { + (None, None, None) + }; let source = { let lang = SourceLanguage::new(Language::Ink, ink_version.clone()); let compiler = SourceCompiler::new(Compiler::RustC, rust_version); - let maybe_wasm = if self.build_artifact == BuildArtifacts::All { + let maybe_wasm = if self.build_artifact == GenerateArtifacts::All { let wasm = fs::read(&self.crate_metadata.dest_wasm)?; // The Wasm which we read must have the same hash as `source.hash` - debug_assert_eq!(blake2_hash(wasm.as_slice()), hash); + debug_assert_eq!(Some(blake2_hash(wasm.as_slice())), hash); Some(SourceWasm::new(wasm)) } else { None }; Source::new(maybe_wasm, hash, lang, compiler) }; + //(dest_wasm, hash, optimization_result, source) + //} // Required contract fields let mut builder = Contract::builder(); @@ -232,7 +238,7 @@ impl GenerateMetadataCommand { /// Compile the contract and then hash the resulting Wasm. /// /// Return a tuple of `(dest_wasm, hash, optimization_result)`. - fn wasm_hash(&self) -> Result<(PathBuf, [u8; 32], super::build::OptimizationResult)> { + fn wasm_hash(&self) -> Result<(PathBuf, [u8; 32], OptimizationResult)> { let (maybe_dest_wasm, maybe_optimization_res) = super::build::execute_with_crate_metadata( &self.crate_metadata, self.verbosity, @@ -263,9 +269,9 @@ fn blake2_hash(code: &[u8]) -> [u8; 32] { pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Option, - build_artifact: BuildArtifacts, + build_artifact: GenerateArtifacts, unstable_options: UnstableFlags, -) -> Result { +) -> Result { let crate_metadata = CrateMetadata::collect(manifest_path)?; let res = GenerateMetadataCommand { crate_metadata, @@ -282,7 +288,7 @@ pub(crate) fn execute( mod tests { use crate::cmd::metadata::blake2_hash; use crate::{ - cmd, cmd::build::BuildArtifacts, crate_metadata::CrateMetadata, util::tests::with_tmp_dir, + cmd, cmd::BuildArtifacts, crate_metadata::CrateMetadata, util::tests::with_tmp_dir, ManifestPath, UnstableFlags, }; use contract_metadata::*; diff --git a/src/main.rs b/src/main.rs index 88892e86..f0a473f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,7 +30,6 @@ use std::{ #[cfg(feature = "extrinsics")] use subxt::PairSigner; -use crate::cmd::build::BuildArtifacts; use anyhow::{Error, Result}; use colored::Colorize; use structopt::{clap, StructOpt}; @@ -152,6 +151,142 @@ impl TryFrom<&UnstableOptions> for UnstableFlags { } } +/// Describes which artifacts to generate +#[derive(Copy, Clone, Eq, PartialEq, Debug, StructOpt)] +#[structopt(name = "build-artifacts")] +pub enum GenerateArtifacts { + /// Generate the Wasm, the metadata and a bundled `.contract` file + #[structopt(name = "all")] + All, + /// Only the Wasm is created, generation of metadata and a bundled `.contract` file is skipped + #[structopt(name = "code-only")] + CodeOnly, + /// Only the Wasm and the metadata are generated, no bundled `.contract` file is created + #[structopt(name = "metadata-only")] + MetadataOnly, +} + +impl GenerateArtifacts { + /// Returns the number of steps required to complete a build artifact. + /// Used as output on the cli. + pub fn steps(&self) -> usize { + match self { + GenerateArtifacts::All => 5, + GenerateArtifacts::CodeOnly => 3, + GenerateArtifacts::MetadataOnly => 1, + } + } + + pub fn display(&self, result: &GenerationResult) -> String { + if self == &GenerateArtifacts::MetadataOnly { + return format!( + "\nYour contract's metadata is ready. You can find it here:\n{}", + result + .dest_metadata + .as_ref() + .expect("metadata path must exist") + .display() + ); + } + + let optimization = GenerationResult::display_optimization(result); + let mut out = format!("\nOriginal wasm size: {:.1}K, Optimized: {:.1}K\n\nYour contract artifacts are ready. You can find them in:\n{}\n\n", + optimization.0, optimization.1, + result.target_directory.display().to_string() + ); + + if self == &GenerateArtifacts::CodeOnly { + let out = format!( + "\nYour contract's code is ready. You can find it here:\n{}", + result + .dest_wasm + .as_ref() + .expect("wasm path must exist") + .display() + ); + return out; + }; + + if let Some(dest_bundle) = result.dest_bundle.as_ref() { + let bundle = format!( + " - {} (code + metadata)\n", + GenerationResult::display(&dest_bundle) + ); + out.push_str(&bundle); + } + if let Some(dest_wasm) = result.dest_wasm.as_ref() { + let wasm = format!( + " - {} (the contract's code)\n", + GenerationResult::display(&dest_wasm) + ); + out.push_str(&wasm); + } + if let Some(dest_metadata) = result.dest_metadata.as_ref() { + let metadata = format!( + " - {} (the contract's metadata)", + GenerationResult::display(&dest_metadata) + ); + out.push_str(&metadata); + } + out + } +} + +impl std::str::FromStr for GenerateArtifacts { + type Err = String; + fn from_str(artifact: &str) -> Result { + match artifact { + "all" => Ok(GenerateArtifacts::All), + "code-only" => Ok(GenerateArtifacts::CodeOnly), + "metadata-only" => Ok(GenerateArtifacts::MetadataOnly), + _ => Err("Could not parse build artifact".to_string()), + } + } +} + +/// Result of the metadata generation process. +pub struct GenerationResult { + /// Path to the resulting metadata file. + pub dest_metadata: Option, + /// Path to the resulting Wasm file. + pub dest_wasm: Option, + /// Path to the bundled file. + pub dest_bundle: Option, + /// Path to the directory where output files are written to. + pub target_directory: PathBuf, + /// If existent the result of the optimization. + pub optimization_result: Option, +} + +/// Result of the optimization process. +pub struct OptimizationResult { + /// The original Wasm size. + pub original_size: f64, + /// The Wasm size after optimizations have been applied. + pub optimized_size: f64, +} + +impl GenerationResult { + /// Returns the base name of the path. + pub fn display(path: &PathBuf) -> &str { + path.file_name() + .expect("file name must exist") + .to_str() + .expect("must be valid utf-8") + } + + /// Returns a tuple of `(original_size, optimized_size)`. + /// + /// Panics if no optimization result is available. + pub fn display_optimization(res: &GenerationResult) -> (f64, f64) { + let optimization = res + .optimization_result + .as_ref() + .expect("optimization result must exist"); + (optimization.original_size, optimization.optimized_size) + } +} + #[derive(Debug, StructOpt)] enum Command { /// Setup and create a new smart contract project @@ -172,19 +307,21 @@ enum Command { /// Which build artifacts to generate. /// /// - `all`: Generate the Wasm, the metadata and a bundled `.contract` file. + /// The metadata file includes the Wasm hash. /// /// - `code-only`: Only the Wasm is created, generation of metadata and a bundled /// `.contract` file is skipped. /// - /// - `metadata-only`: Only the Wasm and the metadata are generated, no bundled - /// `.contract` file is created. + /// - `metadata-only`: Only the metadata iis generated, neither the bundled + /// `.contract`, nor the Wasm file are created. The resulting metadata + /// does not contain the Wasm hash. #[structopt( long = "generate", default_value = "all", value_name = "all | code-only | metadata-only", verbatim_doc_comment )] - build_artifact: BuildArtifacts, + build_artifact: GenerateArtifacts, #[structopt(flatten)] verbosity: VerbosityFlags, #[structopt(flatten)] @@ -273,43 +410,25 @@ fn exec(cmd: Command) -> Result { unstable_options, } => { let manifest_path = ManifestPath::try_from(manifest_path.as_ref())?; - let build_result = cmd::build::execute( - &manifest_path, - verbosity.try_into()?, - true, - *build_artifact, - unstable_options.try_into()?, - )?; + let result = if build_artifact == &GenerateArtifacts::MetadataOnly { + cmd::metadata::execute( + &manifest_path, + verbosity.try_into()?, + *build_artifact, + unstable_options.try_into()?, + )? + } else { + cmd::build::execute( + &manifest_path, + verbosity.try_into()?, + true, + *build_artifact, + unstable_options.try_into()?, + )? + }; - let mut out = format!( - "\nOriginal wasm size: {:.1}K, Optimized: {:.1}K\n\n\ - Your contract artifacts are ready. You can find them in:\n{}\n\n", - cmd::build::BuildResult::display_optimization(&build_result).0, - cmd::build::BuildResult::display_optimization(&build_result).1, - build_result.target_directory.display().to_string() - ); - if let Some(dest_bundle) = build_result.dest_bundle { - let bundle = format!( - " - {} (code + metadata)\n", - cmd::build::BuildResult::display(&dest_bundle) - ); - out.push_str(&bundle); - } - if let Some(dest_wasm) = build_result.dest_wasm { - let wasm = format!( - " - {} (the contract's code)\n", - cmd::build::BuildResult::display(&dest_wasm) - ); - out.push_str(&wasm); - } - if let Some(dest_metadata) = build_result.dest_metadata { - let metadata = format!( - " - {} (the contract's metadata)", - cmd::build::BuildResult::display(&dest_metadata) - ); - out.push_str(&metadata); - } - Ok(out) + let out = build_artifact.display(&result); + return Ok(out); } Command::Check { manifest_path, @@ -321,7 +440,7 @@ fn exec(cmd: Command) -> Result { &manifest_path, verbosity.try_into()?, false, - BuildArtifacts::CodeOnly, + GenerateArtifacts::CodeOnly, unstable_options.try_into()?, )?; assert!(res.dest_wasm.is_none(), "no dest_wasm should exist"); -- GitLab From 923cdedfc0c8bb20a6ad7349c2fc87046450a9e3 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 13:36:24 +0100 Subject: [PATCH 48/60] Make it work with `--features test-ci-only` --- metadata/lib.rs | 4 ++-- src/cmd/metadata.rs | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index 7039e6bc..edcb9b05 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -520,7 +520,7 @@ mod tests { let compiler = SourceCompiler::new(Compiler::RustC, Version::parse("1.46.0-nightly").unwrap()); let wasm = SourceWasm::new(vec![0u8, 1u8, 2u8]); - let source = Source::new(Some(wasm), [0u8; 32], language, compiler); + let source = Source::new(Some(wasm), Some([0u8; 32]), language, compiler); let contract = Contract::builder() .name("incrementer".to_string()) .version(Version::new(2, 1, 0)) @@ -602,7 +602,7 @@ mod tests { let language = SourceLanguage::new(Language::Ink, Version::new(2, 1, 0)); let compiler = SourceCompiler::new(Compiler::RustC, Version::parse("1.46.0-nightly").unwrap()); - let source = Source::new(None, [0u8; 32], language, compiler); + let source = Source::new(None, Some([0u8; 32]), language, compiler); let contract = Contract::builder() .name("incrementer".to_string()) .version(Version::new(2, 1, 0)) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 33c2386f..aeeb67b2 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -288,7 +288,7 @@ pub(crate) fn execute( mod tests { use crate::cmd::metadata::blake2_hash; use crate::{ - cmd, cmd::BuildArtifacts, crate_metadata::CrateMetadata, util::tests::with_tmp_dir, + cmd, crate_metadata::CrateMetadata, util::tests::with_tmp_dir, GenerateArtifacts, ManifestPath, UnstableFlags, }; use contract_metadata::*; @@ -383,20 +383,20 @@ mod tests { test_manifest.write()?; let crate_metadata = CrateMetadata::collect(&test_manifest.manifest_path)?; - let bundle_file = cmd::metadata::execute( + let dest_bundle = cmd::metadata::execute( &test_manifest.manifest_path, None, - BuildArtifacts::All, + GenerateArtifacts::All, UnstableFlags::default(), )? - .bundle_file + .dest_bundle .expect("bundle file not found"); let metadata_json: Map = - serde_json::from_slice(&fs::read(&bundle_file)?)?; + serde_json::from_slice(&fs::read(&dest_bundle)?)?; assert!( - bundle_file.exists(), - format!("Missing metadata file '{}'", bundle_file.display()) + dest_bundle.exists(), + format!("Missing metadata file '{}'", dest_bundle.display()) ); let source = metadata_json.get("source").expect("source not found"); -- GitLab From fcb66c66cbaaeedde38806835da731cc0c85f36f Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 13:41:39 +0100 Subject: [PATCH 49/60] Fix doc test --- metadata/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index edcb9b05..248d2ee6 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -28,7 +28,7 @@ //! let language = SourceLanguage::new(Language::Ink, Version::new(2, 1, 0)); //! let compiler = SourceCompiler::new(Compiler::RustC, Version::parse("1.46.0-nightly").unwrap()); //! let wasm = SourceWasm::new(vec![0u8]); -//! let source = Source::new(Some(wasm), [0u8; 32], language, compiler); +//! let source = Source::new(Some(wasm), Some([0u8; 32]), language, compiler); //! let contract = Contract::builder() //! .name("incrementer".to_string()) //! .version(Version::new(2, 1, 0)) -- GitLab From c5296adfdff7cdc6b9b7fc89731376faf87e1a52 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 14:14:03 +0100 Subject: [PATCH 50/60] Remove comments --- src/cmd/metadata.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index aeeb67b2..7347057f 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -168,7 +168,6 @@ impl GenerateMetadataCommand { .transpose()?; let homepage = self.crate_metadata.homepage.clone(); let license = contract_package.license.clone(); - //{ let (dest_wasm, hash, optimization_result) = if self.build_artifact != GenerateArtifacts::MetadataOnly { let (wasm, hash, optimization) = self.wasm_hash()?; @@ -189,8 +188,6 @@ impl GenerateMetadataCommand { }; Source::new(maybe_wasm, hash, lang, compiler) }; - //(dest_wasm, hash, optimization_result, source) - //} // Required contract fields let mut builder = Contract::builder(); -- GitLab From 4cdc220f7e17ac77616d68e8d61b0e683abb5e78 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 14:33:12 +0100 Subject: [PATCH 51/60] Introduce wrapper type CodeHash --- metadata/lib.rs | 30 ++++++++++++++++-------------- src/cmd/metadata.rs | 15 +++++++++------ 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index 248d2ee6..eb8f785e 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -99,13 +99,23 @@ impl ContractMetadata { } } +/// Representation of the Wasm code hash. +#[derive(Debug, Eq, PartialEq)] +pub struct CodeHash(pub [u8; 32]); + +impl Serialize for CodeHash { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serialize_as_byte_str(&self.0[..], serializer) + } +} + #[derive(Debug, Serialize)] pub struct Source { - #[serde( - serialize_with = "serialize_as_byte_str_foo", - skip_serializing_if = "Option::is_none" - )] - hash: Option<[u8; 32]>, + #[serde(skip_serializing_if = "Option::is_none")] + hash: Option, language: SourceLanguage, compiler: SourceCompiler, #[serde(skip_serializing_if = "Option::is_none")] @@ -116,7 +126,7 @@ impl Source { /// Constructs a new InkProjectSource. pub fn new( wasm: Option, - hash: Option<[u8; 32]>, + hash: Option, language: SourceLanguage, compiler: SourceCompiler, ) -> Self { @@ -436,14 +446,6 @@ impl ContractBuilder { } } -fn serialize_as_byte_str_foo(bytes: &Option<[u8; 32]>, serializer: S) -> Result -where - S: serde::Serializer, -{ - let bytes = bytes.expect("must_exist"); - serialize_as_byte_str(&bytes[..], serializer) -} - /// Serializes the given bytes as byte string. fn serialize_as_byte_str(bytes: &[u8], serializer: S) -> Result where diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 7347057f..fcc436f2 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -25,8 +25,8 @@ use anyhow::Result; use blake2::digest::{Update as _, VariableOutput as _}; use colored::Colorize; use contract_metadata::{ - Compiler, Contract, ContractMetadata, Language, Source, SourceCompiler, SourceLanguage, - SourceWasm, User, + CodeHash, Compiler, Contract, ContractMetadata, Language, Source, SourceCompiler, + SourceLanguage, SourceWasm, User, }; use semver::Version; use std::{fs, path::PathBuf}; @@ -181,7 +181,10 @@ impl GenerateMetadataCommand { let maybe_wasm = if self.build_artifact == GenerateArtifacts::All { let wasm = fs::read(&self.crate_metadata.dest_wasm)?; // The Wasm which we read must have the same hash as `source.hash` - debug_assert_eq!(Some(blake2_hash(wasm.as_slice())), hash); + debug_assert!({ + let expected = blake2_hash(wasm.as_slice()); + Some(expected) == hash + }); Some(SourceWasm::new(wasm)) } else { None @@ -235,7 +238,7 @@ impl GenerateMetadataCommand { /// Compile the contract and then hash the resulting Wasm. /// /// Return a tuple of `(dest_wasm, hash, optimization_result)`. - fn wasm_hash(&self) -> Result<(PathBuf, [u8; 32], OptimizationResult)> { + fn wasm_hash(&self) -> Result<(PathBuf, CodeHash, OptimizationResult)> { let (maybe_dest_wasm, maybe_optimization_res) = super::build::execute_with_crate_metadata( &self.crate_metadata, self.verbosity, @@ -252,12 +255,12 @@ impl GenerateMetadataCommand { } /// Returns the blake2 hash of the submitted slice. -fn blake2_hash(code: &[u8]) -> [u8; 32] { +fn blake2_hash(code: &[u8]) -> CodeHash { let mut output = [0u8; 32]; let mut blake2 = blake2::VarBlake2b::new_keyed(&[], 32); blake2.update(code); blake2.finalize_variable(|result| output.copy_from_slice(result)); - output + CodeHash(output) } /// Generates a file with metadata describing the ABI of the smart-contract. -- GitLab From 930a309dfa5ef5265f87e56d2ed3d8242f0706d3 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 14:34:24 +0100 Subject: [PATCH 52/60] Make it work with `--features test-ci-only` --- metadata/lib.rs | 6 +++--- src/cmd/metadata.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index eb8f785e..c27638d2 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -28,7 +28,7 @@ //! let language = SourceLanguage::new(Language::Ink, Version::new(2, 1, 0)); //! let compiler = SourceCompiler::new(Compiler::RustC, Version::parse("1.46.0-nightly").unwrap()); //! let wasm = SourceWasm::new(vec![0u8]); -//! let source = Source::new(Some(wasm), Some([0u8; 32]), language, compiler); +//! let source = Source::new(Some(wasm), Some(CodeHash([0u8; 32])), language, compiler); //! let contract = Contract::builder() //! .name("incrementer".to_string()) //! .version(Version::new(2, 1, 0)) @@ -522,7 +522,7 @@ mod tests { let compiler = SourceCompiler::new(Compiler::RustC, Version::parse("1.46.0-nightly").unwrap()); let wasm = SourceWasm::new(vec![0u8, 1u8, 2u8]); - let source = Source::new(Some(wasm), Some([0u8; 32]), language, compiler); + let source = Source::new(Some(wasm), Some(CodeHash([0u8; 32])), language, compiler); let contract = Contract::builder() .name("incrementer".to_string()) .version(Version::new(2, 1, 0)) @@ -604,7 +604,7 @@ mod tests { let language = SourceLanguage::new(Language::Ink, Version::new(2, 1, 0)); let compiler = SourceCompiler::new(Compiler::RustC, Version::parse("1.46.0-nightly").unwrap()); - let source = Source::new(None, Some([0u8; 32]), language, compiler); + let source = Source::new(None, Some(CodeHash([0u8; 32])), language, compiler); let contract = Contract::builder() .name("incrementer".to_string()) .version(Version::new(2, 1, 0)) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index fcc436f2..7755afc4 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -453,7 +453,7 @@ mod tests { ), ); - assert_eq!(build_byte_str(&expected_hash[..]), hash.as_str().unwrap()); + assert_eq!(build_byte_str(&expected_hash.0[..]), hash.as_str().unwrap()); assert_eq!(expected_wasm, wasm.as_str().unwrap()); assert_eq!(expected_language, language.as_str().unwrap()); assert_eq!(expected_compiler, compiler.as_str().unwrap()); -- GitLab From 4403bd72274ebdc75b12ab48ecda29ec1aa00099 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 15:28:19 +0100 Subject: [PATCH 53/60] Display important results bold --- src/main.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index f0a473f7..ccf6c433 100644 --- a/src/main.rs +++ b/src/main.rs @@ -186,13 +186,17 @@ impl GenerateArtifacts { .as_ref() .expect("metadata path must exist") .display() + .to_string() + .bold() ); } let optimization = GenerationResult::display_optimization(result); - let mut out = format!("\nOriginal wasm size: {:.1}K, Optimized: {:.1}K\n\nYour contract artifacts are ready. You can find them in:\n{}\n\n", - optimization.0, optimization.1, - result.target_directory.display().to_string() + let mut out = format!( + "\nOriginal wasm size: {}, Optimized: {}\n\nYour contract artifacts are ready. You can find them in:\n{}\n\n", + format!("{:.1}K", optimization.0).bold(), + format!("{:.1}K", optimization.1).bold(), + result.target_directory.display().to_string().bold() ); if self == &GenerateArtifacts::CodeOnly { @@ -203,6 +207,8 @@ impl GenerateArtifacts { .as_ref() .expect("wasm path must exist") .display() + .to_string() + .bold() ); return out; }; @@ -210,21 +216,21 @@ impl GenerateArtifacts { if let Some(dest_bundle) = result.dest_bundle.as_ref() { let bundle = format!( " - {} (code + metadata)\n", - GenerationResult::display(&dest_bundle) + GenerationResult::display(&dest_bundle).bold() ); out.push_str(&bundle); } if let Some(dest_wasm) = result.dest_wasm.as_ref() { let wasm = format!( " - {} (the contract's code)\n", - GenerationResult::display(&dest_wasm) + GenerationResult::display(&dest_wasm).bold() ); out.push_str(&wasm); } if let Some(dest_metadata) = result.dest_metadata.as_ref() { let metadata = format!( " - {} (the contract's metadata)", - GenerationResult::display(&dest_metadata) + GenerationResult::display(&dest_metadata).bold() ); out.push_str(&metadata); } -- GitLab From 0c596f00019556a3d615f192be34735a3e09ed50 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 15:36:06 +0100 Subject: [PATCH 54/60] Include size diff for `code-only` as well --- src/main.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index ccf6c433..953aefab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -192,16 +192,16 @@ impl GenerateArtifacts { } let optimization = GenerationResult::display_optimization(result); - let mut out = format!( - "\nOriginal wasm size: {}, Optimized: {}\n\nYour contract artifacts are ready. You can find them in:\n{}\n\n", + let size_diff = format!( + "\nOriginal wasm size: {}, Optimized: {}\n\n", format!("{:.1}K", optimization.0).bold(), format!("{:.1}K", optimization.1).bold(), - result.target_directory.display().to_string().bold() ); if self == &GenerateArtifacts::CodeOnly { let out = format!( - "\nYour contract's code is ready. You can find it here:\n{}", + "{}Your contract's code is ready. You can find it here:\n{}", + size_diff, result .dest_wasm .as_ref() @@ -213,6 +213,11 @@ impl GenerateArtifacts { return out; }; + let mut out = format!( + "{}Your contract artifacts are ready. You can find them in:\n{}\n\n", + size_diff, + result.target_directory.display().to_string().bold(), + ); if let Some(dest_bundle) = result.dest_bundle.as_ref() { let bundle = format!( " - {} (code + metadata)\n", -- GitLab From d9a0f10606ac3390695fe608460aef95ac54bb9b Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 19:16:10 +0100 Subject: [PATCH 55/60] Remove comment --- src/cmd/build.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index e54c16c1..f65772e2 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -219,12 +219,6 @@ fn optimize_wasm(crate_metadata: &CrateMetadata) -> Result { let original_size = metadata(&crate_metadata.dest_wasm)?.len() as f64 / 1000.0; let optimized_size = metadata(&optimized)?.len() as f64 / 1000.0; - /* - println!( - " Original wasm size: {:.1}K, Optimized: {:.1}K", - original_size, optimized_size - ); - */ // overwrite existing destination wasm file with the optimised version std::fs::rename(&optimized, &crate_metadata.dest_wasm)?; -- GitLab From 8737b9b7dd77a971fbc7324a45b1357d0117e45d Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 19:17:57 +0100 Subject: [PATCH 56/60] Shorten code --- src/cmd/metadata.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 7755afc4..c63d668c 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -103,19 +103,15 @@ impl GenerateMetadataCommand { current_progress += 1; } - if self.build_artifact == GenerateArtifacts::MetadataOnly { - println!( - " {} {}", - format!("[{}/{}]", 1, self.build_artifact.steps()).bold(), - "Generating metadata".bright_green().bold() - ); - } else { - println!( - " {} {}", - format!("[{}/{}]", current_progress, self.build_artifact.steps()).bold(), - "Generating metadata".bright_green().bold() - ); - } + let curr_step = match self.build_artifact { + GenerateArtifacts::MetadataOnly => 1, + _ => current_progress, + }; + println!( + " {} {}", + format!("[{}/{}]", curr_step, self.build_artifact.steps()).bold(), + "Generating metadata".bright_green().bold() + ); metadata.remove_source_wasm_attribute(); let contents = serde_json::to_string_pretty(&metadata)?; fs::write(&out_path_wasm, contents)?; -- GitLab From 234b45f4d5eb512ac77d9b684826525ad1d151c5 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 19:27:35 +0100 Subject: [PATCH 57/60] Clone metadata for correct UI output --- metadata/lib.rs | 20 ++++++++++---------- src/cmd/metadata.rs | 37 +++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index c27638d2..1c1e606d 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -61,7 +61,7 @@ use url::Url; const METADATA_VERSION: &str = "0.1.0"; /// Smart contract metadata. -#[derive(Debug, Serialize)] +#[derive(Clone, Debug, Serialize)] pub struct ContractMetadata { #[serde(rename = "metadataVersion")] metadata_version: semver::Version, @@ -100,7 +100,7 @@ impl ContractMetadata { } /// Representation of the Wasm code hash. -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct CodeHash(pub [u8; 32]); impl Serialize for CodeHash { @@ -112,7 +112,7 @@ impl Serialize for CodeHash { } } -#[derive(Debug, Serialize)] +#[derive(Clone, Debug, Serialize)] pub struct Source { #[serde(skip_serializing_if = "Option::is_none")] hash: Option, @@ -140,7 +140,7 @@ impl Source { } /// The bytes of the compiled Wasm smart contract. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct SourceWasm { wasm: Vec, } @@ -172,7 +172,7 @@ impl Display for SourceWasm { } /// The language and version in which a smart contract is written. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct SourceLanguage { language: Language, version: Version, @@ -201,7 +201,7 @@ impl Display for SourceLanguage { } /// The language in which the smart contract is written. -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum Language { Ink, Solidity, @@ -219,7 +219,7 @@ impl Display for Language { } /// A compiler used to compile a smart contract. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct SourceCompiler { compiler: Compiler, version: Version, @@ -247,7 +247,7 @@ impl SourceCompiler { } /// Compilers used to compile a smart contract. -#[derive(Debug, Serialize)] +#[derive(Clone, Debug, Serialize)] pub enum Compiler { RustC, Solang, @@ -263,7 +263,7 @@ impl Display for Compiler { } /// Metadata about a smart contract. -#[derive(Debug, Serialize)] +#[derive(Clone, Debug, Serialize)] pub struct Contract { name: String, version: Version, @@ -287,7 +287,7 @@ impl Contract { } /// Additional user defined metadata, can be any valid json. -#[derive(Debug, Serialize)] +#[derive(Clone, Debug, Serialize)] pub struct User { #[serde(flatten)] json: Map, diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index c63d668c..091cb697 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -56,7 +56,7 @@ impl GenerateMetadataCommand { util::assert_channel()?; let cargo_meta = &self.crate_metadata.cargo_meta; - let out_path_wasm = cargo_meta.target_directory.join(METADATA_FILE); + let out_path_metadata = cargo_meta.target_directory.join(METADATA_FILE); let fname_bundle = format!("{}.contract", self.crate_metadata.package_name); let out_path_bundle = cargo_meta.target_directory.join(fname_bundle); @@ -90,8 +90,26 @@ impl GenerateMetadataCommand { let ink_meta: serde_json::Map = serde_json::from_slice(&stdout)?; - let mut metadata = ContractMetadata::new(source, contract, user, ink_meta); let mut current_progress = 4; + let metadata = ContractMetadata::new(source, contract, user, ink_meta); + + { + let mut metadata = metadata.clone(); + let curr_step = match self.build_artifact { + GenerateArtifacts::MetadataOnly => 1, + _ => current_progress, + }; + println!( + " {} {}", + format!("[{}/{}]", curr_step, self.build_artifact.steps()).bold(), + "Generating metadata".bright_green().bold() + ); + metadata.remove_source_wasm_attribute(); + let contents = serde_json::to_string_pretty(&metadata)?; + fs::write(&out_path_metadata, contents)?; + current_progress += 1; + } + if self.build_artifact == GenerateArtifacts::All { println!( " {} {}", @@ -100,21 +118,8 @@ impl GenerateMetadataCommand { ); let contents = serde_json::to_string_pretty(&metadata)?; fs::write(&out_path_bundle, contents)?; - current_progress += 1; } - let curr_step = match self.build_artifact { - GenerateArtifacts::MetadataOnly => 1, - _ => current_progress, - }; - println!( - " {} {}", - format!("[{}/{}]", curr_step, self.build_artifact.steps()).bold(), - "Generating metadata".bright_green().bold() - ); - metadata.remove_source_wasm_attribute(); - let contents = serde_json::to_string_pretty(&metadata)?; - fs::write(&out_path_wasm, contents)?; Ok(()) }; @@ -138,7 +143,7 @@ impl GenerateMetadataCommand { None }; Ok(GenerationResult { - dest_metadata: Some(out_path_wasm), + dest_metadata: Some(out_path_metadata), dest_wasm, dest_bundle, optimization_result, -- GitLab From 84742097ffeda9d786f7f06e3a5740bd6f835c1d Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 19:27:52 +0100 Subject: [PATCH 58/60] Remove unnecessary return --- src/main.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 953aefab..9644852f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -438,8 +438,7 @@ fn exec(cmd: Command) -> Result { )? }; - let out = build_artifact.display(&result); - return Ok(out); + build_artifact.display(&result) } Command::Check { manifest_path, -- GitLab From b6b9cad58d3aca8f3730ab9f05a197f839aa4c7a Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 9 Nov 2020 19:28:26 +0100 Subject: [PATCH 59/60] Fix return type --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 9644852f..124cf4c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -438,7 +438,7 @@ fn exec(cmd: Command) -> Result { )? }; - build_artifact.display(&result) + Ok(build_artifact.display(&result)) } Command::Check { manifest_path, -- GitLab From 1c067d95326f99d5f0aa3ac73973993a1a41efa8 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 10 Nov 2020 10:43:49 +0100 Subject: [PATCH 60/60] Print metadata generation in correct step --- src/cmd/metadata.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 091cb697..e80c01e4 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -73,6 +73,16 @@ impl GenerateMetadataCommand { } = self.extended_metadata()?; let generate_metadata = |manifest_path: &ManifestPath| -> Result<()> { + let mut current_progress = 4; + let curr_step = match self.build_artifact { + GenerateArtifacts::MetadataOnly => 1, + _ => current_progress, + }; + println!( + " {} {}", + format!("[{}/{}]", curr_step, self.build_artifact.steps()).bold(), + "Generating metadata".bright_green().bold() + ); let target_dir_arg = format!("--target-dir={}", target_directory.to_string_lossy()); let stdout = util::invoke_cargo( "run", @@ -89,21 +99,9 @@ impl GenerateMetadataCommand { let ink_meta: serde_json::Map = serde_json::from_slice(&stdout)?; - - let mut current_progress = 4; let metadata = ContractMetadata::new(source, contract, user, ink_meta); - { let mut metadata = metadata.clone(); - let curr_step = match self.build_artifact { - GenerateArtifacts::MetadataOnly => 1, - _ => current_progress, - }; - println!( - " {} {}", - format!("[{}/{}]", curr_step, self.build_artifact.steps()).bold(), - "Generating metadata".bright_green().bold() - ); metadata.remove_source_wasm_attribute(); let contents = serde_json::to_string_pretty(&metadata)?; fs::write(&out_path_metadata, contents)?; -- GitLab