Skip to content

Commit

Permalink
Feat(eth-wallet-contract): reproducible build
Browse files Browse the repository at this point in the history
  • Loading branch information
birchmd committed Mar 25, 2024
1 parent abfc04b commit 57dd5ba
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 41 deletions.
68 changes: 35 additions & 33 deletions runtime/near-wallet-contract/build.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
/// This file is run as a part of `cargo build` process and it builds the `Wallet Contract`.
/// The generated WASM file is put to the `./res` directory.
use anyhow::{anyhow, Context, Ok, Result};
use anyhow::{anyhow, Context};

use std::path::{Path, PathBuf};
use std::path::Path;
use std::process::Command;

#[allow(unreachable_code)]
fn main() -> Result<()> {
// TODO(eth-implicit) Remove this once we have a proper way to generate the Wallet Contract WASM file.
return Ok(());
build_contract("./wallet-contract", &[], "wallet_contract")
const IMAGE_TAG: &str = "13430592a7be246dd5a29439791f4081e0107ff3";

fn main() -> anyhow::Result<()> {
build_contract("./implementation", "eth_wallet_contract", "wallet_contract")
}

fn build_contract(dir: &str, args: &[&str], output: &str) -> Result<()> {
let target_dir: PathBuf =
std::env::var("OUT_DIR").context("Failed to read OUT_DIR environment variable")?.into();
fn build_contract(dir: &str, contract_name: &str, output: &str) -> anyhow::Result<()> {
let wasm_target_path = format!("./res/{}.wasm", output);
if Path::new(&wasm_target_path).exists() {
// Skip building if an artifact is already present
return Ok(());
}

// We place the build artifacts in `target_dir` (workspace's build directory).
let mut cmd = cargo_build_cmd(&target_dir);
cmd.args(args);
cmd.current_dir(dir);
run_checking_status(cmd)?;
let absolute_dir = Path::new(dir).canonicalize()?;
docker_build(absolute_dir.to_str().expect("path should be valid UTF-8"))?;

let build_artifact_path =
format!("wasm32-unknown-unknown/release/{}.wasm", dir.replace('-', "_"));
let src = target_dir.join(build_artifact_path);
let wasm_target_path = format!("./res/{}.wasm", output);
format!("target/wasm32-unknown-unknown/release/{}.wasm", contract_name);
let src = absolute_dir.join(build_artifact_path);

std::fs::copy(&src, &wasm_target_path)
.with_context(|| format!("Failed to copy `{}` to `{}`", src.display(), wasm_target_path))?;

println!("cargo:rerun-if-changed={}", dir);
println!("cargo:rerun-if-changed={}", wasm_target_path);
Ok(())
}

Expand All @@ -41,23 +41,25 @@ fn build_contract(dir: &str, args: &[&str], output: &str) -> Result<()> {
/// process, to avoid unexpected behaviors due to the workspace configurations.
// TODO(eth-implicit) Change it to have a reproducible hash of the WASM file.
// see https://github.com/near/nearcore/pull/10269#discussion_r1430139987.
fn cargo_build_cmd(target_dir: &Path) -> Command {
let mut res = Command::new("cargo");

res.env_remove("CARGO_BUILD_RUSTFLAGS");
res.env_remove("CARGO_ENCODED_RUSTFLAGS");
res.env_remove("RUSTC_WORKSPACE_WRAPPER");

res.env("RUSTFLAGS", "-Dwarnings");
res.env("CARGO_TARGET_DIR", target_dir);

res.args(["build", "--target=wasm32-unknown-unknown", "--release"]);

res
}
fn docker_build(host_path: &str) -> anyhow::Result<()> {
let volume_arg = format!("{host_path}:/host");
let image_name = format!("nearprotocol/contract-builder:master-{IMAGE_TAG}-amd64");

fn run_checking_status(mut cmd: Command) -> Result<()> {
cmd.status().with_context(|| format!("Failed to run command `{cmd:?}`")).and_then(|status| {
let mut cmd = Command::new("docker");
let status = cmd
.args([
"run",
"--volume",
&volume_arg,
"-w",
"/host",
"-i",
"--rm",
&image_name,
"./docker-entrypoint.sh",
])
.status();
status.with_context(|| format!("Failed to run command `{cmd:?}`")).and_then(|status| {
if status.success() {
Ok(())
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
RUSTFLAGS='-C link-arg=-s' cargo build --release --target wasm32-unknown-unknown
Binary file modified runtime/near-wallet-contract/res/wallet_contract.wasm
Binary file not shown.
10 changes: 2 additions & 8 deletions runtime/near-wallet-contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,10 @@ mod tests {
use near_primitives_core::hash::CryptoHash;
use std::str::FromStr;

const WALLET_CONTRACT_HASH: &'static str = "5wJJ2YaCq75kVSfx8zoZpevg1uLAn4h7nqUd2njKUEXe";
const MAGIC_BYTES_HASH: &'static str = "31PSU4diHE4cpWju91fb2zTqn5JSDRZ6xNGM2ub8Lgdg";
const WALLET_CONTRACT_HASH: &'static str = "7Za8zoriBqGNFf9AUK8Fbng5KSGw8Q9BLM4oSoLbJ6wq";
const MAGIC_BYTES_HASH: &'static str = "HfA46qim8mtcybTYEwGxWc1AN6a52g6t3XT6SRKzdpDx";

#[test]
#[ignore]
// TODO(eth-implicit) Do not ignore when Wallet Contract build becomes reproducible,
// see https://github.com/near/nearcore/pull/10269#discussion_r1430139987.
fn check_wallet_contract() {
assert!(!wallet_contract().code().is_empty());
let expected_hash =
Expand All @@ -53,9 +50,6 @@ mod tests {
}

#[test]
#[ignore]
// TODO(eth-implicit) Do not ignore when Wallet Contract build becomes reproducible,
// see https://github.com/near/nearcore/pull/10269#discussion_r1430139987.
fn check_wallet_contract_magic_bytes() {
assert!(!wallet_contract_magic_bytes().code().is_empty());
let expected_hash =
Expand Down

0 comments on commit 57dd5ba

Please sign in to comment.