diff --git a/Cargo.lock b/Cargo.lock index 2425e1dc..0308dd88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4306,6 +4306,7 @@ dependencies = [ "op-succinct-client-utils", "op-succinct-host-utils", "rayon", + "reqwest 0.12.8", "serde", "serde_json", "sp1-build", diff --git a/configs/13269/rollup.json b/configs/13269/rollup.json index cd7d9e08..6a46a075 100644 --- a/configs/13269/rollup.json +++ b/configs/13269/rollup.json @@ -10,7 +10,7 @@ }, "l2_time": 1723487352, "system_config": { - "batcherAddr": "0x6322c47FEE60e15FC1B7ba65f1cfd66201E4c61d", + "batcherAddr": "0x6322c47fee60e15fc1b7ba65f1cfd66201e4c61d", "overhead": "0xbc", "scalar": "0xa6fe0", "gasLimit": 30000000, @@ -41,8 +41,8 @@ "ecotone_time": 0, "fjord_time": 0, "granite_time": 1725984001, - "batch_inbox_address": "0x136B12DB1FbaC1d6Aa6D0a1D2b724892c6FbA921", - "deposit_contract_address": "0x16839f9F6a11195A72B88744336EDFf036e7B3d5", - "l1_system_config_address": "0x19145e3aEe49C40D9f499F705F25ac1eA7409834", + "batch_inbox_address": "0x136b12db1fbac1d6aa6d0a1d2b724892c6fba921", + "deposit_contract_address": "0x16839f9f6a11195a72b88744336edff036e7b3d5", + "l1_system_config_address": "0x19145e3aee49c40d9f499f705f25ac1ea7409834", "protocol_versions_address": "0x0000000000000000000000000000000000000000" } \ No newline at end of file diff --git a/justfile b/justfile index 9dee02d7..a9951e8e 100644 --- a/justfile +++ b/justfile @@ -33,7 +33,7 @@ run-multi start end use-cache="false" prove="false": # Runs the cost estimator for a given block range. cost-estimator start end: #!/usr/bin/env bash - cargo run --bin cost_estimator --release -- --start {{start}} --end {{end}} + cargo run --bin cost-estimator --release -- --start {{start}} --end {{end}} # Runs the client program in native execution mode. Modified version of Kona Native Client execution: # https://github.com/ethereum-optimism/kona/blob/ae71b9df103c941c06b0dc5400223c4f13fe5717/bin/client/justfile#L65-L108 diff --git a/scripts/utils/Cargo.toml b/scripts/utils/Cargo.toml index 1fb1f395..43d16db7 100644 --- a/scripts/utils/Cargo.toml +++ b/scripts/utils/Cargo.toml @@ -8,15 +8,19 @@ repository.workspace = true homepage.workspace = true [[bin]] -name = "fetch_and_save_proof" +name = "fetch-and-save-proof" path = "bin/fetch_and_save_proof.rs" +[[bin]] +name = "update-vkeys" +path = "bin/update_vkeys.rs" + [[bin]] name = "vkey" path = "bin/vkey.rs" [[bin]] -name = "cost_estimator" +name = "cost-estimator" path = "bin/cost_estimator.rs" [[bin]] @@ -36,6 +40,7 @@ dotenv.workspace = true log.workspace = true csv.workspace = true serde = { workspace = true } +reqwest = { workspace = true } futures.workspace = true rayon = "1.10.0" serde_json.workspace = true diff --git a/scripts/utils/bin/update_vkeys.rs b/scripts/utils/bin/update_vkeys.rs new file mode 100644 index 00000000..471d1026 --- /dev/null +++ b/scripts/utils/bin/update_vkeys.rs @@ -0,0 +1,116 @@ +use std::env; +use std::str::FromStr; +use std::time::Duration; + +use alloy::network::EthereumWallet; +use alloy::providers::ProviderBuilder; +use alloy::signers::local::PrivateKeySigner; +use alloy::sol; +use alloy_primitives::{Address, B256}; +use anyhow::Result; +use op_succinct_client_utils::types::u32_to_u8; +use op_succinct_host_utils::fetcher::OPSuccinctDataFetcher; +use reqwest::Url; +use sp1_sdk::{utils, HashableKey, ProverClient}; + +pub const AGG_ELF: &[u8] = include_bytes!("../../../elf/aggregation-elf"); +pub const MULTI_BLOCK_ELF: &[u8] = include_bytes!("../../../elf/range-elf"); + +use clap::Parser; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Contract address to check the vkey against. + #[arg(short, long, required = false, value_delimiter = ',')] + contract_addresses: Vec, +} + +sol! { + #[allow(missing_docs)] + #[sol(rpc)] + contract L2OutputOracle { + bytes32 public aggregationVkey; + bytes32 public rangeVkeyCommitment; + + function updateAggregationVKey(bytes32 _aggregationVKey) external onlyOwner; + + function updateRangeVkeyCommitment(bytes32 _rangeVkeyCommitment) external onlyOwner; + } +} + +// Get the verification keys for the ELFs and check them against the contract. +#[tokio::main] +async fn main() -> Result<()> { + dotenv::dotenv().ok(); + utils::setup_logger(); + + let args = Args::parse(); + + let fetcher = OPSuccinctDataFetcher::default(); + + let prover = ProverClient::new(); + + let (_, range_vk) = prover.setup(MULTI_BLOCK_ELF); + + // Get the 32 byte commitment to the vkey from vkey.vk.hash_u32() + let multi_block_vkey_u8 = u32_to_u8(range_vk.vk.hash_u32()); + let multi_block_vkey_b256 = B256::from(multi_block_vkey_u8); + println!( + "Range ELF Verification Key Commitment: {}", + multi_block_vkey_b256 + ); + + let (_, agg_vk) = prover.setup(AGG_ELF); + println!("Aggregation ELF Verification Key: {}", agg_vk.bytes32()); + let agg_vkey_b256 = B256::from_str(&agg_vk.bytes32()).unwrap(); + + let private_key = env::var("PRIVATE_KEY").unwrap(); + let signer: PrivateKeySigner = private_key.parse().expect("Failed to parse private key"); + let wallet = EthereumWallet::from(signer); + + let rpc_url = fetcher.rpc_config.l1_rpc; + + // Wait for 3 required confirmations with a timeout of 60 seconds. + const NUM_CONFIRMATIONS: u64 = 3; + const TIMEOUT_SECONDS: u64 = 60; + + for contract_address in args.contract_addresses { + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .wallet(wallet.clone()) + .on_http(Url::parse(&rpc_url).unwrap()); + + let contract_address = Address::from_str(&contract_address).unwrap(); + let contract = L2OutputOracle::new(contract_address, provider); + + let receipt = contract + .updateAggregationVKey(agg_vkey_b256) + .send() + .await? + .with_required_confirmations(NUM_CONFIRMATIONS) + .with_timeout(Some(Duration::from_secs(TIMEOUT_SECONDS))) + .get_receipt() + .await?; + println!( + "Updated Aggregation VKey on contract {}. Tx: {}", + contract_address, receipt.transaction_hash + ); + + let receipt = contract + .updateRangeVkeyCommitment(multi_block_vkey_b256) + .send() + .await? + .with_required_confirmations(NUM_CONFIRMATIONS) + .with_timeout(Some(Duration::from_secs(TIMEOUT_SECONDS))) + .get_receipt() + .await?; + + println!( + "Updated Range VKey Commitment on contract {}. Tx: {}", + contract_address, receipt.transaction_hash + ); + } + + Ok(()) +} diff --git a/scripts/utils/bin/vkey.rs b/scripts/utils/bin/vkey.rs index baf86315..71bf18c4 100644 --- a/scripts/utils/bin/vkey.rs +++ b/scripts/utils/bin/vkey.rs @@ -1,4 +1,3 @@ -use alloy::sol; use alloy_primitives::B256; use anyhow::Result; use op_succinct_client_utils::types::u32_to_u8; @@ -7,28 +6,6 @@ use sp1_sdk::{utils, HashableKey, ProverClient}; pub const AGG_ELF: &[u8] = include_bytes!("../../../elf/aggregation-elf"); pub const MULTI_BLOCK_ELF: &[u8] = include_bytes!("../../../elf/range-elf"); -use clap::Parser; - -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -struct Args { - /// Contract address to check the vkey against. - #[arg(short, long, required = false)] - contract_address: Option, - - /// RPC URL to use for the provider. - #[arg(short, long, required = false)] - rpc_url: Option, -} - -sol! { - #[allow(missing_docs)] - #[sol(rpc)] - contract L2OutputOracle { - bytes32 public vkey; - } -} - // Get the verification keys for the ELFs and check them against the contract. #[tokio::main] async fn main() -> Result<()> { diff --git a/utils/host/src/fetcher.rs b/utils/host/src/fetcher.rs index e5e3ebd0..73f8eec1 100644 --- a/utils/host/src/fetcher.rs +++ b/utils/host/src/fetcher.rs @@ -45,10 +45,10 @@ impl Default for OPSuccinctDataFetcher { #[derive(Debug, Clone)] pub struct RPCConfig { - l1_rpc: String, - l1_beacon_rpc: String, - l2_rpc: String, - l2_node_rpc: String, + pub l1_rpc: String, + pub l1_beacon_rpc: String, + pub l2_rpc: String, + pub l2_node_rpc: String, } /// The mode corresponding to the chain we are fetching data for.