Skip to content

Commit

Permalink
feat(zk_toolbox): add test upgrade subcommand to zk_toolbox (#2515)
Browse files Browse the repository at this point in the history
## What ❔

<!-- What are the changes this PR brings about? -->
<!-- Example: This PR adds a PR template to the repo. -->
<!-- (For bigger PRs adding more context is appreciated) -->
Add upgrade tests to zk_supervisor

## Why ❔

<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted via `zk fmt` and `zk lint`.

---------

Signed-off-by: Danil <deniallugo@gmail.com>
Co-authored-by: Danil <deniallugo@gmail.com>
  • Loading branch information
manuelmauro and Deniallugo authored Jul 31, 2024
1 parent c8c8334 commit 1a12f5f
Show file tree
Hide file tree
Showing 9 changed files with 339 additions and 79 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/ci-zk-toolbox-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ jobs:
run: |
ci_run zk_supervisor test revert --external-node --ignore-prerequisites --verbose
# This test should be the last one as soon as it
# finished bootloader will be different
- name: Run upgrade test
run: |
ci_run zk_supervisor test upgrade
- name: Show server.log logs
if: always()
run: ci_run cat server.log || true
Expand Down
2 changes: 1 addition & 1 deletion contracts
20 changes: 9 additions & 11 deletions core/tests/upgrade-test/tests/tester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ import * as zksync from 'zksync-ethers';
import * as fs from 'fs';
import * as path from 'path';

type Network = string;

export class Tester {
public runningFee: Map<zksync.types.Address, bigint>;
constructor(
public network: Network,
public ethProvider: ethers.Provider,
public ethWallet: ethers.Wallet,
public syncWallet: zksync.Wallet,
Expand All @@ -18,11 +15,14 @@ export class Tester {
}

// prettier-ignore
static async init(network: Network) {
const ethProvider = new ethers.JsonRpcProvider(process.env.L1_RPC_ADDRESS || process.env.ETH_CLIENT_WEB3_URL);
static async init(ethProviderAddress: string, web3JsonRpc: string) {
const ethProvider = new ethers.JsonRpcProvider(ethProviderAddress);

let ethWallet;
if (network == 'localhost') {
if (process.env.MASTER_WALLET_PK) {
ethWallet = new ethers.Wallet(process.env.MASTER_WALLET_PK);
}
else {
ethProvider.pollingInterval = 100;

const testConfigPath = path.join(process.env.ZKSYNC_HOME!, `etc/test_config/constant`);
Expand All @@ -33,11 +33,9 @@ export class Tester {
);
ethWallet = new ethers.Wallet(ethWalletHD.privateKey, ethProvider);
}
else {
ethWallet = new ethers.Wallet(process.env.MASTER_WALLET_PK!);
}

ethWallet = ethWallet.connect(ethProvider);
const web3Provider = new zksync.Provider(process.env.ZKSYNC_WEB3_API_URL || process.env.API_WEB3_JSON_RPC_HTTP_URL || "http://localhost:3050");
const web3Provider = new zksync.Provider(web3JsonRpc);
web3Provider.pollingInterval = 100; // It's OK to keep it low even on stage.
const syncWallet = new zksync.Wallet(ethWallet.privateKey, web3Provider, ethProvider);

Expand All @@ -61,7 +59,7 @@ export class Tester {
console.log(`Canceled ${cancellationTxs.length} pending transactions`);
}

return new Tester(network, ethProvider, ethWallet, syncWallet, web3Provider);
return new Tester(ethProvider, ethWallet, syncWallet, web3Provider);
}

emptyWallet() {
Expand Down
195 changes: 128 additions & 67 deletions core/tests/upgrade-test/tests/upgrade.test.ts

Large diffs are not rendered by default.

125 changes: 125 additions & 0 deletions core/tests/upgrade-test/tests/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { ethers } from 'ethers';
import * as fs from 'fs';
import { background } from 'utils';
import { getConfigPath } from 'utils/build/file-configs';

export function runServerInBackground({
components,
stdio,
cwd,
useZkInception
}: {
components?: string[];
stdio: any;
cwd?: Parameters<typeof background>[0]['cwd'];
useZkInception?: boolean;
}) {
let command = useZkInception
? 'zk_inception server'
: 'cd $ZKSYNC_HOME && cargo run --bin zksync_server --release --';
if (components && components.length > 0) {
command += ` --components=${components.join(',')}`;
}
background({ command, stdio, cwd });
}

export function setEthSenderSenderAggregatedBlockCommitDeadline(pathToHome: string, fileConfig: any, value: number) {
setPropertyInGeneralConfig(pathToHome, fileConfig, 'aggregated_block_commit_deadline', value);
}

export function setAggregatedBlockProveDeadline(pathToHome: string, fileConfig: any, value: number) {
setPropertyInGeneralConfig(pathToHome, fileConfig, 'aggregated_block_prove_deadline', value);
}

export function setAggregatedBlockExecuteDeadline(pathToHome: string, fileConfig: any, value: number) {
setPropertyInGeneralConfig(pathToHome, fileConfig, 'aggregated_block_execute_deadline', value);
}

export function setBlockCommitDeadlineMs(pathToHome: string, fileConfig: any, value: number) {
setPropertyInGeneralConfig(pathToHome, fileConfig, 'block_commit_deadline_ms', value);
}

function setPropertyInGeneralConfig(pathToHome: string, fileConfig: any, property: string, value: number) {
const generalConfigPath = getConfigPath({
pathToHome,
chain: fileConfig.chain,
configsFolder: 'configs',
config: 'general.yaml'
});
const generalConfig = fs.readFileSync(generalConfigPath, 'utf8');
const regex = new RegExp(`\\b${property}:\\s*\\d+`, 'g');
const newGeneralConfig = generalConfig.replace(regex, `${property}: ${value}`);

fs.writeFileSync(generalConfigPath, newGeneralConfig, 'utf8');
}

export interface Contracts {
l1DefaultUpgradeAbi: any;
governanceAbi: any;
adminFacetAbi: any;
chainAdminAbi: any;
l2ForceDeployUpgraderAbi: any;
complexUpgraderAbi: any;
counterBytecode: any;
stateTransitonManager: any;
}

export function initContracts(pathToHome: string, zkToolbox: boolean): Contracts {
if (zkToolbox) {
const CONTRACTS_FOLDER = `${pathToHome}/contracts`;
return {
l1DefaultUpgradeAbi: new ethers.Interface(
require(`${CONTRACTS_FOLDER}/l1-contracts/out/DefaultUpgrade.sol/DefaultUpgrade.json`).abi
),
governanceAbi: new ethers.Interface(
require(`${CONTRACTS_FOLDER}/l1-contracts/out/Governance.sol/Governance.json`).abi
),
adminFacetAbi: new ethers.Interface(
require(`${CONTRACTS_FOLDER}/l1-contracts/out/IAdmin.sol/IAdmin.json`).abi
),
chainAdminAbi: new ethers.Interface(
require(`${CONTRACTS_FOLDER}/l1-contracts/out/ChainAdmin.sol/ChainAdmin.json`).abi
),
l2ForceDeployUpgraderAbi: new ethers.Interface(
require(`${CONTRACTS_FOLDER}/l2-contracts/artifacts-zk/contracts/ForceDeployUpgrader.sol/ForceDeployUpgrader.json`).abi
),
complexUpgraderAbi: new ethers.Interface(
require(`${CONTRACTS_FOLDER}/system-contracts/artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json`).abi
),
counterBytecode:
require(`${pathToHome}/core/tests/ts-integration/artifacts-zk/contracts/counter/counter.sol/Counter.json`)
.deployedBytecode,
stateTransitonManager: new ethers.Interface(
require(`${CONTRACTS_FOLDER}/l1-contracts/out/StateTransitionManager.sol/StateTransitionManager.json`).abi
)
};
} else {
const L1_CONTRACTS_FOLDER = `${pathToHome}/contracts/l1-contracts/artifacts/contracts`;
return {
l1DefaultUpgradeAbi: new ethers.Interface(
require(`${L1_CONTRACTS_FOLDER}/upgrades/DefaultUpgrade.sol/DefaultUpgrade.json`).abi
),
governanceAbi: new ethers.Interface(
require(`${L1_CONTRACTS_FOLDER}/governance/Governance.sol/Governance.json`).abi
),
adminFacetAbi: new ethers.Interface(
require(`${L1_CONTRACTS_FOLDER}/state-transition/chain-interfaces/IAdmin.sol/IAdmin.json`).abi
),
chainAdminAbi: new ethers.Interface(
require(`${L1_CONTRACTS_FOLDER}/governance/ChainAdmin.sol/ChainAdmin.json`).abi
),
l2ForceDeployUpgraderAbi: new ethers.Interface(
require(`${pathToHome}/contracts/l2-contracts/artifacts-zk/contracts/ForceDeployUpgrader.sol/ForceDeployUpgrader.json`).abi
),
complexUpgraderAbi: new ethers.Interface(
require(`${pathToHome}/contracts/system-contracts/artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json`).abi
),
counterBytecode:
require(`${pathToHome}/core/tests/ts-integration/artifacts-zk/contracts/counter/counter.sol/Counter.json`)
.deployedBytecode,
stateTransitonManager: new ethers.Interface(
require(`${L1_CONTRACTS_FOLDER}/state-transition/StateTransitionManager.sol/StateTransitionManager.json`).abi
)
};
}
}
14 changes: 14 additions & 0 deletions zk_toolbox/crates/zk_inception/src/commands/ecosystem/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,20 @@ async fn deploy_ecosystem_inner(
l1_rpc_url.clone(),
)
.await?;

accept_owner(
shell,
config,
contracts_config.l1.governance_addr,
config.get_wallets()?.governor_private_key(),
contracts_config
.ecosystem_contracts
.state_transition_proxy_addr,
&forge_args,
l1_rpc_url.clone(),
)
.await?;

Ok(contracts_config)
}

Expand Down
5 changes: 5 additions & 0 deletions zk_toolbox/crates/zk_supervisor/src/commands/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ use xshell::Shell;

use crate::messages::{
MSG_INTEGRATION_TESTS_ABOUT, MSG_RECOVERY_TEST_ABOUT, MSG_REVERT_TEST_ABOUT,
MSG_UPGRADE_TEST_ABOUT,
};

mod args;
mod integration;
mod recovery;
mod revert;
mod upgrade;

#[derive(Subcommand, Debug)]
pub enum TestCommands {
Expand All @@ -19,12 +21,15 @@ pub enum TestCommands {
Revert(RevertArgs),
#[clap(about = MSG_RECOVERY_TEST_ABOUT, alias = "rec")]
Recovery(RecoveryArgs),
#[clap(about = MSG_UPGRADE_TEST_ABOUT, alias = "u")]
Upgrade,
}

pub fn run(shell: &Shell, args: TestCommands) -> anyhow::Result<()> {
match args {
TestCommands::Integration(args) => integration::run(shell, args),
TestCommands::Revert(args) => revert::run(shell, args),
TestCommands::Recovery(args) => recovery::run(shell, args),
TestCommands::Upgrade => upgrade::run(shell),
}
}
44 changes: 44 additions & 0 deletions zk_toolbox/crates/zk_supervisor/src/commands/test/upgrade.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use common::{cmd::Cmd, logger, spinner::Spinner};
use config::EcosystemConfig;
use xshell::{cmd, Shell};

use crate::messages::{
MSG_UPGRADE_TEST_INSTALLING_DEPENDENCIES, MSG_UPGRADE_TEST_RUN_INFO,
MSG_UPGRADE_TEST_RUN_SUCCESS,
};

const UPGRADE_TESTS_PATH: &str = "core/tests/upgrade-test";

pub fn run(shell: &Shell) -> anyhow::Result<()> {
let ecosystem_config = EcosystemConfig::from_file(shell)?;
shell.change_dir(ecosystem_config.link_to_code.join(UPGRADE_TESTS_PATH));

logger::info(MSG_UPGRADE_TEST_RUN_INFO);
install_and_build_dependencies(shell, &ecosystem_config)?;
run_test(shell, &ecosystem_config)?;
logger::outro(MSG_UPGRADE_TEST_RUN_SUCCESS);

Ok(())
}

fn install_and_build_dependencies(
shell: &Shell,
ecosystem_config: &EcosystemConfig,
) -> anyhow::Result<()> {
let _dir_guard = shell.push_dir(&ecosystem_config.link_to_code);
let spinner = Spinner::new(MSG_UPGRADE_TEST_INSTALLING_DEPENDENCIES);
Cmd::new(cmd!(shell, "yarn install")).run()?;
Cmd::new(cmd!(shell, "yarn utils build")).run()?;

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

fn run_test(shell: &Shell, ecosystem_config: &EcosystemConfig) -> anyhow::Result<()> {
Spinner::new(MSG_UPGRADE_TEST_RUN_INFO).freeze();
let cmd = Cmd::new(cmd!(shell, "yarn mocha tests/upgrade.test.ts"))
.env("CHAIN_NAME", &ecosystem_config.default_chain);
cmd.with_force_run().run()?;

Ok(())
}
7 changes: 7 additions & 0 deletions zk_toolbox/crates/zk_supervisor/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub(super) const MSG_DATABASE_NEW_MIGRATION_SUCCESS: &str = "Migration created s
pub(super) const MSG_INTEGRATION_TESTS_ABOUT: &str = "Run integration tests";
pub(super) const MSG_REVERT_TEST_ABOUT: &str = "Run revert tests";
pub(super) const MSG_RECOVERY_TEST_ABOUT: &str = "Run recovery tests";
pub(super) const MSG_UPGRADE_TEST_ABOUT: &str = "Run upgrade tests";
pub(super) const MSG_TESTS_EXTERNAL_NODE_HELP: &str = "Run tests for external node";
pub(super) const MSG_TESTS_RECOVERY_SNAPSHOT_HELP: &str =
"Run recovery from a snapshot instead of genesis";
Expand Down Expand Up @@ -113,6 +114,12 @@ pub(super) const MSG_REVERT_TEST_RUN_SUCCESS: &str = "Revert and restart test ra
pub(super) const MSG_RECOVERY_TEST_RUN_INFO: &str = "Running recovery test";
pub(super) const MSG_RECOVERY_TEST_RUN_SUCCESS: &str = "Recovery test ran successfully";

// Upgrade tests related messages
pub(super) const MSG_UPGRADE_TEST_RUN_INFO: &str = "Running upgrade test";
pub(super) const MSG_UPGRADE_TEST_INSTALLING_DEPENDENCIES: &str =
"Building and installing dependencies. This process may take a lot of time...";
pub(super) const MSG_UPGRADE_TEST_RUN_SUCCESS: &str = "Upgrade test ran successfully";

// Cleaning related messages
pub(super) const MSG_DOCKER_COMPOSE_DOWN: &str = "docker compose down";
pub(super) const MSG_DOCKER_COMPOSE_REMOVE_VOLUMES: &str = "docker compose remove volumes";
Expand Down

0 comments on commit 1a12f5f

Please sign in to comment.