Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions core/lib/basic_types/src/commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ impl TryFrom<u8> for L2DACommitmentScheme {
1 => Ok(L2DACommitmentScheme::EmptyNoDA),
2 => Ok(L2DACommitmentScheme::PubdataKeccak256),
3 => Ok(L2DACommitmentScheme::BlobsAndPubdataKeccak256),
4 => Ok(L2DACommitmentScheme::BlobsZksyncOS),
_ => Err("Invalid L2DACommitmentScheme value"),
}
}
Expand Down
2 changes: 1 addition & 1 deletion zkstack_cli/crates/common/src/zks_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ where
.ok_or_else(|| ProviderError::CustomError("Log proof not found!".into()))?;

Ok(FinalizeMigrationParams {
l2_batch_number: l2_to_l1_log.l1_batch_number.unwrap_or_default(),
l2_batch_number: proof.batch_number.0.into(),
l2_message_index: proof.id.into(),
l2_tx_number_in_block: l2_to_l1_log.tx_index_in_l1_batch.unwrap_or_default(),
proof,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,13 @@ pub async fn run_inner(

let (_, l2_da_validator_commitment_scheme) =
context.l1_zk_chain.get_da_validator_pair().await?;
let l2_da_validator_commitment_scheme =
let mut l2_da_validator_commitment_scheme =
L2DACommitmentScheme::try_from(l2_da_validator_commitment_scheme)
.map_err(|err| anyhow::format_err!("Failed to parse L2 DA commitment schema: {err}"))?;
if l2_da_validator_commitment_scheme == L2DACommitmentScheme::BlobsZksyncOS {
// ZK OS Gateway does not support Blobs, so chain should settle via calldata.
l2_da_validator_commitment_scheme = L2DACommitmentScheme::BlobsAndPubdataKeccak256;
}
check_permanent_rollup_and_set_da_validator_via_gateway(
shell,
&args.forge_args,
Expand All @@ -304,8 +308,6 @@ async fn await_for_migration_to_finalize(
) -> anyhow::Result<()> {
while !check_whether_gw_transaction_is_finalized(
gateway_provider,
l1_provider.clone(),
gateway_diamond_proxy,
hash,
GatewayTransactionType::Migration,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,6 @@ pub(crate) async fn get_gateway_migration_state(
let gw_zk_client = get_zk_client(&gw_rpc_url, gw_chain_id.as_u64())?;
let is_tx_finalized = check_whether_gw_transaction_is_finalized(
&gw_zk_client,
l1_provider,
l1_bridgehub.get_zk_chain(gw_chain_id).await?,
migration_transaction,
GatewayTransactionType::Withdrawal,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ use zkstack_cli_config::{
};
use zksync_basic_types::{commitment::L2DACommitmentScheme, H256, U256};
use zksync_system_constants::L2_BRIDGEHUB_ADDRESS;
use zksync_web3_decl::{
client::{Client, L2},
namespaces::EthNamespaceClient,
};
use zksync_web3_decl::client::{Client, L2};

use crate::{
abi::{BridgehubAbi, ZkChainAbi, GATEWAYUTILSABI_ABI},
Expand Down Expand Up @@ -198,16 +195,7 @@ pub async fn run(args: MigrateFromGatewayArgs, shell: &Shell) -> anyhow::Result<

let last_priority_op_hash = *priority_ops.last().unwrap();

await_for_withdrawal_to_finalize(
&gateway_zk_client,
get_ethers_provider(&l1_url)?,
gateway_chain_config
.get_contracts_config()?
.l1
.diamond_proxy_addr,
last_priority_op_hash,
)
.await?;
await_for_withdrawal_to_finalize(&gateway_zk_client, last_priority_op_hash).await?;

let params = gateway_zk_client
.get_finalize_withdrawal_params(last_priority_op_hash, 0)
Expand Down Expand Up @@ -271,58 +259,38 @@ pub(crate) enum GatewayTransactionType {

pub(crate) async fn check_whether_gw_transaction_is_finalized(
gateway_provider: &Client<L2>,
l1_provider: Arc<Provider<Http>>,
gateway_diamond_proxy: Address,
hash: H256,
transaction_type: GatewayTransactionType,
) -> anyhow::Result<bool> {
let Some(receipt) = gateway_provider.get_transaction_receipt(hash).await? else {
return Ok(false);
};

if receipt.l1_batch_number.is_none() {
return Ok(false);
}

let batch_number = receipt.l1_batch_number.unwrap();

match transaction_type {
GatewayTransactionType::Withdrawal => {
if gateway_provider
if let Err(e) = gateway_provider
.get_finalize_withdrawal_params(hash, 0)
.await
.is_err()
{
println!("Withdrawal is not finalized yet: {e:?}");
return Ok(false);
}
}
GatewayTransactionType::Migration => {
if gateway_provider
if let Err(e) = gateway_provider
.get_finalize_migration_params(hash, 0)
.await
.is_err()
{
println!("Migration is not finalized yet: {e:?}");
return Ok(false);
}
}
}

// TODO(PLA-1121): investigate why waiting for the tx proof is not enough.
// This is not expected behavior.
let gateway_contract = ZkChainAbi::new(gateway_diamond_proxy, l1_provider);
Ok(gateway_contract.get_total_batches_executed().await? >= U256::from(batch_number.as_u64()))
Ok(true)
}

async fn await_for_withdrawal_to_finalize(
gateway_provider: &Client<L2>,
l1_provider: Arc<Provider<Http>>,
gateway_diamond_proxy: Address,
hash: H256,
) -> anyhow::Result<()> {
while !check_whether_gw_transaction_is_finalized(
gateway_provider,
l1_provider.clone(),
gateway_diamond_proxy,
hash,
GatewayTransactionType::Withdrawal,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ pub async fn run(args: MigrateToGatewayArgs, shell: &Shell) -> anyhow::Result<()
)
.await?;

let mut chain_secrets_config = chain_config.get_secrets_config().await?.patched();
chain_secrets_config.set_gateway_rpc_url(context.gateway_rpc_url.clone())?;
chain_secrets_config.save().await?;
// let mut chain_secrets_config = chain_config.get_secrets_config().await?.patched();
// chain_secrets_config.set_gateway_rpc_url(context.gateway_rpc_url.clone())?;
// chain_secrets_config.save().await?;

let gw_bridgehub = BridgehubAbi::new(L2_BRIDGEHUB_ADDRESS, gateway_provider);

Expand Down Expand Up @@ -180,6 +180,8 @@ pub(crate) async fn get_migrate_to_gateway_context(
gateway_rpc_url,
new_sl_da_validator: gateway_da_validator_address,
validator: chain_secrets_config.operator.address,
prove_operator: chain_secrets_config.prove_operator.map(|o| o.address),
execute_operator: chain_secrets_config.execute_operator.map(|o| o.address),
min_validator_balance: U256::from(10).pow(19.into()),
refund_recipient: None,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub(crate) struct MigrateToGatewayConfig {
pub(crate) gateway_rpc_url: String,
pub(crate) new_sl_da_validator: Address,
pub(crate) validator: Address,
pub(crate) prove_operator: Option<Address>,
pub(crate) execute_operator: Option<Address>,
pub(crate) min_validator_balance: U256,
pub(crate) refund_recipient: Option<Address>,
}
Expand All @@ -59,6 +61,8 @@ pub(crate) struct MigrateToGatewayContext {
pub(crate) gateway_rpc_url: String,
pub(crate) new_sl_da_validator: Address,
pub(crate) validator: Address,
pub(crate) prove_operator: Option<Address>,
pub(crate) execute_operator: Option<Address>,
pub(crate) min_validator_balance: U256,
pub(crate) l1_provider: Arc<Provider<Http>>,
pub(crate) gw_provider: Arc<Provider<Http>>,
Expand Down Expand Up @@ -184,6 +188,8 @@ impl MigrateToGatewayConfig {
gateway_rpc_url: self.gateway_rpc_url,
new_sl_da_validator: self.new_sl_da_validator,
validator: self.validator,
prove_operator: self.prove_operator,
execute_operator: self.execute_operator,
min_validator_balance: self.min_validator_balance,
l1_provider,
gw_provider,
Expand Down Expand Up @@ -226,9 +232,13 @@ pub(crate) async fn get_migrate_to_gateway_calls(
// Changing L2 DA validator while migrating to gateway is not recommended; we allow changing only the settlement layer one
let (_, l2_da_validator_commitment_scheme) =
context.l1_zk_chain.get_da_validator_pair().await?;
let l2_da_validator_commitment_scheme =
let mut l2_da_validator_commitment_scheme =
L2DACommitmentScheme::try_from(l2_da_validator_commitment_scheme)
.map_err(|err| anyhow::format_err!("Failed to parse L2 DA commitment schema: {err}"))?;
if l2_da_validator_commitment_scheme == L2DACommitmentScheme::BlobsZksyncOS {
// ZK OS Gateway does not support Blobs, so chain should settle via calldata.
l2_da_validator_commitment_scheme = L2DACommitmentScheme::BlobsAndPubdataKeccak256;
}
if !l2_da_validator_commitment_scheme.is_none() {
let da_validator_encoding_result = check_permanent_rollup_and_set_da_validator_via_gateway(
shell,
Expand All @@ -242,85 +252,89 @@ pub(crate) async fn get_migrate_to_gateway_calls(
result.extend(da_validator_encoding_result.calls.into_iter());
}

let is_validator_enabled = if get_minor_protocol_version(context.protocol_version)?
.is_pre_interop_fast_blocks()
{
// In previous versions, we need to check if the validator is enabled
let legacy_validator_timelock = Contract::new(
// fixme: temporarily assign all roles to commit/prove/execute validators (needed for ZKsync OS)
let mut validators = vec![context.validator];
validators.extend(context.prove_operator);
validators.extend(context.execute_operator);

for validator in validators {
let is_validator_enabled = if get_minor_protocol_version(context.protocol_version)?
.is_pre_interop_fast_blocks()
{
// In previous versions, we need to check if the validator is enabled
let legacy_validator_timelock = Contract::new(
context.gw_validator_timelock_addr,
parse_abi(&[
"function validators(uint256 _chainId, address _validator) external view returns (bool)",
])?,
context.gw_provider.clone(),
);
legacy_validator_timelock
.method::<_, bool>("validators", (context.l2_chain_id, context.validator))?
.call()
.await?
} else {
context
.gw_validator_timelock
.has_role_for_chain_id(
context.l2_chain_id.into(),
context
.gw_validator_timelock
.committer_role()
.call()
.await?,
context.validator,
)
.await?
};
legacy_validator_timelock
.method::<_, bool>("validators", (context.l2_chain_id, validator))?
.call()
.await?
} else {
context
.gw_validator_timelock
.has_role_for_chain_id(
context.l2_chain_id.into(),
context
.gw_validator_timelock
.committer_role()
.call()
.await?,
validator,
)
.await?
};

// 4. If validator is not yet present, please include.
if !is_validator_enabled {
let enable_validator_calls = enable_validator_via_gateway(
shell,
forge_args,
foundry_contracts_path,
crate::admin_functions::AdminScriptMode::OnlySave,
context.l1_bridgehub_addr,
context.max_l1_gas_price.into(),
context.l2_chain_id,
context.gateway_chain_id,
context.validator,
context.gw_validator_timelock_addr,
context.refund_recipient,
context.l1_rpc_url.clone(),
)
.await?;
result.extend(enable_validator_calls.calls);
}
// 4. If validator is not yet present, please include.
if !is_validator_enabled {
let enable_validator_calls = enable_validator_via_gateway(
shell,
forge_args,
foundry_contracts_path,
crate::admin_functions::AdminScriptMode::OnlySave,
context.l1_bridgehub_addr,
context.max_l1_gas_price.into(),
context.l2_chain_id,
context.gateway_chain_id,
validator,
context.gw_validator_timelock_addr,
context.refund_recipient,
context.l1_rpc_url.clone(),
)
.await?;
result.extend(enable_validator_calls.calls);
}

let current_validator_balance = context
.gw_provider
.get_balance(context.validator, None)
.await?;
logger::info(format!(
"Current balance of {:#?} = {}",
context.validator, current_validator_balance
));
if current_validator_balance < context.min_validator_balance {
let current_validator_balance = context.gw_provider.get_balance(validator, None).await?;
logger::info(format!(
"Will send {} of the ZK Gateway base token",
context.min_validator_balance - current_validator_balance
"Current balance of {:#?} = {}",
validator, current_validator_balance
));
let supply_validator_balance_calls = admin_l1_l2_tx(
shell,
forge_args,
foundry_contracts_path,
crate::admin_functions::AdminScriptMode::OnlySave,
context.l1_bridgehub_addr,
context.max_l1_gas_price,
context.gateway_chain_id,
context.validator,
context.min_validator_balance - current_validator_balance,
Default::default(),
context.refund_recipient,
context.l1_rpc_url.clone(),
)
.await?;
result.extend(supply_validator_balance_calls.calls);
if current_validator_balance < context.min_validator_balance {
logger::info(format!(
"Will send {} of the ZK Gateway base token",
context.min_validator_balance - current_validator_balance
));
let supply_validator_balance_calls = admin_l1_l2_tx(
shell,
forge_args,
foundry_contracts_path,
crate::admin_functions::AdminScriptMode::OnlySave,
context.l1_bridgehub_addr,
context.max_l1_gas_price,
context.gateway_chain_id,
validator,
context.min_validator_balance - current_validator_balance,
Default::default(),
context.refund_recipient,
context.l1_rpc_url.clone(),
)
.await?;
result.extend(supply_validator_balance_calls.calls);
}
}

Ok((context.chain_admin_address, result))
Expand Down Expand Up @@ -413,6 +427,8 @@ impl MigrateToGatewayCalldataArgs {
gateway_rpc_url: self.gateway_rpc_url,
new_sl_da_validator: self.new_sl_da_validator,
validator: self.validator,
prove_operator: None,
execute_operator: None,
min_validator_balance: self.min_validator_balance.into(),
refund_recipient: self.refund_recipient,
}
Expand Down
4 changes: 3 additions & 1 deletion zkstack_cli/crates/zkstack/src/commands/chain/init/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,10 @@ pub async fn init(
.await?;
spinner.finish();

if !init_args.pause_deposits {
if !init_args.pause_deposits && !init_args.skip_priority_txs {
// Deposits are paused by default to allow immediate Gateway migration. If specified, unpause them.
// When skip_priority_txs is set, the caller manages deposit state separately
// (e.g. via `chain unpause-deposits`).
let spinner = Spinner::new(MSG_UNPAUSING_DEPOSITS_SPINNER);
unpause_deposits(
shell,
Expand Down
Loading
Loading