Skip to content

Commit

Permalink
feat(zk_toolbox): Add zks contracts (#2781)
Browse files Browse the repository at this point in the history
## What ❔

Add zks contracts. Builds contracts
  • Loading branch information
matias-gonz authored Sep 3, 2024
1 parent b82dfa4 commit 19ca512
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 4 deletions.
8 changes: 8 additions & 0 deletions zk_toolbox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,14 @@ Create a snapshot of the current chain:
zks snapshot create
```

### Contracts

Build contracts:

```bash
zks contracts
```

### Format

Format code:
Expand Down
135 changes: 135 additions & 0 deletions zk_toolbox/crates/zk_supervisor/src/commands/contracts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
use std::path::PathBuf;

use clap::{Parser, ValueEnum};
use common::{cmd::Cmd, logger, spinner::Spinner};
use config::EcosystemConfig;
use strum::EnumIter;
use xshell::{cmd, Shell};

use crate::messages::{
MSG_BUILDING_CONTRACTS, MSG_BUILDING_CONTRACTS_SUCCESS, MSG_BUILDING_L1_CONTRACTS_SPINNER,
MSG_BUILDING_L2_CONTRACTS_SPINNER, MSG_BUILDING_SYSTEM_CONTRACTS_SPINNER,
MSG_BUILD_L1_CONTRACTS_HELP, MSG_BUILD_L2_CONTRACTS_HELP, MSG_BUILD_SYSTEM_CONTRACTS_HELP,
MSG_CONTRACTS_DEPS_SPINNER, MSG_NOTHING_TO_BUILD_MSG,
};

#[derive(Debug, Parser)]
pub struct ContractsArgs {
#[clap(long, alias = "l1", help = MSG_BUILD_L1_CONTRACTS_HELP, default_missing_value = "true", num_args = 0..=1)]
pub l1_contracts: Option<bool>,
#[clap(long, alias = "l2", help = MSG_BUILD_L2_CONTRACTS_HELP, default_missing_value = "true", num_args = 0..=1)]
pub l2_contracts: Option<bool>,
#[clap(long, alias = "sc", help = MSG_BUILD_SYSTEM_CONTRACTS_HELP, default_missing_value = "true", num_args = 0..=1)]
pub system_contracts: Option<bool>,
}

impl ContractsArgs {
fn contracts(&self) -> Vec<ContractType> {
if self.l1_contracts.is_none()
&& self.l2_contracts.is_none()
&& self.system_contracts.is_none()
{
return vec![
ContractType::L1,
ContractType::L2,
ContractType::SystemContracts,
];
}

let mut contracts = vec![];

if self.l1_contracts.unwrap_or(false) {
contracts.push(ContractType::L1);
}
if self.l2_contracts.unwrap_or(false) {
contracts.push(ContractType::L2);
}
if self.system_contracts.unwrap_or(false) {
contracts.push(ContractType::SystemContracts);
}

contracts
}
}

#[derive(Debug, ValueEnum, EnumIter, strum::Display, PartialEq, Eq, Clone, Copy)]
#[strum(serialize_all = "lowercase")]
pub enum ContractType {
L1,
L2,
SystemContracts,
}

#[derive(Debug)]
struct ContractBuilder {
dir: PathBuf,
cmd: String,
msg: String,
}

impl ContractBuilder {
fn new(ecosystem: &EcosystemConfig, contract_type: ContractType) -> Self {
match contract_type {
ContractType::L1 => Self {
dir: ecosystem.path_to_foundry(),
cmd: "forge build".to_string(),
msg: MSG_BUILDING_L1_CONTRACTS_SPINNER.to_string(),
},
ContractType::L2 => Self {
dir: ecosystem.link_to_code.clone(),
cmd: "yarn l2-contracts build".to_string(),
msg: MSG_BUILDING_L2_CONTRACTS_SPINNER.to_string(),
},
ContractType::SystemContracts => Self {
dir: ecosystem.link_to_code.join("contracts"),
cmd: "yarn sc build".to_string(),
msg: MSG_BUILDING_SYSTEM_CONTRACTS_SPINNER.to_string(),
},
}
}

fn build(&self, shell: &Shell) -> anyhow::Result<()> {
let spinner = Spinner::new(&self.msg);
let _dir_guard = shell.push_dir(&self.dir);

let mut args = self.cmd.split_whitespace().collect::<Vec<_>>();
let command = args.remove(0); // It's safe to unwrap here because we know that the vec is not empty
let mut cmd = cmd!(shell, "{command}");

for arg in args {
cmd = cmd.arg(arg);
}

Cmd::new(cmd).run()?;

spinner.finish();
Ok(())
}
}

pub fn run(shell: &Shell, args: ContractsArgs) -> anyhow::Result<()> {
let contracts = args.contracts();
if contracts.is_empty() {
logger::outro(MSG_NOTHING_TO_BUILD_MSG);
return Ok(());
}

logger::info(MSG_BUILDING_CONTRACTS);

let ecosystem = EcosystemConfig::from_file(shell)?;
let link_to_code = ecosystem.link_to_code.clone();

let spinner = Spinner::new(MSG_CONTRACTS_DEPS_SPINNER);
let _dir_guard = shell.push_dir(&link_to_code);
Cmd::new(cmd!(shell, "yarn install")).run()?;
spinner.finish();

contracts
.iter()
.map(|contract| ContractBuilder::new(&ecosystem, *contract))
.try_for_each(|builder| builder.build(shell))?;

logger::outro(MSG_BUILDING_CONTRACTS_SUCCESS);

Ok(())
}
1 change: 1 addition & 0 deletions zk_toolbox/crates/zk_supervisor/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod clean;
pub mod contracts;
pub mod database;
pub mod fmt;
pub mod lint;
Expand Down
12 changes: 8 additions & 4 deletions zk_toolbox/crates/zk_supervisor/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use clap::{Parser, Subcommand};
use commands::{
database::DatabaseCommands, lint::LintArgs, snapshot::SnapshotCommands, test::TestCommands,
contracts::ContractsArgs, database::DatabaseCommands, lint::LintArgs,
snapshot::SnapshotCommands, test::TestCommands,
};
use common::{
check_general_prerequisites,
Expand All @@ -10,9 +11,9 @@ use common::{
};
use config::EcosystemConfig;
use messages::{
msg_global_chain_does_not_exist, MSG_PROVER_VERSION_ABOUT, MSG_SUBCOMMAND_CLEAN,
MSG_SUBCOMMAND_DATABASE_ABOUT, MSG_SUBCOMMAND_FMT_ABOUT, MSG_SUBCOMMAND_LINT_ABOUT,
MSG_SUBCOMMAND_SNAPSHOTS_CREATOR_ABOUT, MSG_SUBCOMMAND_TESTS_ABOUT,
msg_global_chain_does_not_exist, MSG_CONTRACTS_ABOUT, MSG_PROVER_VERSION_ABOUT,
MSG_SUBCOMMAND_CLEAN, MSG_SUBCOMMAND_DATABASE_ABOUT, MSG_SUBCOMMAND_FMT_ABOUT,
MSG_SUBCOMMAND_LINT_ABOUT, MSG_SUBCOMMAND_SNAPSHOTS_CREATOR_ABOUT, MSG_SUBCOMMAND_TESTS_ABOUT,
};
use xshell::Shell;

Expand Down Expand Up @@ -49,6 +50,8 @@ enum SupervisorSubcommands {
Markdown,
#[command(about = MSG_PROVER_VERSION_ABOUT)]
ProverVersion,
#[command(about = MSG_CONTRACTS_ABOUT)]
Contracts(ContractsArgs),
}

#[derive(Parser, Debug)]
Expand Down Expand Up @@ -106,6 +109,7 @@ async fn run_subcommand(args: Supervisor, shell: &Shell) -> anyhow::Result<()> {
SupervisorSubcommands::Lint(args) => commands::lint::run(shell, args)?,
SupervisorSubcommands::Fmt(args) => commands::fmt::run(shell.clone(), args).await?,
SupervisorSubcommands::ProverVersion => commands::prover_version::run(shell).await?,
SupervisorSubcommands::Contracts(args) => commands::contracts::run(shell, args)?,
}
Ok(())
}
Expand Down
13 changes: 13 additions & 0 deletions zk_toolbox/crates/zk_supervisor/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub(super) const MSG_SUBCOMMAND_DATABASE_ABOUT: &str = "Database related command
pub(super) const MSG_SUBCOMMAND_TESTS_ABOUT: &str = "Run tests";
pub(super) const MSG_SUBCOMMAND_CLEAN: &str = "Clean artifacts";
pub(super) const MSG_SUBCOMMAND_LINT_ABOUT: &str = "Lint code";
pub(super) const MSG_CONTRACTS_ABOUT: &str = "Build contracts";

pub(super) const MSG_SUBCOMMAND_FMT_ABOUT: &str = "Format code";

Expand Down Expand Up @@ -104,6 +105,18 @@ pub(super) const MSG_PROVER_TEST_SUCCESS: &str = "Prover tests ran successfully"
pub(super) const MSG_POSTGRES_CONFIG_NOT_FOUND_ERR: &str = "Postgres config not found";
pub(super) const MSG_RESETTING_TEST_DATABASES: &str = "Resetting test databases";

// Contract building related messages
pub(super) const MSG_NOTHING_TO_BUILD_MSG: &str = "Nothing to build!";
pub(super) const MSG_BUILDING_CONTRACTS: &str = "Building contracts";
pub(super) const MSG_CONTRACTS_DEPS_SPINNER: &str = "Installing dependencies..";
pub(super) const MSG_BUILDING_L2_CONTRACTS_SPINNER: &str = "Building L2 contracts..";
pub(super) const MSG_BUILDING_L1_CONTRACTS_SPINNER: &str = "Building L1 contracts..";
pub(super) const MSG_BUILDING_SYSTEM_CONTRACTS_SPINNER: &str = "Building system contracts..";
pub(super) const MSG_BUILDING_CONTRACTS_SUCCESS: &str = "Contracts built successfully";
pub(super) const MSG_BUILD_L1_CONTRACTS_HELP: &str = "Build L1 contracts";
pub(super) const MSG_BUILD_L2_CONTRACTS_HELP: &str = "Build L2 contracts";
pub(super) const MSG_BUILD_SYSTEM_CONTRACTS_HELP: &str = "Build system contracts";

// Integration tests related messages
pub(super) fn msg_integration_tests_run(external_node: bool) -> String {
let base = "Running integration tests";
Expand Down

0 comments on commit 19ca512

Please sign in to comment.