From 2b90732699ed17663690e6b5c50089dfb7abe1d0 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Mon, 2 Mar 2026 19:32:48 +0100 Subject: [PATCH 01/20] tee: make MAA attestation client optional when Azure SDK not installed Skip building the C++ attestation client if the Azure Guest Attestation header is absent; emit a cargo warning. Document in README that local dev with mock attestation does not require the SDK. --- .../adapters/tee/attestation_verifier/README.md | 2 ++ crates/adapters/tee/build.rs | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/adapters/tee/attestation_verifier/README.md b/crates/adapters/tee/attestation_verifier/README.md index 84ff7206d..255cc21c1 100644 --- a/crates/adapters/tee/attestation_verifier/README.md +++ b/crates/adapters/tee/attestation_verifier/README.md @@ -2,6 +2,8 @@ Allows to verify the AMD-SEV-SNP attestation that was generated after creating your SRS5, using the official Azure Attestation SDK. +**Optional for local development:** If you only use mock attestation (`SOV_TEE_MOCK_ATTESTATION=1`) and a dev oracle (`ORACLE_DEV_ACCEPT_ALL=1`), you do not need to install the Azure SDK or build this CLI. The `tee` crate build will skip the C++ attestation client when `/usr/include/azguestattestation1/AttestationClient.h` is not present. + Example: ```bash diff --git a/crates/adapters/tee/build.rs b/crates/adapters/tee/build.rs index 7bc0ed309..f336ec3e3 100644 --- a/crates/adapters/tee/build.rs +++ b/crates/adapters/tee/build.rs @@ -1,14 +1,27 @@ #[cfg(all(feature = "maa", target_os = "linux"))] use std::{env, fs, path::PathBuf, process::Command}; +/// Path where the Azure Guest Attestation SDK installs the header (see attestation_verifier/README.md). +#[allow(dead_code)] // used only inside #[cfg(all(feature = "maa", target_os = "linux"))] block +const AZ_SDK_INCLUDE_HEADER: &str = "/usr/include/azguestattestation1/AttestationClient.h"; + fn main() { // The MAA attestation client requires Azure-specific libraries (azguestattestation) - // that are only available on Linux Azure VMs. Skip building on non-Linux platforms. + // that are only available on Linux (and typically on Azure VMs). Skip building on non-Linux platforms. #[cfg(all(feature = "maa", target_os = "linux"))] { // Re-run if anything in the attestation_verifier directory changes. println!("cargo:rerun-if-changed=attestation_verifier"); + let sdk_header = PathBuf::from(AZ_SDK_INCLUDE_HEADER); + if !sdk_header.exists() { + println!( + "cargo:warning=MAA attestation client not built: Azure Guest Attestation SDK not found (missing {}). Install it for real MAA attestation; local mock attestation (SOV_TEE_MOCK_ATTESTATION=1, ORACLE_DEV_ACCEPT_ALL=1) does not require it.", + AZ_SDK_INCLUDE_HEADER + ); + return; + } + let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let att_dir = manifest.join("attestation_verifier"); let bin_path = att_dir.join("AttestationClient"); From 903a2698aafb140606a127258e0bc538d1178fb2 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Mon, 2 Mar 2026 19:38:42 +0100 Subject: [PATCH 02/20] mcp-external: treat SQLite INDEX_DB as unset, fall back to rollup REST optional_index_db_url() now returns None for sqlite:/sqlite3: URLs (since this provider uses PgPool). Log when SQLite is detected and document that commitment-tree sync then uses rollup REST endpoints. --- crates/mcp-external/src/provider.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/crates/mcp-external/src/provider.rs b/crates/mcp-external/src/provider.rs index a2af94192..733a86f7a 100644 --- a/crates/mcp-external/src/provider.rs +++ b/crates/mcp-external/src/provider.rs @@ -202,12 +202,25 @@ fn verifier_submit_retry_delay_ms() -> u64 { .unwrap_or(DEFAULT_VERIFIER_SUBMIT_RETRY_DELAY_MS) } +/// Returns the indexer DB URL only if it is a Postgres URL. SQLite URLs are ignored +/// because this provider uses PgPool; when the URL is SQLite we leave the pool None +/// and commitment-tree sync falls back to rollup REST endpoints. fn optional_index_db_url() -> Option { - std::env::var("MCP_INDEX_DB_URL") + let url = std::env::var("MCP_INDEX_DB_URL") .ok() - .or_else(|| std::env::var("INDEX_DB").ok()) - .map(|v| v.trim().to_string()) - .filter(|v| !v.is_empty()) + .or_else(|| std::env::var("INDEX_DB").ok())?; + let url = url.trim(); + if url.is_empty() { + return None; + } + if url.starts_with("sqlite:") || url.starts_with("sqlite3:") { + tracing::info!( + "[mcp] INDEX_DB is SQLite ({}); commitment-tree sync will use rollup REST endpoints", + url.split('?').next().unwrap_or(url) + ); + return None; + } + Some(url.to_string()) } fn parse_hash32_hex(value: &str) -> Result<[u8; 32]> { From 6d931e16af4e827b9af0bbc63a61e89ad09cc9cf Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Mon, 2 Mar 2026 19:44:20 +0100 Subject: [PATCH 03/20] tee: L1 commit/finalize via executor service (L1 commit finalize placement) Implement executor HTTP client and call it from the TEE manager: - After computing batch_hash: POST /commit-batch (commitBatch on L1). - After attestation and publishing to DA: POST /build-signatures then POST /finalize-batch (finalizeBatch on L1). Config: tee_configuration.executor_url and rollup_id_hex (optional; when unset, no L1 calls). Executor holds sequencer/finalizer keys; rollup only calls the HTTP API. --- Cargo.lock | 1 + crates/adapters/tee/src/maa/mod.rs | 2 +- .../full-node-configs/src/sequencer.rs | 7 + ...onfigs__runner__tests__correct_config.snap | 4 +- crates/full-node/sov-stf-runner/Cargo.toml | 1 + .../src/processes/executor_client.rs | 176 ++++++++++++++++++ .../sov-stf-runner/src/processes/mod.rs | 8 + .../src/processes/tee_manager/mod.rs | 90 ++++++++- .../tests/integration/helpers/runner_init.rs | 2 + .../src/native_only/mod.rs | 32 +++- .../sov-test-utils/src/test_rollup.rs | 2 + examples/rollup-ligero/run_all.sh | 7 +- 12 files changed, 327 insertions(+), 5 deletions(-) create mode 100644 crates/full-node/sov-stf-runner/src/processes/executor_client.rs diff --git a/Cargo.lock b/Cargo.lock index b3363edc4..702ab8be9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14508,6 +14508,7 @@ dependencies = [ "reqwest 0.12.28", "rockbound", "serde", + "serde_json", "sha2 0.10.9", "sov-db", "sov-metrics", diff --git a/crates/adapters/tee/src/maa/mod.rs b/crates/adapters/tee/src/maa/mod.rs index 703e623c1..f6b8e985b 100644 --- a/crates/adapters/tee/src/maa/mod.rs +++ b/crates/adapters/tee/src/maa/mod.rs @@ -1,7 +1,7 @@ use crate::common::BatchPublicDataV1; use anyhow::{Context, Result}; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _}; -use borsh::{from_slice, to_vec}; +use borsh::to_vec; use serde_json::Value; use sha2::{Digest, Sha256}; use std::{ diff --git a/crates/full-node/full-node-configs/src/sequencer.rs b/crates/full-node/full-node-configs/src/sequencer.rs index f09dd7676..8f20da67c 100644 --- a/crates/full-node/full-node-configs/src/sequencer.rs +++ b/crates/full-node/full-node-configs/src/sequencer.rs @@ -25,6 +25,13 @@ impl Default for SequencerKindConfig { pub struct TEEConfiguration { /// URL of the TEE attestation oracle. pub tee_attestation_oracle_url: String, + /// Optional base URL of the Bridge executor service (HTTP). When set, the TEE manager will call + /// POST /commit-batch and POST /build-signatures, POST /finalize-batch to submit L1 batch lifecycle. + #[serde(default)] + pub executor_url: Option, + /// Optional rollup ID (64 hex chars) for BatchPublicDataV1Full. Required when executor_url is set. + #[serde(default)] + pub rollup_id_hex: Option, } /// Configuration data used by sequencer extensions, such as EVM endpoints. diff --git a/crates/full-node/full-node-configs/src/snapshots/full_node_configs__runner__tests__correct_config.snap b/crates/full-node/full-node-configs/src/snapshots/full_node_configs__runner__tests__correct_config.snap index 601476497..8cc2e8b1c 100644 --- a/crates/full-node/full-node-configs/src/snapshots/full_node_configs__runner__tests__correct_config.snap +++ b/crates/full-node/full-node-configs/src/snapshots/full_node_configs__runner__tests__correct_config.snap @@ -67,7 +67,9 @@ expression: config "max_log_limit": 1000, "midnight_bridge": null, "tee_configuration": { - "tee_attestation_oracle_url": "http://127.0.0.1:8090" + "tee_attestation_oracle_url": "http://127.0.0.1:8090", + "executor_url": null, + "rollup_id_hex": null } } }, diff --git a/crates/full-node/sov-stf-runner/Cargo.toml b/crates/full-node/sov-stf-runner/Cargo.toml index de1817a77..ce737fff1 100644 --- a/crates/full-node/sov-stf-runner/Cargo.toml +++ b/crates/full-node/sov-stf-runner/Cargo.toml @@ -25,6 +25,7 @@ num_cpus = { workspace = true } thiserror = { workspace = true } borsh = { workspace = true } serde = { workspace = true } +serde_json = { workspace = true } strum = { workspace = true } toml = { workspace = true } nmt-rs = { workspace = true } diff --git a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs new file mode 100644 index 000000000..cebaf828b --- /dev/null +++ b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs @@ -0,0 +1,176 @@ +//! HTTP client for the Bridge executor service. +//! +//! The executor service (developed in another repo) exposes endpoints to submit +//! Bridge contract calls (commitBatch, finalizeBatch). This client matches the +//! API contract; no code is imported from the reference implementation. + +use alloy_primitives::U256; +use anyhow::{Context, Result}; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use tee::common::BatchPublicDataV1; + +fn base_url_normalized(base_url: &str) -> &str { + base_url.trim_end_matches('/') +} + +async fn post_json( + client: &reqwest::Client, + base_url: &str, + path: &str, + body: &serde_json::Value, +) -> Result { + let url = format!("{}{}", base_url_normalized(base_url), path); + let res = client + .post(&url) + .json(body) + .send() + .await + .context("executor HTTP request failed")?; + let status = res.status(); + let body_bytes = res + .bytes() + .await + .context("executor response body read failed")?; + if !status.is_success() { + let msg = String::from_utf8_lossy(&body_bytes); + let err_msg: String = serde_json::from_str::(&msg) + .ok() + .and_then(|v| v.get("error").and_then(|e| e.as_str()).map(String::from)) + .unwrap_or_else(|| msg.into_owned()); + anyhow::bail!("executor {}: {} (status {})", path, err_msg.trim(), status); + } + serde_json::from_slice(&body_bytes).context("executor response JSON parse failed") +} + +/// HTTP client for the Bridge executor service. +#[derive(Clone)] +pub struct ExecutorClient { + client: reqwest::Client, + base_url: String, +} + +impl ExecutorClient { + /// Creates a new executor client. + pub fn new(client: reqwest::Client, base_url: String) -> Self { + Self { client, base_url } + } + + /// Submits commitBatch to the executor (POST /commit-batch). + /// Hashes must be 32-byte values; they are sent as 64-char hex strings. + pub async fn commit_batch( + &self, + parent_batch_hash: &[u8; 32], + batch_hash: &[u8; 32], + ) -> Result<()> { + let body = json!({ + "parentHash": hex::encode(parent_batch_hash), + "batchHash": hex::encode(batch_hash), + }); + let _: serde_json::Value = post_json(&self.client, &self.base_url, "/commit-batch", &body).await?; + Ok(()) + } + + /// Asks the executor to build signatures for the given batch public data (POST /build-signatures). + /// Returns the `signatures` JSON string to pass to finalize_batch. + pub async fn build_signatures( + &self, + batch_public_data_json: &str, + signature_max_nonce: u64, + ) -> Result { + let batch_public_data: serde_json::Value = + serde_json::from_str(batch_public_data_json).context("batch_public_data JSON")?; + let body = json!({ + "batchPublicData": batch_public_data, + "signatureMaxNonce": signature_max_nonce, + }); + #[derive(serde::Deserialize)] + struct Out { + signatures: String, + } + let out: Out = post_json(&self.client, &self.base_url, "/build-signatures", &body).await?; + Ok(out.signatures) + } + + /// Submits finalizeBatch to the executor (POST /finalize-batch). + pub async fn finalize_batch( + &self, + batch_public_data_json: &str, + signatures_json: &str, + signer_bitmap: u8, + finalize_timestamp: u64, + ) -> Result<()> { + let batch_public_data: serde_json::Value = + serde_json::from_str(batch_public_data_json).context("batch_public_data JSON")?; + let signatures: serde_json::Value = + serde_json::from_str(signatures_json).context("signatures JSON")?; + let body = json!({ + "batchPublicData": batch_public_data, + "signatures": signatures, + "signerBitmap": signer_bitmap, + "finalizeTimestamp": finalize_timestamp, + }); + let _: serde_json::Value = + post_json(&self.client, &self.base_url, "/finalize-batch", &body).await?; + Ok(()) + } +} + +/// JSON shape for BatchPublicDataV1Full as expected by the executor (camelCase, 32-byte fields as hex). +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct BatchPublicDataV1FullJson { + version: u32, + layer2_chain_id: u64, + rollup_id: String, + batch_index: u64, + da_start_height: u64, + da_end_height: u64, + da_commitment: String, + last_processed_queue_index: u64, + message_queue_hash: String, + prev_state_root: String, + prev_batch_hash: String, + post_state_root: String, + batch_hash: String, + withdraw_root: String, +} + +fn bytes32_to_hex(b: &[u8; 32]) -> String { + hex::encode(b) +} + +/// Converts BatchPublicDataV1 and rollup_id to the executor's BatchPublicDataV1Full JSON string. +/// State roots in BatchPublicDataV1 are 64 bytes; the contract expects 32, so we use the first 32 bytes. +pub fn batch_public_data_to_executor_json( + batch: &BatchPublicDataV1, + rollup_id: &[u8; 32], +) -> Result { + let last_processed = batch + .last_processed_queue_index + .min(U256::from(u64::MAX)) + .to::(); + let prev_state_root_32: [u8; 32] = batch.prev_state_root[..32] + .try_into() + .map_err(|_| anyhow::anyhow!("prev_state_root too short"))?; + let post_state_root_32: [u8; 32] = batch.post_state_root[..32] + .try_into() + .map_err(|_| anyhow::anyhow!("post_state_root too short"))?; + let j = BatchPublicDataV1FullJson { + version: batch.version, + layer2_chain_id: batch.layer2_chain_id, + rollup_id: bytes32_to_hex(rollup_id), + batch_index: batch.batch_index, + da_start_height: batch.da_start_height, + da_end_height: batch.da_end_height, + da_commitment: bytes32_to_hex(&batch.da_commitment), + last_processed_queue_index: last_processed, + message_queue_hash: bytes32_to_hex(&batch.message_queue_hash), + prev_state_root: bytes32_to_hex(&prev_state_root_32), + prev_batch_hash: bytes32_to_hex(&batch.prev_batch_hash), + post_state_root: bytes32_to_hex(&post_state_root_32), + batch_hash: bytes32_to_hex(&batch.batch_hash), + withdraw_root: bytes32_to_hex(&batch.withdraw_root), + }; + serde_json::to_string(&j).context("batch public data JSON serialize") +} diff --git a/crates/full-node/sov-stf-runner/src/processes/mod.rs b/crates/full-node/sov-stf-runner/src/processes/mod.rs index 532cc7cfe..1e26512c5 100644 --- a/crates/full-node/sov-stf-runner/src/processes/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/mod.rs @@ -5,9 +5,13 @@ mod stf_info_manager; mod zk_manager; use std::num::NonZero; +#[cfg(feature = "tee")] +mod executor_client; #[cfg(feature = "tee")] mod tee_manager; +#[cfg(feature = "tee")] +pub use executor_client::{ExecutorClient, batch_public_data_to_executor_json}; #[cfg(feature = "tee")] pub use tee_manager::*; @@ -43,6 +47,8 @@ pub async fn start_tee_workflow_in_background( shutdown_receiver: tokio::sync::watch::Receiver<()>, oracle_url: String, midnight_bridge: Option, + executor_client: Option, + rollup_id: Option<[u8; 32]>, ) -> anyhow::Result> where Ps: ProverService, @@ -88,6 +94,8 @@ where reqwest::Client::new(), oracle_url, midnight_bridge, + executor_client, + rollup_id, ) .post_aggregated_proof_to_da_in_background() .await) diff --git a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs index 5fd3c624a..90f7fec3e 100644 --- a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs @@ -17,9 +17,11 @@ use types::{BlockProofInfo, BlockProofStatus, UnAggregatedProofList}; use self::types::AggregateProofMetadata; use super::StateTransitionInfo; +use crate::processes::executor_client::{batch_public_data_to_executor_json, ExecutorClient}; use crate::processes::tee_manager::types::merkle_root_from_leaves; use crate::processes::TEEBatchData; use crate::processes::{hash_to_bytes32, ProverService, PublicDataTee, Receiver}; +use tracing::info; mod types; @@ -94,6 +96,8 @@ pub struct TeeProofManager { http_client: reqwest::Client, oracle_url: String, midnight_bridge: Option, + executor_client: Option, + rollup_id: Option<[u8; 32]>, } impl TeeProofManager @@ -114,6 +118,8 @@ where http_client: reqwest::Client, oracle_url: String, midnight_bridge: Option, + executor_client: Option, + rollup_id: Option<[u8; 32]>, ) -> Self { Self { prover_service, @@ -132,6 +138,8 @@ where http_client, oracle_url, midnight_bridge, + executor_client, + rollup_id, } } @@ -321,6 +329,31 @@ where da_end_height, ); + // Commit batch on L1 via executor service (if configured) + if self.executor_client.is_none() { + tracing::debug!( + batch_index = self.batch_index, + "Executor not configured; skipping L1 commit/finalize (set executor_url and rollup_id_hex in tee_configuration to enable)" + ); + } + if let Some(ref executor) = self.executor_client { + if let Err(e) = executor + .commit_batch(&self.prev_batch_hash, &batch_hash) + .await + { + warn!( + batch_index = self.batch_index, + error = %e, + "Executor commit_batch failed; continuing without L1 commit" + ); + } else { + info!( + batch_index = self.batch_index, + "L1 commitBatch submitted via executor" + ); + } + } + tracing::debug!("Generating TEE attestation..."); let batch = BatchPublicDataV1 { @@ -410,7 +443,7 @@ where let attestation = sov_modules_api::TEEAttestation { attestation: borsh::to_vec(&signed_attestation)?, raw_aggregated_proof: agg_proof.raw_aggregated_proof, - batch_data: batch, + batch_data: batch.clone(), attestation_type: sov_modules_api::TEEAttestationType::MAA, }; @@ -430,6 +463,61 @@ where .publish_tee_attestation_blob_with_metadata(attestation) .await?; + // Finalize batch on L1 via executor service (if configured) + if let (Some(ref executor), Some(rollup_id)) = + (self.executor_client.as_ref(), self.rollup_id.as_ref()) + { + match batch_public_data_to_executor_json(&batch, rollup_id) { + Ok(batch_public_data_json) => { + const SIGNATURE_MAX_NONCE: u64 = 256; + const SIGNER_BITMAP: u8 = 0b111; // three signers + const FINALIZE_TIMESTAMP: u64 = 0; + + match executor + .build_signatures(&batch_public_data_json, SIGNATURE_MAX_NONCE) + .await + { + Ok(signatures_json) => { + if let Err(e) = executor + .finalize_batch( + &batch_public_data_json, + &signatures_json, + SIGNER_BITMAP, + FINALIZE_TIMESTAMP, + ) + .await + { + warn!( + batch_index = self.batch_index, + error = %e, + "Executor finalize_batch failed" + ); + } else { + info!( + batch_index = self.batch_index, + "L1 finalizeBatch submitted via executor" + ); + } + } + Err(e) => { + warn!( + batch_index = self.batch_index, + error = %e, + "Executor build_signatures failed" + ); + } + } + } + Err(e) => { + warn!( + batch_index = self.batch_index, + error = %e, + "Failed to serialize batch public data for executor" + ); + } + } + } + // Update the next height to receive self.stf_info_receiver .inc_next_height_to_receive_by(num_proofs_to_create as u64); diff --git a/crates/full-node/sov-stf-runner/tests/integration/helpers/runner_init.rs b/crates/full-node/sov-stf-runner/tests/integration/helpers/runner_init.rs index 03e9c13e5..60d9537a1 100644 --- a/crates/full-node/sov-stf-runner/tests/integration/helpers/runner_init.rs +++ b/crates/full-node/sov-stf-runner/tests/integration/helpers/runner_init.rs @@ -289,6 +289,8 @@ pub async fn initialize_runner( "https://indexer.preview.midnight.network/api/v3/graphql".to_owned(), "fa8533250190a9d2b39686523e7b13e7dc30647a341f8163dceaec2cdc365f12".to_owned(), )), + None, + None, ) .await .unwrap(); diff --git a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs index 76974e1fd..99696adcc 100644 --- a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs +++ b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs @@ -57,7 +57,7 @@ pub const GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH"); use crate::RollupBlueprint; #[cfg(feature = "tee")] -use sov_stf_runner::processes::start_tee_workflow_in_background; +use sov_stf_runner::processes::{start_tee_workflow_in_background, ExecutorClient}; /// This trait defines how to create all the necessary dependencies required by a rollup. #[allow(clippy::too_many_arguments, clippy::type_complexity)] @@ -559,6 +559,34 @@ pub trait FullNodeBlueprint: RollupBlueprint { } }; + let executor_client = if let Some(tee) = ext.and_then(|e| e.tee_configuration.as_ref()) { + tee.executor_url + .as_ref() + .filter(|s| !s.is_empty()) + .map(|url| -> anyhow::Result<_> { + let client = Client::builder() + .build() + .context("Failed to build executor HTTP client")?; + Ok(ExecutorClient::new(client, url.clone())) + }) + .transpose()? + } else { + None + }; + let rollup_id = ext + .and_then(|e| e.tee_configuration.as_ref()) + .and_then(|tee| { + let hex_str = tee.rollup_id_hex.as_ref()?; + let s = hex_str.strip_prefix("0x").unwrap_or(hex_str).trim(); + if s.len() != 64 || !s.chars().all(|c| c.is_ascii_hexdigit()) { + return None; + } + let bytes = hex::decode(s).ok()?; + let mut arr = [0u8; 32]; + arr.copy_from_slice(bytes.get(..32)?); + Some(arr) + }); + start_tee_workflow_in_background( prover_service, rollup_config.proof_manager.aggregated_proof_block_jump, @@ -568,6 +596,8 @@ pub trait FullNodeBlueprint: RollupBlueprint { secondary_shutdown_receiver, oracle_url, indexer, + executor_client, + rollup_id, ) .await? } diff --git a/crates/module-system/sov-test-utils/src/test_rollup.rs b/crates/module-system/sov-test-utils/src/test_rollup.rs index b2faabcc0..9196f5ca6 100644 --- a/crates/module-system/sov-test-utils/src/test_rollup.rs +++ b/crates/module-system/sov-test-utils/src/test_rollup.rs @@ -234,6 +234,8 @@ impl, StoragePath: AsPath> RollupBuilder&1 | tail -3 + ROLLUP_FEATURE_ARGS=() + if [[ -n "${ROLLUP_CARGO_FEATURES:-}" ]]; then + ROLLUP_FEATURE_ARGS=(--features "$ROLLUP_CARGO_FEATURES") + print_info " with features: $ROLLUP_CARGO_FEATURES" + fi + SKIP_GUEST_BUILD=1 cargo build $BUILD_MODE -p sov-rollup-ligero "${ROLLUP_FEATURE_ARGS[@]}" 2>&1 | tail -5 print_ok "sov-rollup-ligero" print_info "Building proof-verifier-service..." From 22eff575e193953bb249e047a7decb54c042dd1b Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Wed, 11 Mar 2026 15:14:27 +0100 Subject: [PATCH 04/20] add midnight-l2-contracts as rollup-ligero submodule --- .gitmodules | 3 +++ examples/rollup-ligero/midnight-l2-contracts | 1 + 2 files changed, 4 insertions(+) create mode 160000 examples/rollup-ligero/midnight-l2-contracts diff --git a/.gitmodules b/.gitmodules index 06330b9eb..8cd0452c4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "crates/module-system/sov-test-utils/lib/v2-periphery"] path = crates/module-system/sov-test-utils/lib/v2-periphery url = https://github.com/Uniswap/v2-periphery.git +[submodule "examples/rollup-ligero/midnight-l2-contracts"] + path = examples/rollup-ligero/midnight-l2-contracts + url = https://github.com/dcSpark/midnight-l2-contracts diff --git a/examples/rollup-ligero/midnight-l2-contracts b/examples/rollup-ligero/midnight-l2-contracts new file mode 160000 index 000000000..32492ee60 --- /dev/null +++ b/examples/rollup-ligero/midnight-l2-contracts @@ -0,0 +1 @@ +Subproject commit 32492ee60871fa55c39844827260ef8cd0d1b38a From 550b3f5c4c167b68f6adbefd119a06b836550f1a Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Wed, 11 Mar 2026 19:21:55 +0100 Subject: [PATCH 05/20] midnight adapter: update state fetching New contract storage model at `midnight-l2-contracts`, indexer at ledger-v7. --- crates/adapters/midnight/Cargo.toml | 5 +- crates/adapters/midnight/README.md | 4 +- crates/adapters/midnight/src/lib.rs | 99 ++++++++++------------------- 3 files changed, 37 insertions(+), 71 deletions(-) diff --git a/crates/adapters/midnight/Cargo.toml b/crates/adapters/midnight/Cargo.toml index 86893868e..f6b1340bb 100644 --- a/crates/adapters/midnight/Cargo.toml +++ b/crates/adapters/midnight/Cargo.toml @@ -14,11 +14,8 @@ workspace = true [dependencies] anyhow = { workspace = true } -base_crypto = { git = "https://github.com/dcSpark/midnight-ledger", branch = "midnight-l2", package = "midnight-base-crypto" } hex = { workspace = true } -midnight-onchain-state = { git = "https://github.com/dcSpark/midnight-ledger", branch = "midnight-l2" } -midnight-serialize = { git = "https://github.com/dcSpark/midnight-ledger", branch = "midnight-l2" } -midnight-storage = { git = "https://github.com/dcSpark/midnight-ledger", branch = "midnight-l2" } +midnight-node-ledger-helpers = { git = "https://github.com/midnightntwrk/midnight-node", rev = "c0e000e5", package = "midnight-node-ledger-helpers", features = ["can-panic"] } reqwest = { workspace = true, features = ["json"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/crates/adapters/midnight/README.md b/crates/adapters/midnight/README.md index 81eaf2cca..64a9dbf05 100644 --- a/crates/adapters/midnight/README.md +++ b/crates/adapters/midnight/README.md @@ -12,8 +12,8 @@ The crate ships with an integration-style test that can hit a real Midnight inde 1. Export the indexer HTTP endpoint and bridge contract address: ```bash - export MIDNIGHT_INDEXER_ENDPOINT=https://indexer.preview.midnight.network/api/v3/graphql - export MIDNIGHT_CONTRACT_ADDRESS=fa8533250190a9d2b39686523e7b13e7dc30647a341f8163dceaec2cdc365f12 + export MIDNIGHT_INDEXER_ENDPOINT=http://localhost:8088/api/v3/graphql + export MIDNIGHT_CONTRACT_ADDRESS=1a7db08f9532105a8a79b1dd75a098d38b4a5513f8c0745e733ea807a6d9eb07 ``` 2. Execute the test: ```bash diff --git a/crates/adapters/midnight/src/lib.rs b/crates/adapters/midnight/src/lib.rs index 1371d686f..20dfced50 100644 --- a/crates/adapters/midnight/src/lib.rs +++ b/crates/adapters/midnight/src/lib.rs @@ -1,23 +1,18 @@ use anyhow::{anyhow, Context, Result}; -use base_crypto::fab::{AlignedValue, ValueAtom}; use hex::FromHex; -use midnight_onchain_state::state::{ChargedState, ContractMaintenanceAuthority, ContractState}; -use midnight_serialize::{tagged_deserialize, Deserializable}; -use midnight_storage::arena::{set_allow_non_normal_form_deserialization, Sp}; -use midnight_storage::db::InMemoryDB; -use midnight_storage::storage::HashMap as StorageHashMap; +use midnight_node_ledger_helpers::base_crypto::fab::{AlignedValue, ValueAtom}; +use midnight_node_ledger_helpers::mn_ledger_serialize::tagged_deserialize; +use midnight_node_ledger_helpers::mn_ledger_storage::arena::Sp; +use midnight_node_ledger_helpers::onchain_runtime::state::ContractState; +use midnight_node_ledger_helpers::DefaultDB; use reqwest::Client; use serde::{Deserialize, Serialize}; use serde_json::json; use std::collections::{BTreeMap, BTreeSet}; -use std::io::Cursor; use std::ops::Deref; -use std::sync::Once; pub mod utils; -const LEGACY_CONTRACT_STATE_TAG_V4: &[u8] = b"midnight:contract-state[v4]:"; - const CONTRACT_STATE_QUERY: &str = r#" query CONTRACT_STATE_QUERY($address: HexEncoded!, $offset: ContractActionOffset) { contractAction(address: $address, offset: $offset) { @@ -26,8 +21,6 @@ state } "#; -static SET_NORMAL_FORM_FLAG: Once = Once::new(); - /// Client wrapper for querying the Midnight GraphQL indexer. pub struct MidnightIndexerClient { client: Client, @@ -38,7 +31,6 @@ pub struct MidnightIndexerClient { impl MidnightIndexerClient { /// Builds a client for the Midnight indexer GraphQL endpoint. pub fn new(client: Client, endpoint: String, contract_address: String) -> Self { - SET_NORMAL_FORM_FLAG.call_once(|| set_allow_non_normal_form_deserialization(true)); Self { client, endpoint, @@ -138,8 +130,9 @@ pub struct RollupLedger { pub signature_threshold: u8, pub sequencers: BTreeSet<[u8; 32]>, pub finalizers: BTreeSet<[u8; 32]>, - pub committed_batches: BTreeMap, - pub finalized_state_roots: BTreeMap, + pub last_committed_batch_hash: [u8; 32], + pub last_finalized_state_root: [u8; 32], + pub last_finalized_batch_hash: [u8; 32], pub withdraw_roots: BTreeMap, pub misc_data: RollupMiscData, pub first_cross_domain_message_index: u64, @@ -187,40 +180,9 @@ pub struct L2MessageQueueLedger { pub branches: Vec<[u8; 32]>, } -fn deserialize_contract_state(bytes: &[u8]) -> Result> { - match tagged_deserialize(bytes) { - Ok(state) => Ok(state), - Err(primary_err) => match deserialize_contract_state_v4(bytes) { - Ok(Some(legacy)) => Ok(legacy), - Ok(None) => Err(anyhow!( - "failed to deserialize ContractState: {}", - primary_err - )), - Err(legacy_err) => Err(anyhow!( - "failed to deserialize ContractState: {}; legacy decode error: {}", - primary_err, - legacy_err - )), - }, - } -} - -fn deserialize_contract_state_v4(bytes: &[u8]) -> Result>> { - if !bytes.starts_with(LEGACY_CONTRACT_STATE_TAG_V4) { - return Ok(None); - } - - let mut reader = Cursor::new(&bytes[LEGACY_CONTRACT_STATE_TAG_V4.len()..]); - let legacy_value = ::deserialize(&mut reader, 0) - .map_err(|err| anyhow!("legacy contract-state data decode failed: {}", err))?; - let data = ChargedState::new(legacy_value); - - Ok(Some(ContractState { - data, - operations: StorageHashMap::new(), - maintenance_authority: ContractMaintenanceAuthority::new(), - balance: StorageHashMap::new(), - })) +fn deserialize_contract_state(bytes: &[u8]) -> Result> { + tagged_deserialize(bytes) + .map_err(|err| anyhow!("failed to deserialize ContractState: {}", err)) } struct RollupHead { @@ -231,8 +193,9 @@ struct RollupHead { signature_threshold: u8, sequencers: BTreeSet<[u8; 32]>, finalizers: BTreeSet<[u8; 32]>, - committed_batches: BTreeMap, - finalized_state_roots: BTreeMap, + last_committed_batch_hash: [u8; 32], + last_finalized_state_root: [u8; 32], + last_finalized_batch_hash: [u8; 32], withdraw_roots: BTreeMap, misc_data: RollupMiscData, first_cross_domain_message_index: u64, @@ -250,7 +213,7 @@ struct RollupTail { pending_withdrawals: BTreeMap<[u8; 32], u128>, } -fn decode_bridge_ledger(state: &ContractState) -> Result { +fn decode_bridge_ledger(state: &ContractState) -> Result { let root = state.data.get_ref(); let root_parts = expect_array(root).context("bridge state root must be an array")?; if root_parts.len() != 3 { @@ -272,8 +235,9 @@ fn decode_bridge_ledger(state: &ContractState) -> Result) -> Result Result { let items = expect_array(value).context("rollup header must be an array")?; - if items.len() != 12 { + if items.len() != 13 { return Err(anyhow!( - "rollup header expected 12 entries, found {}", + "rollup header expected 13 entries, found {}", items.len() )); } @@ -320,13 +284,17 @@ fn decode_rollup_head(value: &StateValue) -> Result { )?; let sequencers = decode_bytes32_set(iter_next(&mut iter, "sequencers")?.deref(), "sequencers")?; let finalizers = decode_bytes32_set(iter_next(&mut iter, "finalizers")?.deref(), "finalizers")?; - let committed_batches = decode_u64_bytes32_map( - iter_next(&mut iter, "committedBatches")?.deref(), - "committedBatches", + let last_committed_batch_hash = decode_bytes32_value( + iter_next(&mut iter, "lastCommittedBatchHash")?.deref(), + "lastCommittedBatchHash", + )?; + let last_finalized_state_root = decode_bytes32_value( + iter_next(&mut iter, "lastFinalizedStateRoot")?.deref(), + "lastFinalizedStateRoot", )?; - let finalized_state_roots = decode_u64_bytes32_map( - iter_next(&mut iter, "finalizedStateRoots")?.deref(), - "finalizedStateRoots", + let last_finalized_batch_hash = decode_bytes32_value( + iter_next(&mut iter, "lastFinalizedBatchHash")?.deref(), + "lastFinalizedBatchHash", )?; let withdraw_roots = decode_u64_bytes32_map( iter_next(&mut iter, "withdrawRoots")?.deref(), @@ -350,8 +318,9 @@ fn decode_rollup_head(value: &StateValue) -> Result { signature_threshold, sequencers, finalizers, - committed_batches, - finalized_state_roots, + last_committed_batch_hash, + last_finalized_state_root, + last_finalized_batch_hash, withdraw_roots, misc_data, first_cross_domain_message_index, @@ -827,7 +796,7 @@ struct ContractActionState { state: String, } -type StateValue = midnight_onchain_state::state::StateValue; +type StateValue = midnight_node_ledger_helpers::onchain_runtime::state::StateValue; #[cfg(test)] mod tests { From 1aca72f9c69fc6fab5093e41ce7d6c2253c1c525 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Tue, 17 Mar 2026 18:48:39 +0100 Subject: [PATCH 06/20] tee: rollup-managed L1 Bridge lifecycle with deferred DA block production The rollup now owns the full L1 Bridge contract lifecycle: it auto- deploys the contract on genesis (using print-genesis-info to compute the deterministic state root and batch hash), spawns the executor service as a child process, persists the contract address, and tears everything down on shutdown. This replaces the previous manual workflow. --- Cargo.lock | 2456 ++++++++++++++--- .../midnight-da/benches/concurrent_access.rs | 1 + .../midnight-da/src/storable/service.rs | 19 +- .../full-node-configs/src/sequencer.rs | 31 + crates/full-node/sov-blob-sender/src/lib.rs | 2 +- crates/full-node/sov-sequencer/src/lib.rs | 4 +- .../src/processes/bridge_lifecycle.rs | 232 ++ .../src/processes/executor_client.rs | 55 + .../sov-stf-runner/src/processes/mod.rs | 99 +- .../src/processes/tee_manager/mod.rs | 167 +- .../src/native_only/mod.rs | 189 +- .../sov-test-utils/src/test_rollup.rs | 1 + crates/rollup-interface/src/node/da.rs | 12 + examples/rollup-ligero/Cargo.toml | 4 + examples/rollup-ligero/L1_INTERACTIONS.md | 118 + examples/rollup-ligero/README.md | 4 + examples/rollup-ligero/midnight-l2-contracts | 2 +- .../src/bin/print_genesis_info.rs | 111 + 18 files changed, 3043 insertions(+), 464 deletions(-) create mode 100644 crates/full-node/sov-stf-runner/src/processes/bridge_lifecycle.rs create mode 100644 examples/rollup-ligero/L1_INTERACTIONS.md create mode 100644 examples/rollup-ligero/src/bin/print_genesis_info.rs diff --git a/Cargo.lock b/Cargo.lock index 702ab8be9..74c6f2b04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -554,7 +554,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" dependencies = [ "alloy-rlp-derive", - "arrayvec", + "arrayvec 0.7.6", "bytes", ] @@ -565,7 +565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -725,7 +725,7 @@ dependencies = [ "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -742,7 +742,7 @@ dependencies = [ "indexmap 2.13.0", "proc-macro-error2", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", "syn-solidity", "tiny-keccak", @@ -760,7 +760,7 @@ dependencies = [ "heck 0.5.0", "macro-string", "proc-macro2", - "quote", + "quote 1.0.43", "serde_json", "syn 2.0.114", "syn-solidity", @@ -852,7 +852,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "arbitrary", - "arrayvec", + "arrayvec 0.7.6", "derive_arbitrary", "derive_more 2.1.1", "nybbles", @@ -871,7 +871,7 @@ checksum = "b2289a842d02fe63f8c466db964168bb2c7a9fdfb7b24816dbb17d45520575fb" dependencies = [ "darling 0.21.3", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -1038,7 +1038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -1111,7 +1111,7 @@ dependencies = [ "ark-ff-macros 0.5.0", "ark-serialize 0.5.0", "ark-std 0.5.0", - "arrayvec", + "arrayvec 0.7.6", "digest 0.10.7", "educe", "itertools 0.13.0", @@ -1127,7 +1127,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -1137,7 +1137,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -1147,7 +1147,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -1159,7 +1159,7 @@ checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ "num-bigint 0.4.6", "num-traits", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -1172,7 +1172,7 @@ dependencies = [ "num-bigint 0.4.6", "num-traits", "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -1185,7 +1185,7 @@ dependencies = [ "num-bigint 0.4.6", "num-traits", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -1277,7 +1277,7 @@ checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ "ark-serialize-derive", "ark-std 0.5.0", - "arrayvec", + "arrayvec 0.7.6", "digest 0.10.7", "num-bigint 0.4.6", ] @@ -1289,7 +1289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -1347,6 +1347,15 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + [[package]] name = "arrayvec" version = "0.7.6" @@ -1398,6 +1407,119 @@ dependencies = [ "xattr", ] +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -1416,10 +1538,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.89" @@ -1427,7 +1555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -1460,6 +1588,12 @@ dependencies = [ "critical-section", ] +[[package]] +name = "atomic-take" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8ab6b55fe97976e46f91ddbed8d147d966475dc29b2032757ba47e02376fbc3" + [[package]] name = "atomic-waker" version = "1.1.2" @@ -1493,7 +1627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -1754,6 +1888,12 @@ dependencies = [ "match-lookup", ] +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + [[package]] name = "base64" version = "0.13.1" @@ -1868,7 +2008,7 @@ dependencies = [ "lazy_static", "lazycell", "proc-macro2", - "quote", + "quote 1.0.43", "regex", "rustc-hash 1.1.0", "shlex", @@ -1888,13 +2028,43 @@ dependencies = [ "log", "prettyplease", "proc-macro2", - "quote", + "quote 1.0.43", "regex", "rustc-hash 1.1.0", "shlex", "syn 2.0.114", ] +[[package]] +name = "bip32" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db40d3dfbeab4e031d78c844642fa0caa0b0db11ce1607ac9d2986dff1405c69" +dependencies = [ + "bs58", + "hmac 0.12.1", + "k256", + "once_cell", + "pbkdf2 0.12.2", + "rand_core 0.6.4", + "ripemd", + "secp256k1 0.27.0", + "sha2 0.10.9", + "subtle", + "zeroize", +] + +[[package]] +name = "bip39" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc" +dependencies = [ + "bitcoin_hashes", + "serde", + "unicode-normalization", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -1963,7 +2133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f48d6ace212fdf1b45fd6b566bb40808415344642b76c3224c07c8df9da81e97" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -2010,6 +2180,16 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq 0.1.5", +] + [[package]] name = "blake2b_halo2" version = "0.1.0" @@ -2033,7 +2213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b79834656f71332577234b50bfc009996f7449e0c056884e6a02492ded0ca2f3" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.7.6", "constant_time_eq 0.4.2", ] @@ -2044,7 +2224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.7.6", "cc", "cfg-if", "constant_time_eq 0.4.2", @@ -2084,6 +2264,19 @@ dependencies = [ "objc2", ] +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "blockstore" version = "0.7.1" @@ -2224,7 +2417,7 @@ dependencies = [ "once_cell", "proc-macro-crate 3.4.0", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -2272,7 +2465,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -2403,7 +2596,7 @@ dependencies = [ "indexmap 2.13.0", "log", "proc-macro2", - "quote", + "quote 1.0.43", "serde", "serde_json", "syn 2.0.114", @@ -2450,7 +2643,7 @@ dependencies = [ "celestia-proto", "celestia-types", "http 1.4.0", - "jsonrpsee", + "jsonrpsee 0.25.1", "serde", "serde_repr", "thiserror 1.0.69", @@ -2500,7 +2693,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] @@ -2651,7 +2844,7 @@ checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck 0.5.0", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -2694,7 +2887,7 @@ dependencies = [ "bs58", "coins-core", "digest 0.10.7", - "hmac", + "hmac 0.12.1", "k256", "serde", "sha2 0.10.9", @@ -2709,7 +2902,7 @@ checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" dependencies = [ "bitvec", "coins-bip32", - "hmac", + "hmac 0.12.1", "once_cell", "pbkdf2 0.12.2", "rand 0.8.5", @@ -2858,8 +3051,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" dependencies = [ "proc-macro2", - "quote", - "unicode-xid", + "quote 1.0.43", + "unicode-xid 0.2.6", ] [[package]] @@ -3146,6 +3339,31 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "crypto_secretbox" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" +dependencies = [ + "aead", + "cipher", + "generic-array 0.14.7", + "poly1305", + "salsa20", + "subtle", + "zeroize", +] + [[package]] name = "csv" version = "1.4.0" @@ -3228,7 +3446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3238,7 +3456,7 @@ version = "0.1.1" source = "git+https://github.com/risc0/curve25519-dalek?rev=3dccc5b71b806f500e73829e2a5cbfe288cce2a0#3dccc5b71b806f500e73829e2a5cbfe288cce2a0" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3284,7 +3502,7 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote", + "quote 1.0.43", "strsim", "syn 2.0.114", ] @@ -3298,7 +3516,7 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote", + "quote 1.0.43", "serde", "strsim", "syn 2.0.114", @@ -3311,7 +3529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3322,7 +3540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3413,7 +3631,7 @@ dependencies = [ "dashu-ratio", "paste", "proc-macro2", - "quote", + "quote 1.0.43", "rustversion", ] @@ -3571,7 +3789,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -3582,7 +3800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bba95f299f6b9cd47f68a847eca2ae9060a2713af532dc35c342065544845407" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "structmeta", "syn 2.0.114", ] @@ -3594,7 +3812,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3605,7 +3823,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3616,7 +3834,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3637,7 +3855,7 @@ checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling 0.20.11", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3658,7 +3876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3687,9 +3905,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", - "unicode-xid", + "unicode-xid 0.2.6", ] [[package]] @@ -3700,10 +3918,10 @@ checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case 0.10.0", "proc-macro2", - "quote", + "quote 1.0.43", "rustc_version 0.4.1", "syn 2.0.114", - "unicode-xid", + "unicode-xid 0.2.6", ] [[package]] @@ -3833,7 +4051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3888,7 +4106,7 @@ checksum = "1cac124e13ae9aa56acc4241f8c8207501d93afdd8d8e62f0c1f2e12f6508c65" dependencies = [ "darling 0.20.11", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -3974,6 +4192,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-zebra" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0017d969298eec91e3db7a2985a8cab4df6341d86e6f3a6f5878b13fb7846bc9" +dependencies = [ + "curve25519-dalek 4.1.3", + "ed25519", + "rand_core 0.6.4", + "sha2 0.10.9", + "subtle", + "zeroize", +] + [[package]] name = "educe" version = "0.6.0" @@ -3982,7 +4214,7 @@ checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" dependencies = [ "enum-ordinalize", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -4103,7 +4335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -4123,7 +4355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -4135,10 +4367,26 @@ checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ "once_cell", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] +[[package]] +name = "enum_index" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5532bdea562e7be83060c36185eecccba82fe16729d2eaad2891d65417656dd" + +[[package]] +name = "enum_index_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ab22c8085548bf06190113dca556e149ecdbb05ae5b972a2b9899f26b944ee4" +dependencies = [ + "quote 0.3.15", + "syn 0.11.11", +] + [[package]] name = "enumflags2" version = "0.7.12" @@ -4155,7 +4403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -4257,10 +4505,10 @@ dependencies = [ "ctr", "digest 0.10.7", "hex", - "hmac", + "hmac 0.12.1", "pbkdf2 0.11.0", "rand 0.8.5", - "scrypt", + "scrypt 0.10.0", "serde", "serde_json", "sha2 0.10.9", @@ -4283,7 +4531,7 @@ dependencies = [ "serde_json", "sha3", "thiserror 1.0.69", - "uint", + "uint 0.9.5", ] [[package]] @@ -4294,9 +4542,9 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", - "impl-codec", + "impl-codec 0.6.0", "impl-rlp", - "impl-serde", + "impl-serde 0.4.0", "scale-info", "tiny-keccak", ] @@ -4309,12 +4557,12 @@ checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", - "impl-codec", + "impl-codec 0.6.0", "impl-rlp", - "impl-serde", - "primitive-types", + "impl-serde 0.4.0", + "primitive-types 0.12.2", "scale-info", - "uint", + "uint 0.9.5", ] [[package]] @@ -4378,7 +4626,7 @@ dependencies = [ "eyre", "prettyplease", "proc-macro2", - "quote", + "quote 1.0.43", "regex", "reqwest 0.11.27", "serde", @@ -4399,7 +4647,7 @@ dependencies = [ "ethers-contract-abigen", "ethers-core", "proc-macro2", - "quote", + "quote 1.0.43", "serde_json", "syn 2.0.114", ] @@ -4410,7 +4658,7 @@ version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "bytes", "cargo_metadata 0.18.1", "chrono", @@ -4431,7 +4679,7 @@ dependencies = [ "tempfile", "thiserror 1.0.69", "tiny-keccak", - "unicode-xid", + "unicode-xid 0.2.6", ] [[package]] @@ -4582,6 +4830,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "eyre" version = "0.6.12" @@ -4638,7 +4896,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "auto_impl", "bytes", ] @@ -4649,7 +4907,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "auto_impl", "bytes", ] @@ -4689,7 +4947,7 @@ dependencies = [ "num-integer", "num-traits", "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -4828,7 +5086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -4863,6 +5121,34 @@ dependencies = [ "num", ] +[[package]] +name = "frame-decode" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c470df86cf28818dd3cd2fc4667b80dbefe2236c722c3dc1d09e7c6c82d6dfcd" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "scale-type-resolver", + "sp-crypto-hashing", + "thiserror 2.0.17", +] + +[[package]] +name = "frame-metadata" +version = "23.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba5be0edbdb824843a0f9c6f0906ecfc66c5316218d74457003218b24909ed0" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + [[package]] name = "fs-err" version = "3.2.2" @@ -4971,6 +5257,19 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-locks" version = "0.7.1" @@ -4988,7 +5287,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -5122,6 +5421,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand 0.8.5", + "rand_core 0.6.4", +] + [[package]] name = "ghash" version = "0.5.1" @@ -5535,7 +5844,7 @@ dependencies = [ "num-integer", "num-traits", "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -5583,6 +5892,7 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash 0.1.5", + "serde", ] [[package]] @@ -5634,7 +5944,7 @@ dependencies = [ "base64 0.21.7", "byteorder", "flate2", - "nom", + "nom 7.1.3", "num-traits", ] @@ -5685,7 +5995,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", ] [[package]] @@ -5700,7 +6010,17 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ - "hmac", + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", ] [[package]] @@ -5712,6 +6032,17 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.7", + "hmac 0.8.1", +] + [[package]] name = "home" version = "0.5.9" @@ -6148,6 +6479,15 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-codec" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d40b9d5e17727407e55028eafc22b2dc68781786e6d7eb8a21103f5058e3a14" +dependencies = [ + "parity-scale-codec", +] + [[package]] name = "impl-rlp" version = "0.3.0" @@ -6166,6 +6506,15 @@ dependencies = [ "serde", ] +[[package]] +name = "impl-serde" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a143eada6a1ec4aefa5049037a26a6d597bfd64f8c026d07b77133e02b7dd0b" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.3" @@ -6173,7 +6522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -6242,7 +6591,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c727f80bfa4a6c6e2508d2f05b6f4bfce242030bd88ed15ae5331c5b5d30fba7" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -6287,7 +6636,7 @@ dependencies = [ "borsh", "derive_more 1.0.0", "hex", - "jsonrpsee", + "jsonrpsee 0.25.1", "rockbound", "schemars 0.8.22", "serde", @@ -6314,21 +6663,42 @@ dependencies = [ ] [[package]] -name = "inventory" -version = "0.3.21" +name = "introspection" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" +checksum = "8aef96cc8e702a9107d35e7eb802f60c8f3babb94c5b1d5eac7c6b99116344ff" dependencies = [ - "rustversion", + "quote 0.3.15", + "syn 0.11.11", ] [[package]] -name = "io-uring" -version = "0.6.4" +name = "introspection-derive" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595a0399f411a508feb2ec1e970a4a30c249351e30208960d58298de8660b0e5" +checksum = "7f40c436bdcb61b4dcd7c302029c522150b45e4f048cacd0ad845b48ba3b1cac" dependencies = [ - "bitflags 1.3.2", + "introspection", + "quote 0.3.15", + "syn 0.11.11", +] + +[[package]] +name = "inventory" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" +dependencies = [ + "rustversion", +] + +[[package]] +name = "io-uring" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595a0399f411a508feb2ec1e970a4a30c249351e30208960d58298de8660b0e5" +dependencies = [ + "bitflags 1.3.2", "libc", ] @@ -6365,6 +6735,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "is_sorted" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357376465c37db3372ef6a00585d336ed3d0f11d4345eef77ebcb05865392b21" + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -6484,22 +6860,57 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonrpsee" +version = "0.24.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e281ae70cc3b98dac15fced3366a880949e65fc66e345ce857a5682d152f3e62" +dependencies = [ + "jsonrpsee-client-transport 0.24.10", + "jsonrpsee-core 0.24.10", + "jsonrpsee-types 0.24.10", + "jsonrpsee-ws-client 0.24.10", +] + [[package]] name = "jsonrpsee" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fba77a59c4c644fd48732367624d1bcf6f409f9c9a286fbc71d2f1fc0b2ea16" dependencies = [ - "jsonrpsee-client-transport", - "jsonrpsee-core", + "jsonrpsee-client-transport 0.25.1", + "jsonrpsee-core 0.25.1", "jsonrpsee-http-client", "jsonrpsee-proc-macros", "jsonrpsee-server", - "jsonrpsee-types", + "jsonrpsee-types 0.25.1", "jsonrpsee-wasm-client", - "jsonrpsee-ws-client", + "jsonrpsee-ws-client 0.25.1", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.24.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4280b709ac3bb5e16cf3bad5056a0ec8df55fa89edfe996361219aadc2c7ea" +dependencies = [ + "base64 0.22.1", + "futures-util", + "http 1.4.0", + "jsonrpsee-core 0.24.10", + "pin-project", + "rustls 0.23.36", + "rustls-pki-types", + "rustls-platform-verifier", + "soketto", + "thiserror 1.0.69", "tokio", + "tokio-rustls 0.26.4", + "tokio-util", "tracing", + "url", ] [[package]] @@ -6513,7 +6924,7 @@ dependencies = [ "futures-util", "gloo-net", "http 1.4.0", - "jsonrpsee-core", + "jsonrpsee-core 0.25.1", "pin-project", "rustls 0.23.36", "rustls-pki-types", @@ -6527,6 +6938,26 @@ dependencies = [ "url", ] +[[package]] +name = "jsonrpsee-core" +version = "0.24.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348ee569eaed52926b5e740aae20863762b16596476e943c9e415a6479021622" +dependencies = [ + "async-trait", + "futures-timer", + "futures-util", + "jsonrpsee-types 0.24.10", + "pin-project", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tracing", +] + [[package]] name = "jsonrpsee-core" version = "0.25.1" @@ -6540,7 +6971,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "jsonrpsee-types", + "jsonrpsee-types 0.25.1", "parking_lot", "pin-project", "rand 0.9.2", @@ -6566,8 +6997,8 @@ dependencies = [ "hyper 1.8.1", "hyper-rustls 0.27.7", "hyper-util", - "jsonrpsee-core", - "jsonrpsee-types", + "jsonrpsee-core 0.25.1", + "jsonrpsee-types 0.25.1", "rustls 0.23.36", "rustls-platform-verifier", "serde", @@ -6587,7 +7018,7 @@ dependencies = [ "heck 0.5.0", "proc-macro-crate 3.4.0", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -6603,8 +7034,8 @@ dependencies = [ "http-body-util", "hyper 1.8.1", "hyper-util", - "jsonrpsee-core", - "jsonrpsee-types", + "jsonrpsee-core 0.25.1", + "jsonrpsee-types 0.25.1", "pin-project", "route-recognizer", "serde", @@ -6618,6 +7049,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "jsonrpsee-types" +version = "0.24.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0f05e0028e55b15dbd2107163b3c744cd3bb4474f193f95d9708acbf5677e44" +dependencies = [ + "http 1.4.0", + "serde", + "serde_json", + "thiserror 1.0.69", +] + [[package]] name = "jsonrpsee-types" version = "0.25.1" @@ -6636,12 +7079,25 @@ version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b67695cbcf4653f39f8f8738925547e0e23fd9fe315bccf951097b9f6a38781" dependencies = [ - "jsonrpsee-client-transport", - "jsonrpsee-core", - "jsonrpsee-types", + "jsonrpsee-client-transport 0.25.1", + "jsonrpsee-core 0.25.1", + "jsonrpsee-types 0.25.1", "tower 0.5.3", ] +[[package]] +name = "jsonrpsee-ws-client" +version = "0.24.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78fc744f17e7926d57f478cf9ca6e1ee5d8332bf0514860b1a3cdf1742e614cc" +dependencies = [ + "http 1.4.0", + "jsonrpsee-client-transport 0.24.10", + "jsonrpsee-core 0.24.10", + "jsonrpsee-types 0.24.10", + "url", +] + [[package]] name = "jsonrpsee-ws-client" version = "0.25.1" @@ -6649,9 +7105,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da2694c9ff271a9d3ebfe520f6b36820e85133a51be77a3cb549fd615095261" dependencies = [ "http 1.4.0", - "jsonrpsee-client-transport", - "jsonrpsee-core", - "jsonrpsee-types", + "jsonrpsee-client-transport 0.25.1", + "jsonrpsee-core 0.25.1", + "jsonrpsee-types 0.25.1", "tower 0.5.3", "url", ] @@ -6777,6 +7233,16 @@ dependencies = [ "sha3-asm", ] +[[package]] +name = "keccak-hash" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1b8590eb6148af2ea2d75f38e7d29f5ca970d5a4df456b3ef19b8b415d0264" +dependencies = [ + "primitive-types 0.13.1", + "tiny-keccak", +] + [[package]] name = "konst" version = "0.3.16" @@ -6821,7 +7287,7 @@ dependencies = [ "string_cache", "term", "tiny-keccak", - "unicode-xid", + "unicode-xid 0.2.6", "walkdir", ] @@ -6896,7 +7362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a95c68db5d41694cea563c86a4ba4dc02141c16ef64814108cb23def4d5438" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "regex", "syn 2.0.114", ] @@ -6994,12 +7460,14 @@ dependencies = [ "arrayref", "base64 0.22.1", "digest 0.9.0", + "hmac-drbg", "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", "rand 0.8.5", "serde", "sha2 0.9.9", + "typenum", ] [[package]] @@ -7140,7 +7608,7 @@ dependencies = [ "fnv", "lazy_static", "proc-macro2", - "quote", + "quote 1.0.43", "regex-syntax", "syn 2.0.114", ] @@ -7202,6 +7670,15 @@ dependencies = [ "js-sys", ] +[[package]] +name = "lz4" +version = "1.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20b523e860d03443e98350ceaac5e71c6ba89aea7d960769ec3ce37f4de5af4" +dependencies = [ + "lz4-sys", +] + [[package]] name = "lz4-sys" version = "1.11.1+lz4-1.10.0" @@ -7230,7 +7707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -7308,7 +7785,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -7533,6 +8010,38 @@ dependencies = [ "paste", ] +[[package]] +name = "midnight-base-crypto" +version = "1.0.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "anyhow", + "atomic-write-file", + "const-hex", + "ethnum", + "fake", + "ff 0.13.1", + "flate2", + "futures", + "group 0.13.0", + "indicatif", + "k256", + "lazy_static", + "midnight-base-crypto-derive 1.0.0-hard-fork-test", + "midnight-serialize 1.0.0-hard-fork-test", + "pastey 0.1.1", + "rand 0.8.5", + "reqwest 0.12.28", + "serde", + "serde_bytes", + "serde_json", + "sha2 0.10.9", + "signature", + "subtle", + "tracing", + "zeroize", +] + [[package]] name = "midnight-base-crypto" version = "1.0.0-rc.3" @@ -7549,8 +8058,40 @@ dependencies = [ "group 0.13.0", "k256", "lazy_static", - "midnight-base-crypto-derive", - "midnight-serialize", + "midnight-base-crypto-derive 1.0.0-rc.3", + "midnight-serialize 1.0.0-rc.3", + "pastey 0.1.1", + "rand 0.8.5", + "reqwest 0.12.28", + "serde", + "serde_bytes", + "serde_json", + "sha2 0.10.9", + "signature", + "subtle", + "tracing", + "zeroize", +] + +[[package]] +name = "midnight-base-crypto" +version = "1.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "anyhow", + "atomic-write-file", + "const-hex", + "ethnum", + "fake", + "ff 0.13.1", + "flate2", + "futures", + "group 0.13.0", + "indicatif", + "k256", + "lazy_static", + "midnight-base-crypto-derive 1.0.0", + "midnight-serialize 1.0.0", "pastey 0.1.1", "rand 0.8.5", "reqwest 0.12.28", @@ -7564,13 +8105,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "midnight-base-crypto-derive" +version = "1.0.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "proc-macro2", + "quote 1.0.43", + "syn 1.0.109", +] + [[package]] name = "midnight-base-crypto-derive" version = "1.0.0-rc.3" source = "git+https://github.com/dcSpark/midnight-ledger?branch=midnight-l2#6f6a4d6f444099a8e66fe19b97967897cf4a0137" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", + "syn 1.0.109", +] + +[[package]] +name = "midnight-base-crypto-derive" +version = "1.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "proc-macro2", + "quote 1.0.43", "syn 1.0.109", ] @@ -7604,10 +8165,42 @@ source = "git+https://github.com/dcSpark/midnight-ledger?branch=midnight-l2#6f6a dependencies = [ "fake", "lazy_static", - "midnight-base-crypto", - "midnight-serialize", - "midnight-storage", - "midnight-transient-crypto", + "midnight-base-crypto 1.0.0-rc.3", + "midnight-serialize 1.0.0-rc.3", + "midnight-storage 1.1.0-rc.1", + "midnight-transient-crypto 2.0.0-alpha.1", + "rand 0.8.5", + "serde", + "zeroize", +] + +[[package]] +name = "midnight-coin-structure" +version = "2.0.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "fake", + "lazy_static", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-storage 1.1.0-hard-fork-test", + "midnight-transient-crypto 2.0.0-hard-fork-test", + "rand 0.8.5", + "serde", + "zeroize", +] + +[[package]] +name = "midnight-coin-structure" +version = "2.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "fake", + "lazy_static", + "midnight-base-crypto 1.0.0", + "midnight-serialize 1.0.0", + "midnight-storage 1.1.0", + "midnight-transient-crypto 2.0.0", "rand 0.8.5", "serde", "zeroize", @@ -7715,76 +8308,331 @@ dependencies = [ ] [[package]] -name = "midnight-onchain-state" -version = "2.0.0-alpha.1" -source = "git+https://github.com/dcSpark/midnight-ledger?branch=midnight-l2#6f6a4d6f444099a8e66fe19b97967897cf4a0137" +name = "midnight-ledger" +version = "7.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" dependencies = [ + "anyhow", "derive-where", "fake", - "hex", - "midnight-base-crypto", - "midnight-coin-structure", - "midnight-serialize", - "midnight-storage", - "midnight-transient-crypto", + "futures", + "introspection", + "introspection-derive", + "is_sorted", + "itertools 0.14.0", + "lazy_static", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-coin-structure 2.0.0-hard-fork-test", + "midnight-ledger-static 1.0.0-rc.2-hard-fork-test", + "midnight-onchain-runtime 2.0.0-hard-fork-test", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-storage 1.1.0-hard-fork-test", + "midnight-transient-crypto 2.0.0-hard-fork-test", + "midnight-zswap 7.0.0 (git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0)", "rand 0.8.5", + "rayon", + "reqwest 0.12.28", "serde", - "serde_bytes", + "sha2 0.10.9", + "tokio", + "tracing", + "tracing-subscriber 0.3.22", + "zeroize", + "zkir 2.1.0-hard-fork-test", ] [[package]] -name = "midnight-privacy" -version = "0.3.0" +name = "midnight-ledger" +version = "7.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" dependencies = [ "anyhow", - "bech32 0.11.1", - "bincode 1.3.3", - "borsh", - "chacha20poly1305", - "hex", - "hkdf", - "ligero-runner", - "ligetron", - "once_cell", + "derive-where", + "fake", + "futures", + "introspection", + "introspection-derive", + "is_sorted", + "itertools 0.14.0", + "lazy_static", + "midnight-base-crypto 1.0.0", + "midnight-coin-structure 2.0.0", + "midnight-ledger-static 1.0.0-rc.2", + "midnight-onchain-runtime 2.0.0", + "midnight-serialize 1.0.0", + "midnight-storage 1.1.0", + "midnight-transient-crypto 2.0.0", + "midnight-zswap 7.0.0 (git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0)", + "rand 0.8.5", "rayon", - "schemars 0.8.22", - "sea-orm", + "reqwest 0.12.28", "serde", - "serde_json", "sha2 0.10.9", - "sov-address", - "sov-bank", - "sov-kernels", - "sov-ligero-adapter", - "sov-midnight-da", - "sov-mock-da", - "sov-modules-api", - "sov-rollup-interface", - "sov-state", - "sov-test-utils", - "tempfile", - "thiserror 1.0.69", "tokio", "tracing", - "x25519-dalek", + "tracing-subscriber 0.3.22", + "zeroize", + "zkir 2.1.0", ] [[package]] -name = "midnight-proof-pool-service" -version = "0.3.0" +name = "midnight-ledger-static" +version = "1.0.0-rc.2" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" dependencies = [ - "anyhow", - "axum 0.7.9", - "dotenvy", - "hex", - "mcp-external", - "midnight-privacy", - "rand 0.8.5", - "reqwest 0.12.28", - "rusqlite", - "serde", - "serde_json", - "sov-bank", + "proc-macro2", + "quote 1.0.43", +] + +[[package]] +name = "midnight-ledger-static" +version = "1.0.0-rc.2-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "proc-macro2", + "quote 1.0.43", +] + +[[package]] +name = "midnight-node-ledger-helpers" +version = "0.1.0" +source = "git+https://github.com/midnightntwrk/midnight-node?rev=c0e000e5#c0e000e58a56c078171ebbfe366b821b1dc3f932" +dependencies = [ + "async-trait", + "bech32 0.11.1", + "bip32", + "bip39", + "derive-where", + "futures", + "hex", + "itertools 0.14.0", + "lazy_static", + "midnight-base-crypto 1.0.0", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-coin-structure 2.0.0", + "midnight-coin-structure 2.0.0-hard-fork-test", + "midnight-ledger 7.0.0 (git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0)", + "midnight-ledger 7.0.0 (git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0)", + "midnight-onchain-runtime 2.0.0", + "midnight-onchain-runtime 2.0.0-hard-fork-test", + "midnight-serialize 1.0.0", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-storage 1.1.0", + "midnight-storage 1.1.0-hard-fork-test", + "midnight-transient-crypto 2.0.0", + "midnight-transient-crypto 2.0.0-hard-fork-test", + "midnight-zswap 7.0.0 (git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0)", + "midnight-zswap 7.0.0 (git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0)", + "rand 0.8.5", + "serde", + "subxt", + "subxt-signer", + "thiserror 1.0.69", + "tokio", + "toml 0.9.11+spec-1.1.0", + "zkir 2.1.0", + "zkir 2.1.0-hard-fork-test", +] + +[[package]] +name = "midnight-onchain-runtime" +version = "2.0.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "derive-where", + "enum_index", + "enum_index_derive", + "fake", + "hex", + "konst", + "lazy_static", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-coin-structure 2.0.0-hard-fork-test", + "midnight-onchain-state 2.0.0-hard-fork-test", + "midnight-onchain-vm 1.0.1-hard-fork-test", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-storage 1.1.0-hard-fork-test", + "midnight-transient-crypto 2.0.0-hard-fork-test", + "rand 0.8.5", + "serde", + "serde_bytes", + "tracing", +] + +[[package]] +name = "midnight-onchain-runtime" +version = "2.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "derive-where", + "enum_index", + "enum_index_derive", + "fake", + "hex", + "konst", + "lazy_static", + "midnight-base-crypto 1.0.0", + "midnight-coin-structure 2.0.0", + "midnight-onchain-state 2.0.0", + "midnight-onchain-vm 1.0.1", + "midnight-serialize 1.0.0", + "midnight-storage 1.1.0", + "midnight-transient-crypto 2.0.0", + "rand 0.8.5", + "serde", + "serde_bytes", + "tracing", +] + +[[package]] +name = "midnight-onchain-state" +version = "2.0.0-alpha.1" +source = "git+https://github.com/dcSpark/midnight-ledger?branch=midnight-l2#6f6a4d6f444099a8e66fe19b97967897cf4a0137" +dependencies = [ + "derive-where", + "fake", + "hex", + "midnight-base-crypto 1.0.0-rc.3", + "midnight-coin-structure 2.0.0-alpha.1", + "midnight-serialize 1.0.0-rc.3", + "midnight-storage 1.1.0-rc.1", + "midnight-transient-crypto 2.0.0-alpha.1", + "rand 0.8.5", + "serde", + "serde_bytes", +] + +[[package]] +name = "midnight-onchain-state" +version = "2.0.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "derive-where", + "fake", + "hex", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-coin-structure 2.0.0-hard-fork-test", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-storage 1.1.0-hard-fork-test", + "midnight-transient-crypto 2.0.0-hard-fork-test", + "rand 0.8.5", + "serde", + "serde_bytes", +] + +[[package]] +name = "midnight-onchain-state" +version = "2.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "derive-where", + "fake", + "hex", + "midnight-base-crypto 1.0.0", + "midnight-coin-structure 2.0.0", + "midnight-serialize 1.0.0", + "midnight-storage 1.1.0", + "midnight-transient-crypto 2.0.0", + "rand 0.8.5", + "serde", + "serde_bytes", +] + +[[package]] +name = "midnight-onchain-vm" +version = "1.0.1-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "derive-where", + "fake", + "hex", + "konst", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-coin-structure 2.0.0-hard-fork-test", + "midnight-onchain-state 2.0.0-hard-fork-test", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-storage 1.1.0-hard-fork-test", + "midnight-transient-crypto 2.0.0-hard-fork-test", + "rand 0.8.5", + "rpds", + "serde", + "serde_bytes", +] + +[[package]] +name = "midnight-onchain-vm" +version = "1.0.1" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "derive-where", + "fake", + "hex", + "konst", + "midnight-base-crypto 1.0.0", + "midnight-coin-structure 2.0.0", + "midnight-onchain-state 2.0.0", + "midnight-serialize 1.0.0", + "midnight-storage 1.1.0", + "midnight-transient-crypto 2.0.0", + "rand 0.8.5", + "rpds", + "serde", + "serde_bytes", +] + +[[package]] +name = "midnight-privacy" +version = "0.3.0" +dependencies = [ + "anyhow", + "bech32 0.11.1", + "bincode 1.3.3", + "borsh", + "chacha20poly1305", + "hex", + "hkdf", + "ligero-runner", + "ligetron", + "once_cell", + "rayon", + "schemars 0.8.22", + "sea-orm", + "serde", + "serde_json", + "sha2 0.10.9", + "sov-address", + "sov-bank", + "sov-kernels", + "sov-ligero-adapter", + "sov-midnight-da", + "sov-mock-da", + "sov-modules-api", + "sov-rollup-interface", + "sov-state", + "sov-test-utils", + "tempfile", + "thiserror 1.0.69", + "tokio", + "tracing", + "x25519-dalek", +] + +[[package]] +name = "midnight-proof-pool-service" +version = "0.3.0" +dependencies = [ + "anyhow", + "axum 0.7.9", + "dotenvy", + "hex", + "mcp-external", + "midnight-privacy", + "rand 0.8.5", + "reqwest 0.12.28", + "rusqlite", + "serde", + "serde_json", + "sov-bank", "sov-ligero-adapter", "sov-modules-api", "sov-proof-verifier-service", @@ -7815,6 +8663,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "midnight-serialize" +version = "1.0.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "crypto", + "konst", + "lazy_static", + "midnight-serialize-macros 1.0.0-hard-fork-test", + "serde", + "serde_bytes", +] + [[package]] name = "midnight-serialize" version = "1.0.0-rc.3" @@ -7823,21 +8684,79 @@ dependencies = [ "crypto", "konst", "lazy_static", - "midnight-serialize-macros", + "midnight-serialize-macros 1.0.0-rc.3", + "serde", + "serde_bytes", +] + +[[package]] +name = "midnight-serialize" +version = "1.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "crypto", + "konst", + "lazy_static", + "midnight-serialize-macros 1.0.0", "serde", "serde_bytes", ] +[[package]] +name = "midnight-serialize-macros" +version = "1.0.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "proc-macro2", + "quote 1.0.43", + "syn 2.0.114", +] + [[package]] name = "midnight-serialize-macros" version = "1.0.0-rc.3" source = "git+https://github.com/dcSpark/midnight-ledger?branch=midnight-l2#6f6a4d6f444099a8e66fe19b97967897cf4a0137" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", + "syn 2.0.114", +] + +[[package]] +name = "midnight-serialize-macros" +version = "1.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "proc-macro2", + "quote 1.0.43", "syn 2.0.114", ] +[[package]] +name = "midnight-storage" +version = "1.1.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "archery", + "crypto", + "derive-where", + "fake", + "hex", + "itertools 0.14.0", + "konst", + "lru 0.16.3", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-storage-macros 1.0.0-hard-fork-test", + "parity-db", + "parking_lot", + "rand 0.8.5", + "serde", + "sha2 0.10.9", + "sysinfo 0.34.2", + "tempfile", +] + [[package]] name = "midnight-storage" version = "1.1.0-rc.1" @@ -7851,9 +8770,9 @@ dependencies = [ "itertools 0.14.0", "konst", "lru 0.16.3", - "midnight-base-crypto", - "midnight-serialize", - "midnight-storage-macros", + "midnight-base-crypto 1.0.0-rc.3", + "midnight-serialize 1.0.0-rc.3", + "midnight-storage-macros 1.0.0-rc.3", "parking_lot", "rand 0.8.5", "serde", @@ -7862,14 +8781,61 @@ dependencies = [ "tempfile", ] +[[package]] +name = "midnight-storage" +version = "1.1.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "archery", + "crypto", + "derive-where", + "fake", + "hex", + "itertools 0.14.0", + "konst", + "lru 0.16.3", + "midnight-base-crypto 1.0.0", + "midnight-serialize 1.0.0", + "midnight-storage-macros 1.0.0", + "parity-db", + "parking_lot", + "rand 0.8.5", + "serde", + "sha2 0.10.9", + "sysinfo 0.34.2", + "tempfile", +] + +[[package]] +name = "midnight-storage-macros" +version = "1.0.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "midnight-serialize-macros 1.0.0-hard-fork-test", + "proc-macro2", + "quote 1.0.43", + "syn 2.0.114", +] + [[package]] name = "midnight-storage-macros" version = "1.0.0-rc.3" source = "git+https://github.com/dcSpark/midnight-ledger?branch=midnight-l2#6f6a4d6f444099a8e66fe19b97967897cf4a0137" dependencies = [ - "midnight-serialize-macros", + "midnight-serialize-macros 1.0.0-rc.3", "proc-macro2", - "quote", + "quote 1.0.43", + "syn 2.0.114", +] + +[[package]] +name = "midnight-storage-macros" +version = "1.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "midnight-serialize-macros 1.0.0", + "proc-macro2", + "quote 1.0.43", "syn 2.0.114", ] @@ -7890,13 +8856,85 @@ dependencies = [ "k256", "lazy_static", "lru 0.16.3", - "midnight-base-crypto", - "midnight-base-crypto-derive", + "midnight-base-crypto 1.0.0-rc.3", + "midnight-base-crypto-derive 1.0.0-rc.3", + "midnight-circuits", + "midnight-curves", + "midnight-proofs", + "midnight-serialize 1.0.0-rc.3", + "midnight-storage 1.1.0-rc.1", + "midnight-zk-stdlib", + "pastey 0.1.1", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_json", + "sha2 0.10.9", + "signature", + "tracing", + "zeroize", +] + +[[package]] +name = "midnight-transient-crypto" +version = "2.0.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "anyhow", + "blake2b_simd", + "const-hex", + "derive-where", + "fake", + "ff 0.13.1", + "flate2", + "futures", + "group 0.13.0", + "k256", + "lazy_static", + "lru 0.16.3", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-base-crypto-derive 1.0.0-hard-fork-test", "midnight-circuits", "midnight-curves", "midnight-proofs", - "midnight-serialize", - "midnight-storage", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-storage 1.1.0-hard-fork-test", + "midnight-zk-stdlib", + "pastey 0.1.1", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_json", + "sha2 0.10.9", + "signature", + "tracing", + "zeroize", +] + +[[package]] +name = "midnight-transient-crypto" +version = "2.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "anyhow", + "blake2b_simd", + "const-hex", + "derive-where", + "fake", + "ff 0.13.1", + "flate2", + "futures", + "group 0.13.0", + "k256", + "lazy_static", + "lru 0.16.3", + "midnight-base-crypto 1.0.0", + "midnight-base-crypto-derive 1.0.0", + "midnight-circuits", + "midnight-curves", + "midnight-proofs", + "midnight-serialize 1.0.0", + "midnight-storage 1.1.0", "midnight-zk-stdlib", "pastey 0.1.1", "rand 0.8.5", @@ -7931,6 +8969,54 @@ dependencies = [ "sha3-circuit", ] +[[package]] +name = "midnight-zswap" +version = "7.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "derive-where", + "fake", + "futures", + "is_sorted", + "itertools 0.14.0", + "lazy_static", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-coin-structure 2.0.0-hard-fork-test", + "midnight-ledger-static 1.0.0-rc.2-hard-fork-test", + "midnight-onchain-runtime 2.0.0-hard-fork-test", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-storage 1.1.0-hard-fork-test", + "midnight-transient-crypto 2.0.0-hard-fork-test", + "rand 0.8.5", + "serde", + "tracing", + "zeroize", +] + +[[package]] +name = "midnight-zswap" +version = "7.0.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "derive-where", + "fake", + "futures", + "is_sorted", + "itertools 0.14.0", + "lazy_static", + "midnight-base-crypto 1.0.0", + "midnight-coin-structure 2.0.0", + "midnight-ledger-static 1.0.0-rc.2", + "midnight-onchain-runtime 2.0.0", + "midnight-serialize 1.0.0", + "midnight-storage 1.1.0", + "midnight-transient-crypto 2.0.0", + "rand 0.8.5", + "serde", + "tracing", + "zeroize", +] + [[package]] name = "miette" version = "7.6.0" @@ -7949,7 +9035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -8034,7 +9120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -8058,6 +9144,12 @@ dependencies = [ "tempfile", ] +[[package]] +name = "multi-stash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" + [[package]] name = "multibase" version = "0.9.2" @@ -8180,6 +9272,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5b0c77c1b780822bc749a33e39aeb2c07584ab93332303babeabb645298a76e" +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -8188,12 +9286,21 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "nom" -version = "7.1.3" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" dependencies = [ "memchr", - "minimal-lexical", ] [[package]] @@ -8230,7 +9337,7 @@ name = "nomt-core" version = "1.0.0-preview" source = "git+https://github.com/thrumdev/nomt.git?rev=ff4491440d401f32e18fe91041c4344b2bacb068#ff4491440d401f32e18fe91041c4344b2bacb068" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "bitvec", "borsh", "digest 0.10.7", @@ -8336,7 +9443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -8347,7 +9454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -8444,7 +9551,7 @@ checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -8456,7 +9563,7 @@ checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -8531,7 +9638,7 @@ checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" dependencies = [ "flate2", "memchr", - "ruzstd", + "ruzstd 0.6.0", ] [[package]] @@ -8604,7 +9711,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "auto_impl", "bytes", "ethereum-types", @@ -8619,7 +9726,7 @@ checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" dependencies = [ "bytes", "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -8656,7 +9763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -8845,7 +9952,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "proc-macro2-diagnostics", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -9133,13 +10240,34 @@ dependencies = [ "group 0.13.0", ] +[[package]] +name = "parity-db" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6985a45b0597d68448dac9db2907f9f72bbaf63fe3383d4ba15f99096c87212f" +dependencies = [ + "blake2", + "crc32fast", + "fs2", + "hex", + "libc", + "log", + "lz4", + "memmap2", + "parking_lot", + "rand 0.9.2", + "siphasher", + "snap", + "winapi", +] + [[package]] name = "parity-scale-codec" version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "bitvec", "byte-slice-cast", "const_format", @@ -9157,7 +10285,7 @@ checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -9208,7 +10336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "regex", "regex-syntax", "structmeta", @@ -9226,6 +10354,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "pasta_curves" version = "0.4.1" @@ -9293,8 +10432,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ "digest 0.10.7", - "hmac", - "password-hash", + "hmac 0.12.1", + "password-hash 0.4.2", "sha2 0.10.9", ] @@ -9305,7 +10444,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", - "hmac", + "hmac 0.12.1", + "password-hash 0.5.0", ] [[package]] @@ -9421,7 +10561,7 @@ dependencies = [ "phf_generator", "phf_shared", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -9485,7 +10625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -9501,6 +10641,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkcs1" version = "0.7.5" @@ -9562,6 +10713,20 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + [[package]] name = "poly1305" version = "0.8.0" @@ -9693,11 +10858,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", - "impl-codec", + "impl-codec 0.6.0", "impl-rlp", - "impl-serde", + "impl-serde 0.4.0", + "scale-info", + "uint 0.9.5", +] + +[[package]] +name = "primitive-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" +dependencies = [ + "fixed-hash", + "impl-codec 0.7.1", + "impl-serde 0.5.0", "scale-info", - "uint", + "uint 0.10.0", ] [[package]] @@ -9727,7 +10905,7 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", "version_check", ] @@ -9739,7 +10917,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "version_check", ] @@ -9750,7 +10928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", ] [[package]] @@ -9761,7 +10939,7 @@ checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ "proc-macro-error-attr2", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -9781,7 +10959,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", "version_check", "yansi 1.0.1", @@ -9824,7 +11002,7 @@ dependencies = [ "indexmap 2.13.0", "openapiv3", "proc-macro2", - "quote", + "quote 1.0.43", "regex", "schemars 0.8.22", "serde", @@ -9844,7 +11022,7 @@ dependencies = [ "openapiv3", "proc-macro2", "progenitor-impl", - "quote", + "quote 1.0.43", "schemars 0.8.22", "serde", "serde_json", @@ -9917,7 +11095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -9928,7 +11106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -9981,7 +11159,7 @@ dependencies = [ "anyhow", "itertools 0.14.0", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -9994,7 +11172,7 @@ dependencies = [ "anyhow", "itertools 0.14.0", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -10154,6 +11332,12 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" + [[package]] name = "quote" version = "1.0.43" @@ -10386,7 +11570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -10586,7 +11770,7 @@ source = "git+https://github.com/paradigmxyz/reth?tag=v1.7.0#9d56da53ec0ad60e229 dependencies = [ "convert_case 0.7.1", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -10993,7 +12177,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac", + "hmac 0.12.1", "subtle", ] @@ -11396,7 +12580,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -11440,7 +12624,7 @@ checksum = "c75d0a62676bf8c8003c4e3c348e2ceb6a7b3e48323681aaf177fdccdac2ce50" dependencies = [ "darling 0.21.3", "proc-macro2", - "quote", + "quote 1.0.43", "serde_json", "syn 2.0.114", ] @@ -11479,6 +12663,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" +[[package]] +name = "rpds" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd6ce569b15c331b1e5fd8cf6adb0bf240678b5f0cdc4d0f41e11683f6feba9" +dependencies = [ + "archery", +] + [[package]] name = "rrs-lib" version = "0.1.0" @@ -11551,7 +12744,7 @@ dependencies = [ "num-integer", "num-traits", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "proptest", "rand 0.8.5", "rand 0.9.2", @@ -11600,7 +12793,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da0902e4c7c8e997159ab384e6d0fc91c221375f6894346ae107f47dd0f3ccaa" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "rust-embed-utils", "syn 2.0.114", "walkdir", @@ -11622,7 +12815,7 @@ version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61f703d19852dbf87cbc513643fa81428361eb6940f1ac14fd58155d295a3eb0" dependencies = [ - "arrayvec", + "arrayvec 0.7.6", "num-traits", "serde", ] @@ -11831,6 +13024,12 @@ dependencies = [ "twox-hash 1.6.3", ] +[[package]] +name = "ruzstd" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ff0cc5e135c8870a775d3320910cd9b564ec036b4dc0b8741629020be63f01" + [[package]] name = "ryu" version = "1.0.22" @@ -11870,16 +13069,85 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-bits" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27243ab0d2d6235072b017839c5f0cd1a3b1ce45c0f7a715363b0c7d36c76c94" +dependencies = [ + "parity-scale-codec", + "scale-info", + "scale-type-resolver", + "serde", +] + +[[package]] +name = "scale-decode" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d6ed61699ad4d54101ab5a817169259b5b0efc08152f8632e61482d8a27ca3d" +dependencies = [ + "parity-scale-codec", + "primitive-types 0.13.1", + "scale-bits", + "scale-decode-derive", + "scale-type-resolver", + "smallvec", + "thiserror 2.0.17", +] + +[[package]] +name = "scale-decode-derive" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65cb245f7fdb489e7ba43a616cbd34427fe3ba6fe0edc1d0d250085e6c84f3ec" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote 1.0.43", + "syn 2.0.114", +] + +[[package]] +name = "scale-encode" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2a976d73564a59e482b74fd5d95f7518b79ca8c8ca5865398a4d629dd15ee50" +dependencies = [ + "parity-scale-codec", + "primitive-types 0.13.1", + "scale-bits", + "scale-encode-derive", + "scale-type-resolver", + "smallvec", + "thiserror 2.0.17", +] + +[[package]] +name = "scale-encode-derive" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17020f2d59baabf2ddcdc20a4e567f8210baf089b8a8d4785f5fd5e716f92038" +dependencies = [ + "darling 0.20.11", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote 1.0.43", + "syn 2.0.114", +] + [[package]] name = "scale-info" version = "2.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" dependencies = [ + "bitvec", "cfg-if", "derive_more 1.0.0", "parity-scale-codec", "scale-info-derive", + "serde", ] [[package]] @@ -11890,8 +13158,50 @@ checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", - "quote", + "quote 1.0.43", + "syn 2.0.114", +] + +[[package]] +name = "scale-type-resolver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" +dependencies = [ + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-typegen" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c61b6b706a3eaad63b506ab50a1d2319f817ae01cf753adcc3f055f9f0fcd6" +dependencies = [ + "proc-macro2", + "quote 1.0.43", + "scale-info", "syn 2.0.114", + "thiserror 2.0.17", +] + +[[package]] +name = "scale-value" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3b64809a541e8d5a59f7a9d67cc700cdf5d7f907932a83a0afdedc90db07ccb" +dependencies = [ + "base58", + "blake2", + "either", + "parity-scale-codec", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-type-resolver", + "serde", + "thiserror 2.0.17", + "yap", ] [[package]] @@ -11959,7 +13269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "serde_derive_internals", "syn 2.0.114", ] @@ -11971,11 +13281,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4908ad288c5035a8eb12cfdf0d49270def0a268ee162b75eeee0f85d155a7c45" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "serde_derive_internals", "syn 2.0.114", ] +[[package]] +name = "schnorrkel" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9fcb6c2e176e86ec703e22560d99d65a5ee9056ae45a08e13e84ebf796296f" +dependencies = [ + "aead", + "arrayref", + "arrayvec 0.7.6", + "curve25519-dalek 4.1.3", + "getrandom_or_panic", + "merlin", + "rand_core 0.6.4", + "serde_bytes", + "sha2 0.10.9", + "subtle", + "zeroize", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -11994,12 +13323,24 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" dependencies = [ - "hmac", + "hmac 0.12.1", "pbkdf2 0.11.0", "salsa20", "sha2 0.10.9", ] +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash 0.5.0", + "pbkdf2 0.12.2", + "salsa20", + "sha2 0.10.9", +] + [[package]] name = "sct" version = "0.7.1" @@ -12025,7 +13366,7 @@ dependencies = [ "heck 0.4.1", "proc-macro-error2", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -12067,7 +13408,7 @@ checksum = "84c2e64a50a9cc8339f10a27577e10062c7f995488e469f2c95762c5ee847832" dependencies = [ "heck 0.5.0", "proc-macro2", - "quote", + "quote 1.0.43", "sea-bae", "syn 2.0.114", "unicode-ident", @@ -12112,6 +13453,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "secp256k1-sys 0.8.2", +] + [[package]] name = "secp256k1" version = "0.30.0" @@ -12135,6 +13485,15 @@ dependencies = [ "secp256k1-sys 0.11.0", ] +[[package]] +name = "secp256k1-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4473013577ec77b4ee3668179ef1186df3146e2cf2d927bd200974c6fe60fd99" +dependencies = [ + "cc", +] + [[package]] name = "secp256k1-sys" version = "0.10.1" @@ -12153,6 +13512,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secrecy" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" version = "2.11.1" @@ -12292,7 +13660,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -12303,7 +13671,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -12339,7 +13707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -12368,7 +13736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64060d864397305347a78851c51588fd283767e7e7589829e8121d65512340f1" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "serde", "syn 2.0.114", ] @@ -12413,7 +13781,7 @@ checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ "darling 0.21.3", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -12462,7 +13830,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -12679,15 +14047,128 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] -name = "smallvec" -version = "1.15.1" +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "arbitrary", + "serde", +] + +[[package]] +name = "smol" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + +[[package]] +name = "smoldot" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16e5723359f0048bf64bfdfba64e5732a56847d42c4fd3fe56f18280c813413" +dependencies = [ + "arrayvec 0.7.6", + "async-lock", + "atomic-take", + "base64 0.22.1", + "bip39", + "blake2-rfc", + "bs58", + "chacha20", + "crossbeam-queue", + "derive_more 2.1.1", + "ed25519-zebra", + "either", + "event-listener", + "fnv", + "futures-lite", + "futures-util", + "hashbrown 0.15.5", + "hex", + "hmac 0.12.1", + "itertools 0.14.0", + "libm", + "libsecp256k1", + "merlin", + "nom 8.0.0", + "num-bigint 0.4.6", + "num-rational", + "num-traits", + "pbkdf2 0.12.2", + "pin-project", + "poly1305", + "rand 0.8.5", + "rand_chacha 0.3.1", + "ruzstd 0.8.2", + "schnorrkel", + "serde", + "serde_json", + "sha2 0.10.9", + "sha3", + "siphasher", + "slab", + "smallvec", + "soketto", + "twox-hash 2.1.2", + "wasmi", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "smoldot-light" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "f1bba9e591716567d704a8252feeb2f1261a286e1e2cbdd4e49e9197c34a14e2" dependencies = [ - "arbitrary", + "async-channel", + "async-lock", + "base64 0.22.1", + "blake2-rfc", + "bs58", + "derive_more 2.1.1", + "either", + "event-listener", + "fnv", + "futures-channel", + "futures-lite", + "futures-util", + "hashbrown 0.15.5", + "hex", + "itertools 0.14.0", + "log", + "lru 0.12.5", + "parking_lot", + "pin-project", + "rand 0.8.5", + "rand_chacha 0.3.1", "serde", + "serde_json", + "siphasher", + "slab", + "smol", + "smoldot", + "zeroize", ] +[[package]] +name = "snap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" + [[package]] name = "snowbridge-amcl" version = "1.0.2" @@ -12745,7 +14226,7 @@ dependencies = [ "lalrpop-util", "phf", "thiserror 1.0.69", - "unicode-xid", + "unicode-xid 0.2.6", ] [[package]] @@ -13005,7 +14486,7 @@ dependencies = [ "derive_more 1.0.0", "futures", "hex", - "jsonrpsee", + "jsonrpsee 0.25.1", "nmt-rs", "postcard", "proptest", @@ -13142,7 +14623,7 @@ dependencies = [ "full-node-configs", "futures", "hex", - "jsonrpsee", + "jsonrpsee 0.25.1", "prettytable-rs", "prometheus_exporter", "proptest", @@ -13241,7 +14722,7 @@ dependencies = [ "ethereum-types", "ethers", "futures", - "jsonrpsee", + "jsonrpsee 0.25.1", "reth-primitives", "sov-cli", "sov-modules-api", @@ -13290,7 +14771,7 @@ dependencies = [ "ethereum-types", "ethers", "futures", - "jsonrpsee", + "jsonrpsee 0.25.1", "proptest", "reth-primitives", "serde", @@ -13334,7 +14815,7 @@ dependencies = [ "ethers", "hex", "itertools 0.14.0", - "jsonrpsee", + "jsonrpsee 0.25.1", "jsonschema", "lazy_static", "proptest", @@ -13580,10 +15061,7 @@ version = "0.3.0" dependencies = [ "anyhow", "hex", - "midnight-base-crypto", - "midnight-onchain-state", - "midnight-serialize", - "midnight-storage", + "midnight-node-ledger-helpers", "reqwest 0.12.28", "serde", "serde_json", @@ -13726,7 +15204,7 @@ dependencies = [ "digest 0.10.7", "heck 0.5.0", "hex", - "jsonrpsee", + "jsonrpsee 0.25.1", "nearly-linear", "once_cell", "openapiv3", @@ -13775,10 +15253,10 @@ dependencies = [ "darling 0.20.11", "derive_more 1.0.0", "hex", - "jsonrpsee", + "jsonrpsee 0.25.1", "prettier-please", "proc-macro2", - "quote", + "quote 1.0.43", "schemars 0.8.22", "serde", "sov-address", @@ -13845,7 +15323,7 @@ dependencies = [ "axum 0.7.9", "borsh", "hex", - "jsonrpsee", + "jsonrpsee 0.25.1", "schemars 0.8.22", "serde", "sov-metrics", @@ -14150,13 +15628,13 @@ dependencies = [ "full-node-configs", "futures", "hex", - "jsonrpsee", + "jsonrpsee 0.25.1", "ligero", - "midnight-base-crypto", - "midnight-onchain-state", + "midnight-base-crypto 1.0.0-rc.3", + "midnight-onchain-state 2.0.0-alpha.1", "midnight-privacy", - "midnight-serialize", - "midnight-storage", + "midnight-serialize 1.0.0-rc.3", + "midnight-storage 1.1.0-rc.1", "num_cpus", "prometheus_exporter", "rand 0.8.5", @@ -14223,8 +15701,8 @@ dependencies = [ "alloy-rpc-types", "alloy-sol-types", "alloy-transport", - "jsonrpsee-core", - "jsonrpsee-types", + "jsonrpsee-core 0.25.1", + "jsonrpsee-types 0.25.1", "reth-errors", "reth-primitives-traits", "revm", @@ -14250,7 +15728,7 @@ dependencies = [ "full-node-configs", "futures", "hex", - "jsonrpsee", + "jsonrpsee 0.25.1", "midnight-privacy", "mini-moka", "num_cpus", @@ -14394,7 +15872,7 @@ dependencies = [ "bs58", "derive_more 1.0.0", "hex", - "jsonrpsee", + "jsonrpsee 0.25.1", "reqwest 0.12.28", "schemars 0.8.22", "serde", @@ -14498,7 +15976,7 @@ dependencies = [ "futures-util", "hex", "insta", - "jsonrpsee", + "jsonrpsee 0.25.1", "midnight-privacy", "nmt-rs", "num_cpus", @@ -14710,7 +16188,7 @@ version = "0.1.0" dependencies = [ "alloy-dyn-abi", "alloy-primitives", - "arrayvec", + "arrayvec 0.7.6", "bech32 0.11.1", "borsh", "bs58", @@ -14741,7 +16219,7 @@ dependencies = [ "darling 0.20.11", "hex", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", "syn_derive", ] @@ -14819,6 +16297,20 @@ dependencies = [ "tempfile", ] +[[package]] +name = "sp-crypto-hashing" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9927a7f81334ed5b8a98a4a978c81324d12bd9713ec76b5c68fd410174c5eb" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.9", + "sha3", + "twox-hash 1.6.3", +] + [[package]] name = "sp1" version = "0.3.0" @@ -14983,7 +16475,7 @@ version = "5.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a1ed8d5acbb6cea056401791e79ca3cba7c7d5e17d0d44cd60e117f16b11ca" dependencies = [ - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -15171,7 +16663,7 @@ version = "5.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b190465c0c0377f3cacfac2d0ac8a630adf8e1bfac8416be593753bfa4f668e" dependencies = [ - "quote", + "quote 1.0.43", "syn 1.0.109", ] @@ -15385,7 +16877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "sqlx-core", "sqlx-macros-core", "syn 2.0.114", @@ -15403,7 +16895,7 @@ dependencies = [ "hex", "once_cell", "proc-macro2", - "quote", + "quote 1.0.43", "serde", "serde_json", "sha2 0.10.9", @@ -15439,7 +16931,7 @@ dependencies = [ "generic-array 0.14.7", "hex", "hkdf", - "hmac", + "hmac 0.12.1", "itoa", "log", "md-5", @@ -15478,7 +16970,7 @@ dependencies = [ "futures-util", "hex", "hkdf", - "hmac", + "hmac 0.12.1", "home", "itoa", "log", @@ -15541,7 +17033,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -15593,7 +17085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "structmeta-derive", "syn 2.0.114", ] @@ -15605,7 +17097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -15635,7 +17127,7 @@ checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ "heck 0.5.0", "proc-macro2", - "quote", + "quote 1.0.43", "rustversion", "syn 2.0.114", ] @@ -15648,7 +17140,7 @@ checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ "heck 0.5.0", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -15660,7 +17152,7 @@ checksum = "ec3d08fe7078c57309d5c3d938e50eba95ba1d33b9c3a101a8465fc6861a5416" dependencies = [ "heck 0.5.0", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -15702,6 +17194,202 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" +[[package]] +name = "subxt" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e689b7f5635ffd08301b1b7d427300f7c10bc0e66069c4068d36ce6921bc736" +dependencies = [ + "async-trait", + "derive-where", + "either", + "frame-metadata", + "futures", + "hex", + "jsonrpsee 0.24.10", + "parity-scale-codec", + "primitive-types 0.13.1", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-crypto-hashing", + "subxt-core", + "subxt-lightclient", + "subxt-macro", + "subxt-metadata", + "subxt-rpcs", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "tracing", + "url", + "wasm-bindgen-futures", + "web-time", +] + +[[package]] +name = "subxt-codegen" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740eedc385673e6c5e0de60d2ea6d12d311359d3ccea35b86b9161e3acaf938f" +dependencies = [ + "heck 0.5.0", + "parity-scale-codec", + "proc-macro2", + "quote 1.0.43", + "scale-info", + "scale-typegen", + "subxt-metadata", + "syn 2.0.114", + "thiserror 2.0.17", +] + +[[package]] +name = "subxt-core" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f2f40f6145c1805e37339c4e460c4a18fcafae913b15d2c648b7cac991fd903" +dependencies = [ + "base58", + "blake2", + "derive-where", + "frame-decode", + "frame-metadata", + "hashbrown 0.14.5", + "hex", + "impl-serde 0.5.0", + "keccak-hash", + "parity-scale-codec", + "primitive-types 0.13.1", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-crypto-hashing", + "subxt-metadata", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "subxt-lightclient" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61321269d3dcc65b8f884eb4d10e393f7bca22b0688d373a0285d4e8ad7221be" +dependencies = [ + "futures", + "futures-util", + "serde", + "serde_json", + "smoldot-light", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "subxt-macro" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efc6c5054278308a2b01804f00676ece77270a358a2caee6df1358cf81ec0cd5" +dependencies = [ + "darling 0.20.11", + "parity-scale-codec", + "proc-macro-error2", + "quote 1.0.43", + "scale-typegen", + "subxt-codegen", + "subxt-metadata", + "subxt-utils-fetchmetadata", + "syn 2.0.114", +] + +[[package]] +name = "subxt-metadata" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc80c07a71e180a42ba0f12727b1f9f39bf03746df6d546d24edbbc137f64fa1" +dependencies = [ + "frame-decode", + "frame-metadata", + "hashbrown 0.14.5", + "parity-scale-codec", + "scale-info", + "sp-crypto-hashing", + "thiserror 2.0.17", +] + +[[package]] +name = "subxt-rpcs" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fe65228472ea5a6bd23d8f2cd12833706466d2425805b2a38ecedc258df141a" +dependencies = [ + "derive-where", + "frame-metadata", + "futures", + "hex", + "impl-serde 0.5.0", + "jsonrpsee 0.24.10", + "parity-scale-codec", + "primitive-types 0.13.1", + "serde", + "serde_json", + "subxt-core", + "subxt-lightclient", + "thiserror 2.0.17", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "subxt-signer" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "963a6b53626fabc94544fdd64b03b639d5b9762efcd52e417d5292b119622a15" +dependencies = [ + "base64 0.22.1", + "bip39", + "cfg-if", + "crypto_secretbox", + "hex", + "hmac 0.12.1", + "parity-scale-codec", + "pbkdf2 0.12.2", + "regex", + "schnorrkel", + "scrypt 0.11.0", + "secp256k1 0.30.0", + "secrecy", + "serde", + "serde_json", + "sha2 0.10.9", + "sp-crypto-hashing", + "subxt-core", + "thiserror 2.0.17", + "zeroize", +] + +[[package]] +name = "subxt-utils-fetchmetadata" +version = "0.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ed947c63b4620429465c9f7e1f346433ddc21780c4bfcfade1e3a4dcdfab8" +dependencies = [ + "hex", + "parity-scale-codec", + "thiserror 2.0.17", +] + [[package]] name = "svm-rs" version = "0.3.5" @@ -15731,6 +17419,17 @@ dependencies = [ "toml_edit 0.22.27", ] +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +dependencies = [ + "quote 0.3.15", + "synom", + "unicode-xid 0.0.4", +] + [[package]] name = "syn" version = "1.0.109" @@ -15738,7 +17437,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "unicode-ident", ] @@ -15749,7 +17448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "unicode-ident", ] @@ -15761,7 +17460,7 @@ checksum = "5f92d01b5de07eaf324f7fca61cc6bd3d82bbc1de5b6c963e6fe79e86f36580d" dependencies = [ "paste", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -15773,7 +17472,7 @@ checksum = "cdb066a04799e45f5d582e8fc6ec8e6d6896040d00898eb4e6a835196815b219" dependencies = [ "proc-macro-error2", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -15792,6 +17491,15 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +dependencies = [ + "unicode-xid 0.0.4", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -15799,7 +17507,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -16023,7 +17731,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -16035,7 +17743,7 @@ checksum = "43b12f9683de37f9980e485167ee624bfaa0b6b04da661e98e25ef9c2669bc1b" dependencies = [ "derive-ex", "proc-macro2", - "quote", + "quote 1.0.43", "structmeta", "syn 2.0.114", ] @@ -16103,7 +17811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -16114,7 +17822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -16261,7 +17969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -16680,7 +18388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -16812,7 +18520,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -17000,6 +18708,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", + "digest 0.10.7", + "rand 0.8.5", "static_assertions", ] @@ -17044,7 +18754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27a7a9b72ba121f6f1f6c3632b85604cac41aedb5ddc70accbebb6cac83de846" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -17082,7 +18792,7 @@ dependencies = [ "heck 0.5.0", "log", "proc-macro2", - "quote", + "quote 1.0.43", "regress 0.10.5", "schemars 0.8.22", "semver 1.0.27", @@ -17100,7 +18810,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "785e2cdcef0df8160fdd762ed548a637aaec1e83704fdbc14da0df66013ee8d0" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "schemars 0.8.22", "semver 1.0.27", "serde", @@ -17129,6 +18839,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "ulid" version = "1.2.1" @@ -17196,6 +18918,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -17370,7 +19098,7 @@ checksum = "20c24e8ab68ff9ee746aad22d39b5535601e6416d1b0feeabf78be986a5c4392" dependencies = [ "proc-macro-error", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -17380,7 +19108,7 @@ version = "5.0.0-beta.0" source = "git+https://github.com/juhaku/utoipa.git?rev=a985d8c1340f80ab69b2b0e5de799df98d567732#a985d8c1340f80ab69b2b0e5de799df98d567732" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "regex", "syn 2.0.114", ] @@ -17463,7 +19191,7 @@ dependencies = [ "once_cell", "proc-macro-error", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -17588,7 +19316,7 @@ version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ - "quote", + "quote 1.0.43", "wasm-bindgen-macro-support", ] @@ -17600,7 +19328,7 @@ checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ "bumpalo", "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", "wasm-bindgen-shared", ] @@ -17627,6 +19355,56 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmi" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19af97fcb96045dd1d6b4d23e2b4abdbbe81723dbc5c9f016eb52145b320063" +dependencies = [ + "arrayvec 0.7.6", + "multi-stash", + "smallvec", + "spin 0.9.8", + "wasmi_collections", + "wasmi_core", + "wasmi_ir", + "wasmparser", +] + +[[package]] +name = "wasmi_collections" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e80d6b275b1c922021939d561574bf376613493ae2b61c6963b15db0e8813562" + +[[package]] +name = "wasmi_core" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8c51482cc32d31c2c7ff211cd2bedd73c5bd057ba16a2ed0110e7a96097c33" +dependencies = [ + "downcast-rs", + "libm", +] + +[[package]] +name = "wasmi_ir" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e431a14c186db59212a88516788bd68ed51f87aa1e08d1df742522867b5289a" +dependencies = [ + "wasmi_core", +] + +[[package]] +name = "wasmparser" +version = "0.221.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d06bfa36ab3ac2be0dee563380147a5b81ba10dd8885d7fbbc9eb574be67d185" +dependencies = [ + "bitflags 2.10.0", +] + [[package]] name = "wasmtimer" version = "0.4.3" @@ -17805,7 +19583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -17816,7 +19594,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -17827,7 +19605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -17838,7 +19616,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -18340,6 +20118,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" +[[package]] +name = "yap" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe269e7b803a5e8e20cbd97860e136529cd83bf2c9c6d37b142467e7e1f051f" + [[package]] name = "yasna" version = "0.4.0" @@ -18367,7 +20151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", "synstructure", ] @@ -18388,7 +20172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -18408,7 +20192,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", "synstructure", ] @@ -18429,7 +20213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -18462,7 +20246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.43", "syn 2.0.114", ] @@ -18479,7 +20263,7 @@ dependencies = [ "crc32fast", "crossbeam-utils", "flate2", - "hmac", + "hmac 0.12.1", "pbkdf2 0.11.0", "sha1", "time", @@ -18530,6 +20314,52 @@ dependencies = [ "subtle", ] +[[package]] +name = "zkir" +version = "2.1.0-hard-fork-test" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=hard-fork-test-ledger-7.0.0#c567cd4a584ed8b04b4f466c2555be062f7f9c7f" +dependencies = [ + "anyhow", + "const-hex", + "group 0.13.0", + "hex", + "midnight-base-crypto 1.0.0-hard-fork-test", + "midnight-circuits", + "midnight-proofs", + "midnight-serialize 1.0.0-hard-fork-test", + "midnight-transient-crypto 2.0.0-hard-fork-test", + "midnight-zk-stdlib", + "rand 0.8.5", + "rand_chacha 0.3.1", + "serde", + "serde_bytes", + "serde_json", + "tracing", +] + +[[package]] +name = "zkir" +version = "2.1.0" +source = "git+https://github.com/midnightntwrk/midnight-ledger?tag=ledger-7.0.0#8f2ed5c0954770e84b43c5dbb64ecb880d3e9e78" +dependencies = [ + "anyhow", + "const-hex", + "group 0.13.0", + "hex", + "midnight-base-crypto 1.0.0", + "midnight-circuits", + "midnight-proofs", + "midnight-serialize 1.0.0", + "midnight-transient-crypto 2.0.0", + "midnight-zk-stdlib", + "rand 0.8.5", + "rand_chacha 0.3.1", + "serde", + "serde_bytes", + "serde_json", + "tracing", +] + [[package]] name = "zmij" version = "1.0.14" diff --git a/crates/adapters/midnight-da/benches/concurrent_access.rs b/crates/adapters/midnight-da/benches/concurrent_access.rs index 3e8d40c22..42c4e56bb 100644 --- a/crates/adapters/midnight-da/benches/concurrent_access.rs +++ b/crates/adapters/midnight-da/benches/concurrent_access.rs @@ -49,6 +49,7 @@ fn bench_storable_midnight_da_service(c: &mut Criterion) { receiver.clone(), ) .await; + da_service.spawn_background_tasks(receiver.clone()).await; let mut handles = vec![]; diff --git a/crates/adapters/midnight-da/src/storable/service.rs b/crates/adapters/midnight-da/src/storable/service.rs index a9ac4fdc4..e17b37980 100644 --- a/crates/adapters/midnight-da/src/storable/service.rs +++ b/crates/adapters/midnight-da/src/storable/service.rs @@ -268,8 +268,11 @@ impl StorableMidnightDaService { Some(da_layer) => da_layer.clone(), }; - // For read-only replicas, spawn a background task to poll for new blocks - // added by the primary node to the shared database. + // Read-only replicas still need an eager background poller because they + // don't produce blocks themselves. For writable nodes the periodic block + // producer is started later via `spawn_background_tasks` so that callers + // can perform one-time work (genesis init, contract deployment) without + // accumulating a DA block backlog. let handle = if config.readonly_mode { let poll_interval = Duration::from_millis(config.readonly_poll_interval_ms.unwrap_or(1000)); @@ -279,9 +282,7 @@ impl StorableMidnightDaService { poll_interval, )) } else { - config - .block_producing - .spawn_block_producing_if_needed(shutdown_receiver, da_layer.clone()) + None }; Self::construct( @@ -637,6 +638,14 @@ impl DaService for StorableMidnightDaService { self.block_producer_handle.lock().await.take() } + async fn spawn_background_tasks( + &self, + shutdown_receiver: tokio::sync::watch::Receiver<()>, + ) -> Option> { + self.block_producing + .spawn_block_producing_if_needed(shutdown_receiver, self.da_layer.clone()) + } + async fn get_signer(&self) -> ::Address { self.sequencer_da_address } diff --git a/crates/full-node/full-node-configs/src/sequencer.rs b/crates/full-node/full-node-configs/src/sequencer.rs index 8f20da67c..5a8004d92 100644 --- a/crates/full-node/full-node-configs/src/sequencer.rs +++ b/crates/full-node/full-node-configs/src/sequencer.rs @@ -27,11 +27,42 @@ pub struct TEEConfiguration { pub tee_attestation_oracle_url: String, /// Optional base URL of the Bridge executor service (HTTP). When set, the TEE manager will call /// POST /commit-batch and POST /build-signatures, POST /finalize-batch to submit L1 batch lifecycle. + /// Ignored when `l1_bridge` is configured (the rollup manages the executor itself). #[serde(default)] pub executor_url: Option, /// Optional rollup ID (64 hex chars) for BatchPublicDataV1Full. Required when executor_url is set. #[serde(default)] pub rollup_id_hex: Option, + /// Managed L1 Bridge lifecycle. When present, the rollup auto-deploys the Bridge contract on + /// genesis and spawns the executor service as a child process. When absent, legacy behaviour + /// applies (manual executor via `executor_url`, or no L1 interactions at all). + #[serde(default)] + pub l1_bridge: Option, +} + +/// Configuration for rollup-managed L1 Bridge contract deployment and executor service. +#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)] +pub struct L1BridgeConfig { + /// Path to the bridge-cli directory (contains `src/cli.ts` and `src/executor-server.ts`). + /// Relative paths are resolved from the rollup config file location. + pub bridge_cli_path: PathBuf, + /// Midnight network name passed to bridge-cli (`"undeployed"` for local, `"preview"` for testnet). + pub network: String, + /// Port for the managed executor HTTP service (default: 3001). + #[serde(default = "default_executor_port")] + pub executor_port: u16, + /// Hex seed (64 chars) for the deployer/funding wallet on the Midnight L1 network. + pub funding_seed: String, + /// Optional rollup ID (64 hex chars) for BatchPublicDataV1Full. Overrides top-level `rollup_id_hex`. + #[serde(default)] + pub rollup_id_hex: Option, + /// Pre-existing contract address. When set, skip auto-deploy and use this address directly. + #[serde(default)] + pub contract_address: Option, +} + +const fn default_executor_port() -> u16 { + 3001 } /// Configuration data used by sequencer extensions, such as EVM endpoints. diff --git a/crates/full-node/sov-blob-sender/src/lib.rs b/crates/full-node/sov-blob-sender/src/lib.rs index f28704928..a76f6c895 100644 --- a/crates/full-node/sov-blob-sender/src/lib.rs +++ b/crates/full-node/sov-blob-sender/src/lib.rs @@ -311,7 +311,7 @@ where match res { FutureOrShutdownOutput::Output(()) => {} FutureOrShutdownOutput::Shutdown => { - info!("BlobSender: Shutting down task for {blob_id}"); + debug!("BlobSender: Shutting down task for {blob_id}"); } } state.dec_nb_of_concurrent_blob_submissions(); diff --git a/crates/full-node/sov-sequencer/src/lib.rs b/crates/full-node/sov-sequencer/src/lib.rs index 8a814d0f3..fa5a4227b 100644 --- a/crates/full-node/sov-sequencer/src/lib.rs +++ b/crates/full-node/sov-sequencer/src/lib.rs @@ -18,7 +18,9 @@ use axum::async_trait; #[cfg(feature = "test-utils")] pub use common::StateUpdateNotification; pub use common::{react_to_state_updates, Sequencer}; -pub use config::{SeqConfigExtension, SequencerConfig, SequencerKindConfig, TEEConfiguration}; +pub use config::{ + L1BridgeConfig, SeqConfigExtension, SequencerConfig, SequencerKindConfig, TEEConfiguration, +}; pub use rest_api::SequencerApis; use serde::Serialize; use sov_modules_api::capabilities::RollupHeight; diff --git a/crates/full-node/sov-stf-runner/src/processes/bridge_lifecycle.rs b/crates/full-node/sov-stf-runner/src/processes/bridge_lifecycle.rs new file mode 100644 index 000000000..b9c1061f3 --- /dev/null +++ b/crates/full-node/sov-stf-runner/src/processes/bridge_lifecycle.rs @@ -0,0 +1,232 @@ +//! Manages the L1 Bridge contract lifecycle: auto-deploy on genesis and +//! executor service spawning / shutdown. + +use std::path::{Path, PathBuf}; +use std::process::Stdio; +use std::time::Duration; + +use anyhow::{Context, Result}; +use tokio::process::{Child, Command}; +use tracing::{info, warn}; + +const BRIDGE_ADDRESS_FILE: &str = "bridge_contract_address"; + +/// Deploy the Bridge contract via bridge-cli and return the contract address. +/// +/// Spawns `npx tsx src/cli.ts deploy ...` as a subprocess and parses the JSON +/// output for `contractAddress`. +pub async fn deploy_bridge( + cli_path: &Path, + network: &str, + funding_seed: &str, + genesis_state_root_hex: &str, + genesis_batch_hash_hex: &str, + rollup_id_hex: Option<&str>, +) -> Result { + let cli_path = std::fs::canonicalize(cli_path) + .with_context(|| format!("bridge_cli_path not found: {}", cli_path.display()))?; + + let mut args = vec![ + "--yes".to_string(), + "tsx".to_string(), + "src/cli.ts".to_string(), + "deploy".to_string(), + "-n".to_string(), + network.to_string(), + "--deployer-seed".to_string(), + funding_seed.to_string(), + "--genesis-state-root".to_string(), + genesis_state_root_hex.to_string(), + "--genesis-batch-hash".to_string(), + genesis_batch_hash_hex.to_string(), + "--json".to_string(), + ]; + if let Some(rid) = rollup_id_hex { + args.push("--rollup-id".to_string()); + args.push(rid.to_string()); + } + + info!( + cli_dir = %cli_path.display(), + network, + genesis_state_root = genesis_state_root_hex, + "Deploying L1 Bridge contract via bridge-cli (this may take a while)..." + ); + + let output = Command::new("npx") + .args(&args) + .current_dir(&cli_path) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .context("Failed to spawn bridge-cli deploy process")? + .wait_with_output() + .await + .context("bridge-cli deploy process failed")?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + let stdout = String::from_utf8_lossy(&output.stdout); + anyhow::bail!( + "bridge-cli deploy failed (exit {})\nstdout: {}\nstderr: {}", + output.status, + stdout.trim(), + stderr.trim() + ); + } + + let stdout = String::from_utf8_lossy(&output.stdout); + // bridge-cli prints log lines before the JSON; find the last line that looks like JSON. + let json_line = stdout + .lines() + .rev() + .find(|line| line.trim_start().starts_with('{')) + .with_context(|| { + format!( + "No JSON object found in bridge-cli deploy output:\n{}", + stdout.trim() + ) + })?; + let json: serde_json::Value = serde_json::from_str(json_line.trim()).with_context(|| { + format!( + "Failed to parse bridge-cli deploy JSON: {}", + json_line.trim() + ) + })?; + + let address = json + .get("contractAddress") + .and_then(|v| v.as_str()) + .context("bridge-cli deploy output missing 'contractAddress' field")? + .to_string(); + + info!(contract_address = %address, "L1 Bridge contract deployed successfully"); + Ok(address) +} + +/// Spawn the bridge-cli executor service as a child process. +/// +/// Returns the child handle; the caller is responsible for killing it on shutdown. +pub async fn start_executor( + cli_path: &Path, + network: &str, + contract_address: &str, + port: u16, + funding_seed: &str, +) -> Result { + let cli_path = std::fs::canonicalize(cli_path) + .with_context(|| format!("bridge_cli_path not found: {}", cli_path.display()))?; + + info!( + contract_address, + port, + cli_dir = %cli_path.display(), + "Starting managed executor service..." + ); + + let child = Command::new("npx") + .args(["--yes", "tsx", "src/executor-server.ts"]) + .current_dir(&cli_path) + .env("BRIDGE_CONTRACT_ADDRESS", contract_address) + .env("MIDNIGHT_NETWORK", network) + .env("EXECUTOR_PORT", port.to_string()) + .env("FUNDING_SEED", funding_seed) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .kill_on_drop(true) + .spawn() + .context("Failed to spawn executor service process")?; + + info!(pid = child.id(), "Executor service process spawned"); + Ok(child) +} + +/// Persist the Bridge contract address to the rollup's storage directory. +pub fn persist_contract_address(storage_path: &Path, address: &str) -> Result<()> { + let file = storage_path.join(BRIDGE_ADDRESS_FILE); + std::fs::write(&file, address) + .with_context(|| format!("Failed to write bridge address to {}", file.display()))?; + info!(path = %file.display(), address, "Persisted Bridge contract address"); + Ok(()) +} + +/// Load a previously persisted Bridge contract address from the rollup's storage directory. +pub fn load_contract_address(storage_path: &Path) -> Option { + let file = storage_path.join(BRIDGE_ADDRESS_FILE); + match std::fs::read_to_string(&file) { + Ok(s) => { + let trimmed = s.trim().to_string(); + if trimmed.is_empty() { + None + } else { + info!(path = %file.display(), address = %trimmed, "Loaded persisted Bridge contract address"); + Some(trimmed) + } + } + Err(_) => None, + } +} + +/// Resolve the Bridge contract address from configuration or persisted state. +pub fn resolve_contract_address( + config_address: Option<&str>, + storage_path: &Path, +) -> Option { + config_address + .filter(|s| !s.is_empty()) + .map(String::from) + .or_else(|| load_contract_address(storage_path)) +} + +/// Wait for the executor service to become ready by polling its `/state` endpoint. +pub async fn wait_for_executor_ready(base_url: &str, timeout: Duration) -> Result<()> { + let client = reqwest::Client::builder() + .timeout(Duration::from_secs(5)) + .build() + .context("Failed to build health-check HTTP client")?; + + let url = format!("{}/state", base_url.trim_end_matches('/')); + let deadline = tokio::time::Instant::now() + timeout; + let mut interval = Duration::from_millis(500); + let max_interval = Duration::from_secs(3); + + info!(url = %url, timeout_secs = timeout.as_secs(), "Waiting for executor service to become ready..."); + + loop { + match client.get(&url).send().await { + Ok(resp) if resp.status().is_success() => { + info!("Executor service is ready"); + return Ok(()); + } + Ok(resp) => { + warn!(status = %resp.status(), "Executor not ready yet"); + } + Err(_) => {} + } + + if tokio::time::Instant::now() + interval > deadline { + anyhow::bail!( + "Executor service at {} did not become ready within {}s", + base_url, + timeout.as_secs() + ); + } + + tokio::time::sleep(interval).await; + interval = (interval * 2).min(max_interval); + } +} + +/// Build the executor base URL from a port number. +pub fn executor_url(port: u16) -> String { + format!("http://127.0.0.1:{}", port) +} + +/// Resolve the absolute path for bridge_cli_path, relative to the config file directory. +pub fn resolve_bridge_cli_path(bridge_cli_path: &Path, config_dir: &Path) -> PathBuf { + if bridge_cli_path.is_absolute() { + bridge_cli_path.to_path_buf() + } else { + config_dir.join(bridge_cli_path) + } +} diff --git a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs index cebaf828b..332cf847b 100644 --- a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs +++ b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs @@ -43,6 +43,14 @@ async fn post_json( serde_json::from_slice(&body_bytes).context("executor response JSON parse failed") } +/// Key batch fields from the executor's Bridge contract state (GET /state). +#[derive(Debug, Clone)] +pub struct ExecutorBridgeState { + pub last_finalized_batch_index: u64, + pub last_finalized_batch_hash: [u8; 32], + pub last_committed_batch_index: u64, +} + /// HTTP client for the Bridge executor service. #[derive(Clone)] pub struct ExecutorClient { @@ -92,6 +100,53 @@ impl ExecutorClient { Ok(out.signatures) } + /// Fetches Bridge contract state from the executor (GET /state). + /// Returns key batch-related fields for diagnostic cross-checks. + pub async fn get_state(&self) -> Result { + let url = format!("{}/state", base_url_normalized(&self.base_url)); + let res = self + .client + .get(&url) + .send() + .await + .context("executor GET /state request failed")?; + let status = res.status(); + let body_bytes = res + .bytes() + .await + .context("executor /state response body read failed")?; + if !status.is_success() { + let msg = String::from_utf8_lossy(&body_bytes); + anyhow::bail!("executor /state: {} (status {})", msg.trim(), status); + } + let raw: serde_json::Value = + serde_json::from_slice(&body_bytes).context("executor /state JSON parse failed")?; + let last_finalized_batch_index = raw + .get("lastFinalizedBatchIndex") + .and_then(|v| v.as_str()) + .and_then(|s| s.parse::().ok()) + .unwrap_or(0); + let last_finalized_batch_hash = raw + .get("lastFinalizedBatchHash") + .and_then(|v| v.as_str()) + .and_then(|s| { + let s = s.strip_prefix("0x").unwrap_or(s); + hex::decode(s).ok() + }) + .and_then(|b| <[u8; 32]>::try_from(b.as_slice()).ok()) + .unwrap_or([0u8; 32]); + let last_committed_batch_index = raw + .get("lastCommittedBatchIndex") + .and_then(|v| v.as_str()) + .and_then(|s| s.parse::().ok()) + .unwrap_or(0); + Ok(ExecutorBridgeState { + last_finalized_batch_index, + last_finalized_batch_hash, + last_committed_batch_index, + }) + } + /// Submits finalizeBatch to the executor (POST /finalize-batch). pub async fn finalize_batch( &self, diff --git a/crates/full-node/sov-stf-runner/src/processes/mod.rs b/crates/full-node/sov-stf-runner/src/processes/mod.rs index 1e26512c5..4111b6164 100644 --- a/crates/full-node/sov-stf-runner/src/processes/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/mod.rs @@ -5,6 +5,8 @@ mod stf_info_manager; mod zk_manager; use std::num::NonZero; +#[cfg(feature = "tee")] +pub mod bridge_lifecycle; #[cfg(feature = "tee")] mod executor_client; #[cfg(feature = "tee")] @@ -15,7 +17,6 @@ pub use executor_client::{ExecutorClient, batch_public_data_to_executor_json}; #[cfg(feature = "tee")] pub use tee_manager::*; -use borsh::{BorshDeserialize, BorshSerialize}; use op_manager::attestations::AttestationsManager; pub use prover_service::*; #[cfg(feature = "tee")] @@ -30,12 +31,6 @@ use tokio::task::JoinHandle; use tracing::{info, warn}; pub use zk_manager::*; -#[derive(Clone, Default, BorshSerialize, BorshDeserialize)] -pub(crate) struct TEEBatchData { - pub last_batch_index: u64, - pub last_prev_batch_hash: [u8; 32], -} - #[cfg(feature = "tee")] /// Starts a process that generates aggregated proofs in the background. pub async fn start_tee_workflow_in_background( @@ -54,30 +49,84 @@ where Ps: ProverService, Ps::DaService: DaService, { - // Warmup the midnight bridge snapshot - // Most likely super inefficient way to do it, but it's fine for now - if let Some(client) = midnight_bridge.as_ref() { - let _ = client.snapshot().await; - } - let mut batch_data = 0; + let mut batch_data = 0u64; let mut prev_batch_hash = [0u8; 32]; + let mut seeded_from_l1 = false; - // Restore from last known state, if available - if std::fs::metadata("tee_batch_data.borsh").is_ok() { - let data = std::fs::read("tee_batch_data.borsh"); - match data { - Ok(d) => { - let tee_data: TEEBatchData = borsh::from_slice(&d).unwrap_or_default(); - batch_data = tee_data.last_batch_index; - prev_batch_hash = tee_data.last_prev_batch_hash; + // Primary: seed batch cursor from L1 Bridge contract state (via adapter snapshot). + // batch_data is the NEXT batch to create, i.e. lastFinalizedBatchIndex + 1. + if let Some(client) = midnight_bridge.as_ref() { + match client.snapshot().await { + Ok(snap) => { + let last_finalized = snap.rollup.misc_data.last_finalized_batch_index; + batch_data = last_finalized + 1; + prev_batch_hash = snap.rollup.last_finalized_batch_hash; + seeded_from_l1 = true; info!( - "Restored TEE batch data from file: batch_index={}, prev_batch_hash={:?}", - batch_data, prev_batch_hash + last_finalized_batch_index = last_finalized, + next_batch_index = batch_data, + prev_batch_hash = hex::encode(prev_batch_hash), + "Seeded TEE batch cursor from L1 Bridge adapter" ); } Err(e) => { - warn!("Failed to read tee_batch_data.borsh: {}", e); - warn!("Defaulting to initial batch data values."); + warn!( + error = %e, + "L1 Bridge adapter snapshot unavailable at startup" + ); + } + } + } + + // Secondary: seed from executor /state when adapter is not available but executor is. + if !seeded_from_l1 { + if let Some(ref executor) = executor_client { + match executor.get_state().await { + Ok(state) => { + let last_finalized = state.last_finalized_batch_index; + batch_data = last_finalized + 1; + prev_batch_hash = state.last_finalized_batch_hash; + seeded_from_l1 = true; + info!( + last_finalized_batch_index = last_finalized, + next_batch_index = batch_data, + prev_batch_hash = hex::encode(prev_batch_hash), + committed_index = state.last_committed_batch_index, + "Seeded TEE batch cursor from executor /state" + ); + } + Err(e) => { + warn!( + error = %e, + "Executor /state also unavailable" + ); + } + } + } + } + + if !seeded_from_l1 { + warn!( + "No L1 source available; defaulting to batch_index=0. \ + The executor service must be running for TEE mode to commit/finalize batches." + ); + } + + // Diagnostic cross-check: log executor /state even when adapter was primary source. + if seeded_from_l1 && midnight_bridge.is_some() { + if let Some(ref executor) = executor_client { + match executor.get_state().await { + Ok(state) => { + info!( + executor_finalized_index = state.last_finalized_batch_index, + executor_committed_index = state.last_committed_batch_index, + executor_finalized_hash = hex::encode(state.last_finalized_batch_hash), + "Executor /state cross-check at startup" + ); + } + Err(e) => { + warn!(error = %e, "Executor /state cross-check failed (non-fatal)"); + } } } } diff --git a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs index 90f7fec3e..693de9c0a 100644 --- a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs @@ -19,7 +19,6 @@ use self::types::AggregateProofMetadata; use super::StateTransitionInfo; use crate::processes::executor_client::{batch_public_data_to_executor_json, ExecutorClient}; use crate::processes::tee_manager::types::merkle_root_from_leaves; -use crate::processes::TEEBatchData; use crate::processes::{hash_to_bytes32, ProverService, PublicDataTee, Receiver}; use tracing::info; @@ -329,30 +328,36 @@ where da_end_height, ); - // Commit batch on L1 via executor service (if configured) - if self.executor_client.is_none() { - tracing::debug!( - batch_index = self.batch_index, - "Executor not configured; skipping L1 commit/finalize (set executor_url and rollup_id_hex in tee_configuration to enable)" - ); - } - if let Some(ref executor) = self.executor_client { - if let Err(e) = executor + // Commit batch on L1 via executor service (if configured). + // Track success so we only advance the durable batch cursor when L1 accepted both commit AND finalize. + let mut l1_ok = if let Some(ref executor) = self.executor_client { + match executor .commit_batch(&self.prev_batch_hash, &batch_hash) .await { - warn!( - batch_index = self.batch_index, - error = %e, - "Executor commit_batch failed; continuing without L1 commit" - ); - } else { - info!( - batch_index = self.batch_index, - "L1 commitBatch submitted via executor" - ); + Ok(()) => { + info!( + batch_index = self.batch_index, + "L1 commitBatch submitted via executor" + ); + true + } + Err(e) => { + warn!( + batch_index = self.batch_index, + error = %e, + "Executor commit_batch failed; batch cursor will NOT advance" + ); + false + } } - } + } else { + tracing::debug!( + batch_index = self.batch_index, + "Executor not configured; skipping L1 commit/finalize (set executor_url and rollup_id_hex in tee_configuration to enable)" + ); + true // no executor configured, L1 interaction is optional + }; tracing::debug!("Generating TEE attestation..."); @@ -463,57 +468,63 @@ where .publish_tee_attestation_blob_with_metadata(attestation) .await?; - // Finalize batch on L1 via executor service (if configured) - if let (Some(ref executor), Some(rollup_id)) = - (self.executor_client.as_ref(), self.rollup_id.as_ref()) - { - match batch_public_data_to_executor_json(&batch, rollup_id) { - Ok(batch_public_data_json) => { - const SIGNATURE_MAX_NONCE: u64 = 256; - const SIGNER_BITMAP: u8 = 0b111; // three signers - const FINALIZE_TIMESTAMP: u64 = 0; - - match executor - .build_signatures(&batch_public_data_json, SIGNATURE_MAX_NONCE) - .await - { - Ok(signatures_json) => { - if let Err(e) = executor - .finalize_batch( - &batch_public_data_json, - &signatures_json, - SIGNER_BITMAP, - FINALIZE_TIMESTAMP, - ) - .await - { + // Finalize batch on L1 via executor service (if configured). + // Only attempt finalize if commit succeeded -- otherwise the contract is not expecting it. + if l1_ok { + if let (Some(ref executor), Some(rollup_id)) = + (self.executor_client.as_ref(), self.rollup_id.as_ref()) + { + match batch_public_data_to_executor_json(&batch, rollup_id) { + Ok(batch_public_data_json) => { + const SIGNATURE_MAX_NONCE: u64 = 256; + const SIGNER_BITMAP: u8 = 0b111; // three signers + const FINALIZE_TIMESTAMP: u64 = 0; + + match executor + .build_signatures(&batch_public_data_json, SIGNATURE_MAX_NONCE) + .await + { + Ok(signatures_json) => { + if let Err(e) = executor + .finalize_batch( + &batch_public_data_json, + &signatures_json, + SIGNER_BITMAP, + FINALIZE_TIMESTAMP, + ) + .await + { + warn!( + batch_index = self.batch_index, + error = %e, + "Executor finalize_batch failed; batch cursor will NOT advance" + ); + l1_ok = false; + } else { + info!( + batch_index = self.batch_index, + "L1 finalizeBatch submitted via executor" + ); + } + } + Err(e) => { warn!( batch_index = self.batch_index, error = %e, - "Executor finalize_batch failed" - ); - } else { - info!( - batch_index = self.batch_index, - "L1 finalizeBatch submitted via executor" + "Executor build_signatures failed; batch cursor will NOT advance" ); + l1_ok = false; } } - Err(e) => { - warn!( - batch_index = self.batch_index, - error = %e, - "Executor build_signatures failed" - ); - } } - } - Err(e) => { - warn!( - batch_index = self.batch_index, - error = %e, - "Failed to serialize batch public data for executor" - ); + Err(e) => { + warn!( + batch_index = self.batch_index, + error = %e, + "Failed to serialize batch public data for executor; batch cursor will NOT advance" + ); + l1_ok = false; + } } } } @@ -522,24 +533,14 @@ where self.stf_info_receiver .inc_next_height_to_receive_by(num_proofs_to_create as u64); - self.batch_index += 1; - - self.prev_batch_hash = batch_hash; - - let tee_data = TEEBatchData { - last_batch_index: self.batch_index, - last_prev_batch_hash: self.prev_batch_hash, - }; - let serialized_tee_data = borsh::to_vec(&tee_data); - match serialized_tee_data { - Ok(d) => { - if let Err(e) = std::fs::write("tee_batch_data.borsh", d) { - warn!("Failed to write tee_batch_data.borsh: {}", e); - } - } - Err(e) => { - warn!("Failed to serialize TEE batch data for writing: {}", e); - } + if l1_ok { + self.batch_index += 1; + self.prev_batch_hash = batch_hash; + } else { + warn!( + batch_index = self.batch_index, + "L1 commit/finalize failed; batch cursor NOT advanced (will retry same batch next cycle)" + ); } } tracing::debug!("Finished processing STF info"); diff --git a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs index 99696adcc..d1bc040d1 100644 --- a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs +++ b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs @@ -56,6 +56,8 @@ pub use wallet::*; pub const GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH"); use crate::RollupBlueprint; +#[cfg(feature = "tee")] +use sov_stf_runner::processes::bridge_lifecycle; #[cfg(feature = "tee")] use sov_stf_runner::processes::{start_tee_workflow_in_background, ExecutorClient}; @@ -316,6 +318,10 @@ pub trait FullNodeBlueprint: RollupBlueprint { let da_service = self .create_da_service(&rollup_config, secondary_shutdown_receiver.clone()) .await; + // Take any eagerly-spawned background handle (e.g. read-only poller). + // The periodic block producer is NOT started yet -- it will be spawned + // via `spawn_background_tasks` after one-time startup work (genesis + // init, L1 Bridge deployment) is complete. let da_service_handle = da_service.take_background_join_handle().await; let da_service = Arc::new(da_service); let current_finalized_header = da_service.get_last_finalized_block_header().await?; @@ -346,6 +352,8 @@ pub trait FullNodeBlueprint: RollupBlueprint { "Recovering the state root" ); let native_stf = StfBlueprint::new(); + #[allow(unused_variables)] + let is_genesis = prev_root.is_none(); let (prover_storage, prev_state_root, genesis_state_root) = match prev_root { // Missing prev_root means need for initialization None => { @@ -433,6 +441,118 @@ pub trait FullNodeBlueprint: RollupBlueprint { background_handles.push(handle); } + // --- L1 Bridge lifecycle management (early, before runner/sequencer) --- + // Deploying the L1 contract and starting the executor can take a long + // time (~60 s). Performing this work before the runner and sequencer + // are created avoids background-task timeouts and backlog accumulation. + #[cfg(feature = "tee")] + let (mut executor_client, mut rollup_id, mut managed_executor_child): ( + Option, + Option<[u8; 32]>, + Option, + ) = { + let mut executor_client: Option = None; + let mut rollup_id: Option<[u8; 32]> = None; + let mut managed_executor_child: Option = None; + + if operating_mode == OperatingMode::TEE { + let ext = rollup_config.sequencer.extension.as_ref(); + let tee_config = ext.and_then(|e| e.tee_configuration.as_ref()); + let l1_bridge = tee_config.and_then(|t| t.l1_bridge.as_ref()); + let storage_path = std::path::Path::new(&rollup_config.storage.path); + + if let Some(l1b) = l1_bridge { + let config_dir = std::env::current_dir() + .context("Failed to get current directory")?; + let cli_path = bridge_lifecycle::resolve_bridge_cli_path( + &l1b.bridge_cli_path, + &config_dir, + ); + + let contract_address = if is_genesis + && l1b.contract_address.as_ref().map_or(true, |s| s.is_empty()) + { + let root_hex = hex::encode(&genesis_state_root.as_ref()[..32]); + let batch_hash_hex = "00".repeat(32); + let addr = bridge_lifecycle::deploy_bridge( + &cli_path, + &l1b.network, + &l1b.funding_seed, + &root_hex, + &batch_hash_hex, + l1b.rollup_id_hex.as_deref(), + ) + .await?; + bridge_lifecycle::persist_contract_address(storage_path, &addr)?; + addr + } else { + bridge_lifecycle::resolve_contract_address( + l1b.contract_address.as_deref(), + storage_path, + ) + .context( + "No Bridge contract address configured or persisted. \ + Set contract_address in [tee_configuration.l1_bridge] or \ + start with a clean genesis to auto-deploy.", + )? + }; + + let child = bridge_lifecycle::start_executor( + &cli_path, + &l1b.network, + &contract_address, + l1b.executor_port, + &l1b.funding_seed, + ) + .await?; + managed_executor_child = Some(child); + + let exec_url = bridge_lifecycle::executor_url(l1b.executor_port); + bridge_lifecycle::wait_for_executor_ready( + &exec_url, + Duration::from_secs(120), + ) + .await?; + + let http_client = Client::builder() + .build() + .context("Failed to build executor HTTP client")?; + executor_client = Some(ExecutorClient::new(http_client, exec_url)); + + rollup_id = parse_rollup_id_hex( + l1b.rollup_id_hex + .as_deref() + .or(tee_config.and_then(|t| t.rollup_id_hex.as_deref())), + ); + } else if let Some(tee) = tee_config { + executor_client = tee + .executor_url + .as_ref() + .filter(|s| !s.is_empty()) + .map(|url| -> anyhow::Result<_> { + let client = Client::builder() + .build() + .context("Failed to build executor HTTP client")?; + Ok(ExecutorClient::new(client, url.clone())) + }) + .transpose()?; + rollup_id = parse_rollup_id_hex(tee.rollup_id_hex.as_deref()); + } + } + + (executor_client, rollup_id, managed_executor_child) + }; + + // All one-time startup work (genesis init, L1 Bridge deployment) is + // done. Start the DA periodic block producer now so that the runner + // begins with a clean slate (no backlog of accumulated empty blocks). + if let Some(handle) = da_service + .spawn_background_tasks(secondary_shutdown_receiver.clone()) + .await + { + background_handles.push(handle); + } + let visible_state_height_tracker: Box = Box::new( MaximumProvableHeight::new(state_update_sender.subscribe(), Self::Runtime::default()), ); @@ -517,8 +637,8 @@ pub trait FullNodeBlueprint: RollupBlueprint { #[cfg(feature = "tee")] { let ext = rollup_config.sequencer.extension.as_ref(); - let oracle_url = ext - .and_then(|e| e.tee_configuration.as_ref()) + let tee_config = ext.and_then(|e| e.tee_configuration.as_ref()); + let oracle_url = tee_config .map(|t| t.tee_attestation_oracle_url.clone()) .unwrap_or_else(|| "http://127.0.0.1:8090".to_owned()); @@ -526,7 +646,6 @@ pub trait FullNodeBlueprint: RollupBlueprint { let indexer: Option = match bridge { None => None, - Some(cfg) => { if cfg.mock_events_path.is_some() { tracing::warn!( @@ -559,47 +678,34 @@ pub trait FullNodeBlueprint: RollupBlueprint { } }; - let executor_client = if let Some(tee) = ext.and_then(|e| e.tee_configuration.as_ref()) { - tee.executor_url - .as_ref() - .filter(|s| !s.is_empty()) - .map(|url| -> anyhow::Result<_> { - let client = Client::builder() - .build() - .context("Failed to build executor HTTP client")?; - Ok(ExecutorClient::new(client, url.clone())) - }) - .transpose()? - } else { - None - }; - let rollup_id = ext - .and_then(|e| e.tee_configuration.as_ref()) - .and_then(|tee| { - let hex_str = tee.rollup_id_hex.as_ref()?; - let s = hex_str.strip_prefix("0x").unwrap_or(hex_str).trim(); - if s.len() != 64 || !s.chars().all(|c| c.is_ascii_hexdigit()) { - return None; - } - let bytes = hex::decode(s).ok()?; - let mut arr = [0u8; 32]; - arr.copy_from_slice(bytes.get(..32)?); - Some(arr) - }); + // executor_client, rollup_id, and managed_executor_child were + // resolved earlier (before runner/sequencer creation) so that + // L1 Bridge deployment doesn't race with background tasks. - start_tee_workflow_in_background( + let tee_handle = start_tee_workflow_in_background( prover_service, rollup_config.proof_manager.aggregated_proof_block_jump, proof_sender, genesis_state_root, stf_info_receiver, - secondary_shutdown_receiver, + secondary_shutdown_receiver.clone(), oracle_url, indexer, - executor_client, - rollup_id, + executor_client.take(), + rollup_id.take(), ) - .await? + .await?; + + if let Some(mut child) = managed_executor_child.take() { + let mut shutdown_rx = secondary_shutdown_receiver; + background_handles.push(tokio::spawn(async move { + let _ = shutdown_rx.changed().await; + tracing::info!("Shutting down managed executor service..."); + let _ = child.kill().await; + })); + } + + tee_handle } #[cfg(not(feature = "tee"))] { @@ -837,6 +943,19 @@ fn spawn_os_signal_handler(shutdown_sender: tokio::sync::watch::Sender<()>) { }); } +#[cfg(feature = "tee")] +fn parse_rollup_id_hex(hex_str: Option<&str>) -> Option<[u8; 32]> { + let hex_str = hex_str?; + let s = hex_str.strip_prefix("0x").unwrap_or(hex_str).trim(); + if s.len() != 64 || !s.chars().all(|c| c.is_ascii_hexdigit()) { + return None; + } + let bytes = hex::decode(s).ok()?; + let mut arr = [0u8; 32]; + arr.copy_from_slice(bytes.get(..32)?); + Some(arr) +} + /// The result of [`FullNodeBlueprint::create_sequencer`]. pub struct SequencerCreationReceipt { /// The [`ApiState`] that shall be used by REST APIs. diff --git a/crates/module-system/sov-test-utils/src/test_rollup.rs b/crates/module-system/sov-test-utils/src/test_rollup.rs index 9196f5ca6..8fb17a4f0 100644 --- a/crates/module-system/sov-test-utils/src/test_rollup.rs +++ b/crates/module-system/sov-test-utils/src/test_rollup.rs @@ -236,6 +236,7 @@ impl, StoragePath: AsPath> RollupBuilder, + ) -> Option> { + None + } + /// Returns a [`DaSpec::Address`] that signs blobs submitted by this instance of [`DaService`] async fn get_signer(&self) -> ::Address; } diff --git a/examples/rollup-ligero/Cargo.toml b/examples/rollup-ligero/Cargo.toml index 5f5905c65..bda06b376 100644 --- a/examples/rollup-ligero/Cargo.toml +++ b/examples/rollup-ligero/Cargo.toml @@ -179,6 +179,10 @@ path = "src/main.rs" name = "generate-genesis-keys" path = "src/bin/generate_genesis_keys.rs" +[[bin]] +name = "print-genesis-info" +path = "src/bin/print_genesis_info.rs" + [[bin]] name = "generate-authority-fvk" path = "src/bin/generate_authority_fvk.rs" diff --git a/examples/rollup-ligero/L1_INTERACTIONS.md b/examples/rollup-ligero/L1_INTERACTIONS.md new file mode 100644 index 000000000..f5e1c9db3 --- /dev/null +++ b/examples/rollup-ligero/L1_INTERACTIONS.md @@ -0,0 +1,118 @@ +# L1 Interactions for Rollup Ligero + +This guide explains how the TEE rollup interacts with the Midnight L1 Bridge contract, and how to run that flow locally. + +## Short Operational Summary + +In TEE mode, the rollup periodically aggregates DA-backed execution into batch public data, obtains oracle-backed attestation material, then settles to the Midnight Bridge on L1: + +1. `commitBatch(parentBatchHash, batchHash)` records the next batch commitment. +2. `finalizeBatch(batchPublicData, signatures, signerBitmap, finalizeTimestamp)` finalizes that committed batch. + +## Where L1 Contract Tooling Lives + +- Bridge contract and interaction tooling: `examples/rollup-ligero/midnight-l2-contracts` +- Executor service (HTTP API for the rollup): `examples/rollup-ligero/midnight-l2-contracts/bridge-cli` + +## Automated Flow (recommended) + +When `[tee_configuration.l1_bridge]` is configured in `rollup_config_tee_local.toml`, the rollup manages the full Bridge lifecycle automatically: + +1. **Genesis detection**: On first start (empty ledger DB), the rollup computes the genesis state root. +2. **Auto-deploy**: If no `contract_address` is configured or persisted, the rollup invokes `bridge-cli deploy` as a subprocess, passing the genesis state root and batch hash. The resulting contract address is persisted to `/bridge_contract_address`. +3. **Executor startup**: The rollup spawns the executor service as a managed child process with the correct contract address and network configuration. +4. **Health check**: The rollup waits for the executor to become ready (polls `/state`). +5. **Normal operation**: The TEE manager calls `commitBatch` and `finalizeBatch` via the executor. +6. **Shutdown**: When the rollup exits, the managed executor child process is killed automatically. + +On subsequent starts (non-genesis), the rollup loads the persisted contract address and spawns the executor without deploying. + +### Prerequisites + +The local Midnight L1 network must already be running before starting the rollup: + +```bash +cd examples/rollup-ligero/midnight-l2-contracts +npm install +npm run build +npm run setup-standalone +``` + +This starts the Midnight node, indexer, and proof server via Docker. + +### Configuration + +In `rollup_config_tee_local.toml`: + +```toml +[sequencer.extension.tee_configuration] +tee_attestation_oracle_url = "http://127.0.0.1:8090" +rollup_id_hex = "0000000000000000000000000000000000000000000000000000000000000000" + +[sequencer.extension.tee_configuration.l1_bridge] +bridge_cli_path = "midnight-l2-contracts/bridge-cli" +network = "undeployed" +executor_port = 3001 +funding_seed = "0000000000000000000000000000000000000000000000000000000000000001" +# contract_address = "" # uncomment to skip auto-deploy and use a pre-existing contract +``` + +### Running + +```bash +# Fresh start (wipes state, new genesis, auto-deploys contract): +TEE_RESET=1 ./tee_local.sh --release --skip-build + +# Restart (reuses existing state and persisted contract address): +./tee_local.sh --release --skip-build +``` + +### Disabling L1 Interactions + +To run in TEE mode without any L1 interactions, comment out the entire `[sequencer.extension.tee_configuration.l1_bridge]` section. The rollup will operate with local attestations only. + +## Manual Flow (legacy) + +If you prefer to manage the contract and executor manually (or need to connect to an external executor), omit the `l1_bridge` section and use `executor_url` instead. + +### Deploy the Contract Manually + +Compute the genesis values: + +```bash +cargo run --bin print-genesis-info -- --rollup-config rollup_config_tee_local.toml --genesis-dir demo_data_tee/genesis +``` + +Deploy in `midnight-l2-contracts/bridge-cli`: + +```bash +npm run cli -- deploy -n undeployed --genesis-state-root --genesis-batch-hash +``` + +Set `BRIDGE_CONTRACT_ADDRESS` in `bridge-cli/.env`, then start the executor: + +```bash +EXECUTOR_PORT=3001 npm run executor +``` + +### Configure the Rollup + +```toml +[sequencer.extension.tee_configuration] +tee_attestation_oracle_url = "http://127.0.0.1:8090" +executor_url = "http://127.0.0.1:3001" +rollup_id_hex = "0000000000000000000000000000000000000000000000000000000000000000" +``` + +## Log Lines to Watch + +- Success: + - `L1 commitBatch submitted via executor` + - `L1 finalizeBatch submitted via executor` + - `L1 Bridge contract deployed successfully` + - `Executor service is ready` +- Diagnostics/failures: + - `Executor commit_batch failed; batch cursor will NOT advance` + - `Executor finalize_batch failed; batch cursor will NOT advance` + - `Deploying L1 Bridge contract via bridge-cli (this may take a while)...` + - `No L1 source available; defaulting to batch_index=0` diff --git a/examples/rollup-ligero/README.md b/examples/rollup-ligero/README.md index dfd23a40b..51a964ba6 100644 --- a/examples/rollup-ligero/README.md +++ b/examples/rollup-ligero/README.md @@ -92,6 +92,10 @@ export SOV_PROVER_MODE=prove ./target/release/sov-rollup-ligero ``` +For TEE-mode settlement flow and L1 Bridge integration (executor setup, config, and logs), see: + +- [`L1_INTERACTIONS.md`](./L1_INTERACTIONS.md) + ## Service Orchestration ### Run All Services Locally diff --git a/examples/rollup-ligero/midnight-l2-contracts b/examples/rollup-ligero/midnight-l2-contracts index 32492ee60..f122f4d00 160000 --- a/examples/rollup-ligero/midnight-l2-contracts +++ b/examples/rollup-ligero/midnight-l2-contracts @@ -1 +1 @@ -Subproject commit 32492ee60871fa55c39844827260ef8cd0d1b38a +Subproject commit f122f4d00ecc83104f8d6f15aa3895b4f65b3936 diff --git a/examples/rollup-ligero/src/bin/print_genesis_info.rs b/examples/rollup-ligero/src/bin/print_genesis_info.rs new file mode 100644 index 000000000..d57dc5327 --- /dev/null +++ b/examples/rollup-ligero/src/bin/print_genesis_info.rs @@ -0,0 +1,111 @@ +//! Computes and prints rollup genesis info without starting the full node. +//! +//! Use this to get Bridge `initialize` values before rollup startup: +//! - `genesisStateRoot_` (first 32 bytes of rollup genesis state root) +//! - `genesisBatchHash_` (current rollup/bridge convention: 32-byte zero hash) +//! +//! Example: +//! cargo run --bin print-genesis-info -- --rollup-config rollup_config_tee_local.toml --genesis-dir demo_data_tee/genesis + +use std::path::PathBuf; + +use anyhow::Context as _; +use clap::Parser; +use demo_stf::genesis_config::GenesisPaths; +use sov_address::MultiAddressEvm; +use sov_db::storage_manager::NativeStorageManager; +use sov_midnight_da::storable::service::StorableMidnightDaService; +use sov_midnight_da::{BlockProducingConfig, MidnightDaConfig}; +use sov_modules_api::execution_mode::Native; +use sov_modules_rollup_blueprint::FullNodeBlueprint; +use sov_modules_rollup_blueprint::RollupBlueprint; +use sov_modules_stf_blueprint::StfBlueprint; +use sov_rollup_interface::node::da::DaService; +use sov_rollup_ligero::MockDemoRollup; +use sov_stf_runner::{from_toml_path, initialize_state, RollupConfig}; +use tokio::sync::watch; + +#[derive(Parser, Debug)] +#[command(about = "Print rollup genesis info for L1 Bridge initialization")] +struct Args { + /// Path to the rollup config TOML (used for genesis params and genesis height). + #[arg(long, default_value = "rollup_config.toml")] + rollup_config: String, + + /// Path to the genesis config directory (JSON files). + #[arg(long)] + genesis_dir: PathBuf, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let args = Args::parse(); + + let rollup_config: RollupConfig = + from_toml_path(&args.rollup_config) + .with_context(|| format!("Failed to read rollup config from {}", args.rollup_config))?; + + let genesis_paths = GenesisPaths::from_dir(&args.genesis_dir); + let blueprint = MockDemoRollup::::default(); + + let genesis_params = blueprint + .create_genesis_config(&genesis_paths, &rollup_config) + .context("Failed to create genesis config from genesis dir")?; + + let genesis_height = rollup_config.runner.genesis_height; + + let temp_state_dir = tempfile::tempdir().context("Failed to create temp dir for state")?; + let mut storage_config = rollup_config.storage.clone(); + storage_config.path = temp_state_dir.path().to_path_buf(); + + let mut temp_rollup_config = rollup_config.clone(); + temp_rollup_config.storage = storage_config; + let mut da_config = rollup_config.da.clone(); + da_config.connection_string = MidnightDaConfig::sqlite_in_memory(); + da_config.block_producing = BlockProducingConfig::Manual; + da_config.da_layer = None; + temp_rollup_config.da = da_config; + + let mut storage_manager = blueprint + .create_storage_manager(&temp_rollup_config) + .context("Failed to create storage manager")?; + + let (_shutdown_tx, shutdown_rx) = watch::channel(()); + let da_service = StorableMidnightDaService::from_config(temp_rollup_config.da.clone(), shutdown_rx).await; + + let genesis_block = da_service + .get_block_at(genesis_height) + .await + .with_context(|| format!("Failed to get genesis block at height {}", genesis_height))?; + + type Spec = as RollupBlueprint>::Spec; + type Runtime = as RollupBlueprint>::Runtime; + let native_stf = StfBlueprint::::new(); + + let genesis_state_root = initialize_state::< + StfBlueprint, + ::InnerZkvm, + ::OuterZkvm, + StorableMidnightDaService, + NativeStorageManager::Storage>, + >(&native_stf, &mut storage_manager, genesis_block, genesis_params) + .await + .context("Failed to initialize state (compute genesis root)")?; + + let root_bytes = genesis_state_root.as_ref(); + let genesis_state_root_32: [u8; 32] = root_bytes[..32] + .try_into() + .expect("genesis root is at least 32 bytes"); + + // Current bridge/rollup convention for genesis batch hash. + let genesis_batch_hash = [0u8; 32]; + + println!("Bridge initialize values:"); + println!(" genesisStateRoot_={}", hex::encode(genesis_state_root_32)); + println!(" genesisBatchHash_={}", hex::encode(genesis_batch_hash)); + println!(); + println!("Diagnostics:"); + println!(" fullGenesisStateRoot64={}", hex::encode(root_bytes)); + + Ok(()) +} From 53807b84e415e06d76012d6868e9795866375f92 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Tue, 17 Mar 2026 20:01:26 +0100 Subject: [PATCH 07/20] recover committed-but-not-finalized L1 batches on restart After a crash or shutdown between commitBatch and finalizeBatch, the L1 Bridge contract rejects new commits with COMMIT_OUT_OF_ORDER. Persist BatchPublicDataV1Full to pending_finalize.json after each successful commit and complete finalization automatically on startup or during graceful shutdown, making the rollup resilient to mid-cycle interruptions. --- .../src/processes/bridge_lifecycle.rs | 130 ++++++++++++++++++ .../src/processes/executor_client.rs | 11 ++ .../sov-stf-runner/src/processes/mod.rs | 32 ++++- .../src/processes/tee_manager/mod.rs | 60 +++++--- .../src/native_only/mod.rs | 40 ++++++ 5 files changed, 250 insertions(+), 23 deletions(-) diff --git a/crates/full-node/sov-stf-runner/src/processes/bridge_lifecycle.rs b/crates/full-node/sov-stf-runner/src/processes/bridge_lifecycle.rs index b9c1061f3..ad60d75e3 100644 --- a/crates/full-node/sov-stf-runner/src/processes/bridge_lifecycle.rs +++ b/crates/full-node/sov-stf-runner/src/processes/bridge_lifecycle.rs @@ -10,6 +10,7 @@ use tokio::process::{Child, Command}; use tracing::{info, warn}; const BRIDGE_ADDRESS_FILE: &str = "bridge_contract_address"; +const PENDING_FINALIZE_FILE: &str = "pending_finalize.json"; /// Deploy the Bridge contract via bridge-cli and return the contract address. /// @@ -230,3 +231,132 @@ pub fn resolve_bridge_cli_path(bridge_cli_path: &Path, config_dir: &Path) -> Pat config_dir.join(bridge_cli_path) } } + +// --------------------------------------------------------------------------- +// Pending-finalize persistence (crash recovery for committed-but-not-finalized +// batches). The file is written atomically (write tmp + rename) so a crash +// mid-write never leaves a corrupt file. +// --------------------------------------------------------------------------- + +/// Data persisted after a successful `commitBatch` so the batch can be +/// finalized on restart if the rollup crashes before `finalizeBatch` completes. +#[derive(serde::Serialize, serde::Deserialize)] +pub struct PendingFinalize { + /// The L1 batch index that was committed. + pub batch_index: u64, + /// The BatchPublicDataV1Full JSON as expected by the executor. + pub batch_public_data_json: String, + /// Hex-encoded rollup ID (32 bytes). + pub rollup_id_hex: String, +} + +/// Persist the pending-finalize payload to disk (atomic write). +pub fn persist_pending_finalize(storage_path: &Path, data: &PendingFinalize) -> Result<()> { + let target = storage_path.join(PENDING_FINALIZE_FILE); + let tmp = storage_path.join(format!("{PENDING_FINALIZE_FILE}.tmp")); + let json = serde_json::to_string_pretty(data) + .context("Failed to serialize pending_finalize data")?; + std::fs::write(&tmp, json.as_bytes()) + .with_context(|| format!("Failed to write {}", tmp.display()))?; + std::fs::rename(&tmp, &target) + .with_context(|| format!("Failed to rename {} -> {}", tmp.display(), target.display()))?; + info!( + batch_index = data.batch_index, + path = %target.display(), + "Persisted pending-finalize data" + ); + Ok(()) +} + +/// Remove the pending-finalize file after successful finalization. +pub fn remove_pending_finalize(storage_path: &Path) { + let target = storage_path.join(PENDING_FINALIZE_FILE); + match std::fs::remove_file(&target) { + Ok(()) => info!(path = %target.display(), "Removed pending-finalize file"), + Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} + Err(e) => warn!(path = %target.display(), error = %e, "Failed to remove pending-finalize file"), + } +} + +/// Load a previously persisted pending-finalize payload, if any. +pub fn load_pending_finalize(storage_path: &Path) -> Option { + let target = storage_path.join(PENDING_FINALIZE_FILE); + match std::fs::read_to_string(&target) { + Ok(s) => match serde_json::from_str(&s) { + Ok(pf) => Some(pf), + Err(e) => { + warn!(path = %target.display(), error = %e, "Corrupt pending-finalize file; ignoring"); + None + } + }, + Err(e) if e.kind() == std::io::ErrorKind::NotFound => None, + Err(e) => { + warn!(path = %target.display(), error = %e, "Error reading pending-finalize file"); + None + } + } +} + +/// Attempt to complete a pending finalize from a previous run. +/// +/// Returns `true` if a pending batch was successfully finalized, `false` if +/// there was nothing to do, and an error if finalization failed. +pub async fn recover_pending_finalize( + storage_path: &Path, + executor: &super::ExecutorClient, +) -> Result { + use super::executor_client::ExecutorBridgeState; + + let pending = match load_pending_finalize(storage_path) { + Some(pf) => pf, + None => return Ok(false), + }; + + let state: ExecutorBridgeState = executor + .get_state() + .await + .context("Failed to query executor /state for pending-finalize recovery")?; + + if state.last_committed_batch_index <= state.last_finalized_batch_index { + info!( + committed = state.last_committed_batch_index, + finalized = state.last_finalized_batch_index, + "No committed-but-not-finalized gap on L1; removing stale pending-finalize file" + ); + remove_pending_finalize(storage_path); + return Ok(false); + } + + info!( + pending_batch_index = pending.batch_index, + l1_committed = state.last_committed_batch_index, + l1_finalized = state.last_finalized_batch_index, + "Recovering committed-but-not-finalized batch from previous run" + ); + + const SIGNATURE_MAX_NONCE: u64 = 256; + const SIGNER_BITMAP: u8 = 0b111; + const FINALIZE_TIMESTAMP: u64 = 0; + + let signatures_json = executor + .build_signatures(&pending.batch_public_data_json, SIGNATURE_MAX_NONCE) + .await + .context("build_signatures failed during pending-finalize recovery")?; + + executor + .finalize_batch( + &pending.batch_public_data_json, + &signatures_json, + SIGNER_BITMAP, + FINALIZE_TIMESTAMP, + ) + .await + .context("finalize_batch failed during pending-finalize recovery")?; + + info!( + batch_index = pending.batch_index, + "Successfully finalized pending batch from previous run" + ); + remove_pending_finalize(storage_path); + Ok(true) +} diff --git a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs index 332cf847b..36ab55f20 100644 --- a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs +++ b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs @@ -49,6 +49,7 @@ pub struct ExecutorBridgeState { pub last_finalized_batch_index: u64, pub last_finalized_batch_hash: [u8; 32], pub last_committed_batch_index: u64, + pub last_committed_batch_hash: [u8; 32], } /// HTTP client for the Bridge executor service. @@ -140,10 +141,20 @@ impl ExecutorClient { .and_then(|v| v.as_str()) .and_then(|s| s.parse::().ok()) .unwrap_or(0); + let last_committed_batch_hash = raw + .get("lastCommittedBatchHash") + .and_then(|v| v.as_str()) + .and_then(|s| { + let s = s.strip_prefix("0x").unwrap_or(s); + hex::decode(s).ok() + }) + .and_then(|b| <[u8; 32]>::try_from(b.as_slice()).ok()) + .unwrap_or([0u8; 32]); Ok(ExecutorBridgeState { last_finalized_batch_index, last_finalized_batch_hash, last_committed_batch_index, + last_committed_batch_hash, }) } diff --git a/crates/full-node/sov-stf-runner/src/processes/mod.rs b/crates/full-node/sov-stf-runner/src/processes/mod.rs index 4111b6164..52e1b867c 100644 --- a/crates/full-node/sov-stf-runner/src/processes/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/mod.rs @@ -44,11 +44,22 @@ pub async fn start_tee_workflow_in_background( midnight_bridge: Option, executor_client: Option, rollup_id: Option<[u8; 32]>, + storage_path: Option, ) -> anyhow::Result> where Ps: ProverService, Ps::DaService: DaService, { + // ---- Crash recovery: complete a committed-but-not-finalized batch from a + // previous run before anything else. + if let (Some(ref sp), Some(ref executor)) = (&storage_path, &executor_client) { + match bridge_lifecycle::recover_pending_finalize(sp, executor).await { + Ok(true) => info!("Pending-finalize recovery succeeded"), + Ok(false) => {} + Err(e) => warn!(error = %e, "Pending-finalize recovery failed (will proceed; may hit COMMIT_OUT_OF_ORDER)"), + } + } + let mut batch_data = 0u64; let mut prev_batch_hash = [0u8; 32]; let mut seeded_from_l1 = false; @@ -83,15 +94,24 @@ where if let Some(ref executor) = executor_client { match executor.get_state().await { Ok(state) => { - let last_finalized = state.last_finalized_batch_index; - batch_data = last_finalized + 1; - prev_batch_hash = state.last_finalized_batch_hash; + let cursor = std::cmp::max( + state.last_committed_batch_index, + state.last_finalized_batch_index, + ); + prev_batch_hash = if cursor == state.last_committed_batch_index + && state.last_committed_batch_index > state.last_finalized_batch_index + { + state.last_committed_batch_hash + } else { + state.last_finalized_batch_hash + }; + batch_data = cursor + 1; seeded_from_l1 = true; info!( - last_finalized_batch_index = last_finalized, + last_finalized_batch_index = state.last_finalized_batch_index, + last_committed_batch_index = state.last_committed_batch_index, next_batch_index = batch_data, prev_batch_hash = hex::encode(prev_batch_hash), - committed_index = state.last_committed_batch_index, "Seeded TEE batch cursor from executor /state" ); } @@ -121,6 +141,7 @@ where executor_finalized_index = state.last_finalized_batch_index, executor_committed_index = state.last_committed_batch_index, executor_finalized_hash = hex::encode(state.last_finalized_batch_hash), + executor_committed_hash = hex::encode(state.last_committed_batch_hash), "Executor /state cross-check at startup" ); } @@ -145,6 +166,7 @@ where midnight_bridge, executor_client, rollup_id, + storage_path, ) .post_aggregated_proof_to_da_in_background() .await) diff --git a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs index 693de9c0a..322242fce 100644 --- a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs @@ -1,3 +1,4 @@ +use std::path::PathBuf; use std::{env, num::NonZero}; use backon::{BackoffBuilder, ExponentialBuilder}; @@ -97,6 +98,7 @@ pub struct TeeProofManager { midnight_bridge: Option, executor_client: Option, rollup_id: Option<[u8; 32]>, + storage_path: Option, } impl TeeProofManager @@ -119,6 +121,7 @@ where midnight_bridge: Option, executor_client: Option, rollup_id: Option<[u8; 32]>, + storage_path: Option, ) -> Self { Self { prover_service, @@ -139,6 +142,7 @@ where midnight_bridge, executor_client, rollup_id, + storage_path, } } @@ -328,6 +332,23 @@ where da_end_height, ); + // Build the batch struct early so we can persist it for crash recovery. + let batch = BatchPublicDataV1 { + version: 1, + layer2_chain_id: public_data.layer2_chain_id, + batch_index: self.batch_index, + da_start_height, + da_end_height, + da_commitment: da_commitment_root, + prev_state_root: public_data.initial_state_root, + post_state_root: public_data.final_state_root, + prev_batch_hash: self.prev_batch_hash, + batch_hash, + last_processed_queue_index: public_data.last_processed_queue_index, + message_queue_hash: public_data.message_queue_hash, + withdraw_root: public_data.withdraw_root, + }; + // Commit batch on L1 via executor service (if configured). // Track success so we only advance the durable batch cursor when L1 accepted both commit AND finalize. let mut l1_ok = if let Some(ref executor) = self.executor_client { @@ -340,6 +361,24 @@ where batch_index = self.batch_index, "L1 commitBatch submitted via executor" ); + + // Persist batch data so we can finalize on restart if the + // process crashes between commit and finalize. + if let Some(ref sp) = self.storage_path { + if let Some(ref rid) = self.rollup_id { + if let Ok(bpd_json) = batch_public_data_to_executor_json(&batch, rid) { + let pf = super::bridge_lifecycle::PendingFinalize { + batch_index: self.batch_index, + batch_public_data_json: bpd_json, + rollup_id_hex: hex::encode(rid), + }; + if let Err(e) = super::bridge_lifecycle::persist_pending_finalize(sp, &pf) { + warn!(error = %e, "Failed to persist pending-finalize (non-fatal)"); + } + } + } + } + true } Err(e) => { @@ -359,24 +398,6 @@ where true // no executor configured, L1 interaction is optional }; - tracing::debug!("Generating TEE attestation..."); - - let batch = BatchPublicDataV1 { - version: 1, - layer2_chain_id: public_data.layer2_chain_id, - batch_index: self.batch_index, - da_start_height, - da_end_height, - da_commitment: da_commitment_root, - prev_state_root: public_data.initial_state_root, - post_state_root: public_data.final_state_root, - prev_batch_hash: self.prev_batch_hash, - batch_hash, - last_processed_queue_index: public_data.last_processed_queue_index, - message_queue_hash: public_data.message_queue_hash, - withdraw_root: public_data.withdraw_root, - }; - let mock_attestation = env_flag_enabled("SOV_TEE_MOCK_ATTESTATION"); let skip_oracle = env_flag_enabled("SOV_TEE_SKIP_ORACLE"); @@ -505,6 +526,9 @@ where batch_index = self.batch_index, "L1 finalizeBatch submitted via executor" ); + if let Some(ref sp) = self.storage_path { + super::bridge_lifecycle::remove_pending_finalize(sp); + } } } Err(e) => { diff --git a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs index d1bc040d1..3c6ee3247 100644 --- a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs +++ b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs @@ -682,6 +682,9 @@ pub trait FullNodeBlueprint: RollupBlueprint { // resolved earlier (before runner/sequencer creation) so that // L1 Bridge deployment doesn't race with background tasks. + let tee_storage_path = + Some(std::path::PathBuf::from(&rollup_config.storage.path)); + let tee_handle = start_tee_workflow_in_background( prover_service, rollup_config.proof_manager.aggregated_proof_block_jump, @@ -693,14 +696,51 @@ pub trait FullNodeBlueprint: RollupBlueprint { indexer, executor_client.take(), rollup_id.take(), + tee_storage_path, ) .await?; if let Some(mut child) = managed_executor_child.take() { let mut shutdown_rx = secondary_shutdown_receiver; + let shutdown_storage_path = + std::path::PathBuf::from(&rollup_config.storage.path); + let shutdown_exec_url = { + let ext = rollup_config.sequencer.extension.as_ref(); + let tee_config = + ext.and_then(|e| e.tee_configuration.as_ref()); + let l1b = tee_config.and_then(|t| t.l1_bridge.as_ref()); + l1b.map(|b| bridge_lifecycle::executor_url(b.executor_port)) + .or_else(|| { + tee_config + .and_then(|t| t.executor_url.clone()) + }) + }; background_handles.push(tokio::spawn(async move { let _ = shutdown_rx.changed().await; tracing::info!("Shutting down managed executor service..."); + + if let Some(exec_url) = shutdown_exec_url { + let client = ExecutorClient::new( + reqwest::Client::new(), + exec_url, + ); + match bridge_lifecycle::recover_pending_finalize( + &shutdown_storage_path, + &client, + ) + .await + { + Ok(true) => tracing::info!( + "Completed pending finalize during graceful shutdown" + ), + Ok(false) => {} + Err(e) => tracing::warn!( + error = %e, + "Failed to complete pending finalize during shutdown (will recover on next start)" + ), + } + } + let _ = child.kill().await; })); } From 507e25ea11ae0bc99efec1ea5392b04d96489fe4 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Wed, 18 Mar 2026 16:04:16 +0100 Subject: [PATCH 08/20] fix: store pool_state.sqlite inside the data directory so that it gets cleaned properly --- crates/utils/midnight-proof-pool-service/README.md | 2 +- examples/rollup-ligero/Makefile | 1 - examples/rollup-ligero/run_proof_pool.sh | 2 +- examples/rollup-ligero/tee_local.sh | 1 + 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/utils/midnight-proof-pool-service/README.md b/crates/utils/midnight-proof-pool-service/README.md index 5d950fa35..b1588a646 100644 --- a/crates/utils/midnight-proof-pool-service/README.md +++ b/crates/utils/midnight-proof-pool-service/README.md @@ -50,7 +50,7 @@ requested number of pending transactions to the sequencer, and the service refil - `PROOF_GENERATION_INTERVAL_MS` - minimum delay between refill batches in the refill loop (default: `0`, no interval throttle) - `MAX_CONCURRENT_PROOFS` - concurrent proof generations (default: `5`) - Wallet setup/funding/deposit scale-up parallelism also follows `MAX_CONCURRENT_PROOFS` at runtime. -- `POOL_STATE_FILE` - SQLite file used to persist wallet/pending-proof state (example: `examples/rollup-ligero/pool_state.sqlite`) +- `POOL_STATE_FILE` - SQLite file used to persist wallet/pending-proof state (example: `examples/rollup-ligero/demo_data/pool_state.sqlite`) - `PROOF_POOL_TREE_RESOLVE_RETRY_ATTEMPTS` - extra retries for transient tree lag / stale anchor root during self-transfer generation (default: `1`) - `PROOF_POOL_TREE_RESOLVE_RETRY_DELAY_MS` - delay between those retries in ms (default: `750`) - `LIGERO_PROGRAM_PATH` - circuit name or wasm path (default: `note_spend_guest`) diff --git a/examples/rollup-ligero/Makefile b/examples/rollup-ligero/Makefile index 9a65c94f6..134f1e064 100644 --- a/examples/rollup-ligero/Makefile +++ b/examples/rollup-ligero/Makefile @@ -33,7 +33,6 @@ clean: rm -rf ./demo_data rm -rf mock_da.sqlite rm -f wallet_index.sqlite - rm -f pool_state.sqlite pool_state.sqlite-wal pool_state.sqlite-shm # rm -f autogenerated.rs @echo "Removing unsent transactions from local storage" @if [ -f "$(SOV_CLI_REL_PATH)" ]; then \ diff --git a/examples/rollup-ligero/run_proof_pool.sh b/examples/rollup-ligero/run_proof_pool.sh index e938cdc10..786c50d60 100755 --- a/examples/rollup-ligero/run_proof_pool.sh +++ b/examples/rollup-ligero/run_proof_pool.sh @@ -75,7 +75,7 @@ export SEQUENCER_READY_CHECK_TIMEOUT_MS="${SEQUENCER_READY_CHECK_TIMEOUT_MS:-200 export MAX_CONCURRENT_PROOFS="${MAX_CONCURRENT_PROOFS:-5}" export ADMIN_WALLET_PRIVATE_KEY="${ADMIN_WALLET_PRIVATE_KEY:-75fbf8d98746c2692e502942b938c82379fd09ea9f5b60d4d39e87e1b42468fd}" export DA_CONNECTION_STRING="${DA_CONNECTION_STRING:-sqlite://$SCRIPT_DIR/demo_data/da.sqlite?mode=rwc}" -export POOL_STATE_FILE="${POOL_STATE_FILE:-$SCRIPT_DIR/pool_state.sqlite}" +export POOL_STATE_FILE="${POOL_STATE_FILE:-$SCRIPT_DIR/demo_data/pool_state.sqlite}" echo "========================================" echo "Midnight Proof Pool Service" diff --git a/examples/rollup-ligero/tee_local.sh b/examples/rollup-ligero/tee_local.sh index dafc68ad9..20d70f3e9 100755 --- a/examples/rollup-ligero/tee_local.sh +++ b/examples/rollup-ligero/tee_local.sh @@ -135,6 +135,7 @@ export ORACLE_SIGNING_KEY_HEX="${ORACLE_SIGNING_KEY_HEX}" export DA_CONNECTION_STRING="${DA_CONNECTION_STRING:-sqlite://${TEE_DATA_DIR_REL}/da.sqlite?mode=rwc}" export INDEX_DB="${INDEX_DB:-sqlite://${TEE_DATA_DIR_REL}/wallet_index.sqlite?mode=rwc}" export INDEXER_DB_CONNECTION_STRING="${INDEXER_DB_CONNECTION_STRING:-$INDEX_DB}" +export POOL_STATE_FILE="${POOL_STATE_FILE:-${TEE_DATA_DIR_REL}/pool_state.sqlite}" # Make verifier service read the same rollup config. export ROLLUP_CONFIG_PATH="${ROLLUP_CONFIG_PATH:-$TEE_ROLLUP_CONFIG}" From 4dbb90ba96c721533c89cce889f7461065bf7a8e Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Thu, 19 Mar 2026 10:56:42 +0100 Subject: [PATCH 09/20] update Bridge contract state decoding --- crates/adapters/midnight/src/lib.rs | 258 +++++++++++----------------- 1 file changed, 99 insertions(+), 159 deletions(-) diff --git a/crates/adapters/midnight/src/lib.rs b/crates/adapters/midnight/src/lib.rs index 20dfced50..6a4cc5470 100644 --- a/crates/adapters/midnight/src/lib.rs +++ b/crates/adapters/midnight/src/lib.rs @@ -130,6 +130,7 @@ pub struct RollupLedger { pub signature_threshold: u8, pub sequencers: BTreeSet<[u8; 32]>, pub finalizers: BTreeSet<[u8; 32]>, + pub initialized: bool, pub last_committed_batch_hash: [u8; 32], pub last_finalized_state_root: [u8; 32], pub last_finalized_batch_hash: [u8; 32], @@ -193,15 +194,16 @@ struct RollupHead { signature_threshold: u8, sequencers: BTreeSet<[u8; 32]>, finalizers: BTreeSet<[u8; 32]>, + initialized: bool, +} + +struct RollupTail { last_committed_batch_hash: [u8; 32], last_finalized_state_root: [u8; 32], last_finalized_batch_hash: [u8; 32], withdraw_roots: BTreeMap, misc_data: RollupMiscData, first_cross_domain_message_index: u64, -} - -struct RollupTail { next_cross_domain_message_index: u64, next_unfinalized_queue_index: u64, message_rolling_hashes: BTreeMap, @@ -216,16 +218,37 @@ struct RollupTail { fn decode_bridge_ledger(state: &ContractState) -> Result { let root = state.data.get_ref(); let root_parts = expect_array(root).context("bridge state root must be an array")?; - if root_parts.len() != 3 { + if root_parts.len() != 2 { return Err(anyhow!( - "expected 3 top-level state segments, found {}", + "expected 2 top-level state segments, found {}", root_parts.len() )); } + let first = expect_array(root_parts[0].deref()) + .context("first top-level segment must be an array")?; + let second = expect_array(root_parts[1].deref()) + .context("second top-level segment must be an array")?; + if first.len() != 8 || second.len() != 15 { + return Err(anyhow!( + "expected flattened L1 layout with [8, 15] entries, found [{}, {}]", + first.len(), + second.len() + )); + } - let rollup_head = decode_rollup_head(root_parts[0].deref())?; - let (rollup_tail, l2_gateway, l2_messenger, l2_message_queue) = - decode_rollup_tail_and_modules(root_parts[1].deref(), root_parts[2].deref())?; + let (rollup_head, rollup_tail) = decode_rollup_flattened_l1_only(first, second)?; + let l2_gateway = L2GatewayLedger { + balances: BTreeMap::new(), + }; + let l2_messenger = L2MessengerLedger { + last_processed_l1_index: 0, + x_domain_message_sender: [0u8; 32], + }; + let l2_message_queue = L2MessageQueueLedger { + message_count: 0, + withdraw_root: [0u8; 32], + branches: vec![[0u8; 32]; 16], + }; let rollup = RollupLedger { owner: rollup_head.owner, @@ -235,12 +258,13 @@ fn decode_bridge_ledger(state: &ContractState) -> Result) -> Result Result { - let items = expect_array(value).context("rollup header must be an array")?; - if items.len() != 13 { - return Err(anyhow!( - "rollup header expected 13 entries, found {}", - items.len() - )); - } - let mut iter = items.into_iter(); - - let owner = decode_bytes32_value(iter_next(&mut iter, "owner")?.deref(), "owner")?; - let layer2_chain_id = decode_u64_value( - iter_next(&mut iter, "layer2ChainId")?.deref(), - "layer2ChainId", - )?; - let rollup_id = decode_bytes32_value(iter_next(&mut iter, "rollupId")?.deref(), "rollupId")?; +fn decode_rollup_flattened_l1_only( + head_prefix: Vec>, + suffix: Vec>, +) -> Result<(RollupHead, RollupTail)> { + let mut h = head_prefix.into_iter(); + let owner = decode_bytes32_value(iter_next(&mut h, "owner")?.deref(), "owner")?; + let layer2_chain_id = + decode_u64_value(iter_next(&mut h, "layer2ChainId")?.deref(), "layer2ChainId")?; + let rollup_id = decode_bytes32_value(iter_next(&mut h, "rollupId")?.deref(), "rollupId")?; let verifier_set = - decode_curve_point_vector(iter_next(&mut iter, "verifierSet")?.deref(), "verifierSet")?; + decode_curve_point_vector(iter_next(&mut h, "verifierSet")?.deref(), "verifierSet")?; let signature_threshold = decode_u8_value( - iter_next(&mut iter, "signatureThreshold")?.deref(), + iter_next(&mut h, "signatureThreshold")?.deref(), "signatureThreshold", )?; - let sequencers = decode_bytes32_set(iter_next(&mut iter, "sequencers")?.deref(), "sequencers")?; - let finalizers = decode_bytes32_set(iter_next(&mut iter, "finalizers")?.deref(), "finalizers")?; + let sequencers = decode_bytes32_set(iter_next(&mut h, "sequencers")?.deref(), "sequencers")?; + let finalizers = decode_bytes32_set(iter_next(&mut h, "finalizers")?.deref(), "finalizers")?; + let initialized = decode_bool_value(iter_next(&mut h, "initialized")?.deref(), "initialized")?; + + let mut s = suffix.into_iter(); let last_committed_batch_hash = decode_bytes32_value( - iter_next(&mut iter, "lastCommittedBatchHash")?.deref(), + iter_next(&mut s, "lastCommittedBatchHash")?.deref(), "lastCommittedBatchHash", )?; let last_finalized_state_root = decode_bytes32_value( - iter_next(&mut iter, "lastFinalizedStateRoot")?.deref(), + iter_next(&mut s, "lastFinalizedStateRoot")?.deref(), "lastFinalizedStateRoot", )?; let last_finalized_batch_hash = decode_bytes32_value( - iter_next(&mut iter, "lastFinalizedBatchHash")?.deref(), + iter_next(&mut s, "lastFinalizedBatchHash")?.deref(), "lastFinalizedBatchHash", )?; - let withdraw_roots = decode_u64_bytes32_map( - iter_next(&mut iter, "withdrawRoots")?.deref(), - "withdrawRoots", - )?; - let misc_data = decode_misc_data(iter_next(&mut iter, "miscData")?.deref(), "miscData")?; + let withdraw_roots = + decode_u64_bytes32_map(iter_next(&mut s, "withdrawRoots")?.deref(), "withdrawRoots")?; + let misc_data = decode_misc_data(iter_next(&mut s, "miscData")?.deref(), "miscData")?; let first_cross_domain_message_index = decode_u64_value( - iter_next(&mut iter, "firstCrossDomainMessageIndex")?.deref(), + iter_next(&mut s, "firstCrossDomainMessageIndex")?.deref(), "firstCrossDomainMessageIndex", )?; - - if iter.next().is_some() { - return Err(anyhow!("unexpected extra entries in rollup header")); - } - - Ok(RollupHead { - owner, - layer2_chain_id, - rollup_id, - verifier_set, - signature_threshold, - sequencers, - finalizers, - last_committed_batch_hash, - last_finalized_state_root, - last_finalized_batch_hash, - withdraw_roots, - misc_data, - first_cross_domain_message_index, - }) -} - -fn decode_rollup_tail_and_modules( - value: &StateValue, - branch_nodes: &StateValue, -) -> Result<( - RollupTail, - L2GatewayLedger, - L2MessengerLedger, - L2MessageQueueLedger, -)> { - let items = expect_array(value).context("rollup tail must be an array")?; - if items.len() != 15 { - return Err(anyhow!( - "rollup tail expected 15 entries, found {}", - items.len() - )); - } - let mut iter = items.into_iter(); - let next_cross_domain_message_index = decode_u64_value( - iter_next(&mut iter, "nextCrossDomainMessageIndex")?.deref(), + iter_next(&mut s, "nextCrossDomainMessageIndex")?.deref(), "nextCrossDomainMessageIndex", )?; let next_unfinalized_queue_index = decode_u64_value( - iter_next(&mut iter, "nextUnfinalizedQueueIndex")?.deref(), + iter_next(&mut s, "nextUnfinalizedQueueIndex")?.deref(), "nextUnfinalizedQueueIndex", )?; let message_rolling_hashes = decode_u64_bytes32_map( - iter_next(&mut iter, "messageRollingHashes")?.deref(), + iter_next(&mut s, "messageRollingHashes")?.deref(), "messageRollingHashes", )?; - let message_timestamps = decode_u64_u64_map( - iter_next(&mut iter, "messageTimestamps")?.deref(), - "messageTimestamps", - )?; - let l1_to_l2_deposits = decode_deposit_map( - iter_next(&mut iter, "l1ToL2Deposits")?.deref(), - "l1ToL2Deposits", - )?; + let message_timestamps = + decode_u64_u64_map(iter_next(&mut s, "messageTimestamps")?.deref(), "messageTimestamps")?; + let l1_to_l2_deposits = + decode_deposit_map(iter_next(&mut s, "l1ToL2Deposits")?.deref(), "l1ToL2Deposits")?; let executed_l2_to_l1_messages = decode_bytes32_set( - iter_next(&mut iter, "executedL2ToL1Messages")?.deref(), + iter_next(&mut s, "executedL2ToL1Messages")?.deref(), "executedL2ToL1Messages", )?; - let locked_night = - decode_u128_value(iter_next(&mut iter, "lockedNIGHT")?.deref(), "lockedNIGHT")?; - let fee_vault = decode_u128_value(iter_next(&mut iter, "feeVault")?.deref(), "feeVault")?; + let locked_night = decode_u128_value(iter_next(&mut s, "lockedNIGHT")?.deref(), "lockedNIGHT")?; + let fee_vault = decode_u128_value(iter_next(&mut s, "feeVault")?.deref(), "feeVault")?; let pending_withdrawals = decode_bytes32_u128_map( - iter_next(&mut iter, "pendingWithdrawals")?.deref(), + iter_next(&mut s, "pendingWithdrawals")?.deref(), "pendingWithdrawals", )?; - let l2_balances = decode_bytes32_u128_map( - iter_next(&mut iter, "l2GatewayBalances")?.deref(), - "l2GatewayBalances", - )?; - let last_processed_l1_index = decode_u64_value( - iter_next(&mut iter, "lastProcessedL1Index")?.deref(), - "lastProcessedL1Index", - )?; - let x_domain_message_sender = decode_bytes32_value( - iter_next(&mut iter, "xDomainMessageSender")?.deref(), - "xDomainMessageSender", - )?; - let message_count = decode_u64_value( - iter_next(&mut iter, "messageCount")?.deref(), - "messageCount", - )?; - let withdraw_root = decode_bytes32_value( - iter_next(&mut iter, "withdrawRoot")?.deref(), - "withdrawRoot", - )?; - let branch0 = decode_bytes32_value(iter_next(&mut iter, "branch0")?.deref(), "branch0")?; - - if iter.next().is_some() { - return Err(anyhow!("unexpected extra entries in rollup tail")); - } - - let branches = decode_branch_nodes(branch_nodes, branch0)?; - let rollup_tail = RollupTail { + let head = RollupHead { + owner, + layer2_chain_id, + rollup_id, + verifier_set, + signature_threshold, + sequencers, + finalizers, + initialized, + }; + let tail = RollupTail { + last_committed_batch_hash, + last_finalized_state_root, + last_finalized_batch_hash, + withdraw_roots, + misc_data, + first_cross_domain_message_index, next_cross_domain_message_index, next_unfinalized_queue_index, message_rolling_hashes, @@ -415,38 +377,7 @@ fn decode_rollup_tail_and_modules( fee_vault, pending_withdrawals, }; - - let l2_gateway = L2GatewayLedger { - balances: l2_balances, - }; - let l2_messenger = L2MessengerLedger { - last_processed_l1_index, - x_domain_message_sender, - }; - let l2_message_queue = L2MessageQueueLedger { - message_count, - withdraw_root, - branches, - }; - - Ok((rollup_tail, l2_gateway, l2_messenger, l2_message_queue)) -} - -fn decode_branch_nodes(value: &StateValue, branch0: [u8; 32]) -> Result> { - let entries = expect_array(value).context("message queue branches must be an array")?; - if entries.len() != 15 { - return Err(anyhow!( - "expected 15 additional branch nodes, found {}", - entries.len() - )); - } - let mut branches = Vec::with_capacity(16); - branches.push(branch0); - for (idx, entry) in entries.into_iter().enumerate() { - let node = decode_bytes32_value(entry.deref(), &format!("branch{}", idx + 1))?; - branches.push(node); - } - Ok(branches) + Ok((head, tail)) } fn decode_deposit_map(value: &StateValue, label: &str) -> Result> { @@ -619,6 +550,15 @@ fn decode_u8_value(value: &StateValue, label: &str) -> Result { Ok(raw as u8) } +fn decode_bool_value(value: &StateValue, label: &str) -> Result { + let raw = decode_u64_value(value, label)?; + match raw { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(anyhow!("{} exceeded boolean range", label)), + } +} + fn decode_u128_value(value: &StateValue, label: &str) -> Result { extract_cell_u128(value).with_context(|| format!("failed to decode {} as u128", label)) } From f4e24146cabe1fc62055a8d98df20c2044faa35b Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Thu, 19 Mar 2026 11:01:03 +0100 Subject: [PATCH 10/20] unify Midnight interactions between batch lifecycle and L1 deposits tracking --- .../full-node-configs/src/sequencer.rs | 85 +++--- crates/full-node/sov-sequencer/src/lib.rs | 2 +- .../src/processes/executor_client.rs | 126 ++++---- .../sov-stf-runner/src/processes/mod.rs | 5 +- .../src/processes/tee_manager/mod.rs | 2 +- .../src/native_only/mod.rs | 278 ++++++++---------- .../sov-test-utils/src/test_rollup.rs | 3 - examples/rollup-ligero/L1_INTERACTIONS.md | 38 ++- examples/rollup-ligero/rollup_config.toml | 17 +- examples/rollup-ligero/src/lib.rs | 2 +- examples/rollup-ligero/src/midnight_bridge.rs | 20 +- examples/rollup-ligero/src/mock_rollup.rs | 24 +- 12 files changed, 291 insertions(+), 311 deletions(-) diff --git a/crates/full-node/full-node-configs/src/sequencer.rs b/crates/full-node/full-node-configs/src/sequencer.rs index 5a8004d92..db6a4aa1f 100644 --- a/crates/full-node/full-node-configs/src/sequencer.rs +++ b/crates/full-node/full-node-configs/src/sequencer.rs @@ -20,45 +20,11 @@ impl Default for SequencerKindConfig { } } -/// TEE configuration. +/// TEE configuration (attestation oracle only). #[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)] pub struct TEEConfiguration { /// URL of the TEE attestation oracle. pub tee_attestation_oracle_url: String, - /// Optional base URL of the Bridge executor service (HTTP). When set, the TEE manager will call - /// POST /commit-batch and POST /build-signatures, POST /finalize-batch to submit L1 batch lifecycle. - /// Ignored when `l1_bridge` is configured (the rollup manages the executor itself). - #[serde(default)] - pub executor_url: Option, - /// Optional rollup ID (64 hex chars) for BatchPublicDataV1Full. Required when executor_url is set. - #[serde(default)] - pub rollup_id_hex: Option, - /// Managed L1 Bridge lifecycle. When present, the rollup auto-deploys the Bridge contract on - /// genesis and spawns the executor service as a child process. When absent, legacy behaviour - /// applies (manual executor via `executor_url`, or no L1 interactions at all). - #[serde(default)] - pub l1_bridge: Option, -} - -/// Configuration for rollup-managed L1 Bridge contract deployment and executor service. -#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)] -pub struct L1BridgeConfig { - /// Path to the bridge-cli directory (contains `src/cli.ts` and `src/executor-server.ts`). - /// Relative paths are resolved from the rollup config file location. - pub bridge_cli_path: PathBuf, - /// Midnight network name passed to bridge-cli (`"undeployed"` for local, `"preview"` for testnet). - pub network: String, - /// Port for the managed executor HTTP service (default: 3001). - #[serde(default = "default_executor_port")] - pub executor_port: u16, - /// Hex seed (64 chars) for the deployer/funding wallet on the Midnight L1 network. - pub funding_seed: String, - /// Optional rollup ID (64 hex chars) for BatchPublicDataV1Full. Overrides top-level `rollup_id_hex`. - #[serde(default)] - pub rollup_id_hex: Option, - /// Pre-existing contract address. When set, skip auto-deploy and use this address directly. - #[serde(default)] - pub contract_address: Option, } const fn default_executor_port() -> u16 { @@ -76,32 +42,57 @@ pub struct SeqConfigExtension { pub tee_configuration: Option, } -/// Rollup-specific Midnight bridge settings parsed from `[sequencer.extension.midnight_bridge]`. +/// Unified Midnight bridge settings parsed from `[sequencer.extension.midnight_bridge]`. +/// +/// When this section is present, the rollup manages the full Bridge lifecycle: +/// contract deployment, executor service, indexer access, and deposit monitoring. +/// Comment out the entire section to disable all L1 interactions. #[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)] pub struct MidnightBridgeSettings { - /// Path to the JSON file containing `PrivateKeyAndAddress` that the bridge will use for signing transactions. - pub signing_key_path: PathBuf, - /// Optional JSON file containing mock ingress events for the bridge to consume. + // --- Bridge lifecycle (contract deployment & executor service) --- + /// Path to the bridge-cli directory (contains `src/cli.ts` and `src/executor-server.ts`). + /// Relative paths are resolved from the rollup config file location. + pub bridge_cli_path: PathBuf, + /// Midnight network name passed to bridge-cli (`"undeployed"` for local, `"preview"` for testnet). + pub network: String, + /// Port for the managed executor HTTP service (default: 3001). + #[serde(default = "default_executor_port")] + pub executor_port: u16, + /// Hex seed (64 chars) for the deployer/funding wallet on the Midnight L1 network. + pub funding_seed: String, + /// Optional rollup ID (64 hex chars) for `BatchPublicDataV1Full`. #[serde(default)] - pub mock_events_path: Option, + pub rollup_id_hex: Option, + /// Pre-existing contract address (64 hex chars). When set, skip auto-deploy on genesis. + /// When absent, the contract is auto-deployed and the address is persisted to + /// `/bridge_contract_address`. + #[serde(default)] + pub contract_address: Option, + + // --- Indexer access (shared by prover L1 state fetching + deposit monitor) --- /// HTTP endpoint for the Midnight indexer GraphQL API. #[serde(default)] pub indexer_http: Option, - /// Bridge contract address on Midnight (64 hex characters). + /// Timeout (in milliseconds) for requests to the Midnight indexer. + #[serde(default = "default_indexer_timeout_ms")] + pub indexer_timeout_ms: u64, + + // --- Deposit monitoring --- + /// Path to the JSON file containing `PrivateKeyAndAddress` for signing deposit transactions. + pub signing_key_path: PathBuf, + /// Optional JSON file with mock ingress events (for offline testing). When set, the live + /// indexer is not used for deposit monitoring. #[serde(default)] - pub contract_address: Option, - /// How often (in milliseconds) the mock event source should be polled. + pub mock_events_path: Option, + /// How often (in milliseconds) the deposit monitor polls for new events. #[serde(default = "default_bridge_poll_interval_ms")] pub poll_interval_ms: u64, /// Optional bech32 token identifier that should be minted; defaults to the runtime gas token. #[serde(default)] pub token_id_bech32: Option, - /// Maximum fee (in gas token units) that the bridge will attach to generated transactions. + /// Maximum fee (in gas token units) attached to generated deposit transactions. #[serde(default = "default_bridge_max_fee")] pub max_fee: u64, - /// Timeout (in milliseconds) for requests to the Midnight indexer. - #[serde(default = "default_indexer_timeout_ms")] - pub indexer_timeout_ms: u64, /// Optional chain deposit index to start processing from (defaults to zero). #[serde(default = "default_start_deposit_index")] pub start_deposit_index: Option, diff --git a/crates/full-node/sov-sequencer/src/lib.rs b/crates/full-node/sov-sequencer/src/lib.rs index fa5a4227b..fa32dfd18 100644 --- a/crates/full-node/sov-sequencer/src/lib.rs +++ b/crates/full-node/sov-sequencer/src/lib.rs @@ -19,7 +19,7 @@ use axum::async_trait; pub use common::StateUpdateNotification; pub use common::{react_to_state_updates, Sequencer}; pub use config::{ - L1BridgeConfig, SeqConfigExtension, SequencerConfig, SequencerKindConfig, TEEConfiguration, + SeqConfigExtension, SequencerConfig, SequencerKindConfig, TEEConfiguration, }; pub use rest_api::SequencerApis; use serde::Serialize; diff --git a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs index 36ab55f20..bbb9d64dd 100644 --- a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs +++ b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs @@ -4,11 +4,8 @@ //! Bridge contract calls (commitBatch, finalizeBatch). This client matches the //! API contract; no code is imported from the reference implementation. -use alloy_primitives::U256; use anyhow::{Context, Result}; -use serde::{Deserialize, Serialize}; use serde_json::json; -use tee::common::BatchPublicDataV1; fn base_url_normalized(base_url: &str) -> &str { base_url.trim_end_matches('/') @@ -182,61 +179,74 @@ impl ExecutorClient { } } -/// JSON shape for BatchPublicDataV1Full as expected by the executor (camelCase, 32-byte fields as hex). -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct BatchPublicDataV1FullJson { - version: u32, - layer2_chain_id: u64, - rollup_id: String, - batch_index: u64, - da_start_height: u64, - da_end_height: u64, - da_commitment: String, - last_processed_queue_index: u64, - message_queue_hash: String, - prev_state_root: String, - prev_batch_hash: String, - post_state_root: String, - batch_hash: String, - withdraw_root: String, -} +// --- TEE-only helpers for BatchPublicDataV1 serialisation --- -fn bytes32_to_hex(b: &[u8; 32]) -> String { - hex::encode(b) -} +#[cfg(feature = "tee")] +mod tee_helpers { + use alloy_primitives::U256; + use anyhow::{Context, Result}; + use serde::{Deserialize, Serialize}; + use tee::common::BatchPublicDataV1; -/// Converts BatchPublicDataV1 and rollup_id to the executor's BatchPublicDataV1Full JSON string. -/// State roots in BatchPublicDataV1 are 64 bytes; the contract expects 32, so we use the first 32 bytes. -pub fn batch_public_data_to_executor_json( - batch: &BatchPublicDataV1, - rollup_id: &[u8; 32], -) -> Result { - let last_processed = batch - .last_processed_queue_index - .min(U256::from(u64::MAX)) - .to::(); - let prev_state_root_32: [u8; 32] = batch.prev_state_root[..32] - .try_into() - .map_err(|_| anyhow::anyhow!("prev_state_root too short"))?; - let post_state_root_32: [u8; 32] = batch.post_state_root[..32] - .try_into() - .map_err(|_| anyhow::anyhow!("post_state_root too short"))?; - let j = BatchPublicDataV1FullJson { - version: batch.version, - layer2_chain_id: batch.layer2_chain_id, - rollup_id: bytes32_to_hex(rollup_id), - batch_index: batch.batch_index, - da_start_height: batch.da_start_height, - da_end_height: batch.da_end_height, - da_commitment: bytes32_to_hex(&batch.da_commitment), - last_processed_queue_index: last_processed, - message_queue_hash: bytes32_to_hex(&batch.message_queue_hash), - prev_state_root: bytes32_to_hex(&prev_state_root_32), - prev_batch_hash: bytes32_to_hex(&batch.prev_batch_hash), - post_state_root: bytes32_to_hex(&post_state_root_32), - batch_hash: bytes32_to_hex(&batch.batch_hash), - withdraw_root: bytes32_to_hex(&batch.withdraw_root), - }; - serde_json::to_string(&j).context("batch public data JSON serialize") + #[derive(Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + struct BatchPublicDataV1FullJson { + version: u32, + layer2_chain_id: u64, + rollup_id: String, + batch_index: u64, + da_start_height: u64, + da_end_height: u64, + da_commitment: String, + last_processed_queue_index: u64, + message_queue_hash: String, + prev_state_root: String, + prev_batch_hash: String, + post_state_root: String, + batch_hash: String, + withdraw_root: String, + } + + fn bytes32_to_hex(b: &[u8; 32]) -> String { + hex::encode(b) + } + + /// Converts `BatchPublicDataV1` and `rollup_id` to the executor's JSON format. + /// State roots in `BatchPublicDataV1` are 64 bytes; the contract expects 32, so we + /// take the first 32 bytes. + pub fn batch_public_data_to_executor_json( + batch: &BatchPublicDataV1, + rollup_id: &[u8; 32], + ) -> Result { + let last_processed = batch + .last_processed_queue_index + .min(U256::from(u64::MAX)) + .to::(); + let prev_state_root_32: [u8; 32] = batch.prev_state_root[..32] + .try_into() + .map_err(|_| anyhow::anyhow!("prev_state_root too short"))?; + let post_state_root_32: [u8; 32] = batch.post_state_root[..32] + .try_into() + .map_err(|_| anyhow::anyhow!("post_state_root too short"))?; + let j = BatchPublicDataV1FullJson { + version: batch.version, + layer2_chain_id: batch.layer2_chain_id, + rollup_id: bytes32_to_hex(rollup_id), + batch_index: batch.batch_index, + da_start_height: batch.da_start_height, + da_end_height: batch.da_end_height, + da_commitment: bytes32_to_hex(&batch.da_commitment), + last_processed_queue_index: last_processed, + message_queue_hash: bytes32_to_hex(&batch.message_queue_hash), + prev_state_root: bytes32_to_hex(&prev_state_root_32), + prev_batch_hash: bytes32_to_hex(&batch.prev_batch_hash), + post_state_root: bytes32_to_hex(&post_state_root_32), + batch_hash: bytes32_to_hex(&batch.batch_hash), + withdraw_root: bytes32_to_hex(&batch.withdraw_root), + }; + serde_json::to_string(&j).context("batch public data JSON serialize") + } } + +#[cfg(feature = "tee")] +pub use tee_helpers::batch_public_data_to_executor_json; diff --git a/crates/full-node/sov-stf-runner/src/processes/mod.rs b/crates/full-node/sov-stf-runner/src/processes/mod.rs index 52e1b867c..3d9010d79 100644 --- a/crates/full-node/sov-stf-runner/src/processes/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/mod.rs @@ -5,15 +5,14 @@ mod stf_info_manager; mod zk_manager; use std::num::NonZero; -#[cfg(feature = "tee")] pub mod bridge_lifecycle; -#[cfg(feature = "tee")] mod executor_client; #[cfg(feature = "tee")] mod tee_manager; +pub use executor_client::ExecutorClient; #[cfg(feature = "tee")] -pub use executor_client::{ExecutorClient, batch_public_data_to_executor_json}; +pub use executor_client::batch_public_data_to_executor_json; #[cfg(feature = "tee")] pub use tee_manager::*; diff --git a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs index 322242fce..1b54ab2c5 100644 --- a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs @@ -393,7 +393,7 @@ where } else { tracing::debug!( batch_index = self.batch_index, - "Executor not configured; skipping L1 commit/finalize (set executor_url and rollup_id_hex in tee_configuration to enable)" + "Executor not configured; skipping L1 commit/finalize (configure [sequencer.extension.midnight_bridge] to enable)" ); true // no executor configured, L1 interaction is optional }; diff --git a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs index 3c6ee3247..7a6b48af3 100644 --- a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs +++ b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs @@ -5,13 +5,11 @@ mod telemetry; mod wallet; use std::net::SocketAddr; use std::sync::Arc; -#[cfg(feature = "tee")] use std::time::Duration; use anyhow::Context; use async_trait::async_trait; pub use endpoints::*; -#[cfg(feature = "tee")] use reqwest::Client; use sov_db::ledger_db::LedgerDb; use sov_db::schema::{DeltaReader, SchemaBatch}; @@ -38,8 +36,8 @@ use sov_state::storage::NativeStorage; use sov_state::Storage; use sov_stf_runner::make_da_sync_state; use sov_stf_runner::processes::{ - start_op_workflow_in_background, start_operator_workflow_in_background, - start_zk_workflow_in_background, ProverService, RollupProverConfig, + bridge_lifecycle, start_op_workflow_in_background, start_operator_workflow_in_background, + start_zk_workflow_in_background, ExecutorClient, ProverService, RollupProverConfig, RollupProverConfigDiscriminants, }; use sov_stf_runner::{ @@ -57,9 +55,7 @@ pub const GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH"); use crate::RollupBlueprint; #[cfg(feature = "tee")] -use sov_stf_runner::processes::bridge_lifecycle; -#[cfg(feature = "tee")] -use sov_stf_runner::processes::{start_tee_workflow_in_background, ExecutorClient}; +use sov_stf_runner::processes::start_tee_workflow_in_background; /// This trait defines how to create all the necessary dependencies required by a rollup. #[allow(clippy::too_many_arguments, clippy::type_complexity)] @@ -445,103 +441,83 @@ pub trait FullNodeBlueprint: RollupBlueprint { // Deploying the L1 contract and starting the executor can take a long // time (~60 s). Performing this work before the runner and sequencer // are created avoids background-task timeouts and backlog accumulation. - #[cfg(feature = "tee")] - let (mut executor_client, mut rollup_id, mut managed_executor_child): ( - Option, - Option<[u8; 32]>, - Option, - ) = { - let mut executor_client: Option = None; - let mut rollup_id: Option<[u8; 32]> = None; - let mut managed_executor_child: Option = None; - - if operating_mode == OperatingMode::TEE { - let ext = rollup_config.sequencer.extension.as_ref(); - let tee_config = ext.and_then(|e| e.tee_configuration.as_ref()); - let l1_bridge = tee_config.and_then(|t| t.l1_bridge.as_ref()); - let storage_path = std::path::Path::new(&rollup_config.storage.path); - - if let Some(l1b) = l1_bridge { - let config_dir = std::env::current_dir() - .context("Failed to get current directory")?; - let cli_path = bridge_lifecycle::resolve_bridge_cli_path( - &l1b.bridge_cli_path, - &config_dir, - ); + // + // All bridge config now lives in `[sequencer.extension.midnight_bridge]`. + // When that section is present the rollup deploys the contract (on + // genesis), starts the executor child process, and resolves the contract + // address for all downstream consumers (indexer client, TEE manager, …). + let ext = rollup_config.sequencer.extension.as_ref(); + let bridge_cfg = ext.and_then(|e| e.midnight_bridge.as_ref()); + let storage_path = std::path::Path::new(&rollup_config.storage.path); + + #[allow(unused_variables, unused_mut, unused_assignments)] + let mut executor_client: Option = None; + #[allow(unused_variables, unused_mut, unused_assignments)] + let mut rollup_id: Option<[u8; 32]> = None; + let mut managed_executor_child: Option = None; + #[allow(unused_variables, unused_mut, unused_assignments)] + let mut resolved_contract_address: Option = None; + + #[allow(unused_assignments)] + if let Some(bcfg) = bridge_cfg { + let config_dir = + std::env::current_dir().context("Failed to get current directory")?; + let cli_path = + bridge_lifecycle::resolve_bridge_cli_path(&bcfg.bridge_cli_path, &config_dir); + + let contract_address = if is_genesis + && bcfg + .contract_address + .as_ref() + .map_or(true, |s| s.is_empty()) + { + let root_hex = hex::encode(&genesis_state_root.as_ref()[..32]); + let batch_hash_hex = "00".repeat(32); + let addr = bridge_lifecycle::deploy_bridge( + &cli_path, + &bcfg.network, + &bcfg.funding_seed, + &root_hex, + &batch_hash_hex, + bcfg.rollup_id_hex.as_deref(), + ) + .await?; + bridge_lifecycle::persist_contract_address(storage_path, &addr)?; + addr + } else { + bridge_lifecycle::resolve_contract_address( + bcfg.contract_address.as_deref(), + storage_path, + ) + .context( + "No Bridge contract address configured or persisted. \ + Set contract_address in [midnight_bridge] or \ + start with a clean genesis to auto-deploy.", + )? + }; - let contract_address = if is_genesis - && l1b.contract_address.as_ref().map_or(true, |s| s.is_empty()) - { - let root_hex = hex::encode(&genesis_state_root.as_ref()[..32]); - let batch_hash_hex = "00".repeat(32); - let addr = bridge_lifecycle::deploy_bridge( - &cli_path, - &l1b.network, - &l1b.funding_seed, - &root_hex, - &batch_hash_hex, - l1b.rollup_id_hex.as_deref(), - ) - .await?; - bridge_lifecycle::persist_contract_address(storage_path, &addr)?; - addr - } else { - bridge_lifecycle::resolve_contract_address( - l1b.contract_address.as_deref(), - storage_path, - ) - .context( - "No Bridge contract address configured or persisted. \ - Set contract_address in [tee_configuration.l1_bridge] or \ - start with a clean genesis to auto-deploy.", - )? - }; - - let child = bridge_lifecycle::start_executor( - &cli_path, - &l1b.network, - &contract_address, - l1b.executor_port, - &l1b.funding_seed, - ) - .await?; - managed_executor_child = Some(child); + let child = bridge_lifecycle::start_executor( + &cli_path, + &bcfg.network, + &contract_address, + bcfg.executor_port, + &bcfg.funding_seed, + ) + .await?; + managed_executor_child = Some(child); - let exec_url = bridge_lifecycle::executor_url(l1b.executor_port); - bridge_lifecycle::wait_for_executor_ready( - &exec_url, - Duration::from_secs(120), - ) - .await?; + let exec_url = bridge_lifecycle::executor_url(bcfg.executor_port); + bridge_lifecycle::wait_for_executor_ready(&exec_url, Duration::from_secs(120)) + .await?; - let http_client = Client::builder() - .build() - .context("Failed to build executor HTTP client")?; - executor_client = Some(ExecutorClient::new(http_client, exec_url)); + let http_client = Client::builder() + .build() + .context("Failed to build executor HTTP client")?; + executor_client = Some(ExecutorClient::new(http_client, exec_url)); - rollup_id = parse_rollup_id_hex( - l1b.rollup_id_hex - .as_deref() - .or(tee_config.and_then(|t| t.rollup_id_hex.as_deref())), - ); - } else if let Some(tee) = tee_config { - executor_client = tee - .executor_url - .as_ref() - .filter(|s| !s.is_empty()) - .map(|url| -> anyhow::Result<_> { - let client = Client::builder() - .build() - .context("Failed to build executor HTTP client")?; - Ok(ExecutorClient::new(client, url.clone())) - }) - .transpose()?; - rollup_id = parse_rollup_id_hex(tee.rollup_id_hex.as_deref()); - } - } - - (executor_client, rollup_id, managed_executor_child) - }; + rollup_id = parse_rollup_id_hex(bcfg.rollup_id_hex.as_deref()); + resolved_contract_address = Some(contract_address); + } // All one-time startup work (genesis init, L1 Bridge deployment) is // done. Start the DA periodic block producer now so that the runner @@ -593,6 +569,7 @@ pub trait FullNodeBlueprint: RollupBlueprint { ) .await?; + let executor_shutdown_rx = secondary_shutdown_receiver.clone(); if let Some(stf_info_receiver) = runner.take_stf_info_receiver() { let prover_config = prover_config .expect("This code path should not be possible; this is a bug, please report it"); @@ -603,7 +580,6 @@ pub trait FullNodeBlueprint: RollupBlueprint { let proof_sender = Box::new(self.create_proof_sender(&rollup_config, sequencer.proof_sender.clone())?); - let workflow_task_handle = match operating_mode { OperatingMode::Optimistic => { let prover_address = rollup_config.proof_manager.prover_address.clone(); @@ -642,9 +618,10 @@ pub trait FullNodeBlueprint: RollupBlueprint { .map(|t| t.tee_attestation_oracle_url.clone()) .unwrap_or_else(|| "http://127.0.0.1:8090".to_owned()); - let bridge = ext.and_then(|e| e.midnight_bridge.as_ref()); - - let indexer: Option = match bridge { + // Build the MidnightIndexerClient using the resolved contract + // address (from deploy or persistence) and the indexer URL from + // the unified midnight_bridge config. + let indexer: Option = match bridge_cfg { None => None, Some(cfg) => { if cfg.mock_events_path.is_some() { @@ -653,8 +630,10 @@ pub trait FullNodeBlueprint: RollupBlueprint { ); None } else { - match (cfg.indexer_http.as_ref(), cfg.contract_address.as_ref()) - { + let addr = resolved_contract_address + .as_deref() + .or(cfg.contract_address.as_deref()); + match (cfg.indexer_http.as_ref(), addr) { (Some(indexer_http), Some(contract_address)) => { let timeout = Duration::from_millis( cfg.indexer_timeout_ms.max(1), @@ -669,7 +648,7 @@ pub trait FullNodeBlueprint: RollupBlueprint { Some(MidnightIndexerClient::new( client, indexer_http.clone(), - contract_address.clone(), + contract_address.to_owned(), )) } _ => None, @@ -678,10 +657,6 @@ pub trait FullNodeBlueprint: RollupBlueprint { } }; - // executor_client, rollup_id, and managed_executor_child were - // resolved earlier (before runner/sequencer creation) so that - // L1 Bridge deployment doesn't race with background tasks. - let tee_storage_path = Some(std::path::PathBuf::from(&rollup_config.storage.path)); @@ -700,51 +675,6 @@ pub trait FullNodeBlueprint: RollupBlueprint { ) .await?; - if let Some(mut child) = managed_executor_child.take() { - let mut shutdown_rx = secondary_shutdown_receiver; - let shutdown_storage_path = - std::path::PathBuf::from(&rollup_config.storage.path); - let shutdown_exec_url = { - let ext = rollup_config.sequencer.extension.as_ref(); - let tee_config = - ext.and_then(|e| e.tee_configuration.as_ref()); - let l1b = tee_config.and_then(|t| t.l1_bridge.as_ref()); - l1b.map(|b| bridge_lifecycle::executor_url(b.executor_port)) - .or_else(|| { - tee_config - .and_then(|t| t.executor_url.clone()) - }) - }; - background_handles.push(tokio::spawn(async move { - let _ = shutdown_rx.changed().await; - tracing::info!("Shutting down managed executor service..."); - - if let Some(exec_url) = shutdown_exec_url { - let client = ExecutorClient::new( - reqwest::Client::new(), - exec_url, - ); - match bridge_lifecycle::recover_pending_finalize( - &shutdown_storage_path, - &client, - ) - .await - { - Ok(true) => tracing::info!( - "Completed pending finalize during graceful shutdown" - ), - Ok(false) => {} - Err(e) => tracing::warn!( - error = %e, - "Failed to complete pending finalize during shutdown (will recover on next start)" - ), - } - } - - let _ = child.kill().await; - })); - } - tee_handle } #[cfg(not(feature = "tee"))] @@ -760,6 +690,41 @@ pub trait FullNodeBlueprint: RollupBlueprint { background_handles.push(workflow_task_handle); } + // Managed executor child cleanup (runs regardless of operating mode). + if let Some(mut child) = managed_executor_child { + let mut shutdown_rx = executor_shutdown_rx; + let shutdown_storage_path = + std::path::PathBuf::from(&rollup_config.storage.path); + let shutdown_exec_url = + bridge_cfg.map(|b| bridge_lifecycle::executor_url(b.executor_port)); + background_handles.push(tokio::spawn(async move { + let _ = shutdown_rx.changed().await; + tracing::info!("Shutting down managed executor service..."); + + if let Some(exec_url) = shutdown_exec_url { + let client = + ExecutorClient::new(reqwest::Client::new(), exec_url); + match bridge_lifecycle::recover_pending_finalize( + &shutdown_storage_path, + &client, + ) + .await + { + Ok(true) => tracing::info!( + "Completed pending finalize during graceful shutdown" + ), + Ok(false) => {} + Err(e) => tracing::warn!( + error = %e, + "Failed to complete pending finalize during shutdown (will recover on next start)" + ), + } + } + + let _ = child.kill().await; + })); + } + let endpoints = self .create_endpoints( state_update_receiver, @@ -983,7 +948,6 @@ fn spawn_os_signal_handler(shutdown_sender: tokio::sync::watch::Sender<()>) { }); } -#[cfg(feature = "tee")] fn parse_rollup_id_hex(hex_str: Option<&str>) -> Option<[u8; 32]> { let hex_str = hex_str?; let s = hex_str.strip_prefix("0x").unwrap_or(hex_str).trim(); diff --git a/crates/module-system/sov-test-utils/src/test_rollup.rs b/crates/module-system/sov-test-utils/src/test_rollup.rs index 8fb17a4f0..b2faabcc0 100644 --- a/crates/module-system/sov-test-utils/src/test_rollup.rs +++ b/crates/module-system/sov-test-utils/src/test_rollup.rs @@ -234,9 +234,6 @@ impl, StoragePath: AsPath> RollupBuilder/bridge_contract_address`. 3. **Executor startup**: The rollup spawns the executor service as a managed child process with the correct contract address and network configuration. 4. **Health check**: The rollup waits for the executor to become ready (polls `/state`). -5. **Normal operation**: The TEE manager calls `commitBatch` and `finalizeBatch` via the executor. +5. **Normal operation**: The TEE manager calls `commitBatch` and `finalizeBatch` via the executor. The deposit monitor polls the indexer for new deposits. 6. **Shutdown**: When the rollup exits, the managed executor child process is killed automatically. On subsequent starts (non-genesis), the rollup loads the persisted contract address and spawns the executor without deploying. @@ -45,16 +47,21 @@ This starts the Midnight node, indexer, and proof server via Docker. In `rollup_config_tee_local.toml`: ```toml -[sequencer.extension.tee_configuration] -tee_attestation_oracle_url = "http://127.0.0.1:8090" -rollup_id_hex = "0000000000000000000000000000000000000000000000000000000000000000" - -[sequencer.extension.tee_configuration.l1_bridge] +[sequencer.extension.midnight_bridge] bridge_cli_path = "midnight-l2-contracts/bridge-cli" network = "undeployed" executor_port = 3001 funding_seed = "0000000000000000000000000000000000000000000000000000000000000001" -# contract_address = "" # uncomment to skip auto-deploy and use a pre-existing contract +rollup_id_hex = "0000000000000000000000000000000000000000000000000000000000000000" +indexer_http = "http://localhost:8088/api/v3/graphql" +indexer_timeout_ms = 30000 +# contract_address = "" # auto-deployed on genesis if omitted +signing_key_path = "assets/midnight_bridge_signer.json" +poll_interval_ms = 1000 +max_fee = 1000000 + +[sequencer.extension.tee_configuration] +tee_attestation_oracle_url = "http://127.0.0.1:8090" ``` ### Running @@ -69,11 +76,11 @@ TEE_RESET=1 ./tee_local.sh --release --skip-build ### Disabling L1 Interactions -To run in TEE mode without any L1 interactions, comment out the entire `[sequencer.extension.tee_configuration.l1_bridge]` section. The rollup will operate with local attestations only. +To run without any L1 interactions, comment out the entire `[sequencer.extension.midnight_bridge]` section. The rollup will operate without bridge deployment, executor, or deposit monitoring. ## Manual Flow (legacy) -If you prefer to manage the contract and executor manually (or need to connect to an external executor), omit the `l1_bridge` section and use `executor_url` instead. +If you prefer to manage the contract and executor manually, omit the `midnight_bridge` section entirely and deploy the contract and start the executor outside of the rollup process. ### Deploy the Contract Manually @@ -95,15 +102,6 @@ Set `BRIDGE_CONTRACT_ADDRESS` in `bridge-cli/.env`, then start the executor: EXECUTOR_PORT=3001 npm run executor ``` -### Configure the Rollup - -```toml -[sequencer.extension.tee_configuration] -tee_attestation_oracle_url = "http://127.0.0.1:8090" -executor_url = "http://127.0.0.1:3001" -rollup_id_hex = "0000000000000000000000000000000000000000000000000000000000000000" -``` - ## Log Lines to Watch - Success: diff --git a/examples/rollup-ligero/rollup_config.toml b/examples/rollup-ligero/rollup_config.toml index c49314ef6..d0003fcd5 100644 --- a/examples/rollup-ligero/rollup_config.toml +++ b/examples/rollup-ligero/rollup_config.toml @@ -104,13 +104,20 @@ num_cache_warmup_workers = 4 num_parallel_tx_workers = 4 [sequencer.extension] max_log_limit = 20000 -# Example Midnight bridge configuration (disabled) + +# Unified Midnight bridge configuration (disabled for non-TEE local dev). +# Uncomment the entire section to enable L1 interactions: contract deployment, +# executor service, indexer access, and deposit monitoring. # [sequencer.extension.midnight_bridge] -# signing_key_path = "demo_data/midnight_bridge_signer.json" # JSON PrivateKeyAndAddress -# mock_events_path = "demo_data/midnight_bridge_events.json" # Uncomment for offline testing -# indexer_http = "https://indexer.preview.midnight.network/api/v3/graphql" -# contract_address = "fa8533250190a9d2b39686523e7b13e7dc30647a341f8163dceaec2cdc365f12" +# bridge_cli_path = "midnight-l2-contracts/bridge-cli" +# network = "undeployed" +# executor_port = 3001 +# funding_seed = "0000000000000000000000000000000000000000000000000000000000000001" +# rollup_id_hex = "0000000000000000000000000000000000000000000000000000000000000000" +# indexer_http = "http://localhost:8088/api/v3/graphql" # indexer_timeout_ms = 30000 +# contract_address = "" +# signing_key_path = "assets/midnight_bridge_signer.json" # poll_interval_ms = 1000 # max_fee = 1000000 diff --git a/examples/rollup-ligero/src/lib.rs b/examples/rollup-ligero/src/lib.rs index b8212f347..a84d29508 100644 --- a/examples/rollup-ligero/src/lib.rs +++ b/examples/rollup-ligero/src/lib.rs @@ -8,7 +8,7 @@ use std::str::FromStr; use const_rollup_config::{ROLLUP_BATCH_NAMESPACE_RAW, ROLLUP_PROOF_NAMESPACE_RAW}; use sov_celestia_adapter::types::Namespace; -// mod midnight_bridge; // Disabled: Midnight bridge not compiled into this rollup. +mod midnight_bridge; mod mock_rollup; pub use mock_rollup::*; diff --git a/examples/rollup-ligero/src/midnight_bridge.rs b/examples/rollup-ligero/src/midnight_bridge.rs index 4676cce38..aea24d7a9 100644 --- a/examples/rollup-ligero/src/midnight_bridge.rs +++ b/examples/rollup-ligero/src/midnight_bridge.rs @@ -181,15 +181,19 @@ where } /// Spawns the Midnight bridge background task when enabled via `sequencer.extension.midnight_bridge`. +/// +/// `resolved_contract_address` is the contract address that was deployed or loaded during bridge +/// lifecycle startup. When provided it takes precedence over the config value. pub(crate) fn spawn_midnight_bridge( sequencer: Arc, extension: &SeqConfigExtension, cursor_store: Option, + resolved_contract_address: Option<&str>, ) -> Result>>> where Seq: BridgeSequencer, { - let Some(config) = load_runtime_settings(extension)? else { + let Some(config) = load_runtime_settings(extension, resolved_contract_address)? else { debug!("Midnight bridge disabled"); return Ok(None); }; @@ -222,7 +226,10 @@ where Ok(Some(tokio::spawn(async move { bridge.run().await }))) } -fn load_runtime_settings(extension: &SeqConfigExtension) -> Result> { +fn load_runtime_settings( + extension: &SeqConfigExtension, + resolved_contract_address: Option<&str>, +) -> Result> { let Some(raw) = extension.midnight_bridge.as_ref() else { info!("Midnight bridge disabled: missing `[sequencer.extension.midnight_bridge]` block"); return Ok(None); @@ -261,9 +268,12 @@ fn load_runtime_settings(extension: &SeqConfigExtension) -> Result for MockDemoRollup { buffer_raw_txs: true, }; - // let mut endpoints = NodeEndpoints { - let endpoints = NodeEndpoints { + let mut endpoints = NodeEndpoints { jsonrpsee_module: sov_ethereum::get_ethereum_rpc( eth_rpc_config, Arc::clone(&sequencer), @@ -124,8 +123,6 @@ impl FullNodeBlueprint for MockDemoRollup { ..Default::default() }; - // Midnight bridge disabled for this rollup; keep implementation intact. - /* let cursor_store = if extension.midnight_bridge.is_some() { match BridgeCursorStore::open(&rollup_config.storage.path) { Ok(store) => Some(store), @@ -142,12 +139,19 @@ impl FullNodeBlueprint for MockDemoRollup { None }; - if let Some(handle) = - spawn_midnight_bridge(Arc::clone(&sequencer), &extension, cursor_store)? - { + let resolved_addr = + sov_stf_runner::processes::bridge_lifecycle::load_contract_address( + &rollup_config.storage.path, + ); + + if let Some(handle) = spawn_midnight_bridge( + Arc::clone(&sequencer), + &extension, + cursor_store, + resolved_addr.as_deref(), + )? { endpoints.background_handles.push(handle); } - */ Ok(endpoints) } From 28b2070de030eb8766a6492aa6426862d3add9ae Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Thu, 19 Mar 2026 18:28:28 +0100 Subject: [PATCH 11/20] sync Midnight bridge generation + TEE batch seeding from executor --- .../sov-rollup-apis/src/endpoints/dedup.rs | 4 +- .../sov-stf-runner/src/processes/mod.rs | 85 ++++------- .../src/native_only/mod.rs | 2 +- examples/rollup-ligero/midnight-l2-contracts | 2 +- examples/rollup-ligero/src/midnight_bridge.rs | 142 +++++++++++++++++- examples/rollup-ligero/src/mock_rollup.rs | 21 +++ 6 files changed, 195 insertions(+), 61 deletions(-) diff --git a/crates/full-node/sov-rollup-apis/src/endpoints/dedup.rs b/crates/full-node/sov-rollup-apis/src/endpoints/dedup.rs index 7a51ce415..0d0ee344e 100644 --- a/crates/full-node/sov-rollup-apis/src/endpoints/dedup.rs +++ b/crates/full-node/sov-rollup-apis/src/endpoints/dedup.rs @@ -126,13 +126,13 @@ impl SovereignDeDupEndpoint { query: DedupQuery, ) -> Result { let credential_id = CredentialId::from_str(&credential_id)?; - tracing::info!(%credential_id, "Going to provide dedup for"); + tracing::debug!(%credential_id, "Going to provide dedup for"); let uniqueness = Uniqueness::::default(); match query.select { Some(SelectField::Generation) => { let generation = uniqueness.next_generation(&credential_id, &mut state)?; - tracing::info!(%credential_id, %generation, "Providing generation for credential id"); + tracing::debug!(%credential_id, %generation, "Providing generation for credential id"); Ok(DedupResponse { nonce: None, generation: Some(generation), diff --git a/crates/full-node/sov-stf-runner/src/processes/mod.rs b/crates/full-node/sov-stf-runner/src/processes/mod.rs index 3d9010d79..731fc1f7e 100644 --- a/crates/full-node/sov-stf-runner/src/processes/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/mod.rs @@ -63,61 +63,62 @@ where let mut prev_batch_hash = [0u8; 32]; let mut seeded_from_l1 = false; - // Primary: seed batch cursor from L1 Bridge contract state (via adapter snapshot). - // batch_data is the NEXT batch to create, i.e. lastFinalizedBatchIndex + 1. - if let Some(client) = midnight_bridge.as_ref() { - match client.snapshot().await { - Ok(snap) => { - let last_finalized = snap.rollup.misc_data.last_finalized_batch_index; - batch_data = last_finalized + 1; - prev_batch_hash = snap.rollup.last_finalized_batch_hash; + // Prefer executor for seeding when present so the rollup's next commit parent + // matches what the executor (and L1 contract) expect, avoiding BAD_PARENT_BATCH_HASH + // when indexer and executor state differ (e.g. undeployed network or clean restart). + if let Some(ref executor) = executor_client { + match executor.get_state().await { + Ok(state) => { + let cursor = std::cmp::max( + state.last_committed_batch_index, + state.last_finalized_batch_index, + ); + prev_batch_hash = if cursor == state.last_committed_batch_index + && state.last_committed_batch_index > state.last_finalized_batch_index + { + state.last_committed_batch_hash + } else { + state.last_finalized_batch_hash + }; + batch_data = cursor + 1; seeded_from_l1 = true; info!( - last_finalized_batch_index = last_finalized, + last_finalized_batch_index = state.last_finalized_batch_index, + last_committed_batch_index = state.last_committed_batch_index, next_batch_index = batch_data, prev_batch_hash = hex::encode(prev_batch_hash), - "Seeded TEE batch cursor from L1 Bridge adapter" + "Seeded TEE batch cursor from executor /state" ); } Err(e) => { warn!( error = %e, - "L1 Bridge adapter snapshot unavailable at startup" + "Executor /state unavailable at startup" ); } } } - // Secondary: seed from executor /state when adapter is not available but executor is. + // Fallback: seed from L1 Bridge adapter (indexer) when executor did not provide state. if !seeded_from_l1 { - if let Some(ref executor) = executor_client { - match executor.get_state().await { - Ok(state) => { - let cursor = std::cmp::max( - state.last_committed_batch_index, - state.last_finalized_batch_index, - ); - prev_batch_hash = if cursor == state.last_committed_batch_index - && state.last_committed_batch_index > state.last_finalized_batch_index - { - state.last_committed_batch_hash - } else { - state.last_finalized_batch_hash - }; - batch_data = cursor + 1; + if let Some(client) = midnight_bridge.as_ref() { + match client.snapshot().await { + Ok(snap) => { + let last_finalized = snap.rollup.misc_data.last_finalized_batch_index; + batch_data = last_finalized + 1; + prev_batch_hash = snap.rollup.last_finalized_batch_hash; seeded_from_l1 = true; info!( - last_finalized_batch_index = state.last_finalized_batch_index, - last_committed_batch_index = state.last_committed_batch_index, + last_finalized_batch_index = last_finalized, next_batch_index = batch_data, prev_batch_hash = hex::encode(prev_batch_hash), - "Seeded TEE batch cursor from executor /state" + "Seeded TEE batch cursor from L1 Bridge adapter" ); } Err(e) => { warn!( error = %e, - "Executor /state also unavailable" + "L1 Bridge adapter snapshot unavailable at startup" ); } } @@ -126,31 +127,11 @@ where if !seeded_from_l1 { warn!( - "No L1 source available; defaulting to batch_index=0. \ + "No executor or L1 source available; defaulting to batch_index=0. \ The executor service must be running for TEE mode to commit/finalize batches." ); } - // Diagnostic cross-check: log executor /state even when adapter was primary source. - if seeded_from_l1 && midnight_bridge.is_some() { - if let Some(ref executor) = executor_client { - match executor.get_state().await { - Ok(state) => { - info!( - executor_finalized_index = state.last_finalized_batch_index, - executor_committed_index = state.last_committed_batch_index, - executor_finalized_hash = hex::encode(state.last_finalized_batch_hash), - executor_committed_hash = hex::encode(state.last_committed_batch_hash), - "Executor /state cross-check at startup" - ); - } - Err(e) => { - warn!(error = %e, "Executor /state cross-check failed (non-fatal)"); - } - } - } - } - Ok(TeeProofManager::new( prover_service, aggregated_proof_block_jump, diff --git a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs index 7a6b48af3..2bd5ea6ea 100644 --- a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs +++ b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs @@ -507,7 +507,7 @@ pub trait FullNodeBlueprint: RollupBlueprint { managed_executor_child = Some(child); let exec_url = bridge_lifecycle::executor_url(bcfg.executor_port); - bridge_lifecycle::wait_for_executor_ready(&exec_url, Duration::from_secs(120)) + bridge_lifecycle::wait_for_executor_ready(&exec_url, Duration::from_secs(240)) .await?; let http_client = Client::builder() diff --git a/examples/rollup-ligero/midnight-l2-contracts b/examples/rollup-ligero/midnight-l2-contracts index f122f4d00..fd9877767 160000 --- a/examples/rollup-ligero/midnight-l2-contracts +++ b/examples/rollup-ligero/midnight-l2-contracts @@ -1 +1 @@ -Subproject commit f122f4d00ecc83104f8d6f15aa3895b4f65b3936 +Subproject commit fd9877767934d748469be0f7a970e5f580c8222f diff --git a/examples/rollup-ligero/src/midnight_bridge.rs b/examples/rollup-ligero/src/midnight_bridge.rs index aea24d7a9..3b49afe45 100644 --- a/examples/rollup-ligero/src/midnight_bridge.rs +++ b/examples/rollup-ligero/src/midnight_bridge.rs @@ -29,7 +29,7 @@ use sov_modules_api::runtime::capabilities::authentication::{ use sov_modules_api::transaction::TxDetails; use sov_modules_api::transaction::{PriorityFeeBips, Transaction, UnsignedTransaction}; use sov_modules_api::FullyBakedTx; -use sov_modules_api::{Amount, CredentialId, RawTx, Spec}; +use sov_modules_api::{Amount, CredentialId, PrivateKey, PublicKey, RawTx, Spec}; use sov_rollup_interface::common::SlotNumber; use sov_rollup_interface::TxHash; use sov_sequencer::{Sequencer, SequencerNotReadyDetails}; @@ -184,11 +184,17 @@ where /// /// `resolved_contract_address` is the contract address that was deployed or loaded during bridge /// lifecycle startup. When provided it takes precedence over the config value. +/// +/// `rollup_dedup_url` should be the rollup's HTTP base URL (e.g. `http://127.0.0.1:12346`). When set, +/// the bridge fetches the next generation for its credential from the rollup's dedup API at startup, +/// so credit transactions pass the uniqueness check. If omitted, the bridge uses generation 0, which +/// will fail if the bridge credential has already been used on the rollup. pub(crate) fn spawn_midnight_bridge( sequencer: Arc, extension: &SeqConfigExtension, cursor_store: Option, resolved_contract_address: Option<&str>, + rollup_dedup_url: Option, ) -> Result>>> where Seq: BridgeSequencer, @@ -222,7 +228,13 @@ where deposit_source, } = config; - let bridge = MidnightBridge::new(sequencer, runtime, deposit_source, cursor_store)?; + let bridge = MidnightBridge::new( + sequencer, + runtime, + deposit_source, + cursor_store, + rollup_dedup_url, + )?; Ok(Some(tokio::spawn(async move { bridge.run().await }))) } @@ -313,6 +325,13 @@ struct RuntimeBridgeSettings { max_fee: Amount, } +/// Response from the rollup dedup endpoint when using `?select=generation`. +#[derive(Debug, Deserialize)] +struct DedupGenerationResponse { + #[serde(default)] + generation: Option, +} + struct MidnightBridge { sequencer: Arc, settings: RuntimeBridgeSettings, @@ -322,6 +341,8 @@ struct MidnightBridge { idle_notice_sent: bool, next_chain_index: Option, cursor_store: Option, + /// When set, the bridge syncs next_generation from this rollup URL at startup. + rollup_dedup_url: Option, } impl MidnightBridge @@ -333,6 +354,7 @@ where settings: RuntimeBridgeSettings, deposit_source: DepositSource, mut cursor_store: Option, + rollup_dedup_url: Option, ) -> Result { let mut restored_cursor = None; @@ -373,6 +395,7 @@ where idle_notice_sent: false, next_chain_index, cursor_store, + rollup_dedup_url, }; if restored_cursor.is_none() { @@ -397,6 +420,89 @@ where self.persist_cursor(cursor); } + /// Fetches the next generation for the bridge credential from the rollup dedup API + /// and sets `next_generation` so credit transactions pass the uniqueness check. + /// Retries on connection errors so the rollup HTTP server has time to start. + async fn sync_next_generation_from_rollup(&mut self) { + const MAX_DEDUP_RETRIES: u32 = 10; + const RETRY_DELAY_MS: u64 = 500; + + let Some(ref base_url) = self.rollup_dedup_url else { + debug!( + "Midnight bridge has no rollup_dedup_url; using next_generation=0 (may fail if credential already used)" + ); + return; + }; + + let credential_id = self.settings.signing_key.private_key.pub_key().credential_id(); + let url = format!( + "{}/rollup/addresses/{}/dedup?select=generation", + base_url.trim_end_matches('/'), + credential_id + ); + + for attempt in 1..=MAX_DEDUP_RETRIES { + match reqwest::get(&url).await { + Ok(resp) if resp.status().is_success() => { + match resp.json::().await { + Ok(decoded) => { + if let Some(gen) = decoded.generation { + // Never decrease: we may have already incremented locally after + // submitting a credit that isn’t reflected in rollup state yet. + self.next_generation = self.next_generation.max(gen); + debug!( + credential_id = %credential_id, + next_generation = self.next_generation, + "Midnight bridge synced next_generation from rollup dedup" + ); + } else { + warn!( + url = %url, + "Rollup dedup response had no generation field; using next_generation=0" + ); + } + } + Err(err) => { + warn!( + url = %url, + error = ?err, + "Midnight bridge failed to parse dedup response; using next_generation=0" + ); + } + } + return; + } + Ok(resp) => { + warn!( + url = %url, + status = %resp.status(), + "Midnight bridge dedup request failed; using next_generation=0" + ); + return; + } + Err(err) => { + let is_connect_err = err.is_connect(); + if is_connect_err && attempt < MAX_DEDUP_RETRIES { + debug!( + url = %url, + attempt, + max = MAX_DEDUP_RETRIES, + "Rollup not ready, retrying dedup fetch" + ); + tokio::time::sleep(Duration::from_millis(RETRY_DELAY_MS)).await; + } else { + warn!( + url = %url, + error = ?err, + "Midnight bridge failed to fetch dedup; using next_generation=0" + ); + return; + } + } + } + } + } + async fn run(mut self) -> Result<()> { let mut ticker = interval(self.settings.poll_interval); enum PollRequest { @@ -405,6 +511,11 @@ where } loop { ticker.tick().await; + + // Re-sync next_generation each poll so we see current rollup state (initial sync + // can run before state has this credential, giving 0 and then uniqueness failures). + self.sync_next_generation_from_rollup().await; + let request = match &self.deposit_source { DepositSource::Mock(source) => PollRequest::Mock(source.path().to_path_buf()), DepositSource::Indexer(source) => PollRequest::Indexer(source.client_arc()), @@ -921,7 +1032,14 @@ mod tests { events_path: events_path.clone(), }); let mut bridge = - MidnightBridge::new(Arc::clone(&sequencer), settings, deposit_source, None).unwrap(); + MidnightBridge::new( + Arc::clone(&sequencer), + settings, + deposit_source, + None, + None, + ) + .unwrap(); let snapshot = read_deposit_file(&events_path).await.unwrap(); assert_eq!(snapshot.len(), deposits.len()); @@ -977,7 +1095,14 @@ mod tests { let deposit_source = DepositSource::Mock(MockDepositSource { events_path: events_path.clone(), }); - let mut bridge = MidnightBridge::new(sequencer, settings, deposit_source, None).unwrap(); + let mut bridge = MidnightBridge::new( + sequencer, + settings, + deposit_source, + None, + None, + ) + .unwrap(); let deposit = read_deposit_file(&events_path) .await @@ -1028,7 +1153,14 @@ mod tests { let deposit_source = DepositSource::Mock(MockDepositSource { events_path: events_path.clone(), }); - let mut bridge = MidnightBridge::new(sequencer, settings, deposit_source, None).unwrap(); + let mut bridge = MidnightBridge::new( + sequencer, + settings, + deposit_source, + None, + None, + ) + .unwrap(); let deposit = read_deposit_file(&events_path) .await diff --git a/examples/rollup-ligero/src/mock_rollup.rs b/examples/rollup-ligero/src/mock_rollup.rs index b315858c6..8a8beb066 100644 --- a/examples/rollup-ligero/src/mock_rollup.rs +++ b/examples/rollup-ligero/src/mock_rollup.rs @@ -144,11 +144,32 @@ impl FullNodeBlueprint for MockDemoRollup { &rollup_config.storage.path, ); + let rollup_dedup_url = rollup_config + .runner + .http_config + .public_address + .clone() + .or_else(|| { + // Use 127.0.0.1 when bind_host is 0.0.0.0 so the bridge can reach the rollup + // (0.0.0.0 is a server bind address, not a connectable address). + let host = if rollup_config.runner.http_config.bind_host == "0.0.0.0" { + "127.0.0.1" + } else { + &rollup_config.runner.http_config.bind_host + }; + Some(format!( + "http://{}:{}", + host, + rollup_config.runner.http_config.bind_port + )) + }); + if let Some(handle) = spawn_midnight_bridge( Arc::clone(&sequencer), &extension, cursor_store, resolved_addr.as_deref(), + rollup_dedup_url, )? { endpoints.background_handles.push(handle); } From c6643d3601be935558cce928330b12c813bc566d Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Mon, 19 Jan 2026 18:59:35 +0100 Subject: [PATCH 12/20] withdrawal module skelet --- examples/demo-rollup/autogenerated.rs | 101 +++++++ examples/demo-rollup/stf/README.md | 16 + .../demo-rollup/stf/src/genesis_config.rs | 8 + examples/demo-rollup/stf/src/lib.rs | 2 + .../stf/src/midnight_withdrawals.rs | 286 ++++++++++++++++++ examples/demo-rollup/stf/src/runtime.rs | 3 + examples/rollup-ligero/README.md | 60 +++- examples/rollup-ligero/autogenerated.rs | 101 +++++++ .../demo/mock/midnight_withdrawals.json | 3 + .../midnight_withdrawals.json | 3 + 10 files changed, 578 insertions(+), 5 deletions(-) create mode 100644 examples/demo-rollup/stf/src/midnight_withdrawals.rs create mode 100644 examples/test-data/genesis/demo/mock/midnight_withdrawals.json create mode 100644 examples/test-data/genesis/integration-tests/midnight_withdrawals.json diff --git a/examples/demo-rollup/autogenerated.rs b/examples/demo-rollup/autogenerated.rs index 9eaa32a3b..d46215a9f 100644 --- a/examples/demo-rollup/autogenerated.rs +++ b/examples/demo-rollup/autogenerated.rs @@ -278,6 +278,14 @@ pub const SCHEMA_JSON: &str = r#"{ "value": { "ByIndex": 124 } + }, + { + "name": "MidnightWithdrawals", + "discriminant": 16, + "template": null, + "value": { + "ByIndex": 141 + } } ], "hide_tag": false @@ -3458,6 +3466,70 @@ pub const SCHEMA_JSON: &str = r#"{ ] } }, + { + "Tuple": { + "template": null, + "peekable": false, + "fields": [ + { + "value": { + "ByIndex": 142 + }, + "silent": false, + "doc": "" + } + ] + } + }, + { + "Enum": { + "type_name": "CallMessage", + "variants": [ + { + "name": "WithdrawNight", + "discriminant": 0, + "template": null, + "value": { + "ByIndex": 143 + } + } + ], + "hide_tag": false + } + }, + { + "Struct": { + "type_name": "__SovVirtualWallet_CallMessage_WithdrawNight", + "template": null, + "peekable": false, + "fields": [ + { + "display_name": "midnight_address", + "silent": false, + "value": { + "Immediate": "String" + }, + "doc": "" + }, + { + "display_name": "amount", + "silent": false, + "value": { + "ByIndex": 11 + }, + "doc": "" + }, + { + "display_name": "gas_limit", + "silent": false, + "value": { + "ByIndex": 68 + }, + "doc": "" + } + ] + } + }, { "Enum": { "type_name": "UniquenessData", @@ -3793,6 +3865,9 @@ pub const SCHEMA_JSON: &str = r#"{ }, { "name": "midnight_privacy" + }, + { + "name": "midnight_withdrawals" } ] }, @@ -4966,6 +5041,32 @@ pub const SCHEMA_JSON: &str = r#"{ } ] }, + { + "name": "", + "fields_or_variants": [] + }, + { + "name": "CallMessage", + "fields_or_variants": [ + { + "name": "withdraw_night" + } + ] + }, + { + "name": "__SovVirtualWallet_CallMessage_WithdrawNight", + "fields_or_variants": [ + { + "name": "midnight_address" + }, + { + "name": "amount" + }, + { + "name": "gas_limit" + } + ] + }, { "name": "UniquenessData", "fields_or_variants": [ diff --git a/examples/demo-rollup/stf/README.md b/examples/demo-rollup/stf/README.md index d40cb3842..de5384706 100644 --- a/examples/demo-rollup/stf/README.md +++ b/examples/demo-rollup/stf/README.md @@ -134,6 +134,22 @@ complete State Transition Function! Your modules optionally implement RPC methods via the `rpc_gen` macro, in order to enable the full-node to expose them, annotate the `Runtime` with `expose_rpc`. In the example above, you can see how to use the `expose_rpc` macro on the `native` `Runtime`. +### Midnight Withdrawals Prototype + +- `examples/demo-rollup/stf/src/midnight_withdrawals.rs` implements the first slice of the Midnight bridge architecture (design doc §9). +- At genesis we enable it through `midnight_withdrawals.json`; each call to `withdraw_night` burns the canonical NIGHT token and logs a `StoredWithdrawal` keyed by a nonce. +- The module exposes REST helpers underneath `/modules/midnight_withdrawals/...` so rollup operators (or test relayers) can fetch the latest nonce and a specific withdrawal record — this serves as the temporary “proof” requested for the MVP. +- Runtime wiring happens via the new `midnight_withdrawals` field, so every rollup using `demo-stf` automatically gains the burn + log behavior. + +**How this maps to the long-term architecture:** + +1. ✅ Step 1–2 (L2 gateway burns NIGHT and captures calldata) now live inside the STF. +2. 🔜 Steps 3–4 require replacing the simple `StateMap` with a proper append-only Merkle tree / message queue so we can compute `withdrawRoot` deterministically. +3. 🔜 Step 5 needs TEE/attestation wiring so each finalized batch publishes the `withdrawRoot` alongside state roots. +4. 🔜 Steps 6–7 involve the Midnight contracts plus replay protection, fed by the proofs that will eventually be built atop the REST data. + +Until those TODOs land, the REST responses plus the Bank balance delta are the recommended way to exercise and verify the prototype. + ## Make Full Node Integrations Simpler with the State Transition Runner: Now that we have an app, we want to be able to run it. For any custom state transition, your full node implementation is going to need a little diff --git a/examples/demo-rollup/stf/src/genesis_config.rs b/examples/demo-rollup/stf/src/genesis_config.rs index 0bc354746..77933c393 100644 --- a/examples/demo-rollup/stf/src/genesis_config.rs +++ b/examples/demo-rollup/stf/src/genesis_config.rs @@ -5,6 +5,7 @@ use std::convert::AsRef; use std::path::{Path, PathBuf}; +pub use crate::midnight_withdrawals::MidnightWithdrawalsConfig; pub use midnight_privacy::MidnightPrivacyConfig; use serde::de::DeserializeOwned; pub use sov_accounts::{AccountConfig, AccountData}; @@ -56,6 +57,8 @@ pub struct GenesisPaths { pub value_setter_zk_genesis_path: PathBuf, /// Midnight Privacy genesis path pub midnight_privacy_genesis_path: PathBuf, + /// Midnight Withdrawals genesis path + pub midnight_withdrawals_genesis_path: PathBuf, } impl GenesisPaths { @@ -79,6 +82,7 @@ impl GenesisPaths { value_setter_genesis_path: dir.as_ref().join("value_setter.json"), value_setter_zk_genesis_path: dir.as_ref().join("value_setter_zk.json"), midnight_privacy_genesis_path: dir.as_ref().join("midnight_privacy.json"), + midnight_withdrawals_genesis_path: dir.as_ref().join("midnight_withdrawals.json"), } } } @@ -132,6 +136,9 @@ where let midnight_privacy_config: MidnightPrivacyConfig = read_genesis_json(&genesis_paths.midnight_privacy_genesis_path)?; + let midnight_withdrawals_config: MidnightWithdrawalsConfig = + read_genesis_json(&genesis_paths.midnight_withdrawals_genesis_path)?; + Ok(GenesisConfig::new( bank_config, sequencer_registry_config, @@ -149,6 +156,7 @@ where value_setter_config, value_setter_zk_config, midnight_privacy_config, + midnight_withdrawals_config, )) } diff --git a/examples/demo-rollup/stf/src/lib.rs b/examples/demo-rollup/stf/src/lib.rs index e048727b1..73d5954f2 100644 --- a/examples/demo-rollup/stf/src/lib.rs +++ b/examples/demo-rollup/stf/src/lib.rs @@ -3,6 +3,8 @@ #[cfg(feature = "native")] pub mod genesis_config; +/// Prototype Midnight withdrawal module. +pub mod midnight_withdrawals; mod preverified_authenticator; pub mod runtime; #[cfg(feature = "test-utils")] diff --git a/examples/demo-rollup/stf/src/midnight_withdrawals.rs b/examples/demo-rollup/stf/src/midnight_withdrawals.rs new file mode 100644 index 000000000..acb54a8e3 --- /dev/null +++ b/examples/demo-rollup/stf/src/midnight_withdrawals.rs @@ -0,0 +1,286 @@ +//! Minimal Midnight L2 -> L1 withdrawal prototype. + +use std::fmt::Debug; + +use anyhow::{ensure, Context, Result}; +use borsh::{BorshDeserialize, BorshSerialize}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use sov_bank::{config_gas_token_id, Bank, Coins, TokenId}; +use sov_modules_api::macros::{serialize, UniversalWallet}; +use sov_modules_api::{ + Amount, Context as ModuleContext, DaSpec, EventEmitter, GenesisState, Module, ModuleId, + ModuleInfo, ModuleRestApi, SafeString, Spec, StateMap, StateValue, TxState, +}; +use strum::{EnumDiscriminants, EnumIs, VariantArray}; + +#[cfg(feature = "native")] +use sov_modules_api::prelude::axum::{self, routing::get, Router}; +#[cfg(feature = "native")] +use sov_modules_api::prelude::UnwrapInfallible; +#[cfg(feature = "native")] +use sov_modules_api::rest::utils::{errors, ApiResult, Path}; +#[cfg(feature = "native")] +use sov_modules_api::rest::{ApiState, HasCustomRestApi}; +#[cfg(feature = "native")] +use sov_modules_api::ApiStateAccessor; + +/// Midnight L1 identifier used by the prototype bridge. +pub type MidnightAddress = SafeString; + +/// Genesis configuration for the Midnight withdrawal prototype. +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct MidnightWithdrawalsConfig { + /// Enables or disables the withdrawal call entirely. + pub enabled: bool, +} + +/// Basic L2 -> L1 withdrawal queue storing burn records for later proof generation. +#[derive(Clone, ModuleInfo, ModuleRestApi)] +pub struct MidnightWithdrawals { + /// Module identifier assigned by the runtime. + #[id] + pub id: ModuleId, + /// Next nonce assigned to an outbound withdrawal message. + #[state] + pub next_nonce: StateValue, + /// Feature flag controlled at genesis. + #[state] + pub enabled: StateValue, + /// Persisted map of all withdrawal records by nonce. + #[state] + pub withdrawals: StateMap>, + /// Reference to the bank module, used to burn the canonical gas token (NIGHT). + #[module] + pub bank: Bank, +} + +/// Internal record mirroring a queued withdrawal for REST exposures and proofs. +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct StoredWithdrawal { + nonce: u64, + midnight_address: MidnightAddress, + amount: Amount, + token_id: TokenId, + l2_sender: S::Address, + gas_limit: Option, +} + +/// Call messages accepted by [`MidnightWithdrawals`]. +#[derive(Debug, PartialEq, Eq, Clone, JsonSchema, EnumDiscriminants, EnumIs, UniversalWallet)] +#[serialize(Borsh, Serde)] +#[schemars(rename = "MidnightWithdrawalsCallMessage")] +#[strum_discriminants(derive(VariantArray, EnumIs))] +#[serde(rename_all = "snake_case")] +pub enum CallMessage { + /// Burn NIGHT on L2 and enqueue a message for L1 finalization. + WithdrawNight { + /// Midnight recipient identifier supplied by the user. + midnight_address: MidnightAddress, + /// Amount of NIGHT to withdraw. + amount: Amount, + /// Placeholder for future L1 relayer gas budgeting. + gas_limit: Option, + }, +} + +/// Events emitted by [`MidnightWithdrawals`]. +#[derive(Debug, PartialEq, Eq, Clone, JsonSchema)] +#[serialize(Borsh, Serde)] +#[serde(rename_all = "snake_case")] +pub enum Event { + /// Emitted whenever a withdrawal request is queued. + WithdrawalQueued { + /// Sequential nonce assigned to the withdrawal. + nonce: u64, + /// Amount of NIGHT burned on L2. + amount: Amount, + }, +} + +impl Module for MidnightWithdrawals { + type Spec = S; + + type Config = MidnightWithdrawalsConfig; + + type CallMessage = CallMessage; + + type Event = Event; + + fn genesis( + &mut self, + _genesis_rollup_header: &<::Da as DaSpec>::BlockHeader, + config: &Self::Config, + state: &mut impl GenesisState, + ) -> anyhow::Result<()> { + self.next_nonce.set(&0, state)?; + self.enabled.set(&config.enabled, state)?; + Ok(()) + } + + fn call( + &mut self, + msg: Self::CallMessage, + context: &ModuleContext, + state: &mut impl TxState, + ) -> anyhow::Result<()> { + match msg { + CallMessage::WithdrawNight { + midnight_address, + amount, + gas_limit, + } => self.withdraw_night(midnight_address, amount, gas_limit, context, state), + } + } +} + +impl MidnightWithdrawals { + fn withdraw_night( + &mut self, + midnight_address: MidnightAddress, + amount: Amount, + gas_limit: Option, + context: &ModuleContext, + state: &mut impl TxState, + ) -> Result<()> { + self.ensure_enabled(state)?; + ensure!(amount > Amount::ZERO, "Withdrawal amount must be non-zero"); + + let coins = Coins { + amount, + token_id: config_gas_token_id(), + }; + + self.bank + .burn(coins.clone(), context.sender(), state) + .context("Failed to burn NIGHT while initiating withdrawal")?; + + let nonce = self.current_nonce(state)?; + let next_nonce = nonce + .checked_add(1) + .context("Midnight withdrawal nonce overflow")?; + self.next_nonce.set(&next_nonce, state)?; + + let record = StoredWithdrawal { + nonce, + midnight_address, + amount, + token_id: coins.token_id, + l2_sender: context.sender().clone(), + gas_limit, + }; + self.withdrawals.set(&nonce, &record, state)?; + + self.emit_event(state, Event::WithdrawalQueued { nonce, amount }); + + Ok(()) + } + + fn ensure_enabled(&self, state: &mut impl TxState) -> Result<()> { + let enabled = self.enabled.get(state)?.unwrap_or(false); + ensure!( + enabled, + "Midnight withdrawals are disabled in genesis config" + ); + Ok(()) + } + + fn current_nonce(&self, state: &mut impl TxState) -> Result { + Ok(self.next_nonce.get(state)?.unwrap_or(0)) + } + + #[cfg(feature = "native")] + fn record_to_response(record: StoredWithdrawal) -> WithdrawalResponse { + WithdrawalResponse { + nonce: record.nonce, + midnight_address: record.midnight_address, + amount: record.amount, + token_id: record.token_id, + l2_sender_debug: format!("{:?}", record.l2_sender), + gas_limit: record.gas_limit, + } + } +} + +#[cfg(feature = "native")] +impl MidnightWithdrawals +where + S: Spec, + S::Address: Debug, +{ + async fn route_get_withdrawal( + state: ApiState, + mut accessor: ApiStateAccessor, + Path(nonce): Path, + ) -> ApiResult { + let Some(record) = state + .withdrawals + .get(&nonce, &mut accessor) + .unwrap_infallible() + else { + return Err(errors::not_found_404("Midnight withdrawal", nonce)); + }; + Ok(Self::record_to_response(record).into()) + } + + async fn route_latest_nonce( + state: ApiState, + mut accessor: ApiStateAccessor, + ) -> ApiResult { + let next_nonce = state + .next_nonce + .get(&mut accessor) + .unwrap_infallible() + .unwrap_or(0); + Ok(LatestNonceResponse { next_nonce }.into()) + } +} + +#[cfg(feature = "native")] +impl HasCustomRestApi for MidnightWithdrawals +where + S: Spec, + S::Address: Debug, +{ + type Spec = S; + + fn custom_rest_api(&self, state: ApiState) -> Router<()> { + Router::new() + .route( + "/withdrawals/:nonce", + get(Self::route_get_withdrawal), + ) + .route( + "/withdrawals/latest-nonce", + get(Self::route_latest_nonce), + ) + .with_state(state.with(self.clone())) + } +} + +#[cfg(feature = "native")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +struct WithdrawalResponse { + /// Sequential nonce assigned on L2. + pub nonce: u64, + /// Midnight recipient identifier supplied in the call. + pub midnight_address: MidnightAddress, + /// Amount of NIGHT the user burned. + pub amount: Amount, + /// Token identifier (currently always the canonical gas token). + pub token_id: TokenId, + /// Debug representation of the L2 sender, used as a lightweight proof. + pub l2_sender_debug: String, + /// Optional relayer gas limit hint attached by the user. + pub gas_limit: Option, +} + +#[cfg(feature = "native")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +struct LatestNonceResponse { + /// Next nonce that will be assigned to a withdrawal. + pub next_nonce: u64, +} diff --git a/examples/demo-rollup/stf/src/runtime.rs b/examples/demo-rollup/stf/src/runtime.rs index 01af7b4e9..2c8b2aa1f 100644 --- a/examples/demo-rollup/stf/src/runtime.rs +++ b/examples/demo-rollup/stf/src/runtime.rs @@ -44,6 +44,7 @@ use sov_modules_api::{DispatchCall, Event, Genesis, Hooks, MessageCodec, RawTx, #[cfg(feature = "native")] use crate::genesis_config::GenesisPaths; +use crate::midnight_withdrawals; use crate::preverified_authenticator::PreverifiedEvmAuthenticator; mod __generated { @@ -90,6 +91,8 @@ where pub value_setter_zk: sov_value_setter_zk::ValueSetterZk, /// The Midnight Privacy module (shielded pool with Ligero proofs). pub midnight_privacy: midnight_privacy::ValueMidnightPrivacy, + /// Prototype Midnight L2 -> L1 withdrawal queue storing burns and exposing proof endpoints. + pub midnight_withdrawals: midnight_withdrawals::MidnightWithdrawals, } impl sov_modules_stf_blueprint::Runtime for Runtime diff --git a/examples/rollup-ligero/README.md b/examples/rollup-ligero/README.md index 51a964ba6..c6849799b 100644 --- a/examples/rollup-ligero/README.md +++ b/examples/rollup-ligero/README.md @@ -272,18 +272,68 @@ You can use the standard `sov-cli` from the main demo-rollup to interact with th ```bash # Build the CLI from demo-rollup cd ../demo-rollup -cargo build --release --bin sov-cli --features arbitrary +cargo build --bin sov-cli # Create a wallet -../../target/release/sov-cli keys import +../../target/debug/sov-cli keys import -# Import a transaction -../../target/release/sov-cli transactions import value_tx.json +# Import a transaction (example: ValueSetter call) +../../target/debug/sov-cli transactions import from-file value-setter \ + --path value_tx.json \ + --max-fee 1000000000 # Publish transactions -../../target/release/sov-cli transactions publish-batch http://127.0.0.1:12345 +../../target/debug/sov-cli node submit-batch by-address ``` +### Midnight Withdrawals Prototype + +The demo runtime now ships a bare-bones Midnight L2 → L1 withdrawal queue. It burns the canonical NIGHT token inside `sov_bank`, records the request, and exposes a REST endpoint you can treat as a temporary proof source. + +1. **Craft the call.** Create `withdraw_night.json` with the new module and call name. + + ```json + { + "withdraw_night": { + "midnight_address": "midnight1exampledestination000000000000000", + "amount": "1000000", + "gas_limit": null + } + } + ``` + +2. **Submit through the CLI** (or any signing flow) just like other transactions: + + ```bash + ../../target/debug/sov-cli transactions import from-file midnight-withdrawals \ + --path withdraw_night.json \ + --max-fee 1000000000 + ../../target/debug/sov-cli node submit-batch by-address + ``` + +3. **Observe balances dropping.** Query the gas token balance to confirm the burn: + + ```bash + curl http://127.0.0.1:12346/modules/bank/tokens/gas_token/balances/ + ``` + +4. **Fetch the lightweight proof.** Every withdrawal is stored by nonce and mirrored over REST: + + ```bash + curl http://127.0.0.1:12346/modules/midnight-withdrawals/withdrawals/0 | jq + curl http://127.0.0.1:12346/modules/midnight-withdrawals/withdrawals/latest-nonce + ``` + + The JSON contains the sender, target Midnight identifier, amount, and the gas hint. This is the minimal evidence that the withdrawal happened until the Merkle tree and L1 verification contracts are implemented. + +**Next steps toward the full architecture (Section 9 in the bridge design):** + +- Build a real `L2Messenger`/`L2MessageQueue` module that maintains an append-only Merkle tree (steps 3–4). +- Extend the batch attestation/TEE output so every finalized batch carries the `withdrawRoot`, enabling the L1 contracts to verify proofs (step 5). +- Deploy Midnight-side contracts that consume the queued messages, enforce replay protection, and transfer NIGHT back to the user (steps 6–7). + +Until these milestones ship, the REST response above is the canonical source of truth for testing the L2 → L1 UX. + The CLI is compatible because both rollups use the same STF (State Transition Function) and modules. ## Testing diff --git a/examples/rollup-ligero/autogenerated.rs b/examples/rollup-ligero/autogenerated.rs index 9eaa32a3b..d46215a9f 100644 --- a/examples/rollup-ligero/autogenerated.rs +++ b/examples/rollup-ligero/autogenerated.rs @@ -278,6 +278,14 @@ pub const SCHEMA_JSON: &str = r#"{ "value": { "ByIndex": 124 } + }, + { + "name": "MidnightWithdrawals", + "discriminant": 16, + "template": null, + "value": { + "ByIndex": 141 + } } ], "hide_tag": false @@ -3458,6 +3466,70 @@ pub const SCHEMA_JSON: &str = r#"{ ] } }, + { + "Tuple": { + "template": null, + "peekable": false, + "fields": [ + { + "value": { + "ByIndex": 142 + }, + "silent": false, + "doc": "" + } + ] + } + }, + { + "Enum": { + "type_name": "CallMessage", + "variants": [ + { + "name": "WithdrawNight", + "discriminant": 0, + "template": null, + "value": { + "ByIndex": 143 + } + } + ], + "hide_tag": false + } + }, + { + "Struct": { + "type_name": "__SovVirtualWallet_CallMessage_WithdrawNight", + "template": null, + "peekable": false, + "fields": [ + { + "display_name": "midnight_address", + "silent": false, + "value": { + "Immediate": "String" + }, + "doc": "" + }, + { + "display_name": "amount", + "silent": false, + "value": { + "ByIndex": 11 + }, + "doc": "" + }, + { + "display_name": "gas_limit", + "silent": false, + "value": { + "ByIndex": 68 + }, + "doc": "" + } + ] + } + }, { "Enum": { "type_name": "UniquenessData", @@ -3793,6 +3865,9 @@ pub const SCHEMA_JSON: &str = r#"{ }, { "name": "midnight_privacy" + }, + { + "name": "midnight_withdrawals" } ] }, @@ -4966,6 +5041,32 @@ pub const SCHEMA_JSON: &str = r#"{ } ] }, + { + "name": "", + "fields_or_variants": [] + }, + { + "name": "CallMessage", + "fields_or_variants": [ + { + "name": "withdraw_night" + } + ] + }, + { + "name": "__SovVirtualWallet_CallMessage_WithdrawNight", + "fields_or_variants": [ + { + "name": "midnight_address" + }, + { + "name": "amount" + }, + { + "name": "gas_limit" + } + ] + }, { "name": "UniquenessData", "fields_or_variants": [ diff --git a/examples/test-data/genesis/demo/mock/midnight_withdrawals.json b/examples/test-data/genesis/demo/mock/midnight_withdrawals.json new file mode 100644 index 000000000..c26ec9a1e --- /dev/null +++ b/examples/test-data/genesis/demo/mock/midnight_withdrawals.json @@ -0,0 +1,3 @@ +{ + "enabled": true +} \ No newline at end of file diff --git a/examples/test-data/genesis/integration-tests/midnight_withdrawals.json b/examples/test-data/genesis/integration-tests/midnight_withdrawals.json new file mode 100644 index 000000000..c26ec9a1e --- /dev/null +++ b/examples/test-data/genesis/integration-tests/midnight_withdrawals.json @@ -0,0 +1,3 @@ +{ + "enabled": true +} \ No newline at end of file From 689c311e8395856c60a13b5ab79bfbc9bf77550b Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Wed, 21 Jan 2026 16:24:59 +0100 Subject: [PATCH 13/20] port protocol types from L1 (Compact) contract --- Cargo.lock | 1 + crates/adapters/midnight/Cargo.toml | 1 + crates/adapters/midnight/src/lib.rs | 1 + .../adapters/midnight/src/protocol_types.rs | 205 ++++++++++++++++++ .../test-data/protocol/golden-vectors-v1.json | 61 ++++++ 5 files changed, 269 insertions(+) create mode 100644 crates/adapters/midnight/src/protocol_types.rs create mode 100644 crates/adapters/midnight/test-data/protocol/golden-vectors-v1.json diff --git a/Cargo.lock b/Cargo.lock index 74c6f2b04..cb3cce1c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15065,6 +15065,7 @@ dependencies = [ "reqwest 0.12.28", "serde", "serde_json", + "sha2 0.10.9", "tokio", ] diff --git a/crates/adapters/midnight/Cargo.toml b/crates/adapters/midnight/Cargo.toml index f6b1340bb..b97fe5272 100644 --- a/crates/adapters/midnight/Cargo.toml +++ b/crates/adapters/midnight/Cargo.toml @@ -19,6 +19,7 @@ midnight-node-ledger-helpers = { git = "https://github.com/midnightntwrk/midnigh reqwest = { workspace = true, features = ["json"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +sha2 = { workspace = true } [dev-dependencies] tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } diff --git a/crates/adapters/midnight/src/lib.rs b/crates/adapters/midnight/src/lib.rs index 6a4cc5470..75b9ef244 100644 --- a/crates/adapters/midnight/src/lib.rs +++ b/crates/adapters/midnight/src/lib.rs @@ -11,6 +11,7 @@ use serde_json::json; use std::collections::{BTreeMap, BTreeSet}; use std::ops::Deref; +pub mod protocol_types; pub mod utils; const CONTRACT_STATE_QUERY: &str = r#" diff --git a/crates/adapters/midnight/src/protocol_types.rs b/crates/adapters/midnight/src/protocol_types.rs new file mode 100644 index 000000000..75edad1f9 --- /dev/null +++ b/crates/adapters/midnight/src/protocol_types.rs @@ -0,0 +1,205 @@ +use sha2::{Digest, Sha256}; + +/// Domain separator used for L2 → L1 withdrawal messages. +const DS_L2_TO_L1_WITHDRAW: [u8; 32] = pad_domain("mdn:l2l1:wdraw"); +/// Domain separator used for L2 withdrawal tree leaves. +const DS_L2_WITHDRAW_LEAF: [u8; 32] = pad_domain("mdn:l2w:leaf"); + +/// Zero-filled bytes32 helper reused across hashing routines. +pub const ZERO_BYTES32: [u8; 32] = [0u8; 32]; + +/// Canonical withdrawal message payload as defined by `ProtocolTypes`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct WithdrawMessage { + /// L2 sender (compressed as bytes32). + pub sender: [u8; 32], + /// L1 recipient (bytes32 address / commitment). + pub recipient: [u8; 32], + /// Amount of NIGHT to withdraw. + pub amount: u128, + /// Withdrawal nonce assigned by the queue. + pub nonce: u64, +} + +impl WithdrawMessage { + /// Creates a new withdraw message. + pub const fn new(sender: [u8; 32], recipient: [u8; 32], amount: u128, nonce: u64) -> Self { + Self { + sender, + recipient, + amount, + nonce, + } + } +} + +/// Compute the canonical SHA-256 hash of an L2 → L1 withdrawal message. +pub fn hash_withdraw_message(message: &WithdrawMessage) -> [u8; 32] { + let mut hasher = Sha256::new(); + hasher.update(DS_L2_TO_L1_WITHDRAW); + hasher.update(message.sender); + hasher.update(message.recipient); + hasher.update(u128_to_bytes32_le(message.amount)); + hasher.update(u64_to_bytes32_le(message.nonce)); + finalize(hasher) +} + +/// Compute the leaf hash derived from a withdrawal message hash. +pub fn hash_withdraw_leaf(message_hash: &[u8; 32]) -> [u8; 32] { + let mut hasher = Sha256::new(); + hasher.update(DS_L2_WITHDRAW_LEAF); + hasher.update(message_hash); + finalize(hasher) +} + +/// Compute an internal Merkle node hash as `SHA256(left || right)`. +pub fn hash_merkle_node(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] { + let mut hasher = Sha256::new(); + hasher.update(left); + hasher.update(right); + finalize(hasher) +} + +/// Encode a `u64` as a 32-byte little-endian value. +pub fn u64_to_bytes32_le(value: u64) -> [u8; 32] { + let mut out = [0u8; 32]; + out[..8].copy_from_slice(&value.to_le_bytes()); + out +} + +/// Encode a `u128` as a 32-byte little-endian value. +pub fn u128_to_bytes32_le(value: u128) -> [u8; 32] { + let mut out = [0u8; 32]; + out[..16].copy_from_slice(&value.to_le_bytes()); + out +} + +const fn pad_domain(tag: &str) -> [u8; 32] { + let bytes = tag.as_bytes(); + let mut out = [0u8; 32]; + let mut i = 0; + while i < bytes.len() { + out[i] = bytes[i]; + i += 1; + } + out +} + +fn finalize(hasher: Sha256) -> [u8; 32] { + let digest = hasher.finalize(); + let mut out = [0u8; 32]; + out.copy_from_slice(&digest); + out +} + +#[cfg(test)] +mod tests { + use super::*; + use hex::ToHex; + use serde::Deserialize; + + const GOLDEN_VECTORS: &str = + include_str!("../test-data/protocol/golden-vectors-v1.json"); + + #[derive(Deserialize)] + struct GoldenVectors { + vectors: VectorGroup, + #[serde(rename = "zeroHashes")] + zero_hashes: ZeroHashes, + } + + #[derive(Deserialize)] + struct VectorGroup { + #[serde(rename = "withdrawal1")] + withdrawal: WithdrawalVector, + #[serde(rename = "withdrawLeaf1")] + withdraw_leaf: WithdrawLeafVector, + } + + #[derive(Deserialize)] + struct WithdrawalVector { + input: WithdrawalInput, + #[serde(rename = "expectedHash")] + expected_hash: String, + } + + #[derive(Deserialize)] + struct WithdrawalInput { + #[serde(rename = "senderAscii")] + sender_ascii: String, + #[serde(rename = "recipientAscii")] + recipient_ascii: String, + amount: String, + nonce: String, + } + + #[derive(Deserialize)] + struct WithdrawLeafVector { + #[serde(rename = "messageHash")] + message_hash: String, + #[serde(rename = "expectedLeafHash")] + expected_leaf_hash: String, + } + + #[derive(Deserialize)] + struct ZeroHashes { + #[serde(rename = "level0")] + level0: String, + #[serde(rename = "level1")] + level1: String, + } + + #[test] + fn withdrawal_hash_matches_golden_vector() { + let vectors: GoldenVectors = serde_json::from_str(GOLDEN_VECTORS).unwrap(); + let withdrawal = vectors.vectors.withdrawal; + let msg = WithdrawMessage::new( + ascii_to_bytes32(&withdrawal.input.sender_ascii), + ascii_to_bytes32(&withdrawal.input.recipient_ascii), + withdrawal.input.amount.parse().unwrap(), + withdrawal.input.nonce.parse().unwrap(), + ); + let hash = hash_withdraw_message(&msg); + assert_eq!(hash.encode_hex::(), withdrawal.expected_hash); + } + + #[test] + fn withdraw_leaf_hash_matches_vector() { + let vectors: GoldenVectors = serde_json::from_str(GOLDEN_VECTORS).unwrap(); + let leaf = vectors.vectors.withdraw_leaf; + let message_hash = decode_hex32(&leaf.message_hash); + let computed = hash_withdraw_leaf(&message_hash); + assert_eq!(computed.encode_hex::(), leaf.expected_leaf_hash); + } + + #[test] + fn zero_hash_levels_match_contract_reference() { + let vectors: GoldenVectors = serde_json::from_str(GOLDEN_VECTORS).unwrap(); + let zero_level0 = hash_merkle_node(&ZERO_BYTES32, &ZERO_BYTES32); + assert_eq!( + zero_level0.encode_hex::(), + vectors.zero_hashes.level0 + ); + let zero_level1 = hash_merkle_node(&zero_level0, &zero_level0); + assert_eq!( + zero_level1.encode_hex::(), + vectors.zero_hashes.level1 + ); + } + + fn ascii_to_bytes32(input: &str) -> [u8; 32] { + let bytes = input.as_bytes(); + assert!(bytes.len() <= 32, "ascii input longer than 32 bytes"); + let mut out = [0u8; 32]; + out[..bytes.len()].copy_from_slice(bytes); + out + } + + fn decode_hex32(hex_str: &str) -> [u8; 32] { + let bytes = hex::decode(hex_str).unwrap(); + assert_eq!(bytes.len(), 32, "hex input must decode to 32 bytes"); + let mut out = [0u8; 32]; + out.copy_from_slice(&bytes); + out + } +} diff --git a/crates/adapters/midnight/test-data/protocol/golden-vectors-v1.json b/crates/adapters/midnight/test-data/protocol/golden-vectors-v1.json new file mode 100644 index 000000000..dbdc1fe46 --- /dev/null +++ b/crates/adapters/midnight/test-data/protocol/golden-vectors-v1.json @@ -0,0 +1,61 @@ +{ + "version": "1.0", + "description": "Golden test vectors for Protocol V1. DO NOT MODIFY unless making a consensus-breaking change.", + "generatedAt": "2025-12-19", + "encoding": { + "integers": "32-byte little-endian", + "domainSeparators": "32-byte zero-padded ASCII", + "hashFunction": "sha256(concat(bytes32 chunks))" + }, + "domainSeparators": { + "l1ToL2Deposit": "mdn:l1l2:deposit", + "l2ToL1Withdraw": "mdn:l2l1:wdraw", + "l1QueueRolling": "mdn:l1q:rolling", + "l2WithdrawLeaf": "mdn:l2w:leaf", + "merkleNode": "mdn:merkle:node" + }, + "zeroHashes": { + "level0": "f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "level1": "db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "level2": "c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "level3": "536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "level4": "9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30" + }, + "vectors": { + "withdrawal1": { + "input": { + "sender": "616c69636500000000000000000000000000000000000000000000000000000", + "senderAscii": "alice", + "recipient": "626f6200000000000000000000000000000000000000000000000000000000", + "recipientAscii": "bob", + "amount": "1000000000000000000", + "nonce": "1" + }, + "expectedHash": "dd6f90565a8836e42db825008b69d8724ccaeba75976aca34d8a3f0e4be64ccc" + }, + "deposit1": { + "input": { + "sender": "0000000000000000000000000000000000000000000000000000000000000000", + "senderAscii": "", + "recipient": "616c69636500000000000000000000000000000000000000000000000000000", + "recipientAscii": "alice", + "amount": "1000000000000000000", + "nonce": "42", + "gasLimit": "100000", + "dataHash": "0000000000000000000000000000000000000000000000000000000000000000" + }, + "expectedHash": "e2089c3ddcdace28b6aacba8d8a92567c5c96a42252a7a26cefd1acfdae599e4" + }, + "rollingHash1": { + "description": "Initial rolling hash after deposit1", + "prevHash": "0000000000000000000000000000000000000000000000000000000000000000", + "leafHash": "e2089c3ddcdace28b6aacba8d8a92567c5c96a42252a7a26cefd1acfdae599e4", + "expectedHash": "63cd510cb8d3608e2fd452238945d81c136b49a5855b23eb959fcee6e0ce8e80" + }, + "withdrawLeaf1": { + "description": "Withdrawal leaf from withdrawal1", + "messageHash": "dd6f90565a8836e42db825008b69d8724ccaeba75976aca34d8a3f0e4be64ccc", + "expectedLeafHash": "f81a08ee2b411732de65da6753f7986d1222e4c08f3b341e49c23cbc639ebe27" + } + } +} \ No newline at end of file From fccc723fb10bfec879ac4c60d027c3a827ea8f11 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Wed, 21 Jan 2026 18:08:42 +0100 Subject: [PATCH 14/20] message queue, withdrawals root --- Cargo.lock | 2 + examples/demo-rollup/stf/Cargo.toml | 9 +- .../stf/src/midnight_withdrawals.rs | 244 ++++++++++++++++-- 3 files changed, 228 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb3cce1c7..aaa0fe4ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3710,6 +3710,7 @@ version = "0.3.0" dependencies = [ "anyhow", "borsh", + "hex", "midnight-privacy", "schemars 0.8.22", "serde", @@ -3722,6 +3723,7 @@ dependencies = [ "sov-chain-state", "sov-evm", "sov-kernels", + "sov-midnight-adapter", "sov-modules-api", "sov-modules-stf-blueprint", "sov-operator-incentives", diff --git a/examples/demo-rollup/stf/Cargo.toml b/examples/demo-rollup/stf/Cargo.toml index 60569ddc7..0cc4d0dd0 100644 --- a/examples/demo-rollup/stf/Cargo.toml +++ b/examples/demo-rollup/stf/Cargo.toml @@ -17,7 +17,9 @@ borsh = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["alloc", "derive"] } strum = { workspace = true, features = ["derive"] } schemars = { workspace = true } +hex = { workspace = true } +sov-midnight-adapter = { workspace = true } sov-accounts = { workspace = true } sov-address = { workspace = true, features = ["evm"] } sov-attester-incentives = { workspace = true } @@ -70,11 +72,8 @@ native = [ "sov-rollup-apis", "sov-paymaster/native", "sov-address/native", - "sov-test-modules/native" + "sov-test-modules/native", ] # We only activate test-utils if we also have native since all our test-code use native by default. -test-utils = [ - "native", - "sov-test-utils", -] +test-utils = ["native", "sov-test-utils"] diff --git a/examples/demo-rollup/stf/src/midnight_withdrawals.rs b/examples/demo-rollup/stf/src/midnight_withdrawals.rs index acb54a8e3..135bfa0c5 100644 --- a/examples/demo-rollup/stf/src/midnight_withdrawals.rs +++ b/examples/demo-rollup/stf/src/midnight_withdrawals.rs @@ -1,12 +1,17 @@ //! Minimal Midnight L2 -> L1 withdrawal prototype. use std::fmt::Debug; +use std::sync::LazyLock; use anyhow::{ensure, Context, Result}; use borsh::{BorshDeserialize, BorshSerialize}; +use hex::{decode, encode}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use sov_bank::{config_gas_token_id, Bank, Coins, TokenId}; +use sov_midnight_adapter::protocol_types::{ + hash_merkle_node, hash_withdraw_leaf, hash_withdraw_message, WithdrawMessage, ZERO_BYTES32, +}; use sov_modules_api::macros::{serialize, UniversalWallet}; use sov_modules_api::{ Amount, Context as ModuleContext, DaSpec, EventEmitter, GenesisState, Module, ModuleId, @@ -42,12 +47,63 @@ pub struct MidnightWithdrawals { /// Module identifier assigned by the runtime. #[id] pub id: ModuleId, - /// Next nonce assigned to an outbound withdrawal message. - #[state] - pub next_nonce: StateValue, /// Feature flag controlled at genesis. #[state] pub enabled: StateValue, + /// Number of messages appended to the withdrawal queue. + #[state] + pub message_count: StateValue, + /// Current Merkle root of the withdrawal queue. + #[state] + pub withdraw_root: StateValue<[u8; 32]>, + /// Cached branch hash at level 0. + #[state] + pub branch_0: StateValue<[u8; 32]>, + /// Cached branch hash at level 1. + #[state] + pub branch_1: StateValue<[u8; 32]>, + /// Cached branch hash at level 2. + #[state] + pub branch_2: StateValue<[u8; 32]>, + /// Cached branch hash at level 3. + #[state] + pub branch_3: StateValue<[u8; 32]>, + /// Cached branch hash at level 4. + #[state] + pub branch_4: StateValue<[u8; 32]>, + /// Cached branch hash at level 5. + #[state] + pub branch_5: StateValue<[u8; 32]>, + /// Cached branch hash at level 6. + #[state] + pub branch_6: StateValue<[u8; 32]>, + /// Cached branch hash at level 7. + #[state] + pub branch_7: StateValue<[u8; 32]>, + /// Cached branch hash at level 8. + #[state] + pub branch_8: StateValue<[u8; 32]>, + /// Cached branch hash at level 9. + #[state] + pub branch_9: StateValue<[u8; 32]>, + /// Cached branch hash at level 10. + #[state] + pub branch_10: StateValue<[u8; 32]>, + /// Cached branch hash at level 11. + #[state] + pub branch_11: StateValue<[u8; 32]>, + /// Cached branch hash at level 12. + #[state] + pub branch_12: StateValue<[u8; 32]>, + /// Cached branch hash at level 13. + #[state] + pub branch_13: StateValue<[u8; 32]>, + /// Cached branch hash at level 14. + #[state] + pub branch_14: StateValue<[u8; 32]>, + /// Cached branch hash at level 15. + #[state] + pub branch_15: StateValue<[u8; 32]>, /// Persisted map of all withdrawal records by nonce. #[state] pub withdrawals: StateMap>, @@ -61,10 +117,38 @@ pub struct MidnightWithdrawals { pub struct StoredWithdrawal { nonce: u64, midnight_address: MidnightAddress, + recipient_bytes: [u8; 32], + sender_bytes: [u8; 32], amount: Amount, token_id: TokenId, l2_sender: S::Address, gas_limit: Option, + message_hash: [u8; 32], + leaf_hash: [u8; 32], +} + +const TREE_DEPTH: usize = 16; +const MAX_LEAVES: u64 = 1u64 << TREE_DEPTH; + +static ZERO_HASHES: LazyLock<[[u8; 32]; TREE_DEPTH]> = LazyLock::new(|| { + let mut hashes = [[0u8; 32]; TREE_DEPTH]; + hashes[0] = hash_merkle_node(&ZERO_BYTES32, &ZERO_BYTES32); + for level in 1..TREE_DEPTH { + hashes[level] = hash_merkle_node(&hashes[level - 1], &hashes[level - 1]); + } + hashes +}); + +fn zero_hash(level: usize) -> [u8; 32] { + ZERO_HASHES[level] +} + +fn zero_sibling(level: usize) -> [u8; 32] { + if level == 0 { + ZERO_BYTES32 + } else { + zero_hash(level - 1) + } } /// Call messages accepted by [`MidnightWithdrawals`]. @@ -114,8 +198,13 @@ impl Module for MidnightWithdrawals { config: &Self::Config, state: &mut impl GenesisState, ) -> anyhow::Result<()> { - self.next_nonce.set(&0, state)?; self.enabled.set(&config.enabled, state)?; + self.message_count.set(&0, state)?; + let initial_root = zero_hash(TREE_DEPTH - 1); + self.withdraw_root.set(&initial_root, state)?; + for level in 0..TREE_DEPTH { + self.branch_state(level).set(&ZERO_BYTES32, state)?; + } Ok(()) } @@ -157,18 +246,24 @@ impl MidnightWithdrawals { .context("Failed to burn NIGHT while initiating withdrawal")?; let nonce = self.current_nonce(state)?; - let next_nonce = nonce - .checked_add(1) - .context("Midnight withdrawal nonce overflow")?; - self.next_nonce.set(&next_nonce, state)?; + let sender_bytes = Self::sender_bytes(context.sender())?; + let recipient_bytes = Self::recipient_bytes(&midnight_address)?; + let message = WithdrawMessage::new(sender_bytes, recipient_bytes, amount.0, nonce); + let message_hash = hash_withdraw_message(&message); + let leaf_hash = hash_withdraw_leaf(&message_hash); + self.append_leaf(nonce, leaf_hash, state)?; let record = StoredWithdrawal { nonce, midnight_address, + recipient_bytes, + sender_bytes, amount, token_id: coins.token_id, l2_sender: context.sender().clone(), gas_limit, + message_hash, + leaf_hash, }; self.withdrawals.set(&nonce, &record, state)?; @@ -187,7 +282,95 @@ impl MidnightWithdrawals { } fn current_nonce(&self, state: &mut impl TxState) -> Result { - Ok(self.next_nonce.get(state)?.unwrap_or(0)) + Ok(self.message_count.get(state)?.unwrap_or(0)) + } + + fn append_leaf( + &mut self, + expected_index: u64, + leaf_hash: [u8; 32], + state: &mut impl TxState, + ) -> Result<()> { + ensure!( + expected_index < MAX_LEAVES, + "Midnight withdrawal queue is full" + ); + let index = self.message_count.get(state)?.unwrap_or(0); + ensure!( + index == expected_index, + "Midnight withdrawal nonce mismatch: expected {}, found {}", + expected_index, + index + ); + + let mut current = leaf_hash; + for level in 0..TREE_DEPTH { + let bit_set = ((index >> level) & 1) == 1; + let branch_state = self.branch_state(level); + let branch_value = branch_state.get(state)?.unwrap_or(ZERO_BYTES32); + if bit_set { + current = hash_merkle_node(&branch_value, ¤t); + } else { + branch_state.set(¤t, state)?; + let zero = zero_sibling(level); + current = hash_merkle_node(¤t, &zero); + } + } + + self.withdraw_root.set(¤t, state)?; + let next = index + .checked_add(1) + .context("Midnight withdrawal nonce overflow")?; + self.message_count.set(&next, state)?; + Ok(()) + } + + fn branch_state(&mut self, level: usize) -> &mut StateValue<[u8; 32]> { + match level { + 0 => &mut self.branch_0, + 1 => &mut self.branch_1, + 2 => &mut self.branch_2, + 3 => &mut self.branch_3, + 4 => &mut self.branch_4, + 5 => &mut self.branch_5, + 6 => &mut self.branch_6, + 7 => &mut self.branch_7, + 8 => &mut self.branch_8, + 9 => &mut self.branch_9, + 10 => &mut self.branch_10, + 11 => &mut self.branch_11, + 12 => &mut self.branch_12, + 13 => &mut self.branch_13, + 14 => &mut self.branch_14, + 15 => &mut self.branch_15, + _ => unreachable!("Invalid branch level {}", level), + } + } + + fn sender_bytes(address: &S::Address) -> Result<[u8; 32]> { + let raw = address.as_ref(); + ensure!(raw.len() == 32, "Sender address must be exactly 32 bytes"); + let mut out = [0u8; 32]; + out.copy_from_slice(raw); + Ok(out) + } + + fn recipient_bytes(address: &MidnightAddress) -> Result<[u8; 32]> { + let raw = address.as_str(); + let trimmed = raw.strip_prefix("0x").unwrap_or(raw); + let bytes = decode(trimmed).with_context(|| { + format!( + "Failed to decode Midnight recipient {}; expected hex-encoded bytes32", + raw + ) + })?; + ensure!( + bytes.len() == 32, + "Midnight recipient must decode to exactly 32 bytes" + ); + let mut out = [0u8; 32]; + out.copy_from_slice(&bytes); + Ok(out) } #[cfg(feature = "native")] @@ -199,6 +382,10 @@ impl MidnightWithdrawals { token_id: record.token_id, l2_sender_debug: format!("{:?}", record.l2_sender), gas_limit: record.gas_limit, + sender_bytes_hex: encode(record.sender_bytes), + recipient_bytes_hex: encode(record.recipient_bytes), + message_hash_hex: encode(record.message_hash), + leaf_hash_hex: encode(record.leaf_hash), } } } @@ -224,16 +411,25 @@ where Ok(Self::record_to_response(record).into()) } - async fn route_latest_nonce( + async fn route_queue_status( state: ApiState, mut accessor: ApiStateAccessor, - ) -> ApiResult { + ) -> ApiResult { let next_nonce = state - .next_nonce + .message_count .get(&mut accessor) .unwrap_infallible() .unwrap_or(0); - Ok(LatestNonceResponse { next_nonce }.into()) + let withdraw_root = state + .withdraw_root + .get(&mut accessor) + .unwrap_infallible() + .unwrap_or(zero_hash(TREE_DEPTH - 1)); + Ok(QueueStatusResponse { + next_nonce, + withdraw_root_hex: encode(withdraw_root), + } + .into()) } } @@ -247,14 +443,8 @@ where fn custom_rest_api(&self, state: ApiState) -> Router<()> { Router::new() - .route( - "/withdrawals/:nonce", - get(Self::route_get_withdrawal), - ) - .route( - "/withdrawals/latest-nonce", - get(Self::route_latest_nonce), - ) + .route("/withdrawals/:nonce", get(Self::route_get_withdrawal)) + .route("/withdrawals/queue", get(Self::route_queue_status)) .with_state(state.with(self.clone())) } } @@ -275,12 +465,22 @@ struct WithdrawalResponse { pub l2_sender_debug: String, /// Optional relayer gas limit hint attached by the user. pub gas_limit: Option, + /// Hex encoding of the raw sender bytes used in hashing. + pub sender_bytes_hex: String, + /// Hex encoding of the raw Midnight recipient bytes. + pub recipient_bytes_hex: String, + /// Hex encoding of the withdrawal message hash. + pub message_hash_hex: String, + /// Hex encoding of the Merkle leaf hash. + pub leaf_hash_hex: String, } #[cfg(feature = "native")] #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "snake_case")] -struct LatestNonceResponse { +struct QueueStatusResponse { /// Next nonce that will be assigned to a withdrawal. pub next_nonce: u64, + /// Hex encoding of the current withdraw root. + pub withdraw_root_hex: String, } From 54de3631c1483cecb6d432c7318d554271b647db Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Wed, 21 Jan 2026 19:07:28 +0100 Subject: [PATCH 15/20] withdrawal proof --- .../adapters/midnight/src/protocol_types.rs | 3 +- .../stf/src/midnight_withdrawals.rs | 398 +++++++++++++++++- 2 files changed, 397 insertions(+), 4 deletions(-) diff --git a/crates/adapters/midnight/src/protocol_types.rs b/crates/adapters/midnight/src/protocol_types.rs index 75edad1f9..50153a189 100644 --- a/crates/adapters/midnight/src/protocol_types.rs +++ b/crates/adapters/midnight/src/protocol_types.rs @@ -98,8 +98,7 @@ mod tests { use hex::ToHex; use serde::Deserialize; - const GOLDEN_VECTORS: &str = - include_str!("../test-data/protocol/golden-vectors-v1.json"); + const GOLDEN_VECTORS: &str = include_str!("../test-data/protocol/golden-vectors-v1.json"); #[derive(Deserialize)] struct GoldenVectors { diff --git a/examples/demo-rollup/stf/src/midnight_withdrawals.rs b/examples/demo-rollup/stf/src/midnight_withdrawals.rs index 135bfa0c5..1d3c33652 100644 --- a/examples/demo-rollup/stf/src/midnight_withdrawals.rs +++ b/examples/demo-rollup/stf/src/midnight_withdrawals.rs @@ -1,9 +1,11 @@ //! Minimal Midnight L2 -> L1 withdrawal prototype. +use std::array; +use std::collections::BTreeMap; use std::fmt::Debug; use std::sync::LazyLock; -use anyhow::{ensure, Context, Result}; +use anyhow::{bail, ensure, Context, Result}; use borsh::{BorshDeserialize, BorshSerialize}; use hex::{decode, encode}; use schemars::JsonSchema; @@ -20,7 +22,7 @@ use sov_modules_api::{ use strum::{EnumDiscriminants, EnumIs, VariantArray}; #[cfg(feature = "native")] -use sov_modules_api::prelude::axum::{self, routing::get, Router}; +use sov_modules_api::prelude::axum::{self, extract::Query, routing::get, Router}; #[cfg(feature = "native")] use sov_modules_api::prelude::UnwrapInfallible; #[cfg(feature = "native")] @@ -127,6 +129,54 @@ pub struct StoredWithdrawal { leaf_hash: [u8; 32], } +#[derive(Debug, Clone)] +struct WithdrawalProofBundle { + record: StoredWithdrawal, + siblings: [[u8; 32]; TREE_DEPTH], + index_bits_le: [bool; TREE_DEPTH], + leaf_count: u64, + withdraw_root: [u8; 32], +} + +/// Rust-side representation of Compact's `WithdrawProof16` struct. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct L1WithdrawProof16Binary { + /// Finalized batch index that attested the withdraw root. + pub batch_index: u64, + /// Nonce assigned by the withdrawal queue. + pub nonce: u64, + /// Merkle index bits (little-endian, level 0 first). + pub index_bits_le: [bool; TREE_DEPTH], + /// Merkle sibling nodes ordered from leaves to root. + pub siblings: [[u8; 32]; TREE_DEPTH], +} + +impl L1WithdrawProof16Binary { + fn new( + batch_index: u64, + nonce: u64, + index_bits_le: [bool; TREE_DEPTH], + siblings: [[u8; 32]; TREE_DEPTH], + ) -> Self { + Self { + batch_index, + nonce, + index_bits_le, + siblings, + } + } + + #[cfg(feature = "native")] + fn into_response(self) -> L1WithdrawProof16Response { + L1WithdrawProof16Response { + batch_index: self.batch_index, + nonce: self.nonce, + index_bits_le: self.index_bits_le, + sibling_hashes_hex: array::from_fn(|idx| encode(self.siblings[idx])), + } + } +} + const TREE_DEPTH: usize = 16; const MAX_LEAVES: u64 = 1u64 << TREE_DEPTH; @@ -151,6 +201,101 @@ fn zero_sibling(level: usize) -> [u8; 32] { } } +fn index_bits_le(nonce: u64) -> [bool; TREE_DEPTH] { + let mut bits = [false; TREE_DEPTH]; + for level in 0..TREE_DEPTH { + bits[level] = ((nonce >> level) & 1) == 1; + } + bits +} + +struct MerkleArtifacts { + siblings: [[u8; 32]; TREE_DEPTH], + index_bits_le: [bool; TREE_DEPTH], + root: [u8; 32], +} + +fn compute_merkle_artifacts( + nonce: u64, + leaf_count: u64, + fetch_leaf: &mut F, +) -> Result +where + F: FnMut(u64) -> Result<[u8; 32]>, +{ + ensure!(leaf_count <= MAX_LEAVES, "Invalid withdrawal queue depth"); + ensure!( + nonce < leaf_count, + "Withdrawal {nonce} has not been enqueued yet" + ); + + let index_bits = index_bits_le(nonce); + let mut cache = BTreeMap::new(); + let mut siblings = [[0u8; 32]; TREE_DEPTH]; + + for level in 0..TREE_DEPTH { + let block_size = 1u64 << level; + let block_index = nonce / block_size; + let sibling_index = block_index ^ 1; + let sibling_start = sibling_index.saturating_mul(block_size); + + siblings[level] = if sibling_start >= MAX_LEAVES { + if level == 0 { + ZERO_BYTES32 + } else { + zero_hash(level - 1) + } + } else { + compute_subtree_hash(level, sibling_start, leaf_count, &mut cache, fetch_leaf)? + }; + } + + let root = compute_subtree_hash(TREE_DEPTH, 0, leaf_count, &mut cache, fetch_leaf)?; + Ok(MerkleArtifacts { + siblings, + index_bits_le: index_bits, + root, + }) +} + +fn compute_subtree_hash( + level: usize, + start_index: u64, + leaf_count: u64, + cache: &mut BTreeMap<(usize, u64), [u8; 32]>, + fetch_leaf: &mut F, +) -> Result<[u8; 32]> +where + F: FnMut(u64) -> Result<[u8; 32]>, +{ + if let Some(value) = cache.get(&(level, start_index)) { + return Ok(*value); + } + + let value = if start_index >= MAX_LEAVES { + if level == 0 { + ZERO_BYTES32 + } else { + zero_hash(level - 1) + } + } else if level == 0 { + if start_index < leaf_count { + fetch_leaf(start_index)? + } else { + ZERO_BYTES32 + } + } else { + let half = 1u64 << (level - 1); + let left = compute_subtree_hash(level - 1, start_index, leaf_count, cache, fetch_leaf)?; + let right_start = start_index.checked_add(half).unwrap_or(MAX_LEAVES); + let right = compute_subtree_hash(level - 1, right_start, leaf_count, cache, fetch_leaf)?; + hash_merkle_node(&left, &right) + }; + + cache.insert((level, start_index), value); + Ok(value) +} + /// Call messages accepted by [`MidnightWithdrawals`]. #[derive(Debug, PartialEq, Eq, Clone, JsonSchema, EnumDiscriminants, EnumIs, UniversalWallet)] #[serialize(Borsh, Serde)] @@ -325,6 +470,55 @@ impl MidnightWithdrawals { Ok(()) } + #[allow(dead_code)] + fn build_withdrawal_proof( + &mut self, + nonce: u64, + state: &mut impl TxState, + ) -> Result> { + let total = self.message_count.get(state)?.unwrap_or(0); + ensure!(nonce < total, "Withdrawal {nonce} is not available yet"); + let withdraw_root = self + .withdraw_root + .get(state)? + .unwrap_or(zero_hash(TREE_DEPTH - 1)); + let record = self + .withdrawals + .get(&nonce, state)? + .with_context(|| format!("Missing withdrawal record {nonce}"))?; + + let mut cached_leaves = BTreeMap::new(); + let mut fetch_leaf = |index: u64| -> Result<[u8; 32]> { + if let Some(value) = cached_leaves.get(&index) { + return Ok(*value); + } + if index >= total { + return Ok(ZERO_BYTES32); + } + let leaf = self + .withdrawals + .get(&index, state)? + .with_context(|| format!("Missing withdrawal record {index}"))? + .leaf_hash; + cached_leaves.insert(index, leaf); + Ok(leaf) + }; + + let artifacts = compute_merkle_artifacts(nonce, total, &mut fetch_leaf)?; + ensure!( + artifacts.root == withdraw_root, + "Reconstructed withdraw root mismatch while building proof" + ); + + Ok(WithdrawalProofBundle { + record, + siblings: artifacts.siblings, + index_bits_le: artifacts.index_bits_le, + leaf_count: total, + withdraw_root, + }) + } + fn branch_state(&mut self, level: usize) -> &mut StateValue<[u8; 32]> { match level { 0 => &mut self.branch_0, @@ -431,6 +625,75 @@ where } .into()) } + + async fn route_withdrawal_proof( + state: ApiState, + mut accessor: ApiStateAccessor, + Path(nonce): Path, + Query(params): Query, + ) -> ApiResult { + let total = state + .message_count + .get(&mut accessor) + .unwrap_infallible() + .unwrap_or(0); + let Some(record) = state + .withdrawals + .get(&nonce, &mut accessor) + .unwrap_infallible() + else { + return Err(errors::not_found_404("Midnight withdrawal", nonce)); + }; + if nonce >= total { + return Err(errors::bad_request_400( + "Withdrawal has not been enqueued yet", + format!("nonce {nonce} >= message_count {total}"), + )); + } + let withdraw_root = state + .withdraw_root + .get(&mut accessor) + .unwrap_infallible() + .unwrap_or(zero_hash(TREE_DEPTH - 1)); + + let mut cached_leaves = BTreeMap::new(); + let mut fetch_leaf = |index: u64| -> Result<[u8; 32]> { + if let Some(value) = cached_leaves.get(&index) { + return Ok(*value); + } + if index >= total { + return Ok(ZERO_BYTES32); + } + let Some(withdrawal) = state + .withdrawals + .get(&index, &mut accessor) + .unwrap_infallible() + else { + bail!("Missing withdrawal record {index}"); + }; + cached_leaves.insert(index, withdrawal.leaf_hash); + Ok(withdrawal.leaf_hash) + }; + + let artifacts = compute_merkle_artifacts(nonce, total, &mut fetch_leaf) + .map_err(|err| errors::internal_server_error_response_500(err))?; + if artifacts.root != withdraw_root { + return Err(errors::internal_server_error_response_500( + "Merkle root mismatch while reconstructing proof", + )); + } + + let bundle = WithdrawalProofBundle { + record, + siblings: artifacts.siblings, + index_bits_le: artifacts.index_bits_le, + leaf_count: total, + withdraw_root, + }; + let response = + WithdrawalProofResponse::from_bundle(bundle, params.batch_index.unwrap_or_default()); + Ok(response.into()) + } } #[cfg(feature = "native")] @@ -444,6 +707,10 @@ where fn custom_rest_api(&self, state: ApiState) -> Router<()> { Router::new() .route("/withdrawals/:nonce", get(Self::route_get_withdrawal)) + .route( + "/withdrawals/:nonce/proof", + get(Self::route_withdrawal_proof), + ) .route("/withdrawals/queue", get(Self::route_queue_status)) .with_state(state.with(self.clone())) } @@ -484,3 +751,130 @@ struct QueueStatusResponse { /// Hex encoding of the current withdraw root. pub withdraw_root_hex: String, } + +#[cfg(feature = "native")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +struct ProofQuery { + batch_index: Option, +} + +#[cfg(feature = "native")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +struct WithdrawalProofResponse { + pub nonce: u64, + pub midnight_address: MidnightAddress, + pub amount: Amount, + pub token_id: TokenId, + pub l2_sender_debug: String, + pub gas_limit: Option, + pub sender_bytes_hex: String, + pub recipient_bytes_hex: String, + pub message_hash_hex: String, + pub leaf_hash_hex: String, + pub leaf_count: u64, + pub withdraw_root_hex: String, + pub l1_proof: L1WithdrawProof16Response, +} + +#[cfg(feature = "native")] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +struct L1WithdrawProof16Response { + pub batch_index: u64, + pub nonce: u64, + pub index_bits_le: [bool; TREE_DEPTH], + pub sibling_hashes_hex: [String; TREE_DEPTH], +} + +#[cfg(feature = "native")] +impl WithdrawalProofResponse { + fn from_bundle(bundle: WithdrawalProofBundle, batch_index: u64) -> Self + where + S: Spec, + S::Address: Debug, + { + let WithdrawalProofBundle { + record, + siblings, + index_bits_le, + leaf_count, + withdraw_root, + } = bundle; + let l1_proof = + L1WithdrawProof16Binary::new(batch_index, record.nonce, index_bits_le, siblings) + .into_response(); + WithdrawalProofResponse { + nonce: record.nonce, + midnight_address: record.midnight_address, + amount: record.amount, + token_id: record.token_id, + l2_sender_debug: format!("{:?}", record.l2_sender), + gas_limit: record.gas_limit, + sender_bytes_hex: encode(record.sender_bytes), + recipient_bytes_hex: encode(record.recipient_bytes), + message_hash_hex: encode(record.message_hash), + leaf_hash_hex: encode(record.leaf_hash), + leaf_count, + withdraw_root_hex: encode(withdraw_root), + l1_proof, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn sample_leaf(index: u64) -> [u8; 32] { + let sender = [index as u8; 32]; + let mut recipient = [0u8; 32]; + recipient.fill(index as u8 + 1); + let msg = WithdrawMessage::new(sender, recipient, (index as u128) + 1, index); + let message_hash = hash_withdraw_message(&msg); + hash_withdraw_leaf(&message_hash) + } + + fn compute_naive_root(leaves: &[[u8; 32]]) -> [u8; 32] { + let mut level = vec![[0u8; 32]; MAX_LEAVES as usize]; + for (idx, leaf) in leaves.iter().enumerate() { + level[idx] = *leaf; + } + let mut size = MAX_LEAVES as usize; + while size > 1 { + let mut next = 0; + for i in 0..size / 2 { + let left = level[2 * i]; + let right = level[2 * i + 1]; + level[next] = hash_merkle_node(&left, &right); + next += 1; + } + size /= 2; + } + level[0] + } + + #[test] + fn merkle_artifacts_round_trip() { + let total = 4u64; + let leaves: Vec<[u8; 32]> = (0..total).map(sample_leaf).collect(); + let mut fetch = |idx: u64| -> Result<[u8; 32]> { + Ok(*leaves.get(idx as usize).unwrap_or(&ZERO_BYTES32)) + }; + let artifacts = compute_merkle_artifacts(2, total, &mut fetch).unwrap(); + let naive_root = compute_naive_root(&leaves); + assert_eq!(artifacts.root, naive_root); + let mut acc = leaves[2]; + for level in 0..TREE_DEPTH { + let sibling = artifacts.siblings[level]; + let (left, right) = if artifacts.index_bits_le[level] { + (sibling, acc) + } else { + (acc, sibling) + }; + acc = hash_merkle_node(&left, &right); + } + assert_eq!(acc, artifacts.root); + } +} From a71e575542cbba2ffb33d609c0c608f62494800f Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Mon, 30 Mar 2026 12:30:03 +0200 Subject: [PATCH 16/20] new contracts version --- examples/rollup-ligero/midnight-l2-contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rollup-ligero/midnight-l2-contracts b/examples/rollup-ligero/midnight-l2-contracts index fd9877767..635664f1a 160000 --- a/examples/rollup-ligero/midnight-l2-contracts +++ b/examples/rollup-ligero/midnight-l2-contracts @@ -1 +1 @@ -Subproject commit fd9877767934d748469be0f7a970e5f580c8222f +Subproject commit 635664f1af1e2d471ad4c40e505249df59e6730f From 5565d136992c854605ad68a41d14c33187b09043 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Tue, 31 Mar 2026 20:05:37 +0200 Subject: [PATCH 17/20] initialize verifier set on contract genesis --- Cargo.lock | 28 +++++++++---------- .../src/processes/executor_client.rs | 12 ++++++++ .../src/native_only/mod.rs | 11 ++++++++ examples/rollup-ligero/autogenerated.rs | 26 ++++++++--------- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aaa0fe4ba..7fa1fd8fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8295,20 +8295,6 @@ dependencies = [ "tracing-subscriber 0.3.22", ] -[[package]] -name = "midnight-monitor-lambda" -version = "0.3.0" -dependencies = [ - "anyhow", - "lambda_runtime", - "reqwest 0.12.28", - "serde", - "serde_json", - "tokio", - "tracing", - "tracing-subscriber 0.3.22", -] - [[package]] name = "midnight-ledger" version = "7.0.0" @@ -8395,6 +8381,20 @@ dependencies = [ "quote 1.0.43", ] +[[package]] +name = "midnight-monitor-lambda" +version = "0.3.0" +dependencies = [ + "anyhow", + "lambda_runtime", + "reqwest 0.12.28", + "serde", + "serde_json", + "tokio", + "tracing", + "tracing-subscriber 0.3.22", +] + [[package]] name = "midnight-node-ledger-helpers" version = "0.1.0" diff --git a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs index bbb9d64dd..d52b9d916 100644 --- a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs +++ b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs @@ -155,6 +155,18 @@ impl ExecutorClient { }) } + /// Calls the executor's setVerifierSet endpoint (POST /set-verifier-set). + /// + /// The executor reads `VERIFIER_SECRET_KEYS` from its environment (or uses + /// built-in defaults), derives the corresponding public keys, and submits a + /// `setVerifierSet` transaction to the Bridge contract. + pub async fn set_verifier_set(&self) -> Result<()> { + let body = json!({}); + let _: serde_json::Value = + post_json(&self.client, &self.base_url, "/set-verifier-set", &body).await?; + Ok(()) + } + /// Submits finalizeBatch to the executor (POST /finalize-batch). pub async fn finalize_batch( &self, diff --git a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs index 2bd5ea6ea..347ef0fb5 100644 --- a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs +++ b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs @@ -515,6 +515,17 @@ pub trait FullNodeBlueprint: RollupBlueprint { .context("Failed to build executor HTTP client")?; executor_client = Some(ExecutorClient::new(http_client, exec_url)); + if is_genesis { + info!("Setting verifier set on freshly deployed Bridge contract..."); + executor_client + .as_ref() + .expect("executor_client just created") + .set_verifier_set() + .await + .context("Failed to set verifier set on Bridge contract")?; + info!("Verifier set configured successfully"); + } + rollup_id = parse_rollup_id_hex(bcfg.rollup_id_hex.as_deref()); resolved_contract_address = Some(contract_address); } diff --git a/examples/rollup-ligero/autogenerated.rs b/examples/rollup-ligero/autogenerated.rs index d46215a9f..cb70a3383 100644 --- a/examples/rollup-ligero/autogenerated.rs +++ b/examples/rollup-ligero/autogenerated.rs @@ -1,7 +1,7 @@ -pub const CHAIN_HASH: [u8; 32] = [100, 58, 216, 206, 190, 155, 146, 153, 200, 170, 118, 30, 5, 110, 160, 150, 82, 18, 163, 52, 208, 175, 104, 205, 225, 5, 9, 99, 32, 195, 219, 168]; +pub const CHAIN_HASH: [u8; 32] = [88, 188, 166, 204, 116, 229, 243, 99, 58, 64, 222, 43, 69, 23, 233, 69, 71, 2, 253, 63, 17, 209, 44, 100, 166, 192, 65, 237, 146, 7, 149, 16]; #[allow(dead_code)] -pub const SCHEMA_BORSH: &[u8] = &[148, 0, 0, 0, 1, 11, 0, 0, 0, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 118, 101, 114, 115, 105, 111, 110, 101, 100, 95, 116, 120, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 86, 101, 114, 115, 105, 111, 110, 101, 100, 84, 120, 1, 0, 0, 0, 2, 0, 0, 0, 86, 48, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 86, 101, 114, 115, 105, 111, 110, 48, 0, 0, 5, 0, 0, 0, 9, 0, 0, 0, 115, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 114, 117, 110, 116, 105, 109, 101, 95, 99, 97, 108, 108, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 117, 110, 105, 113, 117, 101, 110, 101, 115, 115, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 100, 101, 116, 97, 105, 108, 115, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 0, 0, 0, 69, 100, 50, 53, 53, 49, 57, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 109, 115, 103, 95, 115, 105, 103, 0, 1, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 0, 0, 0, 69, 100, 50, 53, 53, 49, 57, 80, 117, 98, 108, 105, 99, 75, 101, 121, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 82, 117, 110, 116, 105, 109, 101, 67, 97, 108, 108, 16, 0, 0, 0, 4, 0, 0, 0, 66, 97, 110, 107, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 83, 101, 113, 117, 101, 110, 99, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 1, 0, 1, 0, 27, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 79, 112, 101, 114, 97, 116, 111, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 2, 0, 1, 0, 34, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 65, 116, 116, 101, 115, 116, 101, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 3, 0, 1, 0, 37, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 80, 114, 111, 118, 101, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 4, 0, 1, 0, 42, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 65, 99, 99, 111, 117, 110, 116, 115, 5, 0, 1, 0, 46, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 85, 110, 105, 113, 117, 101, 110, 101, 115, 115, 6, 0, 1, 0, 51, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 67, 104, 97, 105, 110, 83, 116, 97, 116, 101, 7, 0, 1, 0, 53, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 66, 108, 111, 98, 83, 116, 111, 114, 97, 103, 101, 8, 0, 1, 0, 55, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 80, 97, 121, 109, 97, 115, 116, 101, 114, 9, 0, 1, 0, 56, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 69, 118, 109, 10, 0, 1, 0, 85, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 11, 0, 1, 0, 88, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 83, 121, 110, 116, 104, 101, 116, 105, 99, 76, 111, 97, 100, 12, 0, 1, 0, 109, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 86, 97, 108, 117, 101, 83, 101, 116, 116, 101, 114, 13, 0, 1, 0, 114, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 86, 97, 108, 117, 101, 83, 101, 116, 116, 101, 114, 90, 107, 14, 0, 1, 0, 120, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 77, 105, 100, 110, 105, 103, 104, 116, 80, 114, 105, 118, 97, 99, 121, 15, 0, 1, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 6, 0, 0, 0, 11, 0, 0, 0, 67, 114, 101, 97, 116, 101, 84, 111, 107, 101, 110, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 1, 1, 26, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 32, 116, 111, 32, 97, 100, 100, 114, 101, 115, 115, 32, 123, 125, 32, 123, 125, 46, 1, 0, 19, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 66, 117, 114, 110, 2, 0, 1, 0, 22, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 77, 105, 110, 116, 3, 0, 1, 0, 23, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 70, 114, 101, 101, 122, 101, 4, 0, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 5, 0, 1, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 1, 42, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 67, 114, 101, 97, 116, 101, 84, 111, 107, 101, 110, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 116, 111, 107, 101, 110, 95, 110, 97, 109, 101, 0, 1, 5, 0, 0, 0, 0, 14, 0, 0, 0, 116, 111, 107, 101, 110, 95, 100, 101, 99, 105, 109, 97, 108, 115, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 105, 110, 105, 116, 105, 97, 108, 95, 98, 97, 108, 97, 110, 99, 101, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 109, 105, 110, 116, 95, 116, 111, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 100, 109, 105, 110, 115, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 115, 117, 112, 112, 108, 121, 95, 99, 97, 112, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 5, 1, 2, 0, 0, 1, 0, 0, 0, 1, 0, 9, 1, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 77, 117, 108, 116, 105, 65, 100, 100, 114, 101, 115, 115, 2, 0, 0, 0, 8, 0, 0, 0, 83, 116, 97, 110, 100, 97, 114, 100, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 86, 109, 1, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 28, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 115, 111, 118, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 12, 0, 0, 0, 0, 0, 0, 0, 3, 0, 11, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 84, 114, 97, 110, 115, 102, 101, 114, 1, 26, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 32, 116, 111, 32, 97, 100, 100, 114, 101, 115, 115, 32, 123, 125, 32, 123, 125, 46, 0, 2, 0, 0, 0, 2, 0, 0, 0, 116, 111, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 67, 111, 105, 110, 115, 1, 23, 0, 0, 0, 123, 125, 32, 99, 111, 105, 110, 115, 32, 111, 102, 32, 116, 111, 107, 101, 110, 32, 73, 68, 32, 123, 125, 1, 2, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 3, 6, 0, 0, 0, 116, 111, 107, 101, 110, 95, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 66, 117, 114, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 77, 105, 110, 116, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 109, 105, 110, 116, 95, 116, 111, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 37, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 70, 114, 101, 101, 122, 101, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 42, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 0, 0, 2, 0, 0, 0, 9, 0, 0, 0, 110, 101, 119, 95, 97, 100, 109, 105, 110, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 12, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 4, 0, 0, 0, 8, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 1, 0, 29, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 1, 0, 1, 0, 31, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 73, 110, 105, 116, 105, 97, 116, 101, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 2, 0, 1, 0, 32, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 3, 0, 1, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 38, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 68, 101, 112, 111, 115, 105, 116, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 49, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 73, 110, 105, 116, 105, 97, 116, 101, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 19, 0, 0, 0, 85, 112, 100, 97, 116, 101, 82, 101, 119, 97, 114, 100, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 82, 101, 119, 97, 114, 100, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 18, 0, 0, 0, 110, 101, 119, 95, 114, 101, 119, 97, 114, 100, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 6, 0, 0, 0, 16, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 65, 116, 116, 101, 115, 116, 101, 114, 0, 0, 1, 0, 39, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 66, 101, 103, 105, 110, 69, 120, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 1, 0, 0, 12, 0, 0, 0, 69, 120, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 2, 0, 0, 18, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 67, 104, 97, 108, 108, 101, 110, 103, 101, 114, 3, 0, 1, 0, 40, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 69, 120, 105, 116, 67, 104, 97, 108, 108, 101, 110, 103, 101, 114, 4, 0, 0, 15, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 5, 0, 1, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 8, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 1, 0, 44, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 1, 0, 1, 0, 45, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 69, 120, 105, 116, 2, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 18, 0, 0, 0, 73, 110, 115, 101, 114, 116, 67, 114, 101, 100, 101, 110, 116, 105, 97, 108, 73, 100, 0, 0, 1, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 78, 111, 116, 73, 110, 115, 116, 97, 110, 116, 105, 97, 98, 108, 101, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 18, 0, 0, 0, 84, 101, 114, 109, 105, 110, 97, 116, 101, 83, 101, 116, 117, 112, 77, 111, 100, 101, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 17, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 80, 97, 121, 109, 97, 115, 116, 101, 114, 0, 0, 1, 0, 58, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 83, 101, 116, 80, 97, 121, 101, 114, 70, 111, 114, 83, 101, 113, 117, 101, 110, 99, 101, 114, 1, 0, 1, 0, 74, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 85, 112, 100, 97, 116, 101, 80, 111, 108, 105, 99, 121, 2, 0, 1, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 103, 105, 115, 116, 101, 114, 80, 97, 121, 109, 97, 115, 116, 101, 114, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 112, 111, 108, 105, 99, 121, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26, 0, 0, 0, 80, 97, 121, 109, 97, 115, 116, 101, 114, 80, 111, 108, 105, 99, 121, 73, 110, 105, 116, 105, 97, 108, 105, 122, 101, 114, 0, 0, 4, 0, 0, 0, 20, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 95, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 121, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 112, 97, 121, 101, 101, 115, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 95, 117, 112, 100, 97, 116, 101, 114, 115, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 95, 115, 101, 113, 117, 101, 110, 99, 101, 114, 115, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 80, 97, 121, 101, 101, 80, 111, 108, 105, 99, 121, 2, 0, 0, 0, 5, 0, 0, 0, 65, 108, 108, 111, 119, 0, 0, 1, 0, 61, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 68, 101, 110, 121, 1, 0, 0, 0, 1, 36, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 80, 97, 121, 101, 101, 80, 111, 108, 105, 99, 121, 95, 65, 108, 108, 111, 119, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 109, 97, 120, 95, 102, 101, 101, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 109, 97, 120, 95, 103, 97, 115, 95, 112, 114, 105, 99, 101, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 116, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 95, 108, 105, 109, 105, 116, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 63, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 8, 1, 3, 0, 66, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 71, 97, 115, 80, 114, 105, 99, 101, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 8, 1, 13, 0, 70, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 65, 117, 116, 104, 111, 114, 105, 122, 101, 100, 83, 101, 113, 117, 101, 110, 99, 101, 114, 115, 2, 0, 0, 0, 3, 0, 0, 0, 65, 108, 108, 0, 0, 0, 4, 0, 0, 0, 83, 111, 109, 101, 1, 0, 1, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 30, 0, 0, 0, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 80, 97, 121, 101, 114, 70, 111, 114, 83, 101, 113, 117, 101, 110, 99, 101, 114, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 112, 97, 121, 101, 114, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 43, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 80, 111, 108, 105, 99, 121, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 112, 97, 121, 101, 114, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 117, 112, 100, 97, 116, 101, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 12, 0, 0, 0, 80, 111, 108, 105, 99, 121, 85, 112, 100, 97, 116, 101, 0, 0, 6, 0, 0, 0, 16, 0, 0, 0, 115, 101, 113, 117, 101, 110, 99, 101, 114, 95, 117, 112, 100, 97, 116, 101, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 117, 112, 100, 97, 116, 101, 114, 115, 95, 116, 111, 95, 97, 100, 100, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 117, 112, 100, 97, 116, 101, 114, 115, 95, 116, 111, 95, 114, 101, 109, 111, 118, 101, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 105, 101, 115, 95, 116, 111, 95, 115, 101, 116, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 105, 101, 115, 95, 116, 111, 95, 100, 101, 108, 101, 116, 101, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 95, 112, 111, 108, 105, 99, 121, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 83, 101, 113, 117, 101, 110, 99, 101, 114, 83, 101, 116, 85, 112, 100, 97, 116, 101, 2, 0, 0, 0, 8, 0, 0, 0, 65, 108, 108, 111, 119, 65, 108, 108, 0, 0, 0, 6, 0, 0, 0, 85, 112, 100, 97, 116, 101, 1, 0, 1, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 22, 0, 0, 0, 65, 108, 108, 111, 119, 101, 100, 83, 101, 113, 117, 101, 110, 99, 101, 114, 85, 112, 100, 97, 116, 101, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 116, 111, 95, 97, 100, 100, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 116, 111, 95, 114, 101, 109, 111, 118, 101, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 73, 0, 0, 0, 0, 0, 0, 0, 3, 0, 17, 0, 0, 0, 0, 0, 0, 0, 3, 0, 69, 0, 0, 0, 0, 0, 0, 0, 3, 0, 60, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 114, 108, 112, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 17, 0, 0, 0, 82, 108, 112, 69, 118, 109, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 114, 108, 112, 0, 1, 2, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 14, 0, 0, 0, 10, 0, 0, 0, 87, 114, 105, 116, 101, 67, 101, 108, 108, 115, 0, 0, 1, 0, 90, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 87, 114, 105, 116, 101, 67, 117, 115, 116, 111, 109, 1, 0, 1, 0, 91, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 82, 101, 97, 100, 67, 101, 108, 108, 115, 2, 0, 1, 0, 93, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 72, 97, 115, 104, 66, 121, 116, 101, 115, 3, 0, 1, 0, 94, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 72, 97, 115, 104, 67, 117, 115, 116, 111, 109, 4, 0, 1, 0, 95, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 83, 116, 111, 114, 101, 83, 105, 103, 110, 97, 116, 117, 114, 101, 5, 0, 1, 0, 96, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 86, 101, 114, 105, 102, 121, 83, 105, 103, 110, 97, 116, 117, 114, 101, 6, 0, 0, 21, 0, 0, 0, 86, 101, 114, 105, 102, 121, 67, 117, 115, 116, 111, 109, 83, 105, 103, 110, 97, 116, 117, 114, 101, 7, 0, 1, 0, 97, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 83, 116, 111, 114, 101, 83, 101, 114, 105, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 8, 0, 1, 0, 98, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 66, 121, 116, 101, 115, 65, 115, 83, 116, 114, 105, 110, 103, 9, 0, 0, 23, 0, 0, 0, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 67, 117, 115, 116, 111, 109, 83, 116, 114, 105, 110, 103, 10, 0, 1, 0, 99, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 68, 101, 108, 101, 116, 101, 67, 101, 108, 108, 115, 11, 0, 1, 0, 100, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 83, 101, 116, 72, 111, 111, 107, 12, 0, 1, 0, 101, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 13, 0, 1, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 87, 114, 105, 116, 101, 67, 101, 108, 108, 115, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 100, 97, 116, 97, 95, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 87, 114, 105, 116, 101, 67, 117, 115, 116, 111, 109, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 7, 0, 0, 0, 99, 111, 110, 116, 101, 110, 116, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 5, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 82, 101, 97, 100, 67, 101, 108, 108, 115, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 72, 97, 115, 104, 66, 121, 116, 101, 115, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 102, 105, 108, 108, 101, 114, 0, 1, 0, 5, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 72, 97, 115, 104, 67, 117, 115, 116, 111, 109, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 55, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 116, 111, 114, 101, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 115, 105, 103, 110, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 101, 115, 115, 97, 103, 101, 0, 1, 5, 0, 0, 0, 0, 1, 62, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 86, 101, 114, 105, 102, 121, 67, 117, 115, 116, 111, 109, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 115, 105, 103, 110, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 101, 115, 115, 97, 103, 101, 0, 1, 5, 0, 0, 0, 0, 1, 62, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 116, 111, 114, 101, 83, 101, 114, 105, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 67, 117, 115, 116, 111, 109, 83, 116, 114, 105, 110, 103, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 68, 101, 108, 101, 116, 101, 67, 101, 108, 108, 115, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 101, 116, 72, 111, 111, 107, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 112, 114, 101, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 112, 111, 115, 116, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 103, 0, 0, 0, 0, 0, 0, 0, 13, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 3, 0, 0, 0, 4, 0, 0, 0, 82, 101, 97, 100, 0, 0, 1, 0, 105, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 87, 114, 105, 116, 101, 1, 0, 1, 0, 106, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 68, 101, 108, 101, 116, 101, 2, 0, 1, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 82, 101, 97, 100, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 36, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 87, 114, 105, 116, 101, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 100, 97, 116, 97, 95, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 37, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 68, 101, 108, 101, 116, 101, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 110, 101, 119, 95, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 30, 0, 0, 0, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 77, 97, 110, 121, 73, 110, 100, 105, 118, 105, 100, 117, 97, 108, 86, 97, 108, 117, 101, 115, 0, 0, 1, 0, 111, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 72, 101, 97, 118, 121, 83, 116, 97, 116, 101, 1, 0, 1, 0, 112, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 82, 117, 110, 67, 80, 85, 72, 101, 97, 118, 121, 79, 112, 101, 114, 97, 116, 105, 111, 110, 2, 0, 1, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 1, 61, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 77, 97, 110, 121, 73, 110, 100, 105, 118, 105, 100, 117, 97, 108, 86, 97, 108, 117, 101, 115, 0, 0, 2, 0, 0, 0, 20, 0, 0, 0, 110, 117, 109, 98, 101, 114, 95, 111, 102, 95, 111, 112, 101, 114, 97, 116, 105, 111, 110, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 97, 108, 116, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 72, 101, 97, 118, 121, 83, 116, 97, 116, 101, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 110, 117, 109, 98, 101, 114, 95, 111, 102, 95, 110, 101, 119, 95, 118, 97, 108, 117, 101, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 20, 0, 0, 0, 109, 97, 120, 95, 104, 101, 97, 118, 121, 95, 115, 116, 97, 116, 101, 95, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 97, 108, 116, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 117, 110, 67, 80, 85, 72, 101, 97, 118, 121, 79, 112, 101, 114, 97, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 105, 116, 101, 114, 97, 116, 105, 111, 110, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 5, 0, 0, 0, 8, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 0, 0, 1, 0, 116, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 83, 101, 116, 77, 97, 110, 121, 86, 97, 108, 117, 101, 115, 1, 0, 1, 0, 117, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 65, 115, 115, 101, 114, 116, 86, 105, 115, 105, 98, 108, 101, 83, 108, 111, 116, 78, 117, 109, 98, 101, 114, 2, 0, 1, 0, 118, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 65, 110, 100, 83, 108, 101, 101, 112, 3, 0, 1, 0, 119, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 80, 97, 110, 105, 99, 4, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 1, 54, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 65, 115, 115, 101, 114, 116, 86, 105, 115, 105, 98, 108, 101, 83, 108, 111, 116, 78, 117, 109, 98, 101, 114, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 101, 120, 112, 101, 99, 116, 101, 100, 95, 118, 105, 115, 105, 98, 108, 101, 95, 115, 108, 111, 116, 95, 110, 117, 109, 98, 101, 114, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 47, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 65, 110, 100, 83, 108, 101, 101, 112, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 12, 0, 0, 0, 115, 108, 101, 101, 112, 95, 109, 105, 108, 108, 105, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 2, 0, 0, 0, 17, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 87, 105, 116, 104, 80, 114, 111, 111, 102, 0, 0, 1, 0, 122, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 1, 0, 1, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 87, 105, 116, 104, 80, 114, 111, 111, 102, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 110, 101, 119, 95, 109, 101, 116, 104, 111, 100, 95, 105, 100, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 8, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 0, 0, 1, 0, 126, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 1, 0, 1, 0, 130, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 2, 0, 1, 0, 135, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 3, 0, 1, 0, 136, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 70, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 4, 0, 1, 0, 137, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 85, 110, 102, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 5, 0, 1, 0, 139, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 65, 100, 100, 80, 111, 111, 108, 65, 100, 109, 105, 110, 6, 0, 1, 0, 140, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 82, 101, 109, 111, 118, 101, 80, 111, 111, 108, 65, 100, 109, 105, 110, 7, 0, 1, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 1, 38, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 68, 101, 112, 111, 115, 105, 116, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 1, 0, 0, 0, 0, 3, 0, 0, 0, 114, 104, 111, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 114, 101, 99, 105, 112, 105, 101, 110, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 118, 105, 101, 119, 95, 102, 118, 107, 115, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 128, 0, 0, 0, 0, 0, 0, 0, 13, 0, 129, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 84, 114, 97, 110, 115, 102, 101, 114, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 97, 110, 99, 104, 111, 114, 95, 114, 111, 111, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 110, 117, 108, 108, 105, 102, 105, 101, 114, 115, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 118, 105, 101, 119, 95, 99, 105, 112, 104, 101, 114, 116, 101, 120, 116, 115, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 133, 0, 0, 0, 0, 0, 0, 0, 13, 0, 134, 0, 0, 0, 0, 0, 0, 0, 1, 13, 0, 0, 0, 69, 110, 99, 114, 121, 112, 116, 101, 100, 78, 111, 116, 101, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 99, 109, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 110, 111, 110, 99, 101, 0, 1, 1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 99, 116, 0, 1, 2, 0, 0, 0, 0, 0, 14, 0, 0, 0, 102, 118, 107, 95, 99, 111, 109, 109, 105, 116, 109, 101, 110, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 109, 97, 99, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 0, 0, 7, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 97, 110, 99, 104, 111, 114, 95, 114, 111, 111, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 108, 108, 105, 102, 105, 101, 114, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 119, 105, 116, 104, 100, 114, 97, 119, 95, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 1, 0, 0, 0, 0, 2, 0, 0, 0, 116, 111, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 118, 105, 101, 119, 95, 99, 105, 112, 104, 101, 114, 116, 101, 120, 116, 115, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 110, 101, 119, 95, 109, 101, 116, 104, 111, 100, 95, 105, 100, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 70, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 97, 100, 100, 114, 101, 115, 115, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 64, 0, 0, 0, 0, 0, 0, 0, 3, 8, 0, 0, 0, 112, 114, 105, 118, 112, 111, 111, 108, 0, 0, 0, 0, 0, 1, 46, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 110, 102, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 97, 100, 100, 114, 101, 115, 115, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 43, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 65, 100, 100, 80, 111, 111, 108, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 46, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 109, 111, 118, 101, 80, 111, 111, 108, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 110, 105, 113, 117, 101, 110, 101, 115, 115, 68, 97, 116, 97, 2, 0, 0, 0, 5, 0, 0, 0, 78, 111, 110, 99, 101, 0, 0, 1, 0, 143, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 71, 101, 110, 101, 114, 97, 116, 105, 111, 110, 1, 0, 1, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 1, 9, 0, 0, 0, 84, 120, 68, 101, 116, 97, 105, 108, 115, 0, 0, 4, 0, 0, 0, 21, 0, 0, 0, 109, 97, 120, 95, 112, 114, 105, 111, 114, 105, 116, 121, 95, 102, 101, 101, 95, 98, 105, 112, 115, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 97, 120, 95, 102, 101, 101, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 99, 104, 97, 105, 110, 95, 105, 100, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 1, 19, 0, 0, 0, 85, 110, 115, 105, 103, 110, 101, 100, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 3, 0, 0, 0, 12, 0, 0, 0, 114, 117, 110, 116, 105, 109, 101, 95, 99, 97, 108, 108, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 117, 110, 105, 113, 117, 101, 110, 101, 115, 115, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 100, 101, 116, 97, 105, 108, 115, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 225, 16, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 84, 101, 115, 116, 67, 104, 97, 105, 110, 49, 91, 190, 78, 133, 80, 109, 242, 86, 96, 227, 47, 33, 78, 65, 74, 101, 221, 54, 245, 195, 131, 47, 159, 218, 9, 204, 51, 225, 153, 162, 254]; +pub const SCHEMA_BORSH: &[u8] = &[151, 0, 0, 0, 1, 11, 0, 0, 0, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 118, 101, 114, 115, 105, 111, 110, 101, 100, 95, 116, 120, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 86, 101, 114, 115, 105, 111, 110, 101, 100, 84, 120, 1, 0, 0, 0, 2, 0, 0, 0, 86, 48, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 86, 101, 114, 115, 105, 111, 110, 48, 0, 0, 5, 0, 0, 0, 9, 0, 0, 0, 115, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 114, 117, 110, 116, 105, 109, 101, 95, 99, 97, 108, 108, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 117, 110, 105, 113, 117, 101, 110, 101, 115, 115, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 100, 101, 116, 97, 105, 108, 115, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 0, 0, 0, 69, 100, 50, 53, 53, 49, 57, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 109, 115, 103, 95, 115, 105, 103, 0, 1, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 0, 0, 0, 69, 100, 50, 53, 53, 49, 57, 80, 117, 98, 108, 105, 99, 75, 101, 121, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 82, 117, 110, 116, 105, 109, 101, 67, 97, 108, 108, 17, 0, 0, 0, 4, 0, 0, 0, 66, 97, 110, 107, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 83, 101, 113, 117, 101, 110, 99, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 1, 0, 1, 0, 27, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 79, 112, 101, 114, 97, 116, 111, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 2, 0, 1, 0, 34, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 65, 116, 116, 101, 115, 116, 101, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 3, 0, 1, 0, 37, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 80, 114, 111, 118, 101, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 4, 0, 1, 0, 42, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 65, 99, 99, 111, 117, 110, 116, 115, 5, 0, 1, 0, 46, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 85, 110, 105, 113, 117, 101, 110, 101, 115, 115, 6, 0, 1, 0, 51, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 67, 104, 97, 105, 110, 83, 116, 97, 116, 101, 7, 0, 1, 0, 53, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 66, 108, 111, 98, 83, 116, 111, 114, 97, 103, 101, 8, 0, 1, 0, 55, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 80, 97, 121, 109, 97, 115, 116, 101, 114, 9, 0, 1, 0, 56, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 69, 118, 109, 10, 0, 1, 0, 85, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 11, 0, 1, 0, 88, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 83, 121, 110, 116, 104, 101, 116, 105, 99, 76, 111, 97, 100, 12, 0, 1, 0, 109, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 86, 97, 108, 117, 101, 83, 101, 116, 116, 101, 114, 13, 0, 1, 0, 114, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 86, 97, 108, 117, 101, 83, 101, 116, 116, 101, 114, 90, 107, 14, 0, 1, 0, 120, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 77, 105, 100, 110, 105, 103, 104, 116, 80, 114, 105, 118, 97, 99, 121, 15, 0, 1, 0, 124, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 77, 105, 100, 110, 105, 103, 104, 116, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 115, 16, 0, 1, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 6, 0, 0, 0, 11, 0, 0, 0, 67, 114, 101, 97, 116, 101, 84, 111, 107, 101, 110, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 1, 1, 26, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 32, 116, 111, 32, 97, 100, 100, 114, 101, 115, 115, 32, 123, 125, 32, 123, 125, 46, 1, 0, 19, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 66, 117, 114, 110, 2, 0, 1, 0, 22, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 77, 105, 110, 116, 3, 0, 1, 0, 23, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 70, 114, 101, 101, 122, 101, 4, 0, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 5, 0, 1, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 1, 42, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 67, 114, 101, 97, 116, 101, 84, 111, 107, 101, 110, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 116, 111, 107, 101, 110, 95, 110, 97, 109, 101, 0, 1, 5, 0, 0, 0, 0, 14, 0, 0, 0, 116, 111, 107, 101, 110, 95, 100, 101, 99, 105, 109, 97, 108, 115, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 105, 110, 105, 116, 105, 97, 108, 95, 98, 97, 108, 97, 110, 99, 101, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 109, 105, 110, 116, 95, 116, 111, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 100, 109, 105, 110, 115, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 115, 117, 112, 112, 108, 121, 95, 99, 97, 112, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 5, 1, 2, 0, 0, 1, 0, 0, 0, 1, 0, 9, 1, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 77, 117, 108, 116, 105, 65, 100, 100, 114, 101, 115, 115, 2, 0, 0, 0, 8, 0, 0, 0, 83, 116, 97, 110, 100, 97, 114, 100, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 86, 109, 1, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 28, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 115, 111, 118, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 12, 0, 0, 0, 0, 0, 0, 0, 3, 0, 11, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 84, 114, 97, 110, 115, 102, 101, 114, 1, 26, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 32, 116, 111, 32, 97, 100, 100, 114, 101, 115, 115, 32, 123, 125, 32, 123, 125, 46, 0, 2, 0, 0, 0, 2, 0, 0, 0, 116, 111, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 67, 111, 105, 110, 115, 1, 23, 0, 0, 0, 123, 125, 32, 99, 111, 105, 110, 115, 32, 111, 102, 32, 116, 111, 107, 101, 110, 32, 73, 68, 32, 123, 125, 1, 2, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 3, 6, 0, 0, 0, 116, 111, 107, 101, 110, 95, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 66, 117, 114, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 77, 105, 110, 116, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 109, 105, 110, 116, 95, 116, 111, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 37, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 70, 114, 101, 101, 122, 101, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 42, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 0, 0, 2, 0, 0, 0, 9, 0, 0, 0, 110, 101, 119, 95, 97, 100, 109, 105, 110, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 12, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 4, 0, 0, 0, 8, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 1, 0, 29, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 1, 0, 1, 0, 31, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 73, 110, 105, 116, 105, 97, 116, 101, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 2, 0, 1, 0, 32, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 3, 0, 1, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 38, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 68, 101, 112, 111, 115, 105, 116, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 49, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 73, 110, 105, 116, 105, 97, 116, 101, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 19, 0, 0, 0, 85, 112, 100, 97, 116, 101, 82, 101, 119, 97, 114, 100, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 82, 101, 119, 97, 114, 100, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 18, 0, 0, 0, 110, 101, 119, 95, 114, 101, 119, 97, 114, 100, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 6, 0, 0, 0, 16, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 65, 116, 116, 101, 115, 116, 101, 114, 0, 0, 1, 0, 39, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 66, 101, 103, 105, 110, 69, 120, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 1, 0, 0, 12, 0, 0, 0, 69, 120, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 2, 0, 0, 18, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 67, 104, 97, 108, 108, 101, 110, 103, 101, 114, 3, 0, 1, 0, 40, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 69, 120, 105, 116, 67, 104, 97, 108, 108, 101, 110, 103, 101, 114, 4, 0, 0, 15, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 5, 0, 1, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 8, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 1, 0, 44, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 1, 0, 1, 0, 45, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 69, 120, 105, 116, 2, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 18, 0, 0, 0, 73, 110, 115, 101, 114, 116, 67, 114, 101, 100, 101, 110, 116, 105, 97, 108, 73, 100, 0, 0, 1, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 78, 111, 116, 73, 110, 115, 116, 97, 110, 116, 105, 97, 98, 108, 101, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 18, 0, 0, 0, 84, 101, 114, 109, 105, 110, 97, 116, 101, 83, 101, 116, 117, 112, 77, 111, 100, 101, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 17, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 80, 97, 121, 109, 97, 115, 116, 101, 114, 0, 0, 1, 0, 58, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 83, 101, 116, 80, 97, 121, 101, 114, 70, 111, 114, 83, 101, 113, 117, 101, 110, 99, 101, 114, 1, 0, 1, 0, 74, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 85, 112, 100, 97, 116, 101, 80, 111, 108, 105, 99, 121, 2, 0, 1, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 103, 105, 115, 116, 101, 114, 80, 97, 121, 109, 97, 115, 116, 101, 114, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 112, 111, 108, 105, 99, 121, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26, 0, 0, 0, 80, 97, 121, 109, 97, 115, 116, 101, 114, 80, 111, 108, 105, 99, 121, 73, 110, 105, 116, 105, 97, 108, 105, 122, 101, 114, 0, 0, 4, 0, 0, 0, 20, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 95, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 121, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 112, 97, 121, 101, 101, 115, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 95, 117, 112, 100, 97, 116, 101, 114, 115, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 95, 115, 101, 113, 117, 101, 110, 99, 101, 114, 115, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 80, 97, 121, 101, 101, 80, 111, 108, 105, 99, 121, 2, 0, 0, 0, 5, 0, 0, 0, 65, 108, 108, 111, 119, 0, 0, 1, 0, 61, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 68, 101, 110, 121, 1, 0, 0, 0, 1, 36, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 80, 97, 121, 101, 101, 80, 111, 108, 105, 99, 121, 95, 65, 108, 108, 111, 119, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 109, 97, 120, 95, 102, 101, 101, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 109, 97, 120, 95, 103, 97, 115, 95, 112, 114, 105, 99, 101, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 116, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 95, 108, 105, 109, 105, 116, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 63, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 8, 1, 3, 0, 66, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 71, 97, 115, 80, 114, 105, 99, 101, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 8, 1, 13, 0, 70, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 65, 117, 116, 104, 111, 114, 105, 122, 101, 100, 83, 101, 113, 117, 101, 110, 99, 101, 114, 115, 2, 0, 0, 0, 3, 0, 0, 0, 65, 108, 108, 0, 0, 0, 4, 0, 0, 0, 83, 111, 109, 101, 1, 0, 1, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 30, 0, 0, 0, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 80, 97, 121, 101, 114, 70, 111, 114, 83, 101, 113, 117, 101, 110, 99, 101, 114, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 112, 97, 121, 101, 114, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 43, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 80, 111, 108, 105, 99, 121, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 112, 97, 121, 101, 114, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 117, 112, 100, 97, 116, 101, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 12, 0, 0, 0, 80, 111, 108, 105, 99, 121, 85, 112, 100, 97, 116, 101, 0, 0, 6, 0, 0, 0, 16, 0, 0, 0, 115, 101, 113, 117, 101, 110, 99, 101, 114, 95, 117, 112, 100, 97, 116, 101, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 117, 112, 100, 97, 116, 101, 114, 115, 95, 116, 111, 95, 97, 100, 100, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 117, 112, 100, 97, 116, 101, 114, 115, 95, 116, 111, 95, 114, 101, 109, 111, 118, 101, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 105, 101, 115, 95, 116, 111, 95, 115, 101, 116, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 105, 101, 115, 95, 116, 111, 95, 100, 101, 108, 101, 116, 101, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 95, 112, 111, 108, 105, 99, 121, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 83, 101, 113, 117, 101, 110, 99, 101, 114, 83, 101, 116, 85, 112, 100, 97, 116, 101, 2, 0, 0, 0, 8, 0, 0, 0, 65, 108, 108, 111, 119, 65, 108, 108, 0, 0, 0, 6, 0, 0, 0, 85, 112, 100, 97, 116, 101, 1, 0, 1, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 22, 0, 0, 0, 65, 108, 108, 111, 119, 101, 100, 83, 101, 113, 117, 101, 110, 99, 101, 114, 85, 112, 100, 97, 116, 101, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 116, 111, 95, 97, 100, 100, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 116, 111, 95, 114, 101, 109, 111, 118, 101, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 73, 0, 0, 0, 0, 0, 0, 0, 3, 0, 17, 0, 0, 0, 0, 0, 0, 0, 3, 0, 69, 0, 0, 0, 0, 0, 0, 0, 3, 0, 60, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 114, 108, 112, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 17, 0, 0, 0, 82, 108, 112, 69, 118, 109, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 114, 108, 112, 0, 1, 2, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 14, 0, 0, 0, 10, 0, 0, 0, 87, 114, 105, 116, 101, 67, 101, 108, 108, 115, 0, 0, 1, 0, 90, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 87, 114, 105, 116, 101, 67, 117, 115, 116, 111, 109, 1, 0, 1, 0, 91, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 82, 101, 97, 100, 67, 101, 108, 108, 115, 2, 0, 1, 0, 93, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 72, 97, 115, 104, 66, 121, 116, 101, 115, 3, 0, 1, 0, 94, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 72, 97, 115, 104, 67, 117, 115, 116, 111, 109, 4, 0, 1, 0, 95, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 83, 116, 111, 114, 101, 83, 105, 103, 110, 97, 116, 117, 114, 101, 5, 0, 1, 0, 96, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 86, 101, 114, 105, 102, 121, 83, 105, 103, 110, 97, 116, 117, 114, 101, 6, 0, 0, 21, 0, 0, 0, 86, 101, 114, 105, 102, 121, 67, 117, 115, 116, 111, 109, 83, 105, 103, 110, 97, 116, 117, 114, 101, 7, 0, 1, 0, 97, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 83, 116, 111, 114, 101, 83, 101, 114, 105, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 8, 0, 1, 0, 98, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 66, 121, 116, 101, 115, 65, 115, 83, 116, 114, 105, 110, 103, 9, 0, 0, 23, 0, 0, 0, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 67, 117, 115, 116, 111, 109, 83, 116, 114, 105, 110, 103, 10, 0, 1, 0, 99, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 68, 101, 108, 101, 116, 101, 67, 101, 108, 108, 115, 11, 0, 1, 0, 100, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 83, 101, 116, 72, 111, 111, 107, 12, 0, 1, 0, 101, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 13, 0, 1, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 87, 114, 105, 116, 101, 67, 101, 108, 108, 115, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 100, 97, 116, 97, 95, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 87, 114, 105, 116, 101, 67, 117, 115, 116, 111, 109, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 7, 0, 0, 0, 99, 111, 110, 116, 101, 110, 116, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 5, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 82, 101, 97, 100, 67, 101, 108, 108, 115, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 72, 97, 115, 104, 66, 121, 116, 101, 115, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 102, 105, 108, 108, 101, 114, 0, 1, 0, 5, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 72, 97, 115, 104, 67, 117, 115, 116, 111, 109, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 55, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 116, 111, 114, 101, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 115, 105, 103, 110, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 101, 115, 115, 97, 103, 101, 0, 1, 5, 0, 0, 0, 0, 1, 62, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 86, 101, 114, 105, 102, 121, 67, 117, 115, 116, 111, 109, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 115, 105, 103, 110, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 101, 115, 115, 97, 103, 101, 0, 1, 5, 0, 0, 0, 0, 1, 62, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 116, 111, 114, 101, 83, 101, 114, 105, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 67, 117, 115, 116, 111, 109, 83, 116, 114, 105, 110, 103, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 68, 101, 108, 101, 116, 101, 67, 101, 108, 108, 115, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 101, 116, 72, 111, 111, 107, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 112, 114, 101, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 112, 111, 115, 116, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 103, 0, 0, 0, 0, 0, 0, 0, 13, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 3, 0, 0, 0, 4, 0, 0, 0, 82, 101, 97, 100, 0, 0, 1, 0, 105, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 87, 114, 105, 116, 101, 1, 0, 1, 0, 106, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 68, 101, 108, 101, 116, 101, 2, 0, 1, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 82, 101, 97, 100, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 36, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 87, 114, 105, 116, 101, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 100, 97, 116, 97, 95, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 37, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 68, 101, 108, 101, 116, 101, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 110, 101, 119, 95, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 30, 0, 0, 0, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 77, 97, 110, 121, 73, 110, 100, 105, 118, 105, 100, 117, 97, 108, 86, 97, 108, 117, 101, 115, 0, 0, 1, 0, 111, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 72, 101, 97, 118, 121, 83, 116, 97, 116, 101, 1, 0, 1, 0, 112, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 82, 117, 110, 67, 80, 85, 72, 101, 97, 118, 121, 79, 112, 101, 114, 97, 116, 105, 111, 110, 2, 0, 1, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 1, 61, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 77, 97, 110, 121, 73, 110, 100, 105, 118, 105, 100, 117, 97, 108, 86, 97, 108, 117, 101, 115, 0, 0, 2, 0, 0, 0, 20, 0, 0, 0, 110, 117, 109, 98, 101, 114, 95, 111, 102, 95, 111, 112, 101, 114, 97, 116, 105, 111, 110, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 97, 108, 116, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 72, 101, 97, 118, 121, 83, 116, 97, 116, 101, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 110, 117, 109, 98, 101, 114, 95, 111, 102, 95, 110, 101, 119, 95, 118, 97, 108, 117, 101, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 20, 0, 0, 0, 109, 97, 120, 95, 104, 101, 97, 118, 121, 95, 115, 116, 97, 116, 101, 95, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 97, 108, 116, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 117, 110, 67, 80, 85, 72, 101, 97, 118, 121, 79, 112, 101, 114, 97, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 105, 116, 101, 114, 97, 116, 105, 111, 110, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 5, 0, 0, 0, 8, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 0, 0, 1, 0, 116, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 83, 101, 116, 77, 97, 110, 121, 86, 97, 108, 117, 101, 115, 1, 0, 1, 0, 117, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 65, 115, 115, 101, 114, 116, 86, 105, 115, 105, 98, 108, 101, 83, 108, 111, 116, 78, 117, 109, 98, 101, 114, 2, 0, 1, 0, 118, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 65, 110, 100, 83, 108, 101, 101, 112, 3, 0, 1, 0, 119, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 80, 97, 110, 105, 99, 4, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 1, 54, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 65, 115, 115, 101, 114, 116, 86, 105, 115, 105, 98, 108, 101, 83, 108, 111, 116, 78, 117, 109, 98, 101, 114, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 101, 120, 112, 101, 99, 116, 101, 100, 95, 118, 105, 115, 105, 98, 108, 101, 95, 115, 108, 111, 116, 95, 110, 117, 109, 98, 101, 114, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 47, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 65, 110, 100, 83, 108, 101, 101, 112, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 12, 0, 0, 0, 115, 108, 101, 101, 112, 95, 109, 105, 108, 108, 105, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 2, 0, 0, 0, 17, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 87, 105, 116, 104, 80, 114, 111, 111, 102, 0, 0, 1, 0, 122, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 1, 0, 1, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 87, 105, 116, 104, 80, 114, 111, 111, 102, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 110, 101, 119, 95, 109, 101, 116, 104, 111, 100, 95, 105, 100, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 8, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 0, 0, 1, 0, 126, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 1, 0, 1, 0, 130, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 2, 0, 1, 0, 135, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 3, 0, 1, 0, 136, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 70, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 4, 0, 1, 0, 137, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 85, 110, 102, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 5, 0, 1, 0, 139, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 65, 100, 100, 80, 111, 111, 108, 65, 100, 109, 105, 110, 6, 0, 1, 0, 140, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 82, 101, 109, 111, 118, 101, 80, 111, 111, 108, 65, 100, 109, 105, 110, 7, 0, 1, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 1, 38, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 68, 101, 112, 111, 115, 105, 116, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 1, 0, 0, 0, 0, 3, 0, 0, 0, 114, 104, 111, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 114, 101, 99, 105, 112, 105, 101, 110, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 118, 105, 101, 119, 95, 102, 118, 107, 115, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 128, 0, 0, 0, 0, 0, 0, 0, 13, 0, 129, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 84, 114, 97, 110, 115, 102, 101, 114, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 97, 110, 99, 104, 111, 114, 95, 114, 111, 111, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 110, 117, 108, 108, 105, 102, 105, 101, 114, 115, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 118, 105, 101, 119, 95, 99, 105, 112, 104, 101, 114, 116, 101, 120, 116, 115, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 133, 0, 0, 0, 0, 0, 0, 0, 13, 0, 134, 0, 0, 0, 0, 0, 0, 0, 1, 13, 0, 0, 0, 69, 110, 99, 114, 121, 112, 116, 101, 100, 78, 111, 116, 101, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 99, 109, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 110, 111, 110, 99, 101, 0, 1, 1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 99, 116, 0, 1, 2, 0, 0, 0, 0, 0, 14, 0, 0, 0, 102, 118, 107, 95, 99, 111, 109, 109, 105, 116, 109, 101, 110, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 109, 97, 99, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 0, 0, 7, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 97, 110, 99, 104, 111, 114, 95, 114, 111, 111, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 108, 108, 105, 102, 105, 101, 114, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 119, 105, 116, 104, 100, 114, 97, 119, 95, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 1, 0, 0, 0, 0, 2, 0, 0, 0, 116, 111, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 118, 105, 101, 119, 95, 99, 105, 112, 104, 101, 114, 116, 101, 120, 116, 115, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 110, 101, 119, 95, 109, 101, 116, 104, 111, 100, 95, 105, 100, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 70, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 97, 100, 100, 114, 101, 115, 115, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 64, 0, 0, 0, 0, 0, 0, 0, 3, 8, 0, 0, 0, 112, 114, 105, 118, 112, 111, 111, 108, 0, 0, 0, 0, 0, 1, 46, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 110, 102, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 97, 100, 100, 114, 101, 115, 115, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 43, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 65, 100, 100, 80, 111, 111, 108, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 46, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 109, 111, 118, 101, 80, 111, 111, 108, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 13, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 78, 105, 103, 104, 116, 0, 0, 1, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 78, 105, 103, 104, 116, 0, 0, 3, 0, 0, 0, 16, 0, 0, 0, 109, 105, 100, 110, 105, 103, 104, 116, 95, 97, 100, 100, 114, 101, 115, 115, 0, 1, 5, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 110, 105, 113, 117, 101, 110, 101, 115, 115, 68, 97, 116, 97, 2, 0, 0, 0, 5, 0, 0, 0, 78, 111, 110, 99, 101, 0, 0, 1, 0, 146, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 71, 101, 110, 101, 114, 97, 116, 105, 111, 110, 1, 0, 1, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 1, 9, 0, 0, 0, 84, 120, 68, 101, 116, 97, 105, 108, 115, 0, 0, 4, 0, 0, 0, 21, 0, 0, 0, 109, 97, 120, 95, 112, 114, 105, 111, 114, 105, 116, 121, 95, 102, 101, 101, 95, 98, 105, 112, 115, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 97, 120, 95, 102, 101, 101, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 99, 104, 97, 105, 110, 95, 105, 100, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 1, 19, 0, 0, 0, 85, 110, 115, 105, 103, 110, 101, 100, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 3, 0, 0, 0, 12, 0, 0, 0, 114, 117, 110, 116, 105, 109, 101, 95, 99, 97, 108, 108, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 117, 110, 105, 113, 117, 101, 110, 101, 115, 115, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 100, 101, 116, 97, 105, 108, 115, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 225, 16, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 84, 101, 115, 116, 67, 104, 97, 105, 110, 189, 33, 197, 161, 104, 9, 147, 107, 209, 142, 226, 254, 192, 53, 116, 76, 223, 195, 190, 210, 164, 210, 25, 39, 173, 49, 14, 63, 116, 34, 65, 158]; #[allow(dead_code)] pub const SCHEMA_JSON: &str = r#"{ @@ -88,7 +88,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "uniqueness", "silent": false, "value": { - "ByIndex": 142 + "ByIndex": 145 }, "doc": "" }, @@ -96,7 +96,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "details", "silent": false, "value": { - "ByIndex": 145 + "ByIndex": 148 }, "doc": "" } @@ -284,7 +284,7 @@ pub const SCHEMA_JSON: &str = r#"{ "discriminant": 16, "template": null, "value": { - "ByIndex": 141 + "ByIndex": 142 } } ], @@ -3473,7 +3473,7 @@ pub const SCHEMA_JSON: &str = r#"{ "fields": [ { "value": { - "ByIndex": 142 + "ByIndex": 143 }, "silent": false, "doc": "" @@ -3490,7 +3490,7 @@ pub const SCHEMA_JSON: &str = r#"{ "discriminant": 0, "template": null, "value": { - "ByIndex": 143 + "ByIndex": 144 } } ], @@ -3539,7 +3539,7 @@ pub const SCHEMA_JSON: &str = r#"{ "discriminant": 0, "template": null, "value": { - "ByIndex": 143 + "ByIndex": 146 } }, { @@ -3547,7 +3547,7 @@ pub const SCHEMA_JSON: &str = r#"{ "discriminant": 1, "template": null, "value": { - "ByIndex": 144 + "ByIndex": 147 } } ], @@ -3604,7 +3604,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "max_priority_fee_bips", "silent": false, "value": { - "ByIndex": 146 + "ByIndex": 149 }, "doc": "" }, @@ -3678,7 +3678,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "uniqueness", "silent": false, "value": { - "ByIndex": 142 + "ByIndex": 145 }, "doc": "" }, @@ -3686,7 +3686,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "details", "silent": false, "value": { - "ByIndex": 145 + "ByIndex": 148 }, "doc": "" } @@ -3696,7 +3696,7 @@ pub const SCHEMA_JSON: &str = r#"{ ], "root_type_indices": [ 0, - 147, + 150, 6, 12 ], From 9f07405408972d3e41995e04d4886d4ae621a263 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Thu, 2 Apr 2026 20:13:46 +0200 Subject: [PATCH 18/20] withdrawal relaying --- examples/demo-rollup/autogenerated.rs | 26 +- .../midnight_withdrawals_plan/README.md | 102 +++++++ .../stf/src/midnight_withdrawals.rs | 8 +- examples/rollup-ligero/Cargo.toml | 4 + examples/rollup-ligero/L1_INTERACTIONS.md | 116 -------- examples/rollup-ligero/MIDNIGHT_BRIDGE.md | 167 ++++++++++++ examples/rollup-ligero/README.md | 2 +- examples/rollup-ligero/src/bin/sov_cli.rs | 15 ++ examples/rollup-ligero/src/midnight_bridge.rs | 255 ++++++++++++++++++ examples/rollup-ligero/src/mock_rollup.rs | 6 +- 10 files changed, 568 insertions(+), 133 deletions(-) create mode 100644 examples/demo-rollup/midnight_withdrawals_plan/README.md delete mode 100644 examples/rollup-ligero/L1_INTERACTIONS.md create mode 100644 examples/rollup-ligero/MIDNIGHT_BRIDGE.md create mode 100644 examples/rollup-ligero/src/bin/sov_cli.rs diff --git a/examples/demo-rollup/autogenerated.rs b/examples/demo-rollup/autogenerated.rs index d46215a9f..cb70a3383 100644 --- a/examples/demo-rollup/autogenerated.rs +++ b/examples/demo-rollup/autogenerated.rs @@ -1,7 +1,7 @@ -pub const CHAIN_HASH: [u8; 32] = [100, 58, 216, 206, 190, 155, 146, 153, 200, 170, 118, 30, 5, 110, 160, 150, 82, 18, 163, 52, 208, 175, 104, 205, 225, 5, 9, 99, 32, 195, 219, 168]; +pub const CHAIN_HASH: [u8; 32] = [88, 188, 166, 204, 116, 229, 243, 99, 58, 64, 222, 43, 69, 23, 233, 69, 71, 2, 253, 63, 17, 209, 44, 100, 166, 192, 65, 237, 146, 7, 149, 16]; #[allow(dead_code)] -pub const SCHEMA_BORSH: &[u8] = &[148, 0, 0, 0, 1, 11, 0, 0, 0, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 118, 101, 114, 115, 105, 111, 110, 101, 100, 95, 116, 120, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 86, 101, 114, 115, 105, 111, 110, 101, 100, 84, 120, 1, 0, 0, 0, 2, 0, 0, 0, 86, 48, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 86, 101, 114, 115, 105, 111, 110, 48, 0, 0, 5, 0, 0, 0, 9, 0, 0, 0, 115, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 114, 117, 110, 116, 105, 109, 101, 95, 99, 97, 108, 108, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 117, 110, 105, 113, 117, 101, 110, 101, 115, 115, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 100, 101, 116, 97, 105, 108, 115, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 0, 0, 0, 69, 100, 50, 53, 53, 49, 57, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 109, 115, 103, 95, 115, 105, 103, 0, 1, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 0, 0, 0, 69, 100, 50, 53, 53, 49, 57, 80, 117, 98, 108, 105, 99, 75, 101, 121, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 82, 117, 110, 116, 105, 109, 101, 67, 97, 108, 108, 16, 0, 0, 0, 4, 0, 0, 0, 66, 97, 110, 107, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 83, 101, 113, 117, 101, 110, 99, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 1, 0, 1, 0, 27, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 79, 112, 101, 114, 97, 116, 111, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 2, 0, 1, 0, 34, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 65, 116, 116, 101, 115, 116, 101, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 3, 0, 1, 0, 37, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 80, 114, 111, 118, 101, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 4, 0, 1, 0, 42, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 65, 99, 99, 111, 117, 110, 116, 115, 5, 0, 1, 0, 46, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 85, 110, 105, 113, 117, 101, 110, 101, 115, 115, 6, 0, 1, 0, 51, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 67, 104, 97, 105, 110, 83, 116, 97, 116, 101, 7, 0, 1, 0, 53, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 66, 108, 111, 98, 83, 116, 111, 114, 97, 103, 101, 8, 0, 1, 0, 55, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 80, 97, 121, 109, 97, 115, 116, 101, 114, 9, 0, 1, 0, 56, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 69, 118, 109, 10, 0, 1, 0, 85, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 11, 0, 1, 0, 88, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 83, 121, 110, 116, 104, 101, 116, 105, 99, 76, 111, 97, 100, 12, 0, 1, 0, 109, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 86, 97, 108, 117, 101, 83, 101, 116, 116, 101, 114, 13, 0, 1, 0, 114, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 86, 97, 108, 117, 101, 83, 101, 116, 116, 101, 114, 90, 107, 14, 0, 1, 0, 120, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 77, 105, 100, 110, 105, 103, 104, 116, 80, 114, 105, 118, 97, 99, 121, 15, 0, 1, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 6, 0, 0, 0, 11, 0, 0, 0, 67, 114, 101, 97, 116, 101, 84, 111, 107, 101, 110, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 1, 1, 26, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 32, 116, 111, 32, 97, 100, 100, 114, 101, 115, 115, 32, 123, 125, 32, 123, 125, 46, 1, 0, 19, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 66, 117, 114, 110, 2, 0, 1, 0, 22, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 77, 105, 110, 116, 3, 0, 1, 0, 23, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 70, 114, 101, 101, 122, 101, 4, 0, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 5, 0, 1, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 1, 42, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 67, 114, 101, 97, 116, 101, 84, 111, 107, 101, 110, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 116, 111, 107, 101, 110, 95, 110, 97, 109, 101, 0, 1, 5, 0, 0, 0, 0, 14, 0, 0, 0, 116, 111, 107, 101, 110, 95, 100, 101, 99, 105, 109, 97, 108, 115, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 105, 110, 105, 116, 105, 97, 108, 95, 98, 97, 108, 97, 110, 99, 101, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 109, 105, 110, 116, 95, 116, 111, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 100, 109, 105, 110, 115, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 115, 117, 112, 112, 108, 121, 95, 99, 97, 112, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 5, 1, 2, 0, 0, 1, 0, 0, 0, 1, 0, 9, 1, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 77, 117, 108, 116, 105, 65, 100, 100, 114, 101, 115, 115, 2, 0, 0, 0, 8, 0, 0, 0, 83, 116, 97, 110, 100, 97, 114, 100, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 86, 109, 1, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 28, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 115, 111, 118, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 12, 0, 0, 0, 0, 0, 0, 0, 3, 0, 11, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 84, 114, 97, 110, 115, 102, 101, 114, 1, 26, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 32, 116, 111, 32, 97, 100, 100, 114, 101, 115, 115, 32, 123, 125, 32, 123, 125, 46, 0, 2, 0, 0, 0, 2, 0, 0, 0, 116, 111, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 67, 111, 105, 110, 115, 1, 23, 0, 0, 0, 123, 125, 32, 99, 111, 105, 110, 115, 32, 111, 102, 32, 116, 111, 107, 101, 110, 32, 73, 68, 32, 123, 125, 1, 2, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 3, 6, 0, 0, 0, 116, 111, 107, 101, 110, 95, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 66, 117, 114, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 77, 105, 110, 116, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 109, 105, 110, 116, 95, 116, 111, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 37, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 70, 114, 101, 101, 122, 101, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 42, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 0, 0, 2, 0, 0, 0, 9, 0, 0, 0, 110, 101, 119, 95, 97, 100, 109, 105, 110, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 12, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 4, 0, 0, 0, 8, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 1, 0, 29, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 1, 0, 1, 0, 31, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 73, 110, 105, 116, 105, 97, 116, 101, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 2, 0, 1, 0, 32, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 3, 0, 1, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 38, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 68, 101, 112, 111, 115, 105, 116, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 49, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 73, 110, 105, 116, 105, 97, 116, 101, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 19, 0, 0, 0, 85, 112, 100, 97, 116, 101, 82, 101, 119, 97, 114, 100, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 82, 101, 119, 97, 114, 100, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 18, 0, 0, 0, 110, 101, 119, 95, 114, 101, 119, 97, 114, 100, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 6, 0, 0, 0, 16, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 65, 116, 116, 101, 115, 116, 101, 114, 0, 0, 1, 0, 39, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 66, 101, 103, 105, 110, 69, 120, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 1, 0, 0, 12, 0, 0, 0, 69, 120, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 2, 0, 0, 18, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 67, 104, 97, 108, 108, 101, 110, 103, 101, 114, 3, 0, 1, 0, 40, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 69, 120, 105, 116, 67, 104, 97, 108, 108, 101, 110, 103, 101, 114, 4, 0, 0, 15, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 5, 0, 1, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 8, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 1, 0, 44, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 1, 0, 1, 0, 45, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 69, 120, 105, 116, 2, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 18, 0, 0, 0, 73, 110, 115, 101, 114, 116, 67, 114, 101, 100, 101, 110, 116, 105, 97, 108, 73, 100, 0, 0, 1, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 78, 111, 116, 73, 110, 115, 116, 97, 110, 116, 105, 97, 98, 108, 101, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 18, 0, 0, 0, 84, 101, 114, 109, 105, 110, 97, 116, 101, 83, 101, 116, 117, 112, 77, 111, 100, 101, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 17, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 80, 97, 121, 109, 97, 115, 116, 101, 114, 0, 0, 1, 0, 58, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 83, 101, 116, 80, 97, 121, 101, 114, 70, 111, 114, 83, 101, 113, 117, 101, 110, 99, 101, 114, 1, 0, 1, 0, 74, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 85, 112, 100, 97, 116, 101, 80, 111, 108, 105, 99, 121, 2, 0, 1, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 103, 105, 115, 116, 101, 114, 80, 97, 121, 109, 97, 115, 116, 101, 114, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 112, 111, 108, 105, 99, 121, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26, 0, 0, 0, 80, 97, 121, 109, 97, 115, 116, 101, 114, 80, 111, 108, 105, 99, 121, 73, 110, 105, 116, 105, 97, 108, 105, 122, 101, 114, 0, 0, 4, 0, 0, 0, 20, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 95, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 121, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 112, 97, 121, 101, 101, 115, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 95, 117, 112, 100, 97, 116, 101, 114, 115, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 95, 115, 101, 113, 117, 101, 110, 99, 101, 114, 115, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 80, 97, 121, 101, 101, 80, 111, 108, 105, 99, 121, 2, 0, 0, 0, 5, 0, 0, 0, 65, 108, 108, 111, 119, 0, 0, 1, 0, 61, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 68, 101, 110, 121, 1, 0, 0, 0, 1, 36, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 80, 97, 121, 101, 101, 80, 111, 108, 105, 99, 121, 95, 65, 108, 108, 111, 119, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 109, 97, 120, 95, 102, 101, 101, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 109, 97, 120, 95, 103, 97, 115, 95, 112, 114, 105, 99, 101, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 116, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 95, 108, 105, 109, 105, 116, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 63, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 8, 1, 3, 0, 66, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 71, 97, 115, 80, 114, 105, 99, 101, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 8, 1, 13, 0, 70, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 65, 117, 116, 104, 111, 114, 105, 122, 101, 100, 83, 101, 113, 117, 101, 110, 99, 101, 114, 115, 2, 0, 0, 0, 3, 0, 0, 0, 65, 108, 108, 0, 0, 0, 4, 0, 0, 0, 83, 111, 109, 101, 1, 0, 1, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 30, 0, 0, 0, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 80, 97, 121, 101, 114, 70, 111, 114, 83, 101, 113, 117, 101, 110, 99, 101, 114, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 112, 97, 121, 101, 114, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 43, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 80, 111, 108, 105, 99, 121, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 112, 97, 121, 101, 114, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 117, 112, 100, 97, 116, 101, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 12, 0, 0, 0, 80, 111, 108, 105, 99, 121, 85, 112, 100, 97, 116, 101, 0, 0, 6, 0, 0, 0, 16, 0, 0, 0, 115, 101, 113, 117, 101, 110, 99, 101, 114, 95, 117, 112, 100, 97, 116, 101, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 117, 112, 100, 97, 116, 101, 114, 115, 95, 116, 111, 95, 97, 100, 100, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 117, 112, 100, 97, 116, 101, 114, 115, 95, 116, 111, 95, 114, 101, 109, 111, 118, 101, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 105, 101, 115, 95, 116, 111, 95, 115, 101, 116, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 105, 101, 115, 95, 116, 111, 95, 100, 101, 108, 101, 116, 101, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 95, 112, 111, 108, 105, 99, 121, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 83, 101, 113, 117, 101, 110, 99, 101, 114, 83, 101, 116, 85, 112, 100, 97, 116, 101, 2, 0, 0, 0, 8, 0, 0, 0, 65, 108, 108, 111, 119, 65, 108, 108, 0, 0, 0, 6, 0, 0, 0, 85, 112, 100, 97, 116, 101, 1, 0, 1, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 22, 0, 0, 0, 65, 108, 108, 111, 119, 101, 100, 83, 101, 113, 117, 101, 110, 99, 101, 114, 85, 112, 100, 97, 116, 101, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 116, 111, 95, 97, 100, 100, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 116, 111, 95, 114, 101, 109, 111, 118, 101, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 73, 0, 0, 0, 0, 0, 0, 0, 3, 0, 17, 0, 0, 0, 0, 0, 0, 0, 3, 0, 69, 0, 0, 0, 0, 0, 0, 0, 3, 0, 60, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 114, 108, 112, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 17, 0, 0, 0, 82, 108, 112, 69, 118, 109, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 114, 108, 112, 0, 1, 2, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 14, 0, 0, 0, 10, 0, 0, 0, 87, 114, 105, 116, 101, 67, 101, 108, 108, 115, 0, 0, 1, 0, 90, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 87, 114, 105, 116, 101, 67, 117, 115, 116, 111, 109, 1, 0, 1, 0, 91, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 82, 101, 97, 100, 67, 101, 108, 108, 115, 2, 0, 1, 0, 93, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 72, 97, 115, 104, 66, 121, 116, 101, 115, 3, 0, 1, 0, 94, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 72, 97, 115, 104, 67, 117, 115, 116, 111, 109, 4, 0, 1, 0, 95, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 83, 116, 111, 114, 101, 83, 105, 103, 110, 97, 116, 117, 114, 101, 5, 0, 1, 0, 96, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 86, 101, 114, 105, 102, 121, 83, 105, 103, 110, 97, 116, 117, 114, 101, 6, 0, 0, 21, 0, 0, 0, 86, 101, 114, 105, 102, 121, 67, 117, 115, 116, 111, 109, 83, 105, 103, 110, 97, 116, 117, 114, 101, 7, 0, 1, 0, 97, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 83, 116, 111, 114, 101, 83, 101, 114, 105, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 8, 0, 1, 0, 98, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 66, 121, 116, 101, 115, 65, 115, 83, 116, 114, 105, 110, 103, 9, 0, 0, 23, 0, 0, 0, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 67, 117, 115, 116, 111, 109, 83, 116, 114, 105, 110, 103, 10, 0, 1, 0, 99, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 68, 101, 108, 101, 116, 101, 67, 101, 108, 108, 115, 11, 0, 1, 0, 100, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 83, 101, 116, 72, 111, 111, 107, 12, 0, 1, 0, 101, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 13, 0, 1, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 87, 114, 105, 116, 101, 67, 101, 108, 108, 115, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 100, 97, 116, 97, 95, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 87, 114, 105, 116, 101, 67, 117, 115, 116, 111, 109, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 7, 0, 0, 0, 99, 111, 110, 116, 101, 110, 116, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 5, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 82, 101, 97, 100, 67, 101, 108, 108, 115, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 72, 97, 115, 104, 66, 121, 116, 101, 115, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 102, 105, 108, 108, 101, 114, 0, 1, 0, 5, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 72, 97, 115, 104, 67, 117, 115, 116, 111, 109, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 55, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 116, 111, 114, 101, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 115, 105, 103, 110, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 101, 115, 115, 97, 103, 101, 0, 1, 5, 0, 0, 0, 0, 1, 62, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 86, 101, 114, 105, 102, 121, 67, 117, 115, 116, 111, 109, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 115, 105, 103, 110, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 101, 115, 115, 97, 103, 101, 0, 1, 5, 0, 0, 0, 0, 1, 62, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 116, 111, 114, 101, 83, 101, 114, 105, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 67, 117, 115, 116, 111, 109, 83, 116, 114, 105, 110, 103, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 68, 101, 108, 101, 116, 101, 67, 101, 108, 108, 115, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 101, 116, 72, 111, 111, 107, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 112, 114, 101, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 112, 111, 115, 116, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 103, 0, 0, 0, 0, 0, 0, 0, 13, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 3, 0, 0, 0, 4, 0, 0, 0, 82, 101, 97, 100, 0, 0, 1, 0, 105, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 87, 114, 105, 116, 101, 1, 0, 1, 0, 106, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 68, 101, 108, 101, 116, 101, 2, 0, 1, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 82, 101, 97, 100, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 36, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 87, 114, 105, 116, 101, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 100, 97, 116, 97, 95, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 37, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 68, 101, 108, 101, 116, 101, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 110, 101, 119, 95, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 30, 0, 0, 0, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 77, 97, 110, 121, 73, 110, 100, 105, 118, 105, 100, 117, 97, 108, 86, 97, 108, 117, 101, 115, 0, 0, 1, 0, 111, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 72, 101, 97, 118, 121, 83, 116, 97, 116, 101, 1, 0, 1, 0, 112, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 82, 117, 110, 67, 80, 85, 72, 101, 97, 118, 121, 79, 112, 101, 114, 97, 116, 105, 111, 110, 2, 0, 1, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 1, 61, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 77, 97, 110, 121, 73, 110, 100, 105, 118, 105, 100, 117, 97, 108, 86, 97, 108, 117, 101, 115, 0, 0, 2, 0, 0, 0, 20, 0, 0, 0, 110, 117, 109, 98, 101, 114, 95, 111, 102, 95, 111, 112, 101, 114, 97, 116, 105, 111, 110, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 97, 108, 116, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 72, 101, 97, 118, 121, 83, 116, 97, 116, 101, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 110, 117, 109, 98, 101, 114, 95, 111, 102, 95, 110, 101, 119, 95, 118, 97, 108, 117, 101, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 20, 0, 0, 0, 109, 97, 120, 95, 104, 101, 97, 118, 121, 95, 115, 116, 97, 116, 101, 95, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 97, 108, 116, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 117, 110, 67, 80, 85, 72, 101, 97, 118, 121, 79, 112, 101, 114, 97, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 105, 116, 101, 114, 97, 116, 105, 111, 110, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 5, 0, 0, 0, 8, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 0, 0, 1, 0, 116, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 83, 101, 116, 77, 97, 110, 121, 86, 97, 108, 117, 101, 115, 1, 0, 1, 0, 117, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 65, 115, 115, 101, 114, 116, 86, 105, 115, 105, 98, 108, 101, 83, 108, 111, 116, 78, 117, 109, 98, 101, 114, 2, 0, 1, 0, 118, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 65, 110, 100, 83, 108, 101, 101, 112, 3, 0, 1, 0, 119, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 80, 97, 110, 105, 99, 4, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 1, 54, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 65, 115, 115, 101, 114, 116, 86, 105, 115, 105, 98, 108, 101, 83, 108, 111, 116, 78, 117, 109, 98, 101, 114, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 101, 120, 112, 101, 99, 116, 101, 100, 95, 118, 105, 115, 105, 98, 108, 101, 95, 115, 108, 111, 116, 95, 110, 117, 109, 98, 101, 114, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 47, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 65, 110, 100, 83, 108, 101, 101, 112, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 12, 0, 0, 0, 115, 108, 101, 101, 112, 95, 109, 105, 108, 108, 105, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 2, 0, 0, 0, 17, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 87, 105, 116, 104, 80, 114, 111, 111, 102, 0, 0, 1, 0, 122, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 1, 0, 1, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 87, 105, 116, 104, 80, 114, 111, 111, 102, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 110, 101, 119, 95, 109, 101, 116, 104, 111, 100, 95, 105, 100, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 8, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 0, 0, 1, 0, 126, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 1, 0, 1, 0, 130, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 2, 0, 1, 0, 135, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 3, 0, 1, 0, 136, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 70, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 4, 0, 1, 0, 137, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 85, 110, 102, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 5, 0, 1, 0, 139, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 65, 100, 100, 80, 111, 111, 108, 65, 100, 109, 105, 110, 6, 0, 1, 0, 140, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 82, 101, 109, 111, 118, 101, 80, 111, 111, 108, 65, 100, 109, 105, 110, 7, 0, 1, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 1, 38, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 68, 101, 112, 111, 115, 105, 116, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 1, 0, 0, 0, 0, 3, 0, 0, 0, 114, 104, 111, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 114, 101, 99, 105, 112, 105, 101, 110, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 118, 105, 101, 119, 95, 102, 118, 107, 115, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 128, 0, 0, 0, 0, 0, 0, 0, 13, 0, 129, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 84, 114, 97, 110, 115, 102, 101, 114, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 97, 110, 99, 104, 111, 114, 95, 114, 111, 111, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 110, 117, 108, 108, 105, 102, 105, 101, 114, 115, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 118, 105, 101, 119, 95, 99, 105, 112, 104, 101, 114, 116, 101, 120, 116, 115, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 133, 0, 0, 0, 0, 0, 0, 0, 13, 0, 134, 0, 0, 0, 0, 0, 0, 0, 1, 13, 0, 0, 0, 69, 110, 99, 114, 121, 112, 116, 101, 100, 78, 111, 116, 101, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 99, 109, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 110, 111, 110, 99, 101, 0, 1, 1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 99, 116, 0, 1, 2, 0, 0, 0, 0, 0, 14, 0, 0, 0, 102, 118, 107, 95, 99, 111, 109, 109, 105, 116, 109, 101, 110, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 109, 97, 99, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 0, 0, 7, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 97, 110, 99, 104, 111, 114, 95, 114, 111, 111, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 108, 108, 105, 102, 105, 101, 114, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 119, 105, 116, 104, 100, 114, 97, 119, 95, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 1, 0, 0, 0, 0, 2, 0, 0, 0, 116, 111, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 118, 105, 101, 119, 95, 99, 105, 112, 104, 101, 114, 116, 101, 120, 116, 115, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 110, 101, 119, 95, 109, 101, 116, 104, 111, 100, 95, 105, 100, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 70, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 97, 100, 100, 114, 101, 115, 115, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 64, 0, 0, 0, 0, 0, 0, 0, 3, 8, 0, 0, 0, 112, 114, 105, 118, 112, 111, 111, 108, 0, 0, 0, 0, 0, 1, 46, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 110, 102, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 97, 100, 100, 114, 101, 115, 115, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 43, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 65, 100, 100, 80, 111, 111, 108, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 46, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 109, 111, 118, 101, 80, 111, 111, 108, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 110, 105, 113, 117, 101, 110, 101, 115, 115, 68, 97, 116, 97, 2, 0, 0, 0, 5, 0, 0, 0, 78, 111, 110, 99, 101, 0, 0, 1, 0, 143, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 71, 101, 110, 101, 114, 97, 116, 105, 111, 110, 1, 0, 1, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 1, 9, 0, 0, 0, 84, 120, 68, 101, 116, 97, 105, 108, 115, 0, 0, 4, 0, 0, 0, 21, 0, 0, 0, 109, 97, 120, 95, 112, 114, 105, 111, 114, 105, 116, 121, 95, 102, 101, 101, 95, 98, 105, 112, 115, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 97, 120, 95, 102, 101, 101, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 99, 104, 97, 105, 110, 95, 105, 100, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 1, 19, 0, 0, 0, 85, 110, 115, 105, 103, 110, 101, 100, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 3, 0, 0, 0, 12, 0, 0, 0, 114, 117, 110, 116, 105, 109, 101, 95, 99, 97, 108, 108, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 117, 110, 105, 113, 117, 101, 110, 101, 115, 115, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 100, 101, 116, 97, 105, 108, 115, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 225, 16, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 84, 101, 115, 116, 67, 104, 97, 105, 110, 49, 91, 190, 78, 133, 80, 109, 242, 86, 96, 227, 47, 33, 78, 65, 74, 101, 221, 54, 245, 195, 131, 47, 159, 218, 9, 204, 51, 225, 153, 162, 254]; +pub const SCHEMA_BORSH: &[u8] = &[151, 0, 0, 0, 1, 11, 0, 0, 0, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 12, 0, 0, 0, 118, 101, 114, 115, 105, 111, 110, 101, 100, 95, 116, 120, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 86, 101, 114, 115, 105, 111, 110, 101, 100, 84, 120, 1, 0, 0, 0, 2, 0, 0, 0, 86, 48, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 86, 101, 114, 115, 105, 111, 110, 48, 0, 0, 5, 0, 0, 0, 9, 0, 0, 0, 115, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 114, 117, 110, 116, 105, 109, 101, 95, 99, 97, 108, 108, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 117, 110, 105, 113, 117, 101, 110, 101, 115, 115, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 100, 101, 116, 97, 105, 108, 115, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 0, 0, 0, 69, 100, 50, 53, 53, 49, 57, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 109, 115, 103, 95, 115, 105, 103, 0, 1, 1, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 0, 0, 0, 69, 100, 50, 53, 53, 49, 57, 80, 117, 98, 108, 105, 99, 75, 101, 121, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 82, 117, 110, 116, 105, 109, 101, 67, 97, 108, 108, 17, 0, 0, 0, 4, 0, 0, 0, 66, 97, 110, 107, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 83, 101, 113, 117, 101, 110, 99, 101, 114, 82, 101, 103, 105, 115, 116, 114, 121, 1, 0, 1, 0, 27, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 79, 112, 101, 114, 97, 116, 111, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 2, 0, 1, 0, 34, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 65, 116, 116, 101, 115, 116, 101, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 3, 0, 1, 0, 37, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 80, 114, 111, 118, 101, 114, 73, 110, 99, 101, 110, 116, 105, 118, 101, 115, 4, 0, 1, 0, 42, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 65, 99, 99, 111, 117, 110, 116, 115, 5, 0, 1, 0, 46, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 85, 110, 105, 113, 117, 101, 110, 101, 115, 115, 6, 0, 1, 0, 51, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 67, 104, 97, 105, 110, 83, 116, 97, 116, 101, 7, 0, 1, 0, 53, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 66, 108, 111, 98, 83, 116, 111, 114, 97, 103, 101, 8, 0, 1, 0, 55, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 80, 97, 121, 109, 97, 115, 116, 101, 114, 9, 0, 1, 0, 56, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 69, 118, 109, 10, 0, 1, 0, 85, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 11, 0, 1, 0, 88, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 83, 121, 110, 116, 104, 101, 116, 105, 99, 76, 111, 97, 100, 12, 0, 1, 0, 109, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 86, 97, 108, 117, 101, 83, 101, 116, 116, 101, 114, 13, 0, 1, 0, 114, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 86, 97, 108, 117, 101, 83, 101, 116, 116, 101, 114, 90, 107, 14, 0, 1, 0, 120, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 77, 105, 100, 110, 105, 103, 104, 116, 80, 114, 105, 118, 97, 99, 121, 15, 0, 1, 0, 124, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 77, 105, 100, 110, 105, 103, 104, 116, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 115, 16, 0, 1, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 6, 0, 0, 0, 11, 0, 0, 0, 67, 114, 101, 97, 116, 101, 84, 111, 107, 101, 110, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 1, 1, 26, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 32, 116, 111, 32, 97, 100, 100, 114, 101, 115, 115, 32, 123, 125, 32, 123, 125, 46, 1, 0, 19, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 66, 117, 114, 110, 2, 0, 1, 0, 22, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 77, 105, 110, 116, 3, 0, 1, 0, 23, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 70, 114, 101, 101, 122, 101, 4, 0, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 5, 0, 1, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 1, 42, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 67, 114, 101, 97, 116, 101, 84, 111, 107, 101, 110, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 116, 111, 107, 101, 110, 95, 110, 97, 109, 101, 0, 1, 5, 0, 0, 0, 0, 14, 0, 0, 0, 116, 111, 107, 101, 110, 95, 100, 101, 99, 105, 109, 97, 108, 115, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 105, 110, 105, 116, 105, 97, 108, 95, 98, 97, 108, 97, 110, 99, 101, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 109, 105, 110, 116, 95, 116, 111, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 100, 109, 105, 110, 115, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 115, 117, 112, 112, 108, 121, 95, 99, 97, 112, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 5, 1, 2, 0, 0, 1, 0, 0, 0, 1, 0, 9, 1, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 77, 117, 108, 116, 105, 65, 100, 100, 114, 101, 115, 115, 2, 0, 0, 0, 8, 0, 0, 0, 83, 116, 97, 110, 100, 97, 114, 100, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 86, 109, 1, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 28, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 115, 111, 118, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 12, 0, 0, 0, 0, 0, 0, 0, 3, 0, 11, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 84, 114, 97, 110, 115, 102, 101, 114, 1, 26, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 32, 116, 111, 32, 97, 100, 100, 114, 101, 115, 115, 32, 123, 125, 32, 123, 125, 46, 0, 2, 0, 0, 0, 2, 0, 0, 0, 116, 111, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 67, 111, 105, 110, 115, 1, 23, 0, 0, 0, 123, 125, 32, 99, 111, 105, 110, 115, 32, 111, 102, 32, 116, 111, 107, 101, 110, 32, 73, 68, 32, 123, 125, 1, 2, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 3, 6, 0, 0, 0, 116, 111, 107, 101, 110, 95, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 66, 117, 114, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 77, 105, 110, 116, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 99, 111, 105, 110, 115, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 109, 105, 110, 116, 95, 116, 111, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 37, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 70, 114, 101, 101, 122, 101, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 42, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 0, 0, 2, 0, 0, 0, 9, 0, 0, 0, 110, 101, 119, 95, 97, 100, 109, 105, 110, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 116, 111, 107, 101, 110, 95, 105, 100, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 12, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 4, 0, 0, 0, 8, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 1, 0, 29, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 1, 0, 1, 0, 31, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 73, 110, 105, 116, 105, 97, 116, 101, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 2, 0, 1, 0, 32, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 3, 0, 1, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 38, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 68, 101, 112, 111, 115, 105, 116, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 49, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 73, 110, 105, 116, 105, 97, 116, 101, 87, 105, 116, 104, 100, 114, 97, 119, 97, 108, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 100, 97, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 19, 0, 0, 0, 85, 112, 100, 97, 116, 101, 82, 101, 119, 97, 114, 100, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 82, 101, 119, 97, 114, 100, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 18, 0, 0, 0, 110, 101, 119, 95, 114, 101, 119, 97, 114, 100, 95, 97, 100, 100, 114, 101, 115, 115, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 6, 0, 0, 0, 16, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 65, 116, 116, 101, 115, 116, 101, 114, 0, 0, 1, 0, 39, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 66, 101, 103, 105, 110, 69, 120, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 1, 0, 0, 12, 0, 0, 0, 69, 120, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 2, 0, 0, 18, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 67, 104, 97, 108, 108, 101, 110, 103, 101, 114, 3, 0, 1, 0, 40, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 69, 120, 105, 116, 67, 104, 97, 108, 108, 101, 110, 103, 101, 114, 4, 0, 0, 15, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 65, 116, 116, 101, 115, 116, 101, 114, 5, 0, 1, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 8, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 0, 0, 1, 0, 44, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 1, 0, 1, 0, 45, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 69, 120, 105, 116, 2, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 18, 0, 0, 0, 73, 110, 115, 101, 114, 116, 67, 114, 101, 100, 101, 110, 116, 105, 97, 108, 73, 100, 0, 0, 1, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 78, 111, 116, 73, 110, 115, 116, 97, 110, 116, 105, 97, 98, 108, 101, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 18, 0, 0, 0, 84, 101, 114, 109, 105, 110, 97, 116, 101, 83, 101, 116, 117, 112, 77, 111, 100, 101, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 17, 0, 0, 0, 82, 101, 103, 105, 115, 116, 101, 114, 80, 97, 121, 109, 97, 115, 116, 101, 114, 0, 0, 1, 0, 58, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 83, 101, 116, 80, 97, 121, 101, 114, 70, 111, 114, 83, 101, 113, 117, 101, 110, 99, 101, 114, 1, 0, 1, 0, 74, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 85, 112, 100, 97, 116, 101, 80, 111, 108, 105, 99, 121, 2, 0, 1, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 103, 105, 115, 116, 101, 114, 80, 97, 121, 109, 97, 115, 116, 101, 114, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 112, 111, 108, 105, 99, 121, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26, 0, 0, 0, 80, 97, 121, 109, 97, 115, 116, 101, 114, 80, 111, 108, 105, 99, 121, 73, 110, 105, 116, 105, 97, 108, 105, 122, 101, 114, 0, 0, 4, 0, 0, 0, 20, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 95, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 121, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 112, 97, 121, 101, 101, 115, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 95, 117, 112, 100, 97, 116, 101, 114, 115, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 95, 115, 101, 113, 117, 101, 110, 99, 101, 114, 115, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 80, 97, 121, 101, 101, 80, 111, 108, 105, 99, 121, 2, 0, 0, 0, 5, 0, 0, 0, 65, 108, 108, 111, 119, 0, 0, 1, 0, 61, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 68, 101, 110, 121, 1, 0, 0, 0, 1, 36, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 80, 97, 121, 101, 101, 80, 111, 108, 105, 99, 121, 95, 65, 108, 108, 111, 119, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 109, 97, 120, 95, 102, 101, 101, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 109, 97, 120, 95, 103, 97, 115, 95, 112, 114, 105, 99, 101, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 116, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 95, 108, 105, 109, 105, 116, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 63, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 8, 1, 3, 0, 66, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 71, 97, 115, 80, 114, 105, 99, 101, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 8, 1, 13, 0, 70, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 65, 117, 116, 104, 111, 114, 105, 122, 101, 100, 83, 101, 113, 117, 101, 110, 99, 101, 114, 115, 2, 0, 0, 0, 3, 0, 0, 0, 65, 108, 108, 0, 0, 0, 4, 0, 0, 0, 83, 111, 109, 101, 1, 0, 1, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 30, 0, 0, 0, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 80, 97, 121, 101, 114, 70, 111, 114, 83, 101, 113, 117, 101, 110, 99, 101, 114, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 112, 97, 121, 101, 114, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 43, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 80, 111, 108, 105, 99, 121, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 112, 97, 121, 101, 114, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 117, 112, 100, 97, 116, 101, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 12, 0, 0, 0, 80, 111, 108, 105, 99, 121, 85, 112, 100, 97, 116, 101, 0, 0, 6, 0, 0, 0, 16, 0, 0, 0, 115, 101, 113, 117, 101, 110, 99, 101, 114, 95, 117, 112, 100, 97, 116, 101, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 117, 112, 100, 97, 116, 101, 114, 115, 95, 116, 111, 95, 97, 100, 100, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 117, 112, 100, 97, 116, 101, 114, 115, 95, 116, 111, 95, 114, 101, 109, 111, 118, 101, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 105, 101, 115, 95, 116, 111, 95, 115, 101, 116, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 112, 97, 121, 101, 101, 95, 112, 111, 108, 105, 99, 105, 101, 115, 95, 116, 111, 95, 100, 101, 108, 101, 116, 101, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 95, 112, 111, 108, 105, 99, 121, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 83, 101, 113, 117, 101, 110, 99, 101, 114, 83, 101, 116, 85, 112, 100, 97, 116, 101, 2, 0, 0, 0, 8, 0, 0, 0, 65, 108, 108, 111, 119, 65, 108, 108, 0, 0, 0, 6, 0, 0, 0, 85, 112, 100, 97, 116, 101, 1, 0, 1, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 22, 0, 0, 0, 65, 108, 108, 111, 119, 101, 100, 83, 101, 113, 117, 101, 110, 99, 101, 114, 85, 112, 100, 97, 116, 101, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 116, 111, 95, 97, 100, 100, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 116, 111, 95, 114, 101, 109, 111, 118, 101, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 73, 0, 0, 0, 0, 0, 0, 0, 3, 0, 17, 0, 0, 0, 0, 0, 0, 0, 3, 0, 69, 0, 0, 0, 0, 0, 0, 0, 3, 0, 60, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 114, 108, 112, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 17, 0, 0, 0, 82, 108, 112, 69, 118, 109, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 114, 108, 112, 0, 1, 2, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 14, 0, 0, 0, 10, 0, 0, 0, 87, 114, 105, 116, 101, 67, 101, 108, 108, 115, 0, 0, 1, 0, 90, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 87, 114, 105, 116, 101, 67, 117, 115, 116, 111, 109, 1, 0, 1, 0, 91, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 82, 101, 97, 100, 67, 101, 108, 108, 115, 2, 0, 1, 0, 93, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 72, 97, 115, 104, 66, 121, 116, 101, 115, 3, 0, 1, 0, 94, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 72, 97, 115, 104, 67, 117, 115, 116, 111, 109, 4, 0, 1, 0, 95, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 83, 116, 111, 114, 101, 83, 105, 103, 110, 97, 116, 117, 114, 101, 5, 0, 1, 0, 96, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 86, 101, 114, 105, 102, 121, 83, 105, 103, 110, 97, 116, 117, 114, 101, 6, 0, 0, 21, 0, 0, 0, 86, 101, 114, 105, 102, 121, 67, 117, 115, 116, 111, 109, 83, 105, 103, 110, 97, 116, 117, 114, 101, 7, 0, 1, 0, 97, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 83, 116, 111, 114, 101, 83, 101, 114, 105, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 8, 0, 1, 0, 98, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 66, 121, 116, 101, 115, 65, 115, 83, 116, 114, 105, 110, 103, 9, 0, 0, 23, 0, 0, 0, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 67, 117, 115, 116, 111, 109, 83, 116, 114, 105, 110, 103, 10, 0, 1, 0, 99, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 68, 101, 108, 101, 116, 101, 67, 101, 108, 108, 115, 11, 0, 1, 0, 100, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 83, 101, 116, 72, 111, 111, 107, 12, 0, 1, 0, 101, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 13, 0, 1, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 87, 114, 105, 116, 101, 67, 101, 108, 108, 115, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 100, 97, 116, 97, 95, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 87, 114, 105, 116, 101, 67, 117, 115, 116, 111, 109, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 7, 0, 0, 0, 99, 111, 110, 116, 101, 110, 116, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 5, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 82, 101, 97, 100, 67, 101, 108, 108, 115, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 50, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 72, 97, 115, 104, 66, 121, 116, 101, 115, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 102, 105, 108, 108, 101, 114, 0, 1, 0, 5, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 72, 97, 115, 104, 67, 117, 115, 116, 111, 109, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 55, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 116, 111, 114, 101, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 115, 105, 103, 110, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 101, 115, 115, 97, 103, 101, 0, 1, 5, 0, 0, 0, 0, 1, 62, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 86, 101, 114, 105, 102, 121, 67, 117, 115, 116, 111, 109, 83, 105, 103, 110, 97, 116, 117, 114, 101, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 115, 105, 103, 110, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 112, 117, 98, 95, 107, 101, 121, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 101, 115, 115, 97, 103, 101, 0, 1, 5, 0, 0, 0, 0, 1, 62, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 116, 111, 114, 101, 83, 101, 114, 105, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 68, 101, 115, 101, 114, 105, 97, 108, 105, 122, 101, 67, 117, 115, 116, 111, 109, 83, 116, 114, 105, 110, 103, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 105, 110, 112, 117, 116, 0, 1, 2, 0, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 68, 101, 108, 101, 116, 101, 67, 101, 108, 108, 115, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 109, 95, 99, 101, 108, 108, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 83, 101, 116, 72, 111, 111, 107, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 112, 114, 101, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 112, 111, 115, 116, 0, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 103, 0, 0, 0, 0, 0, 0, 0, 13, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 3, 0, 0, 0, 4, 0, 0, 0, 82, 101, 97, 100, 0, 0, 1, 0, 105, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 87, 114, 105, 116, 101, 1, 0, 1, 0, 106, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 68, 101, 108, 101, 116, 101, 2, 0, 1, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 82, 101, 97, 100, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 36, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 87, 114, 105, 116, 101, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 9, 0, 0, 0, 100, 97, 116, 97, 95, 115, 105, 122, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 1, 37, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 72, 111, 111, 107, 115, 67, 111, 110, 102, 105, 103, 95, 68, 101, 108, 101, 116, 101, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 98, 101, 103, 105, 110, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 52, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 65, 99, 99, 101, 115, 115, 80, 97, 116, 116, 101, 114, 110, 77, 101, 115, 115, 97, 103, 101, 115, 95, 85, 112, 100, 97, 116, 101, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 110, 101, 119, 95, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 3, 0, 0, 0, 30, 0, 0, 0, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 77, 97, 110, 121, 73, 110, 100, 105, 118, 105, 100, 117, 97, 108, 86, 97, 108, 117, 101, 115, 0, 0, 1, 0, 111, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 72, 101, 97, 118, 121, 83, 116, 97, 116, 101, 1, 0, 1, 0, 112, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 82, 117, 110, 67, 80, 85, 72, 101, 97, 118, 121, 79, 112, 101, 114, 97, 116, 105, 111, 110, 2, 0, 1, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 1, 61, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 77, 97, 110, 121, 73, 110, 100, 105, 118, 105, 100, 117, 97, 108, 86, 97, 108, 117, 101, 115, 0, 0, 2, 0, 0, 0, 20, 0, 0, 0, 110, 117, 109, 98, 101, 114, 95, 111, 102, 95, 111, 112, 101, 114, 97, 116, 105, 111, 110, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 97, 108, 116, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 97, 100, 65, 110, 100, 83, 101, 116, 72, 101, 97, 118, 121, 83, 116, 97, 116, 101, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 110, 117, 109, 98, 101, 114, 95, 111, 102, 95, 110, 101, 119, 95, 118, 97, 108, 117, 101, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 20, 0, 0, 0, 109, 97, 120, 95, 104, 101, 97, 118, 121, 95, 115, 116, 97, 116, 101, 95, 115, 105, 122, 101, 0, 1, 0, 8, 1, 0, 0, 0, 0, 4, 0, 0, 0, 115, 97, 108, 116, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 51, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 117, 110, 67, 80, 85, 72, 101, 97, 118, 121, 79, 112, 101, 114, 97, 116, 105, 111, 110, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 105, 116, 101, 114, 97, 116, 105, 111, 110, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 5, 0, 0, 0, 8, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 0, 0, 1, 0, 116, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 83, 101, 116, 77, 97, 110, 121, 86, 97, 108, 117, 101, 115, 1, 0, 1, 0, 117, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 65, 115, 115, 101, 114, 116, 86, 105, 115, 105, 98, 108, 101, 83, 108, 111, 116, 78, 117, 109, 98, 101, 114, 2, 0, 1, 0, 118, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 65, 110, 100, 83, 108, 101, 101, 112, 3, 0, 1, 0, 119, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 80, 97, 110, 105, 99, 4, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 1, 54, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 65, 115, 115, 101, 114, 116, 86, 105, 115, 105, 98, 108, 101, 83, 108, 111, 116, 78, 117, 109, 98, 101, 114, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 101, 120, 112, 101, 99, 116, 101, 100, 95, 118, 105, 115, 105, 98, 108, 101, 95, 115, 108, 111, 116, 95, 110, 117, 109, 98, 101, 114, 0, 1, 0, 8, 1, 0, 0, 0, 0, 1, 47, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 65, 110, 100, 83, 108, 101, 101, 112, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 12, 0, 0, 0, 115, 108, 101, 101, 112, 95, 109, 105, 108, 108, 105, 115, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 2, 0, 0, 0, 17, 0, 0, 0, 83, 101, 116, 86, 97, 108, 117, 101, 87, 105, 116, 104, 80, 114, 111, 111, 102, 0, 0, 1, 0, 122, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 1, 0, 1, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 1, 48, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 83, 101, 116, 86, 97, 108, 117, 101, 87, 105, 116, 104, 80, 114, 111, 111, 102, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 118, 97, 108, 117, 101, 0, 1, 0, 7, 1, 0, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 110, 101, 119, 95, 109, 101, 116, 104, 111, 100, 95, 105, 100, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 8, 0, 0, 0, 7, 0, 0, 0, 68, 101, 112, 111, 115, 105, 116, 0, 0, 1, 0, 126, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 84, 114, 97, 110, 115, 102, 101, 114, 1, 0, 1, 0, 130, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 2, 0, 1, 0, 135, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 3, 0, 1, 0, 136, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 70, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 4, 0, 1, 0, 137, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 85, 110, 102, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 5, 0, 1, 0, 139, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 65, 100, 100, 80, 111, 111, 108, 65, 100, 109, 105, 110, 6, 0, 1, 0, 140, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 82, 101, 109, 111, 118, 101, 80, 111, 111, 108, 65, 100, 109, 105, 110, 7, 0, 1, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 1, 38, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 68, 101, 112, 111, 115, 105, 116, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 1, 0, 0, 0, 0, 3, 0, 0, 0, 114, 104, 111, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 114, 101, 99, 105, 112, 105, 101, 110, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 118, 105, 101, 119, 95, 102, 118, 107, 115, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 128, 0, 0, 0, 0, 0, 0, 0, 13, 0, 129, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 84, 114, 97, 110, 115, 102, 101, 114, 0, 0, 5, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 97, 110, 99, 104, 111, 114, 95, 114, 111, 111, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 110, 117, 108, 108, 105, 102, 105, 101, 114, 115, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 118, 105, 101, 119, 95, 99, 105, 112, 104, 101, 114, 116, 101, 120, 116, 115, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 133, 0, 0, 0, 0, 0, 0, 0, 13, 0, 134, 0, 0, 0, 0, 0, 0, 0, 1, 13, 0, 0, 0, 69, 110, 99, 114, 121, 112, 116, 101, 100, 78, 111, 116, 101, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 99, 109, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 110, 111, 110, 99, 101, 0, 1, 1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 99, 116, 0, 1, 2, 0, 0, 0, 0, 0, 14, 0, 0, 0, 102, 118, 107, 95, 99, 111, 109, 109, 105, 116, 109, 101, 110, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 109, 97, 99, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 0, 0, 7, 0, 0, 0, 5, 0, 0, 0, 112, 114, 111, 111, 102, 0, 1, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 97, 110, 99, 104, 111, 114, 95, 114, 111, 111, 116, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 110, 117, 108, 108, 105, 102, 105, 101, 114, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 119, 105, 116, 104, 100, 114, 97, 119, 95, 97, 109, 111, 117, 110, 116, 0, 1, 0, 9, 1, 0, 0, 0, 0, 2, 0, 0, 0, 116, 111, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 118, 105, 101, 119, 95, 99, 105, 112, 104, 101, 114, 116, 101, 120, 116, 115, 0, 0, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 103, 97, 115, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 112, 100, 97, 116, 101, 77, 101, 116, 104, 111, 100, 73, 100, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 110, 101, 119, 95, 109, 101, 116, 104, 111, 100, 95, 105, 100, 0, 1, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 70, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 97, 100, 100, 114, 101, 115, 115, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 64, 0, 0, 0, 0, 0, 0, 0, 3, 8, 0, 0, 0, 112, 114, 105, 118, 112, 111, 111, 108, 0, 0, 0, 0, 0, 1, 46, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 85, 110, 102, 114, 101, 101, 122, 101, 65, 100, 100, 114, 101, 115, 115, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 97, 100, 100, 114, 101, 115, 115, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 43, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 65, 100, 100, 80, 111, 111, 108, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 46, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 82, 101, 109, 111, 118, 101, 80, 111, 111, 108, 65, 100, 109, 105, 110, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 1, 0, 0, 0, 13, 0, 0, 0, 87, 105, 116, 104, 100, 114, 97, 119, 78, 105, 103, 104, 116, 0, 0, 1, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 0, 95, 95, 83, 111, 118, 86, 105, 114, 116, 117, 97, 108, 87, 97, 108, 108, 101, 116, 95, 67, 97, 108, 108, 77, 101, 115, 115, 97, 103, 101, 95, 87, 105, 116, 104, 100, 114, 97, 119, 78, 105, 103, 104, 116, 0, 0, 3, 0, 0, 0, 16, 0, 0, 0, 109, 105, 100, 110, 105, 103, 104, 116, 95, 97, 100, 100, 114, 101, 115, 115, 0, 1, 5, 0, 0, 0, 0, 6, 0, 0, 0, 97, 109, 111, 117, 110, 116, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 85, 110, 105, 113, 117, 101, 110, 101, 115, 115, 68, 97, 116, 97, 2, 0, 0, 0, 5, 0, 0, 0, 78, 111, 110, 99, 101, 0, 0, 1, 0, 146, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 71, 101, 110, 101, 114, 97, 116, 105, 111, 110, 1, 0, 1, 0, 147, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 1, 9, 0, 0, 0, 84, 120, 68, 101, 116, 97, 105, 108, 115, 0, 0, 4, 0, 0, 0, 21, 0, 0, 0, 109, 97, 120, 95, 112, 114, 105, 111, 114, 105, 116, 121, 95, 102, 101, 101, 95, 98, 105, 112, 115, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 109, 97, 120, 95, 102, 101, 101, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 103, 97, 115, 95, 108, 105, 109, 105, 116, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 99, 104, 97, 105, 110, 95, 105, 100, 0, 1, 0, 8, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 0, 8, 1, 0, 0, 0, 0, 0, 1, 19, 0, 0, 0, 85, 110, 115, 105, 103, 110, 101, 100, 84, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 0, 0, 3, 0, 0, 0, 12, 0, 0, 0, 114, 117, 110, 116, 105, 109, 101, 95, 99, 97, 108, 108, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 117, 110, 105, 113, 117, 101, 110, 101, 115, 115, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 100, 101, 116, 97, 105, 108, 115, 0, 0, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 225, 16, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 84, 101, 115, 116, 67, 104, 97, 105, 110, 189, 33, 197, 161, 104, 9, 147, 107, 209, 142, 226, 254, 192, 53, 116, 76, 223, 195, 190, 210, 164, 210, 25, 39, 173, 49, 14, 63, 116, 34, 65, 158]; #[allow(dead_code)] pub const SCHEMA_JSON: &str = r#"{ @@ -88,7 +88,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "uniqueness", "silent": false, "value": { - "ByIndex": 142 + "ByIndex": 145 }, "doc": "" }, @@ -96,7 +96,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "details", "silent": false, "value": { - "ByIndex": 145 + "ByIndex": 148 }, "doc": "" } @@ -284,7 +284,7 @@ pub const SCHEMA_JSON: &str = r#"{ "discriminant": 16, "template": null, "value": { - "ByIndex": 141 + "ByIndex": 142 } } ], @@ -3473,7 +3473,7 @@ pub const SCHEMA_JSON: &str = r#"{ "fields": [ { "value": { - "ByIndex": 142 + "ByIndex": 143 }, "silent": false, "doc": "" @@ -3490,7 +3490,7 @@ pub const SCHEMA_JSON: &str = r#"{ "discriminant": 0, "template": null, "value": { - "ByIndex": 143 + "ByIndex": 144 } } ], @@ -3539,7 +3539,7 @@ pub const SCHEMA_JSON: &str = r#"{ "discriminant": 0, "template": null, "value": { - "ByIndex": 143 + "ByIndex": 146 } }, { @@ -3547,7 +3547,7 @@ pub const SCHEMA_JSON: &str = r#"{ "discriminant": 1, "template": null, "value": { - "ByIndex": 144 + "ByIndex": 147 } } ], @@ -3604,7 +3604,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "max_priority_fee_bips", "silent": false, "value": { - "ByIndex": 146 + "ByIndex": 149 }, "doc": "" }, @@ -3678,7 +3678,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "uniqueness", "silent": false, "value": { - "ByIndex": 142 + "ByIndex": 145 }, "doc": "" }, @@ -3686,7 +3686,7 @@ pub const SCHEMA_JSON: &str = r#"{ "display_name": "details", "silent": false, "value": { - "ByIndex": 145 + "ByIndex": 148 }, "doc": "" } @@ -3696,7 +3696,7 @@ pub const SCHEMA_JSON: &str = r#"{ ], "root_type_indices": [ 0, - 147, + 150, 6, 12 ], diff --git a/examples/demo-rollup/midnight_withdrawals_plan/README.md b/examples/demo-rollup/midnight_withdrawals_plan/README.md new file mode 100644 index 000000000..9c3308a53 --- /dev/null +++ b/examples/demo-rollup/midnight_withdrawals_plan/README.md @@ -0,0 +1,102 @@ +# Midnight Withdrawals Roadmap + +This document tracks the work required to bring the Rust STF-side implementation of Midnight withdrawals in `demo-stf` (and, by extension, all rollups that embed it such as `rollup-ligero`) to parity with the Compact contracts shipped under `examples/rollup-ligero/midnight-l2-contracts`. Each milestone below produces a testable artifact so we can ship incremental value. + +## Background + +- The Compact contracts define the desired behavior: `L2Gateway` debits balances, `L2Messenger` hashes messages and leaves using helpers in `ProtocolTypes`, `L2MessageQueue` maintains a 16-level incremental tree, and L1 verifies proofs via `relayWithdrawNIGHTWithProof`. +- Our goal is to reproduce that logic on the STF side so the bridge background worker ( [examples/rollup-ligero/src/midnight_bridge.rs](../demo-rollup/src/midnight_bridge.rs) ) can originate real `relayWithdrawNIGHTWithProof` calls against the compiled contract artifacts (or on-chain deployment) without bespoke shims. + +## Constraints + +1. **Hashing / domain separation**: mirror the exact logic in `ProtocolTypes` (via the JS/WASM bundle in `examples/rollup-ligero/midnight-l2-contracts/bridge-contract/dist`). Do *not* switch to Poseidon; keep the SHA-256 based `persistentHash` domain separators already in the Compact sources. +2. **Tree depth**: keep the current 16-level queue so we match `WithdrawProof16`. Scaling to 40+ levels can be a later iteration once the Compact contract evolves. +3. **Module scope**: continue using a single `MidnightWithdrawals` module; only split it if a clean boundary emerges organically. +4. **TEE attestations**: skip wiring the withdraw root into batch attestations for now, but document the TODO and leave hook points. +5. **Location**: all STF changes ship through `examples/demo-rollup`, since `rollup-ligero` reuses that STF wholesale. + +## Success Criteria + +- We can generate the same withdrawal message hash and Merkle leaf as the Compact `L2Messenger` given identical inputs. +- The STF maintains the same append-only Merkle tree as `L2MessageQueue`; hashed siblings produced by the STF verify inside the Compact `Bridge` WASM via `relayWithdrawNIGHTWithProof`. +- The Midnight bridge background worker can assemble a proof by calling REST endpoints (or CLI helpers), submit it to the L1 contract, and observe `claimL1WithdrawalUnshielded` succeed in the managed WASM environment. + +## Phased Plan + +### Phase 1 — Protocol helpers & fixtures ✅ + +**Objective**: ensure Rust-side hashing matches Compact `ProtocolTypes`. + +**Status (complete)**: +- `sov_midnight_adapter::protocol_types` ([crates/adapters/midnight/src/protocol_types.rs](../../../crates/adapters/midnight/src/protocol_types.rs)) implements `WithdrawMessage`, `hash_withdraw_message`, `hash_withdraw_leaf`, and `hash_merkle_node` with SHA-256 domain separators (`mdn:l2l1:wdraw`, `mdn:l2w:leaf`) matching Compact `ProtocolTypes`. +- Golden test vectors committed at `crates/adapters/midnight/test-data/protocol/golden-vectors-v1.json`, derived from the JS/WASM contract sources. +- Three unit tests (`withdrawal_hash_matches_golden_vector`, `withdraw_leaf_hash_matches_vector`, `zero_hash_levels_match_contract_reference`) confirm cross-language determinism: `cargo test -p sov-midnight-adapter protocol_types`. +- `MidnightWithdrawals` STF module imports these helpers and stores `message_hash` + `leaf_hash` in every `StoredWithdrawal` record. + +### Phase 2 — In-module Merkle queue ✅ + +**Objective**: replace the ad-hoc `StateMap` with the incremental Merkle tree. + +**Status (complete)**: +- `MidnightWithdrawals` now stores `message_count`, `withdraw_root`, and 16 cached branch values (`branch_0`–`branch_15`) as `StateValue` fields, mirroring `L2MessageQueue`. +- The append algorithm uses bit decomposition of the nonce, branch caching, and precomputed `ZERO_HASHES` (lazy-initialized). Helper functions `index_bits_le`, `zero_hash`, `zero_sibling`, and `compute_merkle_artifacts` implement the tree logic inline. +- REST endpoints expose the queue state (root, leaf count) and enriched per-withdrawal metadata including `message_hash` and `leaf_hash`. + +### Phase 3 — Proof assembly API ✅ + +**Objective**: allow clients to fetch everything needed for `relayWithdrawNIGHTWithProof`. + +**Status (complete)**: +- `GET /modules/midnight-withdrawals/withdrawals/{nonce}/proof?batch_index=` (requires `--features native`) returns the withdrawal payload, Merkle siblings, and an `l1_proof` blob matching Compact's `WithdrawProof16` layout. The `batch_index` query parameter lets bridge tooling stamp the finalized batch that attested the root. +- `L1WithdrawProof16Binary` struct encodes the proof with correct ordering and endianness for the Compact contract; `into_response()` serializes it as hex for the REST layer. +- Proof assembly recomputes the 16-level tree on demand via `compute_merkle_artifacts`, so the STF emits canonical siblings even after additional leaves are appended. +- Unit coverage: `cargo test -p demo-stf --features native merkle_artifacts_round_trip` verifies that proof data rebuilds the stored withdraw root. + +### Phase 4 — Bridge worker integration ⬜ + +**Objective**: close the loop so proofs can be relayed automatically. + +**Architecture**: the rollup already manages a TS executor service (`bridge-cli/src/executor-server.ts`) as a child process (see `examples/rollup-ligero/MIDNIGHT_BRIDGE.md`). The executor exposes `POST /relay-withdraw-night-with-proof` which delegates to `bridge-cli/src/commands/relay-withdraw-night-with-proof.ts` — this command calls `bridgeContract.callTx.relayWithdrawNIGHTWithProof(...)` via the Compact SDK and is ready to use. A Rust `executor_client::relay_withdraw_night_with_proof()` helper in `bridge-cli/decoder-rs/src/executor_client.rs` already wraps the HTTP call. + +**Work items**: +- Add a withdrawal relay loop in `MidnightBridge` (`examples/rollup-ligero/src/midnight_bridge.rs`) that, after each finalized batch: + 1. Queries the STF REST API for unrelayed withdrawals and their proofs (`GET /modules/midnight-withdrawals/withdrawals/{nonce}/proof?batch_index=`). + 2. Calls the executor's `POST /relay-withdraw-night-with-proof` endpoint (via the existing `executor_client` helper or a direct HTTP POST) with the proof payload (`l2Sender`, `recipient`, `amount`, `batchIndex`, `nonce`, `indexBits`, `siblings`). + 3. Tracks which nonces have been successfully relayed (e.g., persisting a cursor in the accessory DB) to avoid duplicate submissions. +- Record the `withdraw_root` per finalized batch inside the STF state so the worker can confirm that the proof's root belongs to a published batch. (Full attestation wiring remains TODO; for now, store the root in a batch accessory DB or emit an event.) +- Optionally follow up with `POST /claim-l1-withdrawal-unshielded` (also available on the executor) so recipients can claim on L1 without a separate tool. +- Expand observability: metrics for queue length, proof generation latency, and relay success/failure counts. + +**Testing**: +- End-to-end integration test using `bridge-cli/decoder-rs test-withdraw` (which already exercises the full deposit → withdraw → relay → claim flow against the executor) to validate the automated path. +- Manual runbook documented in `examples/rollup-ligero/MIDNIGHT_BRIDGE.md` for operators. + +### Phase 5 — Hardening & TODOs ⬜ + +**Objective**: make the feature production-ready and highlight remaining gaps. + +**Work items**: +- Add configuration flags for maximum queue depth warnings, proof generation limits, and REST pagination. +- Provide tooling to export/import queue state snapshots (useful for debugging or migration within devnets). +- Document outstanding TODOs, especially: + - Wiring withdraw roots into `BatchPublicDataV1` and TEE attestations (blocked on the separate attestation effort). + - Scaling the Merkle tree beyond 16 levels once the Compact contracts upgrade (`withdrawProof16` → flexible depth). + - Switching to Poseidon-based hashing once the protocol mandates it. + +**Testing**: +- Stress/regression tests covering queue persistence (drop/restart node), multiple concurrent withdrawals, and bridge worker restarts. +- Lint/docs checks to ensure all operator-facing docs reference the new flow. + +## Next Steps + +1. Phase 4 is next — wire the bridge worker to fetch proofs and relay `relayWithdrawNIGHTWithProof` calls to L1. +2. Track progress via a dedicated GitHub issue or project board so each phase can be merged independently. + +--- + +**TODO (Attestation Integration Placeholder)**: once the TEE pipeline exposes `withdrawRoot` inside `BatchPublicDataV1`, we need to: +- Extend the STF batch builder to read the module's root after each slot and include it in the batch metadata. +- Update the bridge worker to verify that the proof's root matches the attested value instead of trusting local state. +- Ensure the L1 contract stores the root per batch so relays can reference finalized batch indices. + +Until then, proofs should only be treated as devnet-quality evidence. diff --git a/examples/demo-rollup/stf/src/midnight_withdrawals.rs b/examples/demo-rollup/stf/src/midnight_withdrawals.rs index 1d3c33652..6382db505 100644 --- a/examples/demo-rollup/stf/src/midnight_withdrawals.rs +++ b/examples/demo-rollup/stf/src/midnight_withdrawals.rs @@ -543,9 +543,13 @@ impl MidnightWithdrawals { fn sender_bytes(address: &S::Address) -> Result<[u8; 32]> { let raw = address.as_ref(); - ensure!(raw.len() == 32, "Sender address must be exactly 32 bytes"); + ensure!( + raw.len() <= 32, + "Sender address must be at most 32 bytes, got {}", + raw.len() + ); let mut out = [0u8; 32]; - out.copy_from_slice(raw); + out[..raw.len()].copy_from_slice(raw); Ok(out) } diff --git a/examples/rollup-ligero/Cargo.toml b/examples/rollup-ligero/Cargo.toml index bda06b376..2eaef7554 100644 --- a/examples/rollup-ligero/Cargo.toml +++ b/examples/rollup-ligero/Cargo.toml @@ -194,3 +194,7 @@ path = "src/bin/decrypt_authority_notes.rs" [[bin]] name = "rollup-ligero-service-controller" path = "src/bin/rollup_ligero_service_controller.rs" + +[[bin]] +name = "sov-cli" +path = "src/bin/sov_cli.rs" diff --git a/examples/rollup-ligero/L1_INTERACTIONS.md b/examples/rollup-ligero/L1_INTERACTIONS.md deleted file mode 100644 index 7a6783a57..000000000 --- a/examples/rollup-ligero/L1_INTERACTIONS.md +++ /dev/null @@ -1,116 +0,0 @@ -# L1 Interactions for Rollup Ligero - -This guide explains how the rollup interacts with the Midnight L1 Bridge contract, and how to run that flow locally. - -## Short Operational Summary - -In TEE mode, the rollup periodically aggregates DA-backed execution into batch public data, obtains oracle-backed attestation material, then settles to the Midnight Bridge on L1: - -1. `commitBatch(parentBatchHash, batchHash)` records the next batch commitment. -2. `finalizeBatch(batchPublicData, signatures, signerBitmap, finalizeTimestamp)` finalizes that committed batch. - -The bridge lifecycle (contract deployment, executor service, indexer access, deposit monitoring) is configured through a single `[sequencer.extension.midnight_bridge]` section and works in any operating mode. Comment out the entire section to disable all L1 interactions. - -## Where L1 Contract Tooling Lives - -- Bridge contract and interaction tooling: `examples/rollup-ligero/midnight-l2-contracts` -- Executor service (HTTP API for the rollup): `examples/rollup-ligero/midnight-l2-contracts/bridge-cli` - -## Automated Flow (recommended) - -When `[sequencer.extension.midnight_bridge]` is configured in the rollup config, the rollup manages the full Bridge lifecycle automatically: - -1. **Genesis detection**: On first start (empty ledger DB), the rollup computes the genesis state root. -2. **Auto-deploy**: If no `contract_address` is configured or persisted, the rollup invokes `bridge-cli deploy` as a subprocess, passing the genesis state root and batch hash. The resulting contract address is persisted to `/bridge_contract_address`. -3. **Executor startup**: The rollup spawns the executor service as a managed child process with the correct contract address and network configuration. -4. **Health check**: The rollup waits for the executor to become ready (polls `/state`). -5. **Normal operation**: The TEE manager calls `commitBatch` and `finalizeBatch` via the executor. The deposit monitor polls the indexer for new deposits. -6. **Shutdown**: When the rollup exits, the managed executor child process is killed automatically. - -On subsequent starts (non-genesis), the rollup loads the persisted contract address and spawns the executor without deploying. - -### Prerequisites - -The local Midnight L1 network must already be running before starting the rollup: - -```bash -cd examples/rollup-ligero/midnight-l2-contracts -npm install -npm run build -npm run setup-standalone -``` - -This starts the Midnight node, indexer, and proof server via Docker. - -### Configuration - -In `rollup_config_tee_local.toml`: - -```toml -[sequencer.extension.midnight_bridge] -bridge_cli_path = "midnight-l2-contracts/bridge-cli" -network = "undeployed" -executor_port = 3001 -funding_seed = "0000000000000000000000000000000000000000000000000000000000000001" -rollup_id_hex = "0000000000000000000000000000000000000000000000000000000000000000" -indexer_http = "http://localhost:8088/api/v3/graphql" -indexer_timeout_ms = 30000 -# contract_address = "" # auto-deployed on genesis if omitted -signing_key_path = "assets/midnight_bridge_signer.json" -poll_interval_ms = 1000 -max_fee = 1000000 - -[sequencer.extension.tee_configuration] -tee_attestation_oracle_url = "http://127.0.0.1:8090" -``` - -### Running - -```bash -# Fresh start (wipes state, new genesis, auto-deploys contract): -TEE_RESET=1 ./tee_local.sh --release --skip-build - -# Restart (reuses existing state and persisted contract address): -./tee_local.sh --release --skip-build -``` - -### Disabling L1 Interactions - -To run without any L1 interactions, comment out the entire `[sequencer.extension.midnight_bridge]` section. The rollup will operate without bridge deployment, executor, or deposit monitoring. - -## Manual Flow (legacy) - -If you prefer to manage the contract and executor manually, omit the `midnight_bridge` section entirely and deploy the contract and start the executor outside of the rollup process. - -### Deploy the Contract Manually - -Compute the genesis values: - -```bash -cargo run --bin print-genesis-info -- --rollup-config rollup_config_tee_local.toml --genesis-dir demo_data_tee/genesis -``` - -Deploy in `midnight-l2-contracts/bridge-cli`: - -```bash -npm run cli -- deploy -n undeployed --genesis-state-root --genesis-batch-hash -``` - -Set `BRIDGE_CONTRACT_ADDRESS` in `bridge-cli/.env`, then start the executor: - -```bash -EXECUTOR_PORT=3001 npm run executor -``` - -## Log Lines to Watch - -- Success: - - `L1 commitBatch submitted via executor` - - `L1 finalizeBatch submitted via executor` - - `L1 Bridge contract deployed successfully` - - `Executor service is ready` -- Diagnostics/failures: - - `Executor commit_batch failed; batch cursor will NOT advance` - - `Executor finalize_batch failed; batch cursor will NOT advance` - - `Deploying L1 Bridge contract via bridge-cli (this may take a while)...` - - `No L1 source available; defaulting to batch_index=0` diff --git a/examples/rollup-ligero/MIDNIGHT_BRIDGE.md b/examples/rollup-ligero/MIDNIGHT_BRIDGE.md new file mode 100644 index 000000000..35181c72d --- /dev/null +++ b/examples/rollup-ligero/MIDNIGHT_BRIDGE.md @@ -0,0 +1,167 @@ +# Midnight Bridge for Rollup Ligero + +The Midnight Bridge is a configurable component of the rollup. When `[sequencer.extension.midnight_bridge]` is present in the rollup config TOML, the rollup will run the following types of Midnight L1 network interactions: + +## Midnight Bridge responsibilities - overview + +### 1. L1 Bridge contract deployment + +If `contract_address` is not provided in config and the rollup is starting from genesis, it will deploy a new Bridge contract instance to the configured Midnight network. + +### 2. Settling batches on L1 + +In TEE mode, the rollup periodically aggregates DA-backed execution into batch public data, obtains oracle-backed attestation material, then settles to the Midnight Bridge on L1: + +1. `commitBatch(parentBatchHash, batchHash)` records the next batch commitment. +2. `finalizeBatch(batchPublicData, signatures, signerBitmap, finalizeTimestamp)` finalizes that committed batch. + +### 3. Bridging - deposits + +TODO: extend with a bit of extra detail to look more like sections 2. and 4. + +The rollup observes the L1 Bridge contract for deposit events where NIGHT token is locked on the contract. Each such event comes with an L2 (rollup) bridging recipient address to which the rollup credits the appropriate bridged funds. + +### 4. Bridging - withdrawals + +The other leg of the bridge: moving NIGHT from L2 back to L1. + +1. A user submits a `WithdrawNight` transaction on L2, which burns L2 NIGHT and appends the withdrawal to a 16-level incremental Merkle tree inside the `MidnightWithdrawals` STF module. +2. Each finalized batch attests the cumulative `withdrawRoot` to the L1 Bridge contract via `finalizeBatch`. +3. The bridge worker automatically detects pending withdrawals and relays their Merkle proofs to L1 by calling the executor's `POST /relay-withdraw-night-with-proof` endpoint. +4. Once relayed, the recipient can claim funds on L1 via `claimL1WithdrawalUnshielded`. + +## Testing + +### Prerequisites + +The repository (or the `feature/midnight-bridge` branch) needs to be checked ot with submodules: + +```bash +git clone --branch feature/midnight-bridge --recurse-submodules https://github.com/dcSpark/sovereign-sdk.git +# or, if already cloned: +git checkout feature/midnight-bridge +git submodule update --init --recursive +``` + +Bridge contract and interaction tooling now lives in `examples/rollup-ligero/midnight-l2-contracts`. + +The local Midnight L1 network must already be running before starting the rollup: + +```bash +cd examples/rollup-ligero/midnight-l2-contracts +npm install +npm run build +npm run setup-standalone +``` + +This starts the Midnight node, indexer, and proof server via Docker. + +### Configuration + +In `rollup_config_tee_local.toml`: + +```toml +[sequencer.extension.midnight_bridge] +bridge_cli_path = "midnight-l2-contracts/bridge-cli" +network = "undeployed" +executor_port = 3001 +funding_seed = "0000000000000000000000000000000000000000000000000000000000000001" +rollup_id_hex = "0000000000000000000000000000000000000000000000000000000000000000" +indexer_http = "http://localhost:8088/api/v3/graphql" +indexer_timeout_ms = 30000 +# contract_address = "" # auto-deployed on genesis if omitted +signing_key_path = "assets/midnight_bridge_signer.json" +poll_interval_ms = 1000 +max_fee = 1000000 + +[sequencer.extension.tee_configuration] +tee_attestation_oracle_url = "http://127.0.0.1:8090" +``` + +### Running + +```bash +# Fresh start (wipes state, new genesis, auto-deploys contract): +TEE_RESET=1 ./tee_local.sh --release --skip-build + +# Restart (reuses existing state and persisted contract address): +./tee_local.sh --release --skip-build +``` + +### Making deposits + +TODO + +### Making withdrawals + +**Step 1 — Initiate a withdrawal on L2** (burns NIGHT, enqueues a message): + +```bash +# Create the call message (use your own midnight_address): +cat > withdraw_night.json << 'EOF' +{ + "withdraw_night": { + "midnight_address": "1e524a8e02b8022f243db6c992f48c866dff4fa3b1c01624f9f2c1d269e11017", + "amount": "1000000000000", + "gas_limit": null + } +} +EOF + +# Build sov-cli if needed (must use rollup-ligero's, not demo-rollup's — they +# link different ed25519 implementations and signatures are incompatible): +# cargo build -p sov-rollup-ligero --bin sov-cli --release + +# One-time setup: point sov-cli at the rollup and import a genesis-funded key. +rm ~/.sov_cli_wallet/wallet_state.json +python3 -c "import json; json.dump(json.load(open('demo_data_tee/genesis/generated_keypairs.json'))[0], open('/tmp/user_key.json','w'))" +../../target/release/sov-cli node set-url http://127.0.0.1:12346 +../../target/release/sov-cli keys import --path /tmp/user_key.json --nickname user + +# Import and submit the withdrawal: +../../target/release/sov-cli transactions import from-file midnight-withdrawals \ + --path withdraw_night.json \ + --max-fee 1000000000 +../../target/release/sov-cli node submit-batch by-nickname user +``` + +**Step 2 — Verify the withdrawal was queued:** + +```bash +curl -s http://127.0.0.1:12346/modules/midnight-withdrawals/withdrawals/queue | jq +# → {"next_nonce": 1, "withdraw_root_hex": "..."} +``` + +**Step 3 — Wait for automatic relay.** After the next batch is finalized on L1, the bridge worker relays the withdrawal proof automatically. You can inspect the proof at any time: + +```bash +curl -s http://127.0.0.1:12346/modules/midnight-withdrawals/withdrawals/0/proof?batch_index=1 | jq +``` + +**Step 4 — Claim on L1.** Once the proof has been relayed, the recipient claims funds via the executor: + +```bash +curl -s -X POST http://127.0.0.1:3001/claim-l1-withdrawal-unshielded \ + -H 'Content-Type: application/json' \ + -d '{ + "recipient": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff", + "amount": "1000000" + }' | jq +``` + +### Disabling L1 Interactions + +To run without any L1 interactions, comment out the entire `[sequencer.extension.midnight_bridge]` section. The rollup will operate without bridge deployment, executor, or deposit monitoring. + +## Operation details + +When `[sequencer.extension.midnight_bridge]` is configured in the rollup config, the rollup manages the full Bridge lifecycle automatically: + +1. **Genesis detection**: On first start (empty ledger DB), the rollup computes the genesis state root. +2. **Auto-deploy**: If no `contract_address` is configured or persisted, the rollup invokes `bridge-cli deploy` as a subprocess, passing the genesis state root and batch hash. The resulting contract address is persisted to `/bridge_contract_address`. +3. **Executor startup**: The rollup spawns the executor service as a managed child process with the correct contract address and network configuration. +4. **Health check**: The rollup waits for the executor to become ready (polls `/state`). +5. **Normal operation**: The TEE manager calls `commitBatch` and `finalizeBatch` via the executor. The deposit monitor polls the indexer for new deposits. +6. **Shutdown**: When the rollup exits, the managed executor child process is killed automatically. + +On subsequent starts (non-genesis), the rollup loads the persisted contract address and spawns the executor without deploying. diff --git a/examples/rollup-ligero/README.md b/examples/rollup-ligero/README.md index c6849799b..fa37f09d2 100644 --- a/examples/rollup-ligero/README.md +++ b/examples/rollup-ligero/README.md @@ -94,7 +94,7 @@ export SOV_PROVER_MODE=prove For TEE-mode settlement flow and L1 Bridge integration (executor setup, config, and logs), see: -- [`L1_INTERACTIONS.md`](./L1_INTERACTIONS.md) +- [`MIDNIGHT_BRIDGE.md`](./MIDNIGHT_BRIDGE.md) ## Service Orchestration diff --git a/examples/rollup-ligero/src/bin/sov_cli.rs b/examples/rollup-ligero/src/bin/sov_cli.rs new file mode 100644 index 000000000..185bc4955 --- /dev/null +++ b/examples/rollup-ligero/src/bin/sov_cli.rs @@ -0,0 +1,15 @@ +use demo_stf::runtime::RuntimeSubcommand; +use sov_modules_api::cli::{FileNameArg, JsonStringArg}; +use sov_modules_rollup_blueprint::WalletBlueprint; +use sov_rollup_ligero::MockDemoRollup; + +include!("../../autogenerated.rs"); + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + MockDemoRollup::run_wallet::< + RuntimeSubcommand, + RuntimeSubcommand, + >() + .await +} diff --git a/examples/rollup-ligero/src/midnight_bridge.rs b/examples/rollup-ligero/src/midnight_bridge.rs index 3b49afe45..ddca74cf0 100644 --- a/examples/rollup-ligero/src/midnight_bridge.rs +++ b/examples/rollup-ligero/src/midnight_bridge.rs @@ -58,6 +58,7 @@ pub(crate) struct BridgeCursorStore { impl BridgeCursorStore { const KEY_BYTES: &'static [u8] = b"midnight_bridge.cursor"; + const WITHDRAWAL_RELAY_KEY: &'static [u8] = b"midnight_bridge.withdrawal_relay_cursor"; const CURSOR_SUBDIR: &'static str = "midnight_bridge_cursor"; pub(crate) fn open(storage_path: &Path) -> Result { @@ -118,6 +119,37 @@ impl BridgeCursorStore { .write_schemas(batch) .context("Failed to persist Midnight bridge cursor") } + + fn load_withdrawal_relay_cursor(&self) -> Result> { + let raw = self + .accessor + .get_value_option(&Self::WITHDRAWAL_RELAY_KEY.to_vec(), SlotNumber::GENESIS) + .context("Failed to read withdrawal relay cursor from accessory DB")?; + match raw { + Some(bytes) => { + anyhow::ensure!( + bytes.len() == 8, + "Withdrawal relay cursor payload must be 8 bytes, got {}", + bytes.len() + ); + let mut arr = [0u8; 8]; + arr.copy_from_slice(&bytes); + Ok(Some(u64::from_le_bytes(arr))) + } + None => Ok(None), + } + } + + fn persist_withdrawal_relay_cursor(&self, cursor: u64) -> Result<()> { + let bytes = cursor.to_le_bytes().to_vec(); + let batch = AccessoryDb::materialize_values( + vec![(Self::WITHDRAWAL_RELAY_KEY.to_vec(), Some(bytes))], + SlotNumber::GENESIS, + )?; + self.db + .write_schemas(batch) + .context("Failed to persist withdrawal relay cursor") + } } struct BridgeConfig { @@ -223,6 +255,11 @@ where } } + let executor_base_url = extension + .midnight_bridge + .as_ref() + .map(|b| format!("http://127.0.0.1:{}", b.executor_port)); + let BridgeConfig { runtime, deposit_source, @@ -234,6 +271,7 @@ where deposit_source, cursor_store, rollup_dedup_url, + executor_base_url, )?; Ok(Some(tokio::spawn(async move { bridge.run().await }))) } @@ -332,6 +370,38 @@ struct DedupGenerationResponse { generation: Option, } +/// Response from `GET /modules/midnight-withdrawals/withdrawals/queue`. +#[derive(Debug, Deserialize)] +struct WithdrawalQueueStatusResponse { + next_nonce: u64, +} + +/// Response from `GET /modules/midnight-withdrawals/withdrawals/{nonce}/proof`. +#[derive(Debug, Deserialize)] +struct WithdrawalProofResponse { + sender_bytes_hex: String, + recipient_bytes_hex: String, + amount: String, + l1_proof: L1ProofResponse, +} + +/// The `l1_proof` sub-object within [`WithdrawalProofResponse`]. +#[derive(Debug, Deserialize)] +struct L1ProofResponse { + batch_index: u64, + nonce: u64, + index_bits_le: Vec, + sibling_hashes_hex: Vec, +} + +/// Partial response from the executor's `GET /state` endpoint. +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct ExecutorStateResponse { + #[serde(default)] + last_finalized_batch_index: Option, +} + struct MidnightBridge { sequencer: Arc, settings: RuntimeBridgeSettings, @@ -343,6 +413,10 @@ struct MidnightBridge { cursor_store: Option, /// When set, the bridge syncs next_generation from this rollup URL at startup. rollup_dedup_url: Option, + /// Next withdrawal nonce to relay to L1 (all nonces below this have been relayed). + next_relay_nonce: u64, + /// Base URL for the managed executor HTTP service (e.g. `http://127.0.0.1:3001`). + executor_base_url: Option, } impl MidnightBridge @@ -355,6 +429,7 @@ where deposit_source: DepositSource, mut cursor_store: Option, rollup_dedup_url: Option, + executor_base_url: Option, ) -> Result { let mut restored_cursor = None; @@ -386,6 +461,22 @@ where DepositSource::Mock(_) => None, }; + // Restore the withdrawal relay cursor from persistent storage. + let next_relay_nonce = cursor_store + .as_ref() + .and_then(|store| match store.load_withdrawal_relay_cursor() { + Ok(Some(cursor)) => { + info!(cursor, "Midnight bridge restored withdrawal relay cursor"); + Some(cursor) + } + Ok(None) => None, + Err(err) => { + warn!(error = ?err, "Failed to read withdrawal relay cursor"); + None + } + }) + .unwrap_or(0); + let bridge = Self { sequencer, settings, @@ -396,6 +487,8 @@ where next_chain_index, cursor_store, rollup_dedup_url, + next_relay_nonce, + executor_base_url, }; if restored_cursor.is_none() { @@ -420,6 +513,163 @@ where self.persist_cursor(cursor); } + fn advance_relay_cursor(&mut self, next_nonce: u64) { + self.next_relay_nonce = next_nonce; + if let Some(store) = &self.cursor_store { + if let Err(err) = store.persist_withdrawal_relay_cursor(next_nonce) { + warn!( + value = next_nonce, + error = ?err, + "Failed to persist withdrawal relay cursor" + ); + } + } + } + + /// Relays pending L2→L1 withdrawal proofs to the executor service. + /// + /// For each unrelayed nonce, fetches the Merkle proof from the rollup REST API and + /// POSTs it to the executor's `relay-withdraw-night-with-proof` endpoint. The relay + /// cursor is persisted after each successful relay so progress survives restarts. + async fn relay_pending_withdrawals(&mut self) -> Result<()> { + let executor_url = match &self.executor_base_url { + Some(url) => url.clone(), + None => return Ok(()), + }; + let rollup_url = match &self.rollup_dedup_url { + Some(url) => url.trim_end_matches('/').to_string(), + None => return Ok(()), + }; + + // 1. Get last finalized batch index from the executor. + let state_url = format!("{}/state", executor_url.trim_end_matches('/')); + let state_resp: ExecutorStateResponse = match reqwest::get(&state_url).await { + Ok(resp) if resp.status().is_success() => resp + .json() + .await + .context("Failed to parse executor /state response")?, + Ok(resp) => { + debug!( + status = %resp.status(), + "Executor /state returned non-success; skipping withdrawal relay" + ); + return Ok(()); + } + Err(err) => { + debug!(error = ?err, "Executor /state unreachable; skipping withdrawal relay"); + return Ok(()); + } + }; + + let finalized_batch_index: u64 = state_resp + .last_finalized_batch_index + .as_deref() + .and_then(|s| s.parse().ok()) + .unwrap_or(0); + + if finalized_batch_index == 0 { + return Ok(()); + } + + // 2. Get the withdrawal queue status from the rollup. + let queue_url = format!( + "{}/modules/midnight-withdrawals/withdrawals/queue", + rollup_url + ); + let queue_resp: WithdrawalQueueStatusResponse = reqwest::get(&queue_url) + .await + .context("Failed to fetch withdrawal queue status")? + .json() + .await + .context("Failed to parse withdrawal queue status")?; + + let next_nonce = queue_resp.next_nonce; + if next_nonce <= self.next_relay_nonce { + return Ok(()); + } + + // 3. Relay each pending withdrawal. + let client = reqwest::Client::new(); + for nonce in self.next_relay_nonce..next_nonce { + let proof_url = format!( + "{}/modules/midnight-withdrawals/withdrawals/{}/proof?batch_index={}", + rollup_url, nonce, finalized_batch_index + ); + let proof: WithdrawalProofResponse = match reqwest::get(&proof_url).await { + Ok(resp) if resp.status().is_success() => resp + .json() + .await + .context("Failed to parse withdrawal proof response")?, + Ok(resp) => { + let status = resp.status(); + let body = resp.text().await.unwrap_or_default(); + warn!( + nonce, + status = %status, + body = %body, + "Failed to fetch withdrawal proof; will retry next cycle" + ); + break; + } + Err(err) => { + warn!(nonce, error = ?err, "Failed to fetch withdrawal proof; will retry next cycle"); + break; + } + }; + + let relay_url = format!( + "{}/relay-withdraw-night-with-proof", + executor_url.trim_end_matches('/') + ); + let relay_body = serde_json::json!({ + "l2Sender": proof.sender_bytes_hex, + "recipient": proof.recipient_bytes_hex, + "amount": proof.amount, + "batchIndex": proof.l1_proof.batch_index.to_string(), + "nonce": proof.l1_proof.nonce.to_string(), + "indexBits": proof.l1_proof.index_bits_le, + "siblings": proof.l1_proof.sibling_hashes_hex, + }); + + match client.post(&relay_url).json(&relay_body).send().await { + Ok(resp) if resp.status().is_success() => { + info!( + nonce, + batch_index = finalized_batch_index, + amount = %proof.amount, + "Relayed withdrawal proof to L1 executor" + ); + self.advance_relay_cursor(nonce + 1); + } + Ok(resp) => { + let status = resp.status(); + let body = resp.text().await.unwrap_or_default(); + if body.contains("ALREADY_EXECUTED") { + info!( + nonce, + "Withdrawal already executed on L1; advancing cursor" + ); + self.advance_relay_cursor(nonce + 1); + continue; + } + warn!( + nonce, + status = %status, + body = %body, + "Withdrawal relay failed; will retry next cycle" + ); + break; + } + Err(err) => { + warn!(nonce, error = ?err, "Withdrawal relay request failed; will retry next cycle"); + break; + } + } + } + + Ok(()) + } + /// Fetches the next generation for the bridge credential from the rollup dedup API /// and sets `next_generation` so credit transactions pass the uniqueness check. /// Retries on connection errors so the rollup HTTP server has time to start. @@ -533,6 +783,11 @@ where if let Err(err) = poll_result { warn!(error = ?err, "Midnight bridge failed to fetch deposits"); } + + // Relay pending L2→L1 withdrawal proofs to the executor. + if let Err(err) = self.relay_pending_withdrawals().await { + warn!(error = ?err, "Withdrawal relay cycle failed"); + } } } diff --git a/examples/rollup-ligero/src/mock_rollup.rs b/examples/rollup-ligero/src/mock_rollup.rs index 8a8beb066..8f029c777 100644 --- a/examples/rollup-ligero/src/mock_rollup.rs +++ b/examples/rollup-ligero/src/mock_rollup.rs @@ -16,7 +16,9 @@ use sov_modules_api::rest::StateUpdateReceiver; use sov_modules_api::{NodeEndpoints, Spec, Storage, SyncStatus, ZkVerifier}; use sov_modules_rollup_blueprint::pluggable_traits::PluggableSpec; use sov_modules_rollup_blueprint::proof_sender::SovApiProofSender; -use sov_modules_rollup_blueprint::{FullNodeBlueprint, RollupBlueprint, SequencerCreationReceipt}; +use sov_modules_rollup_blueprint::{ + FullNodeBlueprint, RollupBlueprint, SequencerCreationReceipt, WalletBlueprint, +}; use sov_rollup_interface::zk::aggregated_proof::CodeCommitment; use sov_sequencer::{ProofBlobSender, Sequencer}; use sov_stf_runner::processes::{ParallelProverService, ProverService, RollupProverConfig}; @@ -53,6 +55,8 @@ where type Runtime = Runtime; } +impl WalletBlueprint for MockDemoRollup {} + #[async_trait] impl FullNodeBlueprint for MockDemoRollup { type DaService = StorableMidnightDaService; From 894e1ad1cb032a318617f43bc4f9fb05ae92ce37 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Wed, 8 Apr 2026 21:52:10 +0200 Subject: [PATCH 19/20] Withdrawal relay: bridge worker, TEE withdraw_root wiring, and batch settlement resilience MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Bridge worker automatically relays L2→L1 withdrawal proofs to the executor's POST /relay-withdraw-night-with-proof after each batch finalization, with persistent cursor tracking and root-mismatch guard. - Wire STF's MidnightWithdrawals.withdraw_root into BatchPublicDataV1 via the prover querying the rollup REST API, breaking the circular dependency where the L1 contract only had the empty tree root. - Add TEE batch settlement resilience: L1 state resync before each commit (handles committed-but-not-finalized, cursor drift, prev_batch_hash mismatch), exponential backoff on failures, and diagnostic logging. - Add sov-cli binary to rollup-ligero (required due to ed25519-dalek version mismatch between Risc0 and Ligero adapters). - Fix sender_bytes zero-padding for 28-byte addresses in MidnightWithdrawals. - Add withdrawRoot to executor /state endpoint (bridge-cli TS). - Update MIDNIGHT_BRIDGE.md with deposit and withdrawal CLI walkthroughs. --- crates/full-node/sov-stf-runner/Cargo.toml | 2 +- .../sov-stf-runner/src/processes/mod.rs | 2 + .../processes/prover_service/parallel/mod.rs | 5 +- .../prover_service/parallel/prover.rs | 55 ++++++++- .../src/processes/tee_manager/mod.rs | 106 +++++++++++++++++- .../tests/integration/helpers/runner_init.rs | 1 + .../tests/integration/prover_service_tests.rs | 1 + .../src/native_only/mod.rs | 21 ++++ .../src/rt_agnostic_blueprint.rs | 1 + .../demo-rollup/src/celestia_nomt_rollup.rs | 1 + examples/demo-rollup/src/celestia_rollup.rs | 1 + examples/demo-rollup/src/mock_nomt_rollup.rs | 1 + examples/demo-rollup/src/mock_rollup.rs | 1 + examples/rollup-ligero/MIDNIGHT_BRIDGE.md | 43 ++++++- examples/rollup-ligero/src/midnight_bridge.rs | 39 +++++++ examples/rollup-ligero/src/mock_rollup.rs | 18 +++ 16 files changed, 288 insertions(+), 10 deletions(-) diff --git a/crates/full-node/sov-stf-runner/Cargo.toml b/crates/full-node/sov-stf-runner/Cargo.toml index ce737fff1..cccf28103 100644 --- a/crates/full-node/sov-stf-runner/Cargo.toml +++ b/crates/full-node/sov-stf-runner/Cargo.toml @@ -48,7 +48,7 @@ tower-http = { workspace = true, features = ["normalize-path", "cors"] } tee = { workspace = true, optional = true } tower-layer = "0.3.3" futures-util = "0.3.31" -reqwest = { version = "0.12", features = ["json"] } +reqwest = { version = "0.12", features = ["json", "blocking"] } sha2 = { workspace = true } [dev-dependencies] diff --git a/crates/full-node/sov-stf-runner/src/processes/mod.rs b/crates/full-node/sov-stf-runner/src/processes/mod.rs index 731fc1f7e..2b3e136ab 100644 --- a/crates/full-node/sov-stf-runner/src/processes/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/mod.rs @@ -44,6 +44,7 @@ pub async fn start_tee_workflow_in_background( executor_client: Option, rollup_id: Option<[u8; 32]>, storage_path: Option, + rollup_url: Option, ) -> anyhow::Result> where Ps: ProverService, @@ -147,6 +148,7 @@ where executor_client, rollup_id, storage_path, + rollup_url, ) .post_aggregated_proof_to_da_in_background() .await) diff --git a/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/mod.rs b/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/mod.rs index baef82cde..c2ffd3ef4 100644 --- a/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/mod.rs @@ -63,6 +63,7 @@ where code_commitment: CodeCommitment, prover_address: Address, storage_path: Option, + rollup_url: Option, ) -> Self { let verifier = Arc::new(Verifier { da_verifier }); @@ -70,7 +71,7 @@ where inner_vm, outer_vm, prover_config: config, - prover_state: Prover::new(prover_address, num_threads, code_commitment, storage_path), + prover_state: Prover::new(prover_address, num_threads, code_commitment, storage_path, rollup_url), verifier, } } @@ -85,6 +86,7 @@ where code_commitment: CodeCommitment, prover_address: Address, storage_path: Option, + rollup_url: Option, ) -> Self { let num_cpus = num_cpus::get(); assert!(num_cpus > 1, "Unable to create parallel prover service"); @@ -98,6 +100,7 @@ where code_commitment, prover_address, storage_path, + rollup_url, ) } } diff --git a/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/prover.rs b/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/prover.rs index d6922bbff..32e567908 100644 --- a/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/prover.rs +++ b/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/prover.rs @@ -77,6 +77,8 @@ pub(crate) struct Prover { l1_bridge_cache_path: Option, l1_bridge_cached: Arc>, warned_no_midnight_bridge: AtomicBool, + /// Rollup REST base URL for querying STF module state (e.g. withdraw_root). + rollup_url: Option, phantom: std::marker::PhantomData<(StateRoot, Witness, Da)>, } @@ -88,11 +90,39 @@ where StateRoot: Serialize + DeserializeOwned + Clone + AsRef<[u8]> + Send + Sync + 'static, Witness: Serialize + DeserializeOwned + Send + Sync + 'static, { + /// Fetches the current withdraw root from the L2 STF via the rollup REST API. + /// Called inside `block_in_place`, so uses a blocking HTTP request. + fn fetch_stf_withdraw_root(rollup_url: &str) -> anyhow::Result<[u8; 32]> { + let queue_url = format!( + "{}/modules/midnight-withdrawals/withdrawals/queue", + rollup_url.trim_end_matches('/') + ); + let resp = reqwest::blocking::get(&queue_url) + .map_err(|e| anyhow::anyhow!("STF withdrawal queue request failed: {e}"))?; + if !resp.status().is_success() { + anyhow::bail!("STF withdrawal queue returned HTTP {}", resp.status()); + } + #[derive(serde::Deserialize)] + struct QueueStatus { + withdraw_root_hex: String, + } + let status: QueueStatus = resp + .json() + .map_err(|e| anyhow::anyhow!("Failed to parse STF queue response: {e}"))?; + let bytes = hex::decode(&status.withdraw_root_hex) + .map_err(|e| anyhow::anyhow!("Failed to decode withdraw_root_hex: {e}"))?; + let root: [u8; 32] = bytes + .try_into() + .map_err(|v: Vec| anyhow::anyhow!("withdraw_root must be 32 bytes, got {}", v.len()))?; + Ok(root) + } + pub(crate) fn new( prover_address: Address, num_threads: usize, code_commitment: CodeCommitment, storage_path: Option, + rollup_url: Option, ) -> Self { let l1_bridge_cache_path = storage_path .as_ref() @@ -119,6 +149,7 @@ where l1_bridge_cache_path, l1_bridge_cached: Arc::new(RwLock::new(cached)), warned_no_midnight_bridge: AtomicBool::new(false), + rollup_url, phantom: PhantomData, } } @@ -296,7 +327,29 @@ where ); } - if let Some(root) = snap.rollup.withdraw_roots.values().next_back() { + // Prefer the STF's own withdraw root over the L1 snapshot value. + // The L1 snapshot reflects the previous batch's root (circular + // dependency: L1 only has the root after we finalize). + if let Some(ref url) = self.rollup_url { + match Self::fetch_stf_withdraw_root(url) { + Ok(root) => { + tracing::info!( + withdraw_root = hex::encode(root), + "Using STF withdraw root from rollup REST API" + ); + l1_bridge.withdraw_root = root; + } + Err(e) => { + tracing::warn!( + error = %e, + "Failed to fetch STF withdraw root; falling back to L1 snapshot" + ); + if let Some(root) = snap.rollup.withdraw_roots.values().next_back() { + l1_bridge.withdraw_root = *root; + } + } + } + } else if let Some(root) = snap.rollup.withdraw_roots.values().next_back() { l1_bridge.withdraw_root = *root; } else { tracing::warn!( diff --git a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs index 1b54ab2c5..34de41123 100644 --- a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs @@ -99,6 +99,10 @@ pub struct TeeProofManager { executor_client: Option, rollup_id: Option<[u8; 32]>, storage_path: Option, + /// Rollup REST base URL for querying STF module state (e.g. withdraw_root). + rollup_url: Option, + /// Consecutive L1 settlement failure count (for exponential backoff). + l1_settlement_failures: u32, } impl TeeProofManager @@ -122,6 +126,7 @@ where executor_client: Option, rollup_id: Option<[u8; 32]>, storage_path: Option, + rollup_url: Option, ) -> Self { Self { prover_service, @@ -143,6 +148,8 @@ where executor_client, rollup_id, storage_path, + rollup_url, + l1_settlement_failures: 0, } } @@ -333,6 +340,8 @@ where ); // Build the batch struct early so we can persist it for crash recovery. + // NOTE: withdraw_root is now sourced from the L2 STF (via the prover's + // REST query to the rollup), not the L1 indexer snapshot. let batch = BatchPublicDataV1 { version: 1, layer2_chain_id: public_data.layer2_chain_id, @@ -349,9 +358,90 @@ where withdraw_root: public_data.withdraw_root, }; + // Backoff: if previous settlement failed, wait before retrying. + if self.l1_settlement_failures > 0 { + let delay_secs = std::cmp::min( + 2u64.saturating_pow(self.l1_settlement_failures), + 60, + ); + info!( + batch_index = self.batch_index, + failures = self.l1_settlement_failures, + delay_secs, + "Backing off before retrying L1 settlement" + ); + sleep(Duration::from_secs(delay_secs)).await; + } + + // Resync: query L1 state to detect if the contract is ahead of our + // cursor (e.g. after crash recovery finalized a batch, or if the + // executor returned an error but the L1 tx actually succeeded). + let mut skip_settlement = false; + let mut skip_commit = false; + if let Some(ref executor) = self.executor_client { + match executor.get_state().await { + Ok(state) => { + info!( + batch_index = self.batch_index, + l1_finalized = state.last_finalized_batch_index, + l1_committed = state.last_committed_batch_index, + prev_batch_hash = hex::encode(self.prev_batch_hash), + "L1 state before batch settlement" + ); + if state.last_finalized_batch_index >= self.batch_index { + // L1 already finalized this batch (or later) — resync cursor. + info!( + batch_index = self.batch_index, + l1_finalized = state.last_finalized_batch_index, + "L1 is ahead; resyncing cursor" + ); + self.batch_index = state.last_finalized_batch_index + 1; + self.prev_batch_hash = state.last_finalized_batch_hash; + if let Some(ref sp) = self.storage_path { + super::bridge_lifecycle::remove_pending_finalize(sp); + } + self.l1_settlement_failures = 0; + skip_settlement = true; + } else if state.last_committed_batch_index >= self.batch_index + && state.last_committed_batch_index > state.last_finalized_batch_index + { + // Batch already committed but not finalized — skip commit, + // proceed directly to finalize. + info!( + batch_index = self.batch_index, + "Batch already committed on L1; skipping commit, proceeding to finalize" + ); + skip_commit = true; + } else if state.last_finalized_batch_hash != self.prev_batch_hash + && state.last_finalized_batch_index + 1 == self.batch_index + { + // Our prev_batch_hash doesn't match L1's — resync. + warn!( + batch_index = self.batch_index, + our_prev = hex::encode(self.prev_batch_hash), + l1_prev = hex::encode(state.last_finalized_batch_hash), + "prev_batch_hash mismatch; resyncing from L1" + ); + self.prev_batch_hash = state.last_finalized_batch_hash; + } + } + Err(e) => { + warn!( + batch_index = self.batch_index, + error = %e, + "Failed to query executor state for resync; proceeding with cached cursor" + ); + } + } + } + // Commit batch on L1 via executor service (if configured). // Track success so we only advance the durable batch cursor when L1 accepted both commit AND finalize. - let mut l1_ok = if let Some(ref executor) = self.executor_client { + let mut l1_ok = if skip_settlement { + true // cursor already resynced above + } else if skip_commit { + true // commit already on L1, proceed to finalize + } else if let Some(ref executor) = self.executor_client { match executor .commit_batch(&self.prev_batch_hash, &batch_hash) .await @@ -491,7 +581,8 @@ where // Finalize batch on L1 via executor service (if configured). // Only attempt finalize if commit succeeded -- otherwise the contract is not expecting it. - if l1_ok { + // Skip if we already resynced the cursor above. + if l1_ok && !skip_settlement { if let (Some(ref executor), Some(rollup_id)) = (self.executor_client.as_ref(), self.rollup_id.as_ref()) { @@ -558,12 +649,17 @@ where .inc_next_height_to_receive_by(num_proofs_to_create as u64); if l1_ok { - self.batch_index += 1; - self.prev_batch_hash = batch_hash; + if !skip_settlement { + self.batch_index += 1; + self.prev_batch_hash = batch_hash; + } + self.l1_settlement_failures = 0; } else { + self.l1_settlement_failures = self.l1_settlement_failures.saturating_add(1); warn!( batch_index = self.batch_index, - "L1 commit/finalize failed; batch cursor NOT advanced (will retry same batch next cycle)" + failures = self.l1_settlement_failures, + "L1 commit/finalize failed; batch cursor NOT advanced (will retry with backoff)" ); } } diff --git a/crates/full-node/sov-stf-runner/tests/integration/helpers/runner_init.rs b/crates/full-node/sov-stf-runner/tests/integration/helpers/runner_init.rs index 60d9537a1..00b9c6b5b 100644 --- a/crates/full-node/sov-stf-runner/tests/integration/helpers/runner_init.rs +++ b/crates/full-node/sov-stf-runner/tests/integration/helpers/runner_init.rs @@ -291,6 +291,7 @@ pub async fn initialize_runner( )), None, None, + None, ) .await .unwrap(); diff --git a/crates/full-node/sov-stf-runner/tests/integration/prover_service_tests.rs b/crates/full-node/sov-stf-runner/tests/integration/prover_service_tests.rs index b264b6890..a7da038f7 100644 --- a/crates/full-node/sov-stf-runner/tests/integration/prover_service_tests.rs +++ b/crates/full-node/sov-stf-runner/tests/integration/prover_service_tests.rs @@ -328,6 +328,7 @@ fn make_new_prover() -> TestProver { Default::default(), Default::default(), None, + None, ), inner_vm, num_worker_threads: num_threads, diff --git a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs index 347ef0fb5..62f7c7268 100644 --- a/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs +++ b/crates/module-system/sov-modules-rollup-blueprint/src/native_only/mod.rs @@ -671,6 +671,26 @@ pub trait FullNodeBlueprint: RollupBlueprint { let tee_storage_path = Some(std::path::PathBuf::from(&rollup_config.storage.path)); + // Build the rollup URL so the TEE manager can query STF + // module state (e.g. the withdrawal queue root). + let tee_rollup_url = rollup_config + .runner + .http_config + .public_address + .clone() + .or_else(|| { + let host = + if rollup_config.runner.http_config.bind_host == "0.0.0.0" { + "127.0.0.1" + } else { + &rollup_config.runner.http_config.bind_host + }; + Some(format!( + "http://{}:{}", + host, rollup_config.runner.http_config.bind_port + )) + }); + let tee_handle = start_tee_workflow_in_background( prover_service, rollup_config.proof_manager.aggregated_proof_block_jump, @@ -683,6 +703,7 @@ pub trait FullNodeBlueprint: RollupBlueprint { executor_client.take(), rollup_id.take(), tee_storage_path, + tee_rollup_url, ) .await?; diff --git a/crates/module-system/sov-test-utils/src/rt_agnostic_blueprint.rs b/crates/module-system/sov-test-utils/src/rt_agnostic_blueprint.rs index 888767492..32a070cff 100644 --- a/crates/module-system/sov-test-utils/src/rt_agnostic_blueprint.rs +++ b/crates/module-system/sov-test-utils/src/rt_agnostic_blueprint.rs @@ -125,6 +125,7 @@ where CodeCommitment::default(), rollup_config.proof_manager.prover_address.clone(), Some(rollup_config.storage.path.clone()), + None, ) } diff --git a/examples/demo-rollup/src/celestia_nomt_rollup.rs b/examples/demo-rollup/src/celestia_nomt_rollup.rs index 77dde2a71..9a98fabd4 100644 --- a/examples/demo-rollup/src/celestia_nomt_rollup.rs +++ b/examples/demo-rollup/src/celestia_nomt_rollup.rs @@ -177,6 +177,7 @@ impl FullNodeBlueprint for CelestiaNomtDemoRollup { CodeCommitment::default(), rollup_config.proof_manager.prover_address, Some(rollup_config.storage.path.clone()), + None, ) } diff --git a/examples/demo-rollup/src/celestia_rollup.rs b/examples/demo-rollup/src/celestia_rollup.rs index eec487e7f..cd7a6aad1 100644 --- a/examples/demo-rollup/src/celestia_rollup.rs +++ b/examples/demo-rollup/src/celestia_rollup.rs @@ -163,6 +163,7 @@ impl FullNodeBlueprint for CelestiaDemoRollup { CodeCommitment::default(), rollup_config.proof_manager.prover_address, Some(rollup_config.storage.path.clone()), + None, ) } diff --git a/examples/demo-rollup/src/mock_nomt_rollup.rs b/examples/demo-rollup/src/mock_nomt_rollup.rs index 348a6e924..a812f6696 100644 --- a/examples/demo-rollup/src/mock_nomt_rollup.rs +++ b/examples/demo-rollup/src/mock_nomt_rollup.rs @@ -161,6 +161,7 @@ impl FullNodeBlueprint for MockNomtDemoRollup { CodeCommitment::default(), rollup_config.proof_manager.prover_address, Some(rollup_config.storage.path.clone()), + None, ) } diff --git a/examples/demo-rollup/src/mock_rollup.rs b/examples/demo-rollup/src/mock_rollup.rs index 60f04aafb..4e6579f99 100644 --- a/examples/demo-rollup/src/mock_rollup.rs +++ b/examples/demo-rollup/src/mock_rollup.rs @@ -147,6 +147,7 @@ impl FullNodeBlueprint for MockDemoRollup { CodeCommitment::default(), rollup_config.proof_manager.prover_address, Some(rollup_config.storage.path.clone()), + None, ) } diff --git a/examples/rollup-ligero/MIDNIGHT_BRIDGE.md b/examples/rollup-ligero/MIDNIGHT_BRIDGE.md index 35181c72d..9a834ddae 100644 --- a/examples/rollup-ligero/MIDNIGHT_BRIDGE.md +++ b/examples/rollup-ligero/MIDNIGHT_BRIDGE.md @@ -90,7 +90,46 @@ TEE_RESET=1 ./tee_local.sh --release --skip-build ### Making deposits -TODO +Deposits lock NIGHT on the L1 Bridge contract and credit the corresponding amount on L2. The rollup automatically detects deposit events via the Midnight indexer and mints funds to the specified L2 recipient. + +**Via the executor** (simplest — uses the running executor service): + +```bash +# Deposit 1 000 000 000 000 tNIGHT to an L2 address (the amount must not exceed +# the funding wallet's balance on the Midnight network): +curl -s -X POST http://127.0.0.1:3001/deposit \ + -H 'Content-Type: application/json' \ + -d '{ + "amount": "1000000000000", + "l2Recipient": "sov16fkyars4xdzl7c8cdspuvuacf52jktgnacjpxsg0hyf0zlk6jqm" + }' | jq +``` + +The `l2Recipient` is the 64-hex-char credential ID of the L2 account that will receive the bridged funds. You can obtain it from an L2 key file: + +```bash +python3 -c " +import json, hashlib +key = json.load(open('demo_data_tee/genesis/generated_keypairs.json'))[0] +print('address:', key['address']) +" +``` + +**Via the decoder-rs CLI** (alternative, useful for scripting): + +```bash +cd midnight-l2-contracts/bridge-cli/decoder-rs +cargo run -- deposit \ + --executor-url http://127.0.0.1:3001 \ + --amount 1000000000000 \ + --l2-recipient sov16fkyars4xdzl7c8cdspuvuacf52jktgnacjpxsg0hyf0zlk6jqm +``` + +After a few seconds the rollup will pick up the deposit event and credit funds. Verify: + +```bash +curl -s http://127.0.0.1:12346/modules/bank/tokens/gas_token/balances/sov16fkyars4xdzl7c8cdspuvuacf52jktgnacjpxsg0hyf0zlk6jqm | jq +``` ### Making withdrawals @@ -144,7 +183,7 @@ curl -s http://127.0.0.1:12346/modules/midnight-withdrawals/withdrawals/0/proof? curl -s -X POST http://127.0.0.1:3001/claim-l1-withdrawal-unshielded \ -H 'Content-Type: application/json' \ -d '{ - "recipient": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff", + "recipient": "1e524a8e02b8022f243db6c992f48c866dff4fa3b1c01624f9f2c1d269e11017", "amount": "1000000" }' | jq ``` diff --git a/examples/rollup-ligero/src/midnight_bridge.rs b/examples/rollup-ligero/src/midnight_bridge.rs index ddca74cf0..c6078e505 100644 --- a/examples/rollup-ligero/src/midnight_bridge.rs +++ b/examples/rollup-ligero/src/midnight_bridge.rs @@ -382,6 +382,7 @@ struct WithdrawalProofResponse { sender_bytes_hex: String, recipient_bytes_hex: String, amount: String, + withdraw_root_hex: String, l1_proof: L1ProofResponse, } @@ -400,6 +401,8 @@ struct L1ProofResponse { struct ExecutorStateResponse { #[serde(default)] last_finalized_batch_index: Option, + #[serde(default, rename = "withdrawRoot")] + withdraw_root: Option, } struct MidnightBridge { @@ -571,6 +574,13 @@ where return Ok(()); } + let l1_withdraw_root = state_resp.withdraw_root.as_deref().unwrap_or("(not available)"); + debug!( + finalized_batch_index, + l1_withdraw_root, + "Withdrawal relay: executor state" + ); + // 2. Get the withdrawal queue status from the rollup. let queue_url = format!( "{}/modules/midnight-withdrawals/withdrawals/queue", @@ -617,6 +627,35 @@ where } }; + // Diagnostic: log the full proof data for debugging. + debug!( + nonce, + batch_index = finalized_batch_index, + sender = %proof.sender_bytes_hex, + recipient = %proof.recipient_bytes_hex, + amount = %proof.amount, + stf_withdraw_root = %proof.withdraw_root_hex, + l1_withdraw_root, + index_bits = ?proof.l1_proof.index_bits_le, + siblings_count = proof.l1_proof.sibling_hashes_hex.len(), + "Relaying withdrawal proof" + ); + + // Guard: skip relay if the STF's withdraw root doesn't match the L1 + // batch's root — this means the batch was finalized before this + // withdrawal was included. A future batch will cover it. + if l1_withdraw_root != "(not available)" + && !proof.withdraw_root_hex.eq_ignore_ascii_case(l1_withdraw_root) + { + debug!( + nonce, + stf_root = %proof.withdraw_root_hex, + l1_root = l1_withdraw_root, + "Withdrawal not yet covered by finalized batch; will retry after next finalization" + ); + break; + } + let relay_url = format!( "{}/relay-withdraw-night-with-proof", executor_url.trim_end_matches('/') diff --git a/examples/rollup-ligero/src/mock_rollup.rs b/examples/rollup-ligero/src/mock_rollup.rs index 8f029c777..1a6409b25 100644 --- a/examples/rollup-ligero/src/mock_rollup.rs +++ b/examples/rollup-ligero/src/mock_rollup.rs @@ -201,6 +201,23 @@ impl FullNodeBlueprint for MockDemoRollup { let outer_vm = MockZkvmHost::new_non_blocking(); let da_verifier = Default::default(); + let rollup_url = rollup_config + .runner + .http_config + .public_address + .clone() + .or_else(|| { + let host = if rollup_config.runner.http_config.bind_host == "0.0.0.0" { + "127.0.0.1" + } else { + &rollup_config.runner.http_config.bind_host + }; + Some(format!( + "http://{}:{}", + host, rollup_config.runner.http_config.bind_port + )) + }); + ParallelProverService::new_with_default_workers( inner_vm, outer_vm, @@ -209,6 +226,7 @@ impl FullNodeBlueprint for MockDemoRollup { CodeCommitment::default(), rollup_config.proof_manager.prover_address, Some(rollup_config.storage.path.clone()), + rollup_url, ) } From ff0df721b6d16ee5ecfd5ae2cd7927324a539303 Mon Sep 17 00:00:00 2001 From: Ladislav Dubravsky Date: Mon, 13 Apr 2026 11:25:38 +0200 Subject: [PATCH 20/20] TEE batch settlement: discard stale proof on resync, log state roots, add executor timeout - When the L1 state resync detects the contract is ahead of our cursor (e.g. after a transient executor error where the L1 tx actually succeeded), return early from process_stf_info instead of using the current proof. The proof was generated for the now-skipped batch range and its initial_state_root won't chain from L1's new lastFinalizedStateRoot, causing BAD_PREV_STATE_ROOT. - Add 180s timeout to the executor HTTP client so the rollup fails fast and can recover via resync when the Midnight SDK hangs on response parsing. - Log a "Sending request to executor service" line before each executor call so it's clear when the rollup is blocked on the executor vs idle. - Log batch state roots from the prover for diagnostics. - Promote withdrawal relay state and root-mismatch guard logs back to info so the relay loop's progress is visible without enabling debug logging. - Fix prover's message_queue_hash lookup to use last_processed_l1_index instead of nextCrossDomainMessageIndex-1, fixing BAD_MESSAGE_QUEUE_HASH after deposits. --- .../src/processes/executor_client.rs | 1 + .../sov-stf-runner/src/processes/mod.rs | 5 ++- .../prover_service/parallel/prover.rs | 13 ++++--- .../src/processes/tee_manager/mod.rs | 36 ++++++++++++------- examples/rollup-ligero/MIDNIGHT_BRIDGE.md | 9 +++-- examples/rollup-ligero/midnight-l2-contracts | 2 +- examples/rollup-ligero/src/midnight_bridge.rs | 7 ++-- examples/rollup-ligero/withdraw_night.json | 7 ++++ 8 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 examples/rollup-ligero/withdraw_night.json diff --git a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs index d52b9d916..9eedaff5e 100644 --- a/crates/full-node/sov-stf-runner/src/processes/executor_client.rs +++ b/crates/full-node/sov-stf-runner/src/processes/executor_client.rs @@ -18,6 +18,7 @@ async fn post_json( body: &serde_json::Value, ) -> Result { let url = format!("{}{}", base_url_normalized(base_url), path); + tracing::info!(path, "Sending request to executor service (this may take a while)…"); let res = client .post(&url) .json(body) diff --git a/crates/full-node/sov-stf-runner/src/processes/mod.rs b/crates/full-node/sov-stf-runner/src/processes/mod.rs index 2b3e136ab..345cf5d77 100644 --- a/crates/full-node/sov-stf-runner/src/processes/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/mod.rs @@ -142,7 +142,10 @@ where prev_batch_hash, stf_info_receiver, shutdown_receiver, - reqwest::Client::new(), + reqwest::Client::builder() + .timeout(std::time::Duration::from_secs(60)) + .build() + .expect("Failed to build HTTP client"), oracle_url, midnight_bridge, executor_client, diff --git a/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/prover.rs b/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/prover.rs index 32e567908..d1ceb84f6 100644 --- a/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/prover.rs +++ b/crates/full-node/sov-stf-runner/src/processes/prover_service/parallel/prover.rs @@ -313,17 +313,20 @@ where l1_bridge.layer2_chain_id = snap.rollup.layer2_chain_id; - let index = snap - .rollup - .next_cross_domain_message_index - .saturating_sub(1); + // Use last_processed_l1_index as the lookup key — this is the + // index sent as lastProcessedQueueIndex in the batch, and the L1 + // contract validates messageQueueHash against this exact index. + // Using nextCrossDomainMessageIndex-1 would pick up deposits + // that arrived after the batch range. + let index = snap.l2_messenger.last_processed_l1_index; if let Some(h) = snap.rollup.message_rolling_hashes.get(&index) { l1_bridge.message_queue_hash = *h; } else { tracing::warn!( + last_processed_l1_index = index, next_cross_domain_message_index = snap.rollup.next_cross_domain_message_index, - "Missing message rolling hash for expected index; keeping cached value" + "Missing message rolling hash for last_processed index; keeping cached value" ); } diff --git a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs index 34de41123..f522ed1ec 100644 --- a/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs +++ b/crates/full-node/sov-stf-runner/src/processes/tee_manager/mod.rs @@ -339,6 +339,16 @@ where da_end_height, ); + // Log state roots for diagnostics (truncated to 32 bytes, same as L1). + info!( + batch_index = self.batch_index, + prev_state_root = hex::encode(&public_data.initial_state_root[..32]), + post_state_root = hex::encode(&public_data.final_state_root[..32]), + da_start_height, + da_end_height, + "Batch state roots from prover" + ); + // Build the batch struct early so we can persist it for crash recovery. // NOTE: withdraw_root is now sourced from the L2 STF (via the prover's // REST query to the rollup), not the L1 indexer snapshot. @@ -376,7 +386,6 @@ where // Resync: query L1 state to detect if the contract is ahead of our // cursor (e.g. after crash recovery finalized a batch, or if the // executor returned an error but the L1 tx actually succeeded). - let mut skip_settlement = false; let mut skip_commit = false; if let Some(ref executor) = self.executor_client { match executor.get_state().await { @@ -389,11 +398,13 @@ where "L1 state before batch settlement" ); if state.last_finalized_batch_index >= self.batch_index { - // L1 already finalized this batch (or later) — resync cursor. + // L1 already finalized this batch (or later) — resync cursor + // and discard the current proof (its state roots don't chain + // from L1's new lastFinalizedStateRoot). info!( batch_index = self.batch_index, l1_finalized = state.last_finalized_batch_index, - "L1 is ahead; resyncing cursor" + "L1 is ahead; resyncing cursor and discarding current proof" ); self.batch_index = state.last_finalized_batch_index + 1; self.prev_batch_hash = state.last_finalized_batch_hash; @@ -401,7 +412,12 @@ where super::bridge_lifecycle::remove_pending_finalize(sp); } self.l1_settlement_failures = 0; - skip_settlement = true; + // Advance the DA height cursor (the proof was consumed) but + // don't use it — the next call will produce a proof that + // chains correctly from the new cursor. + self.stf_info_receiver + .inc_next_height_to_receive_by(num_proofs_to_create as u64); + return Ok(()); } else if state.last_committed_batch_index >= self.batch_index && state.last_committed_batch_index > state.last_finalized_batch_index { @@ -437,9 +453,7 @@ where // Commit batch on L1 via executor service (if configured). // Track success so we only advance the durable batch cursor when L1 accepted both commit AND finalize. - let mut l1_ok = if skip_settlement { - true // cursor already resynced above - } else if skip_commit { + let mut l1_ok = if skip_commit { true // commit already on L1, proceed to finalize } else if let Some(ref executor) = self.executor_client { match executor @@ -582,7 +596,7 @@ where // Finalize batch on L1 via executor service (if configured). // Only attempt finalize if commit succeeded -- otherwise the contract is not expecting it. // Skip if we already resynced the cursor above. - if l1_ok && !skip_settlement { + if l1_ok { if let (Some(ref executor), Some(rollup_id)) = (self.executor_client.as_ref(), self.rollup_id.as_ref()) { @@ -649,10 +663,8 @@ where .inc_next_height_to_receive_by(num_proofs_to_create as u64); if l1_ok { - if !skip_settlement { - self.batch_index += 1; - self.prev_batch_hash = batch_hash; - } + self.batch_index += 1; + self.prev_batch_hash = batch_hash; self.l1_settlement_failures = 0; } else { self.l1_settlement_failures = self.l1_settlement_failures.saturating_add(1); diff --git a/examples/rollup-ligero/MIDNIGHT_BRIDGE.md b/examples/rollup-ligero/MIDNIGHT_BRIDGE.md index 9a834ddae..2fa63b750 100644 --- a/examples/rollup-ligero/MIDNIGHT_BRIDGE.md +++ b/examples/rollup-ligero/MIDNIGHT_BRIDGE.md @@ -17,9 +17,12 @@ In TEE mode, the rollup periodically aggregates DA-backed execution into batch p ### 3. Bridging - deposits -TODO: extend with a bit of extra detail to look more like sections 2. and 4. +Moving NIGHT from L1 into the rollup. -The rollup observes the L1 Bridge contract for deposit events where NIGHT token is locked on the contract. Each such event comes with an L2 (rollup) bridging recipient address to which the rollup credits the appropriate bridged funds. +1. A user (or script) calls the L1 Bridge contract's deposit function, locking NIGHT and specifying an L2 recipient address. +2. The deposit is recorded on L1 as a cross-domain message with a rolling hash chain (`messageRollingHashes`). +3. The rollup's bridge worker polls the Midnight indexer for new deposit events, constructs a `Bank::Mint` transaction for each, and submits it to the sequencer. +4. The minted funds appear at the specified L2 address on the next processed block. ### 4. Bridging - withdrawals @@ -141,7 +144,7 @@ cat > withdraw_night.json << 'EOF' { "withdraw_night": { "midnight_address": "1e524a8e02b8022f243db6c992f48c866dff4fa3b1c01624f9f2c1d269e11017", - "amount": "1000000000000", + "amount": "100000000000", "gas_limit": null } } diff --git a/examples/rollup-ligero/midnight-l2-contracts b/examples/rollup-ligero/midnight-l2-contracts index 635664f1a..6f7f8eebe 160000 --- a/examples/rollup-ligero/midnight-l2-contracts +++ b/examples/rollup-ligero/midnight-l2-contracts @@ -1 +1 @@ -Subproject commit 635664f1af1e2d471ad4c40e505249df59e6730f +Subproject commit 6f7f8eebec0efd903dac372b3ff4aa7504a2938e diff --git a/examples/rollup-ligero/src/midnight_bridge.rs b/examples/rollup-ligero/src/midnight_bridge.rs index c6078e505..3254aa54a 100644 --- a/examples/rollup-ligero/src/midnight_bridge.rs +++ b/examples/rollup-ligero/src/midnight_bridge.rs @@ -575,10 +575,11 @@ where } let l1_withdraw_root = state_resp.withdraw_root.as_deref().unwrap_or("(not available)"); - debug!( + info!( finalized_batch_index, l1_withdraw_root, - "Withdrawal relay: executor state" + next_relay_nonce = self.next_relay_nonce, + "Withdrawal relay: checking state" ); // 2. Get the withdrawal queue status from the rollup. @@ -647,7 +648,7 @@ where if l1_withdraw_root != "(not available)" && !proof.withdraw_root_hex.eq_ignore_ascii_case(l1_withdraw_root) { - debug!( + info!( nonce, stf_root = %proof.withdraw_root_hex, l1_root = l1_withdraw_root, diff --git a/examples/rollup-ligero/withdraw_night.json b/examples/rollup-ligero/withdraw_night.json new file mode 100644 index 000000000..ffb1c71c0 --- /dev/null +++ b/examples/rollup-ligero/withdraw_night.json @@ -0,0 +1,7 @@ +{ + "withdraw_night": { + "midnight_address": "1e524a8e02b8022f243db6c992f48c866dff4fa3b1c01624f9f2c1d269e11017", + "amount": "100000000000", + "gas_limit": null + } +}