From 8fd0b845cbba746a4b00c4032fdb7adaafae7506 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 3 Aug 2022 17:55:49 -0400 Subject: [PATCH 01/18] Write (slightly-hardcoded) build info to metadata --- metadata/lib.rs | 7 +++++ src/cmd/build.rs | 31 +++++++++++++++++++++ src/cmd/metadata.rs | 65 +++++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 4 +-- 4 files changed, 103 insertions(+), 4 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index 76aa32ef2..3d22c4fa5 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -137,6 +137,11 @@ pub struct Source { /// with the metadata. #[serde(skip_serializing_if = "Option::is_none")] pub wasm: Option, + /// Extra information about the environment in which the contract was built. + /// + /// Useful for producing deterministic builds. + #[serde(skip_serializing_if = "Option::is_none")] + pub build_info: Option>, } impl Source { @@ -146,12 +151,14 @@ impl Source { hash: CodeHash, language: SourceLanguage, compiler: SourceCompiler, + build_info: Option>, ) -> Self { Source { hash, language, compiler, wasm, + build_info, } } } diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 72cf7dc89..05c12eb16 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -281,6 +281,8 @@ fn exec_cargo_for_wasm_target( let cargo_build = |manifest_path: &ManifestPath| { let target_dir = &crate_metadata.target_directory; let target_dir = format!("--target-dir={}", target_dir.to_string_lossy()); + + // TODO: So we'll need to find a way to include these into the `BuildInfo`. let mut args = vec![ "--target=wasm32-unknown-unknown", "-Zbuild-std", @@ -789,6 +791,11 @@ pub fn assert_debug_mode_supported(ink_version: &Version) -> anyhow::Result<()> /// /// It does so by invoking `cargo build` and then post processing the final binary. pub(crate) fn execute(args: ExecuteArgs) -> Result { + use crate::cmd::metadata::{ + BuildInfo, + WasmOptSettings, + }; + let ExecuteArgs { manifest_path, verbosity, @@ -802,6 +809,29 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { output_type, } = args; + let rustc_version = contract_metadata::SourceCompiler { + compiler: contract_metadata::Compiler::RustC, + version: Version::parse(&rustc_version::version()?.to_string())?, + }; + + // TODO: This we should be able to get by doing something like: + // + // `let version: Version = invoke_cargo(contract, --version).parse()` + let cargo_contract_version = Version::parse("1.4.0").expect("TODO"); + + let build_info = BuildInfo { + rustc_version, + cargo_contract_version, + build_mode, + // TODO: I think we'll need to pull this out from the wasm_build function + features: vec![], + // TODO: Maybe extract version from check_wasm_opt_version_compatibility() + wasm_opt_settings: WasmOptSettings { + version: 0, + optimization_passes, + }, + }; + let crate_metadata = CrateMetadata::collect(&manifest_path)?; assert_compatible_ink_dependencies(&manifest_path, verbosity)?; @@ -911,6 +941,7 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { verbosity, build_artifact.steps(), &unstable_flags, + build_info, )?; (Some(optimization_result), Some(metadata_result)) } diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 0e759e9c0..799cc292a 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -22,7 +22,9 @@ use crate::{ ManifestPath, Workspace, }, + BuildMode, Network, + OptimizationPasses, UnstableFlags, Verbosity, }; @@ -73,6 +75,33 @@ struct ExtendedMetadataResult { user: Option, } +/// Information about the settings used to build a particular ink! contract. +/// +/// Note that this should be an optional part of the metadata since it may not necessarily +/// translate to other languages (e.g ask!, Solidity). +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub struct BuildInfo { + /// The version of `rustc` used to build the contract. + pub rustc_version: SourceCompiler, + /// The version of `cargo-contract` used to build the contract. + pub cargo_contract_version: Version, + /// The type of build that was used when building the contract. + pub build_mode: BuildMode, + /// The list of supplied Cargo features. + pub features: Vec, + /// Information about the `wasm-opt` optimization settings. + pub wasm_opt_settings: WasmOptSettings, +} + +/// Settings used when optimizing the Wasm binary using Binaryen's `wasm-opt`. +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub struct WasmOptSettings { + /// Version of `wasm-opt`. + pub version: u64, + /// The level of optimization used during the `wasm-opt` run. + pub optimization_passes: OptimizationPasses, +} + /// Generates a file with metadata describing the ABI of the smart contract. /// /// It does so by generating and invoking a temporary workspace member. @@ -83,6 +112,7 @@ pub(crate) fn execute( verbosity: Verbosity, total_steps: usize, unstable_options: &UnstableFlags, + build_info: BuildInfo, ) -> Result { util::assert_channel()?; @@ -97,7 +127,7 @@ pub(crate) fn execute( source, contract, user, - } = extended_metadata(crate_metadata, final_contract_wasm)?; + } = extended_metadata(crate_metadata, final_contract_wasm, build_info)?; let generate_metadata = |manifest_path: &ManifestPath| -> Result<()> { let mut current_progress = 4; @@ -173,6 +203,7 @@ pub(crate) fn execute( fn extended_metadata( crate_metadata: &CrateMetadata, final_contract_wasm: &Path, + build_info: BuildInfo, ) -> Result { let contract_package = &crate_metadata.root_package; let ink_version = &crate_metadata.ink_version; @@ -195,7 +226,37 @@ fn extended_metadata( let compiler = SourceCompiler::new(Compiler::RustC, rust_version); let wasm = fs::read(final_contract_wasm)?; let hash = blake2_hash(wasm.as_slice()); - Source::new(Some(SourceWasm::new(wasm)), hash, lang, compiler) + + // TODO: lol + let mut build_info_map = serde_json::Map::new(); + build_info_map.insert( + "cargo_contract_version".to_string(), + serde_json::to_value(build_info.rustc_version)?, + ); + build_info_map.insert( + "cargo_contract_version".to_string(), + serde_json::to_value(build_info.cargo_contract_version)?, + ); + build_info_map.insert( + "build_mode".to_string(), + serde_json::to_value(build_info.build_mode)?, + ); + build_info_map.insert( + "features".to_string(), + serde_json::to_value(build_info.features)?, + ); + build_info_map.insert( + "wasm_opt_settings".to_string(), + serde_json::to_value(build_info.wasm_opt_settings)?, + ); + + Source::new( + Some(SourceWasm::new(wasm)), + hash, + lang, + compiler, + Some(build_info_map), + ) }; // Required contract fields diff --git a/src/main.rs b/src/main.rs index 6819209dc..49a65645e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -88,7 +88,7 @@ impl FromStr for HexData { } } -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub enum OptimizationPasses { Zero, One, @@ -264,7 +264,7 @@ impl Default for BuildArtifacts { } /// The mode to build the contract in. -#[derive(Eq, PartialEq, Copy, Clone, Debug, serde::Serialize)] +#[derive(Eq, PartialEq, Copy, Clone, Debug, serde::Serialize, serde::Deserialize)] pub enum BuildMode { /// Functionality to output debug messages is build into the contract. Debug, From 92ad53076e9147d244e145dafb4816440fe4b3f6 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 4 Aug 2022 12:22:23 -0400 Subject: [PATCH 02/18] Add `channel-date` formatted rustc version to metadata --- src/cmd/build.rs | 19 ++++++++++--------- src/cmd/metadata.rs | 6 ++++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 05c12eb16..d974a6b45 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -809,15 +809,16 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { output_type, } = args; - let rustc_version = contract_metadata::SourceCompiler { - compiler: contract_metadata::Compiler::RustC, - version: Version::parse(&rustc_version::version()?.to_string())?, - }; - - // TODO: This we should be able to get by doing something like: - // - // `let version: Version = invoke_cargo(contract, --version).parse()` - let cargo_contract_version = Version::parse("1.4.0").expect("TODO"); + let rustc_version = rustc_version::version_meta()?; + let rustc_version = format!( + "{:?}-{}", + rustc_version.channel, + rustc_version.commit_date.expect("TODO") + ) + .to_lowercase(); + + let cargo_contract_version = env!("CARGO_PKG_VERSION"); + let cargo_contract_version = Version::parse(cargo_contract_version).expect("TODO"); let build_info = BuildInfo { rustc_version, diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 799cc292a..6f283ae3c 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -82,7 +82,9 @@ struct ExtendedMetadataResult { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct BuildInfo { /// The version of `rustc` used to build the contract. - pub rustc_version: SourceCompiler, + /// + /// TODO: Should add a Display impl to `rustc_version::VersionMeta` and use that instead + pub rustc_version: String, /// The version of `cargo-contract` used to build the contract. pub cargo_contract_version: Version, /// The type of build that was used when building the contract. @@ -230,7 +232,7 @@ fn extended_metadata( // TODO: lol let mut build_info_map = serde_json::Map::new(); build_info_map.insert( - "cargo_contract_version".to_string(), + "rustc_version".to_string(), serde_json::to_value(build_info.rustc_version)?, ); build_info_map.insert( From 42e22c46c663340b75630ebfdeac4789d67cbb22 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 4 Aug 2022 12:28:22 -0400 Subject: [PATCH 03/18] Remove `features` from `BuildInfo` Since we hardcode these into `cargo-contract` we shouldn't need to track these manually --- src/cmd/build.rs | 3 --- src/cmd/metadata.rs | 6 ------ 2 files changed, 9 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index d974a6b45..cb94ded84 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -282,7 +282,6 @@ fn exec_cargo_for_wasm_target( let target_dir = &crate_metadata.target_directory; let target_dir = format!("--target-dir={}", target_dir.to_string_lossy()); - // TODO: So we'll need to find a way to include these into the `BuildInfo`. let mut args = vec![ "--target=wasm32-unknown-unknown", "-Zbuild-std", @@ -824,8 +823,6 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { rustc_version, cargo_contract_version, build_mode, - // TODO: I think we'll need to pull this out from the wasm_build function - features: vec![], // TODO: Maybe extract version from check_wasm_opt_version_compatibility() wasm_opt_settings: WasmOptSettings { version: 0, diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 6f283ae3c..1c7efcab1 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -89,8 +89,6 @@ pub struct BuildInfo { pub cargo_contract_version: Version, /// The type of build that was used when building the contract. pub build_mode: BuildMode, - /// The list of supplied Cargo features. - pub features: Vec, /// Information about the `wasm-opt` optimization settings. pub wasm_opt_settings: WasmOptSettings, } @@ -243,10 +241,6 @@ fn extended_metadata( "build_mode".to_string(), serde_json::to_value(build_info.build_mode)?, ); - build_info_map.insert( - "features".to_string(), - serde_json::to_value(build_info.features)?, - ); build_info_map.insert( "wasm_opt_settings".to_string(), serde_json::to_value(build_info.wasm_opt_settings)?, From beac37ef67e4cab5dc4118b06e627b5ab06f5437 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 8 Aug 2022 16:09:29 -0400 Subject: [PATCH 04/18] Add `wasm-opt` version to metadata --- src/cmd/build.rs | 20 ++++++++++++++++---- src/cmd/metadata.rs | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index cb94ded84..f2929f5c4 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -658,7 +658,7 @@ fn do_optimization( /// compatible with `cargo-contract`. /// /// Currently this must be a version >= 99. -fn check_wasm_opt_version_compatibility(wasm_opt_path: &Path) -> Result<()> { +fn check_wasm_opt_version_compatibility(wasm_opt_path: &Path) -> Result { let mut cmd_res = Command::new(wasm_opt_path).arg("--version").output(); // The following condition is a workaround for a spurious CI failure: @@ -740,7 +740,8 @@ fn check_wasm_opt_version_compatibility(wasm_opt_path: &Path) -> Result<()> { github_note, ); } - Ok(()) + + Ok(version_number) } /// Asserts that the contract's dependencies are compatible to the ones used in ink!. @@ -808,6 +809,7 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { output_type, } = args; + // TODO: This would be slightly nicer if `VersionMeta` had a `Display` implementation let rustc_version = rustc_version::version_meta()?; let rustc_version = format!( "{:?}-{}", @@ -819,13 +821,20 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { let cargo_contract_version = env!("CARGO_PKG_VERSION"); let cargo_contract_version = Version::parse(cargo_contract_version).expect("TODO"); + // TODO: We'll want to refactor this. Two main things: + // 1. We want to be able to get the version number without necessarily calling `which` + // 2. We want to make sure that we don't need to check for the existence of `wasm-opt` in the + // `check` codepath (only in the `BuildArtifacts::All` path) + let wasm_opt_path = which::which("wasm-opt").expect("TODO"); + let wasm_opt_path = wasm_opt_path.as_path(); + let version = check_wasm_opt_version_compatibility(wasm_opt_path)?; + let build_info = BuildInfo { rustc_version, cargo_contract_version, build_mode, - // TODO: Maybe extract version from check_wasm_opt_version_compatibility() wasm_opt_settings: WasmOptSettings { - version: 0, + version, optimization_passes, }, }; @@ -884,6 +893,9 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { format!("[4/{}]", build_artifact.steps()).bold(), "Optimizing wasm file".bright_green().bold() ); + + // TODO: Build the BuildInfo struct here? + let optimization_result = optimize_wasm(&crate_metadata, optimization_passes, keep_debug_symbols)?; diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 1c7efcab1..5c72ce8bf 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -97,7 +97,7 @@ pub struct BuildInfo { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct WasmOptSettings { /// Version of `wasm-opt`. - pub version: u64, + pub version: u32, /// The level of optimization used during the `wasm-opt` run. pub optimization_passes: OptimizationPasses, } From f6c3fa289fd9b1a4e7d00241d54febb42770e864 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 8 Aug 2022 17:47:03 -0400 Subject: [PATCH 05/18] Move `BuildInfo` construction to `build` closure --- src/cmd/build.rs | 75 +++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index f2929f5c4..0d7234d75 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -791,10 +791,7 @@ pub fn assert_debug_mode_supported(ink_version: &Version) -> anyhow::Result<()> /// /// It does so by invoking `cargo build` and then post processing the final binary. pub(crate) fn execute(args: ExecuteArgs) -> Result { - use crate::cmd::metadata::{ - BuildInfo, - WasmOptSettings, - }; + use crate::cmd::metadata::BuildInfo; let ExecuteArgs { manifest_path, @@ -809,36 +806,6 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { output_type, } = args; - // TODO: This would be slightly nicer if `VersionMeta` had a `Display` implementation - let rustc_version = rustc_version::version_meta()?; - let rustc_version = format!( - "{:?}-{}", - rustc_version.channel, - rustc_version.commit_date.expect("TODO") - ) - .to_lowercase(); - - let cargo_contract_version = env!("CARGO_PKG_VERSION"); - let cargo_contract_version = Version::parse(cargo_contract_version).expect("TODO"); - - // TODO: We'll want to refactor this. Two main things: - // 1. We want to be able to get the version number without necessarily calling `which` - // 2. We want to make sure that we don't need to check for the existence of `wasm-opt` in the - // `check` codepath (only in the `BuildArtifacts::All` path) - let wasm_opt_path = which::which("wasm-opt").expect("TODO"); - let wasm_opt_path = wasm_opt_path.as_path(); - let version = check_wasm_opt_version_compatibility(wasm_opt_path)?; - - let build_info = BuildInfo { - rustc_version, - cargo_contract_version, - build_mode, - wasm_opt_settings: WasmOptSettings { - version, - optimization_passes, - }, - }; - let crate_metadata = CrateMetadata::collect(&manifest_path)?; assert_compatible_ink_dependencies(&manifest_path, verbosity)?; @@ -846,7 +813,9 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { assert_debug_mode_supported(&crate_metadata.ink_version)?; } - let build = || -> Result { + let build = || -> Result<(OptimizationResult, BuildInfo)> { + use crate::cmd::metadata::WasmOptSettings; + if skip_linting { maybe_println!( verbosity, @@ -894,12 +863,39 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { "Optimizing wasm file".bright_green().bold() ); - // TODO: Build the BuildInfo struct here? + // TODO: This would be slightly nicer if `VersionMeta` had a `Display` implementation + let rustc_version = rustc_version::version_meta()?; + let rustc_version = format!( + "{:?}-{}", + rustc_version.channel, + rustc_version.commit_date.expect("TODO") + ) + .to_lowercase(); + + let cargo_contract_version = env!("CARGO_PKG_VERSION"); + let cargo_contract_version = + Version::parse(cargo_contract_version).expect("TODO"); + + // TODO: We'll want to refactor this to be able to get the version number without + // necessarily calling `which` + let wasm_opt_path = which::which("wasm-opt").expect("TODO"); + let wasm_opt_path = wasm_opt_path.as_path(); + let version = check_wasm_opt_version_compatibility(wasm_opt_path)?; + + let build_info = BuildInfo { + rustc_version, + cargo_contract_version, + build_mode, + wasm_opt_settings: WasmOptSettings { + version, + optimization_passes, + }, + }; let optimization_result = optimize_wasm(&crate_metadata, optimization_passes, keep_debug_symbols)?; - Ok(optimization_result) + Ok((optimization_result, build_info)) }; let (opt_result, metadata_result) = match build_artifact { @@ -938,11 +934,11 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { (None, None) } BuildArtifacts::CodeOnly => { - let optimization_result = build()?; + let (optimization_result, _build_info) = build()?; (Some(optimization_result), None) } BuildArtifacts::All => { - let optimization_result = build()?; + let (optimization_result, build_info) = build()?; let metadata_result = super::metadata::execute( &crate_metadata, @@ -953,6 +949,7 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { &unstable_flags, build_info, )?; + (Some(optimization_result), Some(metadata_result)) } }; From ad19ec95c9ae3a3c544fb6fcbb08a0a13dc58359 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 8 Aug 2022 18:13:15 -0400 Subject: [PATCH 06/18] Add `build_info` field to tests --- metadata/lib.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/metadata/lib.rs b/metadata/lib.rs index 3d22c4fa5..d86d2023a 100644 --- a/metadata/lib.rs +++ b/metadata/lib.rs @@ -28,7 +28,9 @@ //! 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), CodeHash([0u8; 32]), language, compiler); +//! // Optional information about how the contract was build +//! let build_info: Map = Map::new(); +//! let source = Source::new(Some(wasm), CodeHash([0u8; 32]), language, compiler, Some(build_info)); //! let contract = Contract::builder() //! .name("incrementer".to_string()) //! .version(Version::new(2, 1, 0)) @@ -653,7 +655,25 @@ mod tests { Version::parse("1.46.0-nightly").unwrap(), ); let wasm = SourceWasm::new(vec![0u8, 1u8, 2u8]); - let source = Source::new(Some(wasm), CodeHash([0u8; 32]), language, compiler); + let build_info = json! { + { + "example_compiler_version": 42, + "example_settings": [], + "example_name": "increment" + } + } + .as_object() + .unwrap() + .clone(); + + let source = Source::new( + Some(wasm), + CodeHash([0u8; 32]), + language, + compiler, + Some(build_info), + ); + let contract = Contract::builder() .name("incrementer".to_string()) .version(Version::new(2, 1, 0)) @@ -697,7 +717,12 @@ mod tests { "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "language": "ink! 2.1.0", "compiler": "rustc 1.46.0-nightly", - "wasm": "0x000102" + "wasm": "0x000102", + "build_info": { + "example_compiler_version": 42, + "example_settings": [], + "example_name": "increment" + } }, "contract": { "name": "incrementer", @@ -736,7 +761,7 @@ mod tests { Compiler::RustC, Version::parse("1.46.0-nightly").unwrap(), ); - let source = Source::new(None, CodeHash([0u8; 32]), language, compiler); + let source = Source::new(None, CodeHash([0u8; 32]), language, compiler, None); let contract = Contract::builder() .name("incrementer".to_string()) .version(Version::new(2, 1, 0)) @@ -789,7 +814,24 @@ mod tests { Version::parse("1.46.0-nightly").unwrap(), ); let wasm = SourceWasm::new(vec![0u8, 1u8, 2u8]); - let source = Source::new(Some(wasm), CodeHash([0u8; 32]), language, compiler); + let build_info = json! { + { + "example_compiler_version": 42, + "example_settings": [], + "example_name": "increment", + } + } + .as_object() + .unwrap() + .clone(); + + let source = Source::new( + Some(wasm), + CodeHash([0u8; 32]), + language, + compiler, + Some(build_info), + ); let contract = Contract::builder() .name("incrementer".to_string()) .version(Version::new(2, 1, 0)) From a12564c4a756e75475c0618cfc56b20a672afad9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 10 Aug 2022 17:16:59 -0400 Subject: [PATCH 07/18] Improve conversion between `BuildInfo` and `serde_json::Map` --- src/cmd/metadata.rs | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 5c72ce8bf..a71bad23b 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -93,6 +93,15 @@ pub struct BuildInfo { pub wasm_opt_settings: WasmOptSettings, } +impl TryFrom for serde_json::Map { + type Error = serde_json::Error; + + fn try_from(build_info: BuildInfo) -> Result { + let tmp = serde_json::to_string(&build_info)?; + serde_json::from_str(&tmp) + } +} + /// Settings used when optimizing the Wasm binary using Binaryen's `wasm-opt`. #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct WasmOptSettings { @@ -227,31 +236,12 @@ fn extended_metadata( let wasm = fs::read(final_contract_wasm)?; let hash = blake2_hash(wasm.as_slice()); - // TODO: lol - let mut build_info_map = serde_json::Map::new(); - build_info_map.insert( - "rustc_version".to_string(), - serde_json::to_value(build_info.rustc_version)?, - ); - build_info_map.insert( - "cargo_contract_version".to_string(), - serde_json::to_value(build_info.cargo_contract_version)?, - ); - build_info_map.insert( - "build_mode".to_string(), - serde_json::to_value(build_info.build_mode)?, - ); - build_info_map.insert( - "wasm_opt_settings".to_string(), - serde_json::to_value(build_info.wasm_opt_settings)?, - ); - Source::new( Some(SourceWasm::new(wasm)), hash, lang, compiler, - Some(build_info_map), + Some(build_info.try_into()?), ) }; From 6a2a1b322c2e333c79e7cd08a36b460d414aad33 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 18 Aug 2022 15:39:49 -0400 Subject: [PATCH 08/18] Add `version` getter to `WasmOptHandler` --- src/cmd/build.rs | 16 ++++++---------- src/wasm_opt.rs | 9 +++++++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 6f550e905..34d4b652d 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -667,26 +667,22 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { let cargo_contract_version = Version::parse(cargo_contract_version).expect("TODO"); - // TODO: We'll want to refactor this to be able to get the version number without - // necessarily calling `which` - let version = 0; + let handler = WasmOptHandler::new(optimization_passes, keep_debug_symbols)?; + let optimization_result = handler.optimize( + &crate_metadata.dest_wasm, + &crate_metadata.contract_artifact_name, + )?; let build_info = BuildInfo { rustc_version, cargo_contract_version, build_mode, wasm_opt_settings: WasmOptSettings { - version, + version: handler.version(), optimization_passes, }, }; - let handler = WasmOptHandler::new(optimization_passes, keep_debug_symbols)?; - let optimization_result = handler.optimize( - &crate_metadata.dest_wasm, - &crate_metadata.contract_artifact_name, - )?; - Ok((optimization_result, build_info)) }; diff --git a/src/wasm_opt.rs b/src/wasm_opt.rs index 70655e22d..4dbcfbabe 100644 --- a/src/wasm_opt.rs +++ b/src/wasm_opt.rs @@ -53,7 +53,7 @@ pub struct WasmOptHandler { /// Whether or not to keep debugging information in the final Wasm binary. keep_debug_symbols: bool, /// The version number of the `wasm-opt` binary being executed. - _version: u32, + version: u32, } impl WasmOptHandler { @@ -81,7 +81,7 @@ impl WasmOptHandler { wasm_opt_path, optimization_level, keep_debug_symbols, - _version: version, + version, }) } @@ -158,6 +158,11 @@ impl WasmOptHandler { }) } + /// The version number of the `wasm-opt` binary being executed. + pub fn version(&self) -> u32 { + self.version + } + /// Checks if the `wasm-opt` binary under `wasm_opt_path` returns a version /// compatible with `cargo-contract`. /// From 8d5f92d4a2f64f8f638f7e5e1f47a41597c7ac27 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 18 Aug 2022 16:00:10 -0400 Subject: [PATCH 09/18] Move code which indicates current toolchain to `utils` --- src/cmd/build.rs | 19 +++++-------------- src/util.rs | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 34d4b652d..597c07a29 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -654,27 +654,18 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { "Optimizing wasm file".bright_green().bold() ); - // TODO: This would be slightly nicer if `VersionMeta` had a `Display` implementation - let rustc_version = rustc_version::version_meta()?; - let rustc_version = format!( - "{:?}-{}", - rustc_version.channel, - rustc_version.commit_date.expect("TODO") - ) - .to_lowercase(); - - let cargo_contract_version = env!("CARGO_PKG_VERSION"); - let cargo_contract_version = - Version::parse(cargo_contract_version).expect("TODO"); - let handler = WasmOptHandler::new(optimization_passes, keep_debug_symbols)?; let optimization_result = handler.optimize( &crate_metadata.dest_wasm, &crate_metadata.contract_artifact_name, )?; + let cargo_contract_version = env!("CARGO_PKG_VERSION"); + let cargo_contract_version = + Version::parse(cargo_contract_version).expect("TODO"); + let build_info = BuildInfo { - rustc_version, + rustc_version: util::rustc_toolchain()?, cargo_contract_version, build_mode, wasm_opt_settings: WasmOptSettings { diff --git a/src/util.rs b/src/util.rs index f18a01935..6d9da7a18 100644 --- a/src/util.rs +++ b/src/util.rs @@ -54,6 +54,20 @@ pub fn assert_channel() -> Result<()> { } } +/// Returns the current Rust toolchain formatted by `[-]`. +pub(crate) fn rustc_toolchain() -> Result { + let meta = rustc_version::version_meta()?; + let commit_date = if let Some(date) = meta.commit_date { + format!("-{}", date) + } else { + "".to_string() + }; + + let toolchain = format!("{:?}{}", meta.channel, commit_date,).to_lowercase(); + + Ok(toolchain) +} + /// Invokes `cargo` with the subcommand `command` and the supplied `args`. /// /// In case `working_dir` is set, the command will be invoked with that folder From 5a2ad6ada05e284adcba30c733dd5f8e21bb0f94 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 18 Aug 2022 16:15:23 -0400 Subject: [PATCH 10/18] Handle case where `cargo-contract` version can't be parsed --- src/cmd/build.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 597c07a29..227b335ed 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -660,9 +660,15 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { &crate_metadata.contract_artifact_name, )?; - let cargo_contract_version = env!("CARGO_PKG_VERSION"); let cargo_contract_version = - Version::parse(cargo_contract_version).expect("TODO"); + if let Ok(version) = Version::parse(env!("CARGO_PKG_VERSION")) { + version + } else { + anyhow::bail!( + "Unable to parse version number for the currently running \ + `cargo-contract` binary." + ); + }; let build_info = BuildInfo { rustc_version: util::rustc_toolchain()?, From 7ec78dd7f956845c6f926a0c8f87d727107aac73 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 29 Aug 2022 15:06:49 -0400 Subject: [PATCH 11/18] Use a stable `rustc` version --- src/cmd/build.rs | 3 ++- src/cmd/metadata.rs | 6 ++---- src/util.rs | 14 -------------- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index c4f7805d7..b462869c7 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -665,7 +665,8 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { }; let build_info = BuildInfo { - rustc_version: util::rustc_toolchain()?, + rustc_version: rustc_version::version() + .expect("`rustc` always has a version associated with it."), cargo_contract_version, build_mode, wasm_opt_settings: WasmOptSettings { diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index cd621c602..c0572860b 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -81,10 +81,8 @@ struct ExtendedMetadataResult { /// translate to other languages (e.g ask!, Solidity). #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct BuildInfo { - /// The version of `rustc` used to build the contract. - /// - /// TODO: Should add a Display impl to `rustc_version::VersionMeta` and use that instead - pub rustc_version: String, + /// The stable version of `rustc` used to build the contract. + pub rustc_version: Version, /// The version of `cargo-contract` used to build the contract. pub cargo_contract_version: Version, /// The type of build that was used when building the contract. diff --git a/src/util.rs b/src/util.rs index 93ff3a596..21dab1242 100644 --- a/src/util.rs +++ b/src/util.rs @@ -62,20 +62,6 @@ fn assert_channel() -> Result<()> { } } -/// Returns the current Rust toolchain formatted by `[-]`. -pub(crate) fn rustc_toolchain() -> Result { - let meta = rustc_version::version_meta()?; - let commit_date = if let Some(date) = meta.commit_date { - format!("-{}", date) - } else { - "".to_string() - }; - - let toolchain = format!("{:?}{}", meta.channel, commit_date,).to_lowercase(); - - Ok(toolchain) -} - /// Invokes `cargo` with the subcommand `command` and the supplied `args`. /// /// In case `working_dir` is set, the command will be invoked with that folder From 46ea7828dc2458a6000ffc978214166f14fce464 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 29 Sep 2022 16:15:48 -0400 Subject: [PATCH 12/18] Add `keep_debug_symbols` to metadata --- crates/cargo-contract/src/cmd/build/mod.rs | 1 + crates/cargo-contract/src/cmd/metadata.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/crates/cargo-contract/src/cmd/build/mod.rs b/crates/cargo-contract/src/cmd/build/mod.rs index 694e2f79e..9bc0a70a0 100644 --- a/crates/cargo-contract/src/cmd/build/mod.rs +++ b/crates/cargo-contract/src/cmd/build/mod.rs @@ -673,6 +673,7 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { wasm_opt_settings: WasmOptSettings { version: handler.version(), optimization_passes, + keep_debug_symbols, }, }; diff --git a/crates/cargo-contract/src/cmd/metadata.rs b/crates/cargo-contract/src/cmd/metadata.rs index cc35f4ae3..698bfc9bc 100644 --- a/crates/cargo-contract/src/cmd/metadata.rs +++ b/crates/cargo-contract/src/cmd/metadata.rs @@ -107,6 +107,8 @@ pub struct WasmOptSettings { pub version: u32, /// The level of optimization used during the `wasm-opt` run. pub optimization_passes: OptimizationPasses, + /// Whether or not the Wasm name section should be kept. + pub keep_debug_symbols: bool, } /// Generates a file with metadata describing the ABI of the smart contract. From 276a7a4af02e56851807f6ad189d6675804e8181 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 29 Sep 2022 17:42:08 -0400 Subject: [PATCH 13/18] Add `CHANGELOG` entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1ca16059..d2a5f1e48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- Add Rust specific build info to metadata - [#680](https://github.com/paritytech/cargo-contract/pull/680) + +### Fixed - Fix storage deposit limit encoding - [#751](https://github.com/paritytech/cargo-contract/pull/751) ## [2.0.0-alpha.3] - 2022-09-21 From 83aed6de5fc9d2012bbe053f43c5f55c477ba1fe Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 19 Oct 2022 18:06:36 -0400 Subject: [PATCH 14/18] Remove `version` from `WasmOptSettings` Since we're using the `wasm-opt` library from crates.io we'll assume that every matching version of `cargo-contract` contains the same version of `wasm-opt`. This doesn't hold if a user installs without the `--locked` flag though, so we may want to add this back in the future to warn users if there are mismatching `wasm-opt` versions. --- crates/cargo-contract/src/cmd/build/mod.rs | 1 - crates/cargo-contract/src/cmd/metadata.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/crates/cargo-contract/src/cmd/build/mod.rs b/crates/cargo-contract/src/cmd/build/mod.rs index 2105b574f..62cf6e9b7 100644 --- a/crates/cargo-contract/src/cmd/build/mod.rs +++ b/crates/cargo-contract/src/cmd/build/mod.rs @@ -671,7 +671,6 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { cargo_contract_version, build_mode, wasm_opt_settings: WasmOptSettings { - version: handler.version(), optimization_passes, keep_debug_symbols, }, diff --git a/crates/cargo-contract/src/cmd/metadata.rs b/crates/cargo-contract/src/cmd/metadata.rs index 698bfc9bc..fd46ef6dc 100644 --- a/crates/cargo-contract/src/cmd/metadata.rs +++ b/crates/cargo-contract/src/cmd/metadata.rs @@ -103,8 +103,6 @@ impl TryFrom for serde_json::Map { /// Settings used when optimizing the Wasm binary using Binaryen's `wasm-opt`. #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct WasmOptSettings { - /// Version of `wasm-opt`. - pub version: u32, /// The level of optimization used during the `wasm-opt` run. pub optimization_passes: OptimizationPasses, /// Whether or not the Wasm name section should be kept. From bae9094237bc1d583facc0da2b74a57673c80350 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 19 Oct 2022 18:30:03 -0400 Subject: [PATCH 15/18] Add target triple to `build_info` --- crates/cargo-contract/src/cmd/build/mod.rs | 3 +-- crates/cargo-contract/src/cmd/metadata.rs | 2 +- crates/cargo-contract/src/util/mod.rs | 8 ++++++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/cargo-contract/src/cmd/build/mod.rs b/crates/cargo-contract/src/cmd/build/mod.rs index 62cf6e9b7..750cc35e2 100644 --- a/crates/cargo-contract/src/cmd/build/mod.rs +++ b/crates/cargo-contract/src/cmd/build/mod.rs @@ -666,8 +666,7 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { }; let build_info = BuildInfo { - rustc_version: rustc_version::version() - .expect("`rustc` always has a version associated with it."), + rustc_version: crate::util::rustc_toolchain()?, cargo_contract_version, build_mode, wasm_opt_settings: WasmOptSettings { diff --git a/crates/cargo-contract/src/cmd/metadata.rs b/crates/cargo-contract/src/cmd/metadata.rs index fd46ef6dc..b6edebea4 100644 --- a/crates/cargo-contract/src/cmd/metadata.rs +++ b/crates/cargo-contract/src/cmd/metadata.rs @@ -82,7 +82,7 @@ struct ExtendedMetadataResult { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct BuildInfo { /// The stable version of `rustc` used to build the contract. - pub rustc_version: Version, + pub rustc_version: String, /// The version of `cargo-contract` used to build the contract. pub cargo_contract_version: Version, /// The type of build that was used when building the contract. diff --git a/crates/cargo-contract/src/util/mod.rs b/crates/cargo-contract/src/util/mod.rs index e4c45ba84..d22bfcab6 100644 --- a/crates/cargo-contract/src/util/mod.rs +++ b/crates/cargo-contract/src/util/mod.rs @@ -65,6 +65,14 @@ fn assert_channel() -> Result<()> { } } +// Returns the current Rust toolchain formatted by `-`. +pub(crate) fn rustc_toolchain() -> Result { + let meta = rustc_version::version_meta()?; + let toolchain = format!("{:?}-{}", meta.channel, meta.host,).to_lowercase(); + + Ok(toolchain) +} + /// Invokes `cargo` with the subcommand `command` and the supplied `args`. /// /// In case `working_dir` is set, the command will be invoked with that folder From 00e8213c1f3826731b8bf139e43ce4cc2280ac68 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 19 Oct 2022 18:49:44 -0400 Subject: [PATCH 16/18] Move `CARGO_PKG_VERSION` into a const --- crates/cargo-contract/src/cmd/build/mod.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/cargo-contract/src/cmd/build/mod.rs b/crates/cargo-contract/src/cmd/build/mod.rs index 750cc35e2..d744c40bd 100644 --- a/crates/cargo-contract/src/cmd/build/mod.rs +++ b/crates/cargo-contract/src/cmd/build/mod.rs @@ -67,6 +67,9 @@ use std::{ /// This is the maximum number of pages available for a contract to allocate. const MAX_MEMORY_PAGES: u32 = 16; +/// Version of the currently executing `cargo-contract` binary. +const VERSION: &'static str = env!("CARGO_PKG_VERSION"); + /// Arguments to use when executing `build` or `check` commands. #[derive(Default)] pub(crate) struct ExecuteArgs { @@ -655,15 +658,14 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { &crate_metadata.contract_artifact_name, )?; - let cargo_contract_version = - if let Ok(version) = Version::parse(env!("CARGO_PKG_VERSION")) { - version - } else { - anyhow::bail!( - "Unable to parse version number for the currently running \ + let cargo_contract_version = if let Ok(version) = Version::parse(VERSION) { + version + } else { + anyhow::bail!( + "Unable to parse version number for the currently running \ `cargo-contract` binary." - ); - }; + ); + }; let build_info = BuildInfo { rustc_version: crate::util::rustc_toolchain()?, From a75b72695dfc340aba0520c12a0566ac6b23f809 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 19 Oct 2022 19:06:25 -0400 Subject: [PATCH 17/18] Appease Clippy --- crates/cargo-contract/src/cmd/build/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cargo-contract/src/cmd/build/mod.rs b/crates/cargo-contract/src/cmd/build/mod.rs index d744c40bd..ff29de9e7 100644 --- a/crates/cargo-contract/src/cmd/build/mod.rs +++ b/crates/cargo-contract/src/cmd/build/mod.rs @@ -68,7 +68,7 @@ use std::{ const MAX_MEMORY_PAGES: u32 = 16; /// Version of the currently executing `cargo-contract` binary. -const VERSION: &'static str = env!("CARGO_PKG_VERSION"); +const VERSION: &str = env!("CARGO_PKG_VERSION"); /// Arguments to use when executing `build` or `check` commands. #[derive(Default)] From 6eea64c5702e01bee036178dd52866bfcdc022f5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 20 Oct 2022 11:43:57 -0400 Subject: [PATCH 18/18] Rename field to more accurate `rust_toolchain` --- crates/cargo-contract/src/cmd/build/mod.rs | 2 +- crates/cargo-contract/src/cmd/metadata.rs | 4 ++-- crates/cargo-contract/src/util/mod.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/cargo-contract/src/cmd/build/mod.rs b/crates/cargo-contract/src/cmd/build/mod.rs index ff29de9e7..b3fd8f429 100644 --- a/crates/cargo-contract/src/cmd/build/mod.rs +++ b/crates/cargo-contract/src/cmd/build/mod.rs @@ -668,7 +668,7 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { }; let build_info = BuildInfo { - rustc_version: crate::util::rustc_toolchain()?, + rust_toolchain: crate::util::rust_toolchain()?, cargo_contract_version, build_mode, wasm_opt_settings: WasmOptSettings { diff --git a/crates/cargo-contract/src/cmd/metadata.rs b/crates/cargo-contract/src/cmd/metadata.rs index b6edebea4..e2ecdd06a 100644 --- a/crates/cargo-contract/src/cmd/metadata.rs +++ b/crates/cargo-contract/src/cmd/metadata.rs @@ -81,8 +81,8 @@ struct ExtendedMetadataResult { /// translate to other languages (e.g ask!, Solidity). #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct BuildInfo { - /// The stable version of `rustc` used to build the contract. - pub rustc_version: String, + /// The Rust toolchain used to build the contract. + pub rust_toolchain: String, /// The version of `cargo-contract` used to build the contract. pub cargo_contract_version: Version, /// The type of build that was used when building the contract. diff --git a/crates/cargo-contract/src/util/mod.rs b/crates/cargo-contract/src/util/mod.rs index d22bfcab6..a92ce9359 100644 --- a/crates/cargo-contract/src/util/mod.rs +++ b/crates/cargo-contract/src/util/mod.rs @@ -66,7 +66,7 @@ fn assert_channel() -> Result<()> { } // Returns the current Rust toolchain formatted by `-`. -pub(crate) fn rustc_toolchain() -> Result { +pub(crate) fn rust_toolchain() -> Result { let meta = rustc_version::version_meta()?; let toolchain = format!("{:?}-{}", meta.channel, meta.host,).to_lowercase();