Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions crates/build/src/crate_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ impl CrateMetadata {
pub fn metadata_path(&self) -> PathBuf {
self.target_directory.join(METADATA_FILE)
}

/// Get the path of the contract bundle, containing metadata + code
pub fn contract_bundle_path(&self) -> PathBuf {
let target_directory = self.target_directory.clone();
let fname_bundle = format!("{}.contract", self.contract_artifact_name);
target_directory.join(fname_bundle)
}
}

/// Get the result of `cargo metadata`, together with the root package id.
Expand Down
12 changes: 12 additions & 0 deletions crates/build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,18 @@ pub fn execute(args: ExecuteArgs) -> Result<BuildResult> {
})
}

/// Returns the blake2 hash of the code slice.
pub fn code_hash(code: &[u8]) -> [u8; 32] {
use blake2::digest::{
consts::U32,
Digest as _,
};
let mut blake2 = blake2::Blake2b::<U32>::new();
blake2.update(code);
let result = blake2.finalize();
result.into()
}

/// Testing individual functions where the build itself is not actually invoked. See [`tests`] for
/// all tests which invoke the `build` command.
#[cfg(test)]
Expand Down
33 changes: 10 additions & 23 deletions crates/build/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with cargo-contract. If not, see <http://www.gnu.org/licenses/>.

use crate::{
code_hash,
crate_metadata::CrateMetadata,
maybe_println,
util,
Expand All @@ -31,13 +32,8 @@ use crate::{
};

use anyhow::Result;
use blake2::digest::{
consts::U32,
Digest as _,
};
use colored::Colorize;
use contract_metadata::{
CodeHash,
Compiler,
Contract,
ContractMetadata,
Expand All @@ -58,7 +54,7 @@ use std::{
};
use url::Url;

const METADATA_FILE: &str = "metadata.json";
pub const METADATA_FILE: &str = "metadata.json";

/// Metadata generation result.
#[derive(serde::Serialize)]
Expand Down Expand Up @@ -122,11 +118,8 @@ pub(crate) fn execute(
unstable_options: &UnstableFlags,
build_info: BuildInfo,
) -> Result<MetadataResult> {
let target_directory = crate_metadata.target_directory.clone();
let out_path_metadata = target_directory.join(METADATA_FILE);

let fname_bundle = format!("{}.contract", crate_metadata.contract_artifact_name);
let out_path_bundle = target_directory.join(fname_bundle);
let out_path_metadata = crate_metadata.metadata_path();
let out_path_bundle = crate_metadata.contract_bundle_path();

// build the extended contract project metadata
let ExtendedMetadataResult {
Expand All @@ -142,8 +135,10 @@ pub(crate) fn execute(
format!("{}", build_steps).bold(),
"Generating metadata".bright_green().bold()
);
let target_dir_arg =
format!("--target-dir={}", target_directory.to_string_lossy());
let target_dir_arg = format!(
"--target-dir={}",
crate_metadata.target_directory.to_string_lossy()
);
let stdout = util::invoke_cargo(
"run",
[
Expand Down Expand Up @@ -230,10 +225,10 @@ fn extended_metadata(
let lang = SourceLanguage::new(Language::Ink, ink_version.clone());
let compiler = SourceCompiler::new(Compiler::RustC, rust_version);
let wasm = fs::read(final_contract_wasm)?;
let hash = blake2_hash(wasm.as_slice());
let hash = code_hash(wasm.as_slice());
Source::new(
Some(SourceWasm::new(wasm)),
hash,
hash.into(),
lang,
compiler,
Some(build_info.try_into()?),
Expand Down Expand Up @@ -280,11 +275,3 @@ fn extended_metadata(
user,
})
}

/// Returns the blake2 hash of the submitted slice.
pub fn blake2_hash(code: &[u8]) -> CodeHash {
let mut blake2 = blake2::Blake2b::<U32>::new();
blake2.update(code);
let result = blake2.finalize();
CodeHash(result.into())
}
4 changes: 2 additions & 2 deletions crates/build/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ fn generates_metadata(manifest_path: &ManifestPath) -> Result<()> {

// calculate wasm hash
let fs_wasm = fs::read(&crate_metadata.dest_wasm)?;
let expected_hash = crate::metadata::blake2_hash(&fs_wasm[..]);
let expected_hash = crate::code_hash(&fs_wasm[..]);
let expected_wasm = build_byte_str(&fs_wasm);

let expected_language =
Expand All @@ -514,7 +514,7 @@ fn generates_metadata(manifest_path: &ManifestPath) -> Result<()> {
serde_json::Value::Array(vec!["and".into(), "their".into(), "values".into()]),
);

assert_eq!(build_byte_str(&expected_hash.0[..]), 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());
Expand Down
10 changes: 4 additions & 6 deletions crates/cargo-contract/src/cmd/extrinsics/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use super::{
BalanceVariant,
Client,
ContractMessageTranscoder,
CrateMetadata,
DefaultConfig,
ExtrinsicOpts,
PairSigner,
Expand Down Expand Up @@ -95,10 +94,9 @@ impl CallCommand {
}

pub fn run(&self) -> Result<(), ErrorVariant> {
let crate_metadata = CrateMetadata::from_manifest_path(
self.extrinsic_opts.manifest_path.as_ref(),
)?;
let transcoder = ContractMessageTranscoder::load(crate_metadata.metadata_path())?;
let artifacts = self.extrinsic_opts.contract_artifacts()?;
let transcoder = artifacts.contract_transcoder()?;

let call_data = transcoder.encode(&self.message, &self.args)?;
tracing::debug!("Message data: {:?}", hex::encode(&call_data));

Expand Down Expand Up @@ -218,7 +216,7 @@ impl CallCommand {
let result = submit_extrinsic(client, &call, signer).await?;

let display_events =
DisplayEvents::from_events(&result, transcoder, &client.metadata())?;
DisplayEvents::from_events(&result, Some(transcoder), &client.metadata())?;

let output = if self.output_json {
display_events.to_json()?
Expand Down
59 changes: 41 additions & 18 deletions crates/cargo-contract/src/cmd/extrinsics/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,21 @@ use colored::Colorize as _;
use contract_build::Verbosity;
use contract_transcode::{
ContractMessageTranscoder,
Hex,
TranscoderBuilder,
Value,
};

use anyhow::Result;
use std::fmt::Write;
use std::{
fmt::Write,
str::FromStr,
};
use subxt::{
self,
blocks::ExtrinsicEvents,
events::StaticEvent,
metadata::EventFieldMetadata,
};

/// Field that represent data of an event from invoking a contract extrinsic.
Expand Down Expand Up @@ -78,7 +83,7 @@ impl DisplayEvents {
/// Parses events and returns an object which can be serialised
pub fn from_events(
result: &ExtrinsicEvents<DefaultConfig>,
transcoder: &ContractMessageTranscoder,
transcoder: Option<&ContractMessageTranscoder>,
subxt_metadata: &subxt::Metadata,
) -> Result<DisplayEvents> {
let mut events: Vec<Event> = vec![];
Expand Down Expand Up @@ -111,22 +116,12 @@ impl DisplayEvents {
) && field_metadata.name() == Some("data")
{
tracing::debug!("event data: {:?}", hex::encode(&event_data));
match transcoder.decode_contract_event(event_data) {
Ok(contract_event) => {
let field = Field::new(
String::from("data"),
contract_event,
field_metadata.type_name().map(|s| s.to_string()),
);
event_entry.fields.push(field);
}
Err(err) => {
tracing::warn!(
"Decoding contract event failed: {:?}. It might have come from another contract.",
err
)
}
}
let field = contract_event_data_field(
transcoder,
field_metadata,
event_data,
)?;
event_entry.fields.push(field);
} else {
let field_name = field_metadata
.name()
Expand Down Expand Up @@ -208,3 +203,31 @@ impl DisplayEvents {
Ok(serde_json::to_string_pretty(self)?)
}
}

/// Construct the contract event data field, attempting to decode the event using the
/// [`ContractMessageTranscoder`] if available.
fn contract_event_data_field(
transcoder: Option<&ContractMessageTranscoder>,
field_metadata: &EventFieldMetadata,
event_data: &mut &[u8],
) -> Result<Field> {
let event_value = if let Some(transcoder) = transcoder {
match transcoder.decode_contract_event(event_data) {
Ok(contract_event) => contract_event,
Err(err) => {
tracing::warn!(
"Decoding contract event failed: {:?}. It might have come from another contract.",
err
);
Value::Hex(Hex::from_str(&hex::encode(&event_data))?)
}
}
} else {
Value::Hex(Hex::from_str(&hex::encode(event_data))?)
};
Ok(Field::new(
String::from("data"),
event_value,
field_metadata.type_name().map(|s| s.to_string()),
))
}
Loading