Skip to content

Commit

Permalink
verify and reproducible subcommands
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Benfield committed Feb 1, 2024
1 parent a2ac0dd commit 98b202d
Show file tree
Hide file tree
Showing 9 changed files with 459 additions and 79 deletions.
122 changes: 93 additions & 29 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,27 @@ Usage: cargo stylus deploy [OPTIONS]

See `--help` for all available flags and default values.

## Verifying Stylus Programs

**cargo stylus verify**

Verifies that a deployed smart contract is identical to that produced by the
current project. Since Stylus smart contracts include a hash of all project
files, this additionally verifies that code comments and other files are
identical. To ensure build reproducibility, if a program is to be verified,
it should be both deployed and verified using `cargo stylus reproducible`.

See `--help` for all available flags and default values.

## Reproducibly Deploying and Verifying

**cargo stylus reproducible**

Runs a `cargo stylus` command in a Docker container to ensure build
reproducibility.

See `--help` for all available flags and default values.

## Deploying Non-Rust WASM Projects

The Stylus tool can also be used to deploy non-Rust, WASM projects to Stylus by specifying the WASM file directly with the `--wasm-file-path` flag to any of the cargo stylus commands.
Expand Down
10 changes: 5 additions & 5 deletions src/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,16 @@ pub async fn run_checks(cfg: CheckConfig) -> eyre::Result<bool> {
Some(path) => PathBuf::from_str(path).unwrap(),
None => project::build_project_dylib(BuildConfig {
opt_level: project::OptLevel::default(),
nightly: cfg.nightly,
nightly: cfg.common_cfg.nightly,
rebuild: true,
skip_contract_size_check: cfg.skip_contract_size_check,
skip_contract_size_check: cfg.common_cfg.skip_contract_size_check,
})
.map_err(|e| eyre!("failed to build project to WASM: {e}"))?,
};
println!("Reading WASM file at {}", wasm_file_path.display().grey());

let (precompressed_bytes, init_code) =
project::compress_wasm(&wasm_file_path, cfg.skip_contract_size_check)
project::compress_wasm(&wasm_file_path, cfg.common_cfg.skip_contract_size_check)
.map_err(|e| eyre!("failed to get compressed WASM bytes: {e}"))?;

let precompressed_size = FileByteSize::new(precompressed_bytes.len() as u64);
Expand All @@ -85,10 +85,10 @@ pub async fn run_checks(cfg: CheckConfig) -> eyre::Result<bool> {

println!(
"Connecting to Stylus RPC endpoint: {}",
&cfg.endpoint.mint()
&cfg.common_cfg.endpoint.mint()
);

let provider = util::new_provider(&cfg.endpoint)?;
let provider = util::new_provider(&cfg.common_cfg.endpoint)?;

let mut expected_program_addr = cfg.clone().expected_program_address;

Expand Down
46 changes: 15 additions & 31 deletions src/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub async fn deploy(cfg: DeployConfig) -> eyre::Result<()> {
.map_err(|e| eyre!("Stylus checks failed: {e}"))?;
let wallet = wallet::load(&cfg.check_cfg).map_err(|e| eyre!("could not load wallet: {e}"))?;

let provider = util::new_provider(&cfg.check_cfg.endpoint)?;
let provider = util::new_provider(&cfg.check_cfg.common_cfg.endpoint)?;

let chain_id = provider
.get_chainid()
Expand Down Expand Up @@ -112,25 +112,29 @@ programs to Stylus chains here https://docs.arbitrum.io/stylus/stylus-quickstart
}

if deploy {
let build_cfg = BuildConfig {
opt_level: project::OptLevel::default(),
nightly: cfg.check_cfg.common_cfg.nightly,
rebuild: false, // The check step at the start of this command rebuilt.
skip_contract_size_check: cfg.check_cfg.common_cfg.skip_contract_size_check,
};
let wasm_file_path: PathBuf = match &cfg.check_cfg.wasm_file_path {
Some(path) => PathBuf::from_str(path).unwrap(),
None => project::build_project_dylib(BuildConfig {
opt_level: project::OptLevel::default(),
nightly: cfg.check_cfg.nightly,
rebuild: false, // The check step at the start of this command rebuilt.
skip_contract_size_check: cfg.check_cfg.skip_contract_size_check,
})
.map_err(|e| eyre!("could not build project to WASM: {e}"))?,
None => project::build_project_dylib(build_cfg)
.map_err(|e| eyre!("could not build project to WASM: {e}"))?,
};
let (_, init_code) =
project::compress_wasm(&wasm_file_path, cfg.check_cfg.skip_contract_size_check)?;
let hash = project::hash_files(build_cfg)?;
let (_, init_code) = project::compress_wasm(
&wasm_file_path,
cfg.check_cfg.common_cfg.skip_contract_size_check,
)?;
println!("");
println!("{}", "====DEPLOYMENT====".grey());
println!(
"Deploying program to address {}",
to_checksum(&expected_program_addr, None).mint(),
);
let deployment_calldata = program_deployment_calldata(&init_code);
let deployment_calldata = project::program_deployment_calldata(&init_code, &hash);

// Output the tx data to a user's specified directory if desired.
if let Some(tx_data_output_dir) = output_dir {
Expand Down Expand Up @@ -205,26 +209,6 @@ pub fn activation_calldata(program_addr: &H160) -> Vec<u8> {
activate_calldata
}

/// Prepares an EVM bytecode prelude for contract creation.
pub fn program_deployment_calldata(code: &[u8]) -> Vec<u8> {
let mut code_len = [0u8; 32];
U256::from(code.len()).to_big_endian(&mut code_len);
let mut deploy: Vec<u8> = vec![];
deploy.push(0x7f); // PUSH32
deploy.extend(code_len);
deploy.push(0x80); // DUP1
deploy.push(0x60); // PUSH1
deploy.push(0x2a); // 42 the prelude length
deploy.push(0x60); // PUSH1
deploy.push(0x00);
deploy.push(0x39); // CODECOPY
deploy.push(0x60); // PUSH1
deploy.push(0x00);
deploy.push(0xf3); // RETURN
deploy.extend(code);
deploy
}

fn write_tx_data(tx_kind: TxKind, path: &Path, data: &[u8]) -> eyre::Result<()> {
let file_name = format!("{tx_kind}_tx_data");
let path = path.join(file_name);
Expand Down
Loading

0 comments on commit 98b202d

Please sign in to comment.