From f14492f035dc69141694d65ab3123be9798559b1 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Mon, 17 Nov 2025 19:52:39 +0600 Subject: [PATCH 01/22] Update metadata --- src/chain/quantus_subxt.rs | 49 +++++++++++++++++-------------------- src/quantus_metadata.scale | Bin 165253 -> 165263 bytes 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/chain/quantus_subxt.rs b/src/chain/quantus_subxt.rs index a94a0d2..eb76445 100644 --- a/src/chain/quantus_subxt.rs +++ b/src/chain/quantus_subxt.rs @@ -8103,7 +8103,7 @@ pub mod api { [::core::primitive::u8; 32usize], runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >, ::core::primitive::u32, runtime_types::quantus_runtime::OriginCaller, @@ -9174,7 +9174,7 @@ pub mod api { pub type ProposalOrigin = runtime_types::quantus_runtime::OriginCaller; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >; pub type EnactmentMoment = runtime_types::frame_support::traits::schedule::DispatchTime< @@ -9665,7 +9665,7 @@ pub mod api { pub type Track = ::core::primitive::u16; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >; } impl ::subxt::ext::subxt_core::events::StaticEvent for Submitted { @@ -9759,7 +9759,7 @@ pub mod api { pub type Track = ::core::primitive::u16; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >; pub type Tally = runtime_types::pallet_conviction_voting::types::Tally<::core::primitive::u128>; @@ -10016,7 +10016,7 @@ pub mod api { ::core::primitive::u32, runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >, ::core::primitive::u128, runtime_types::pallet_conviction_voting::types::Tally< @@ -10916,7 +10916,7 @@ pub mod api { ::core::primitive::u128, runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >, >; pub type Param0 = ::subxt::ext::subxt_core::utils::H256; @@ -13176,7 +13176,7 @@ pub mod api { pub type ProposalOrigin = runtime_types::quantus_runtime::OriginCaller; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >; pub type EnactmentMoment = runtime_types::frame_support::traits::schedule::DispatchTime< @@ -13667,7 +13667,7 @@ pub mod api { pub type Track = ::core::primitive::u16; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >; } impl ::subxt::ext::subxt_core::events::StaticEvent for Submitted { @@ -13761,7 +13761,7 @@ pub mod api { pub type Track = ::core::primitive::u16; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >; pub type Tally = runtime_types::pallet_ranked_collective::Tally; } @@ -14012,7 +14012,7 @@ pub mod api { ::core::primitive::u32, runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >, ::core::primitive::u128, runtime_types::pallet_ranked_collective::Tally, @@ -24993,7 +24993,7 @@ pub mod api { >, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >, enactment_moment: runtime_types::frame_support::traits::schedule::DispatchTime< @@ -25150,7 +25150,7 @@ pub mod api { track: ::core::primitive::u16, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >, }, #[codec(index = 1)] @@ -25180,7 +25180,7 @@ pub mod api { track: ::core::primitive::u16, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >, tally: runtime_types::pallet_conviction_voting::types::Tally< ::core::primitive::u128, @@ -25273,7 +25273,7 @@ pub mod api { track: ::core::primitive::u16, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >, }, #[codec(index = 1)] @@ -25303,7 +25303,7 @@ pub mod api { track: ::core::primitive::u16, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::qp_poseidon::PoseidonHasher, + runtime_types::quantus_runtime::PoseidonHeaderHasher, >, tally: runtime_types::pallet_ranked_collective::Tally, }, @@ -27287,17 +27287,6 @@ pub mod api { } } } - pub mod qp_poseidon { - use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct PoseidonHasher; - } pub mod qp_scheduler { use super::runtime_types; #[derive( @@ -27407,6 +27396,14 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct PoseidonHeaderHasher; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] pub struct Runtime; #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, diff --git a/src/quantus_metadata.scale b/src/quantus_metadata.scale index 0e8740a72063206e0373c3ad06b37ff657e98131..ca82fd5affea3364a3f85313a2456d88412f75bd 100644 GIT binary patch delta 53 zcmZqe=IZa}YS_Za Date: Mon, 17 Nov 2025 19:59:29 +0600 Subject: [PATCH 02/22] Remove referenda --- src/cli/mod.rs | 13 - src/cli/referenda.rs | 814 ------------------------------------ src/cli/referenda_decode.rs | 243 ----------- src/cli/tech_referenda.rs | 718 ------------------------------- 4 files changed, 1788 deletions(-) delete mode 100644 src/cli/referenda.rs delete mode 100644 src/cli/referenda_decode.rs delete mode 100644 src/cli/tech_referenda.rs diff --git a/src/cli/mod.rs b/src/cli/mod.rs index f505027..162b1f7 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -12,8 +12,6 @@ pub mod high_security; pub mod metadata; pub mod preimage; pub mod recovery; -pub mod referenda; -pub mod referenda_decode; pub mod reversible; pub mod runtime; pub mod scheduler; @@ -21,7 +19,6 @@ pub mod send; pub mod storage; pub mod system; pub mod tech_collective; -pub mod tech_referenda; pub mod treasury; pub mod wallet; @@ -94,12 +91,6 @@ pub enum Commands { /// Tech Referenda management commands (for runtime upgrade proposals) #[command(subcommand)] Preimage(preimage::PreimageCommands), - #[command(subcommand)] - TechReferenda(tech_referenda::TechReferendaCommands), - - /// Standard Referenda management commands (public governance) - #[command(subcommand)] - Referenda(referenda::ReferendaCommands), /// Treasury management commands #[command(subcommand)] @@ -277,10 +268,6 @@ pub async fn execute_command( tech_collective::handle_tech_collective_command(tech_collective_cmd, node_url).await, Commands::Preimage(preimage_cmd) => preimage::handle_preimage_command(preimage_cmd, node_url, finalized).await, - Commands::TechReferenda(tech_referenda_cmd) => - tech_referenda::handle_tech_referenda_command(tech_referenda_cmd, node_url).await, - Commands::Referenda(referenda_cmd) => - referenda::handle_referenda_command(referenda_cmd, node_url).await, Commands::Treasury(treasury_cmd) => treasury::handle_treasury_command(treasury_cmd, node_url).await, Commands::Runtime(runtime_cmd) => diff --git a/src/cli/referenda.rs b/src/cli/referenda.rs deleted file mode 100644 index 5071cb3..0000000 --- a/src/cli/referenda.rs +++ /dev/null @@ -1,814 +0,0 @@ -//! `quantus referenda` subcommand - manage standard Referenda proposals -use crate::{ - chain::quantus_subxt, cli::common::submit_transaction, error::QuantusError, log_error, - log_print, log_success, log_verbose, -}; -use clap::Subcommand; -use colored::Colorize; -use std::str::FromStr; - -/// Standard Referenda management commands -#[derive(Subcommand, Debug)] -pub enum ReferendaCommands { - /// Submit a simple proposal (System::remark) to test Referenda - SubmitRemark { - /// Message to include in the remark - #[arg(long)] - message: String, - - /// Wallet name to sign with - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - - /// Origin type: signed (default), none (for signaling track), root - #[arg(long, default_value = "signed")] - origin: String, - }, - - /// Submit a proposal using existing preimage hash - Submit { - /// Preimage hash (must already exist on chain) - #[arg(long)] - preimage_hash: String, - - /// Wallet name to sign with - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - - /// Origin type: signed (default), none (for signaling track), root - #[arg(long, default_value = "signed")] - origin: String, - }, - - /// List all active Referenda proposals - List, - - /// Get details of a specific Referendum - Get { - /// Referendum index - #[arg(short, long)] - index: u32, - - /// Decode and display the proposal call in human-readable format - #[arg(long)] - decode: bool, - }, - - /// Check the status of a Referendum - Status { - /// Referendum index - #[arg(short, long)] - index: u32, - }, - - /// Place a decision deposit for a Referendum - PlaceDecisionDeposit { - /// Referendum index - #[arg(short, long)] - index: u32, - - /// Wallet name to sign with - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Vote on a Referendum (uses conviction voting) - Vote { - /// Referendum index - #[arg(short, long)] - index: u32, - - /// Vote aye (true) or nay (false) - #[arg(long)] - aye: bool, - - /// Conviction (0=None, 1=Locked1x, 2=Locked2x, up to 6=Locked6x) - #[arg(long, default_value = "0")] - conviction: u8, - - /// Amount to vote with - #[arg(long)] - amount: String, - - /// Wallet name to sign with - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Refund submission deposit for a completed Referendum - RefundSubmissionDeposit { - /// Referendum index - #[arg(short, long)] - index: u32, - - /// Wallet name that submitted the referendum - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Refund decision deposit for a completed Referendum - RefundDecisionDeposit { - /// Referendum index - #[arg(short, long)] - index: u32, - - /// Wallet name that placed the decision deposit - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Get Referenda configuration - Config, -} - -/// Handle referenda commands -pub async fn handle_referenda_command( - command: ReferendaCommands, - node_url: &str, -) -> crate::error::Result<()> { - let quantus_client = crate::chain::client::QuantusClient::new(node_url).await?; - - match command { - ReferendaCommands::SubmitRemark { message, from, password, password_file, origin } => - submit_remark_proposal( - &quantus_client, - &message, - &from, - password, - password_file, - &origin, - ) - .await, - ReferendaCommands::Submit { preimage_hash, from, password, password_file, origin } => - submit_proposal( - &quantus_client, - &preimage_hash, - &from, - password, - password_file, - &origin, - ) - .await, - ReferendaCommands::List => list_proposals(&quantus_client).await, - ReferendaCommands::Get { index, decode } => - get_proposal_details(&quantus_client, index, decode).await, - ReferendaCommands::Status { index } => get_proposal_status(&quantus_client, index).await, - ReferendaCommands::PlaceDecisionDeposit { index, from, password, password_file } => - place_decision_deposit(&quantus_client, index, &from, password, password_file).await, - ReferendaCommands::Vote { - index, - aye, - conviction, - amount, - from, - password, - password_file, - } => - vote_on_referendum( - &quantus_client, - index, - aye, - conviction, - &amount, - &from, - password, - password_file, - ) - .await, - ReferendaCommands::RefundSubmissionDeposit { index, from, password, password_file } => - refund_submission_deposit(&quantus_client, index, &from, password, password_file).await, - ReferendaCommands::RefundDecisionDeposit { index, from, password, password_file } => - refund_decision_deposit(&quantus_client, index, &from, password, password_file).await, - ReferendaCommands::Config => get_config(&quantus_client).await, - } -} - -/// Submit a simple System::remark proposal -async fn submit_remark_proposal( - quantus_client: &crate::chain::client::QuantusClient, - message: &str, - from: &str, - password: Option, - password_file: Option, - origin_type: &str, -) -> crate::error::Result<()> { - use qp_poseidon::PoseidonHasher; - - log_print!("📝 Submitting System::remark Proposal to Referenda"); - log_print!(" đŸ’Ŧ Message: {}", message.bright_cyan()); - log_print!(" 🔑 Submitted by: {}", from.bright_yellow()); - log_print!(" đŸŽ¯ Origin type: {}", origin_type.bright_magenta()); - - // Load wallet keypair - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - // Build System::remark call and encode it - let remark_bytes = message.as_bytes().to_vec(); - let remark_payload = quantus_subxt::api::tx().system().remark(remark_bytes.clone()); - let metadata = quantus_client.client().metadata(); - let encoded_call = <_ as subxt::tx::Payload>::encode_call_data(&remark_payload, &metadata) - .map_err(|e| QuantusError::Generic(format!("Failed to encode call data: {:?}", e)))?; - - log_verbose!("📝 Encoded call size: {} bytes", encoded_call.len()); - - // Compute preimage hash using Poseidon - let preimage_hash: sp_core::H256 = - ::hash(&encoded_call); - - log_print!("🔗 Preimage hash: {:?}", preimage_hash); - - // Submit Preimage::note_preimage - type PreimageBytes = quantus_subxt::api::preimage::calls::types::note_preimage::Bytes; - let bounded_bytes: PreimageBytes = encoded_call.clone(); - - log_print!("📝 Submitting preimage..."); - let note_preimage_tx = quantus_subxt::api::tx().preimage().note_preimage(bounded_bytes); - let preimage_tx_hash = - submit_transaction(quantus_client, &keypair, note_preimage_tx, None).await?; - log_print!("✅ Preimage transaction submitted: {:?}", preimage_tx_hash); - - // Wait for preimage transaction confirmation - log_print!("âŗ Waiting for preimage transaction confirmation..."); - - // Build Referenda::submit call using Lookup preimage reference - type ProposalBounded = - quantus_subxt::api::runtime_types::frame_support::traits::preimages::Bounded< - quantus_subxt::api::runtime_types::quantus_runtime::RuntimeCall, - quantus_subxt::api::runtime_types::qp_poseidon::PoseidonHasher, - >; - - let preimage_hash_subxt: subxt::utils::H256 = preimage_hash; - let proposal: ProposalBounded = - ProposalBounded::Lookup { hash: preimage_hash_subxt, len: encoded_call.len() as u32 }; - - // Create origin based on origin_type parameter - let account_id_sp = keypair.to_account_id_32(); - let account_id_subxt: subxt::ext::subxt_core::utils::AccountId32 = - subxt::ext::subxt_core::utils::AccountId32(*account_id_sp.as_ref()); - - let origin_caller = match origin_type.to_lowercase().as_str() { - "signed" => { - let raw_origin = - quantus_subxt::api::runtime_types::frame_support::dispatch::RawOrigin::Signed( - account_id_subxt, - ); - quantus_subxt::api::runtime_types::quantus_runtime::OriginCaller::system(raw_origin) - }, - "none" => { - let raw_origin = - quantus_subxt::api::runtime_types::frame_support::dispatch::RawOrigin::None; - quantus_subxt::api::runtime_types::quantus_runtime::OriginCaller::system(raw_origin) - }, - "root" => { - let raw_origin = - quantus_subxt::api::runtime_types::frame_support::dispatch::RawOrigin::Root; - quantus_subxt::api::runtime_types::quantus_runtime::OriginCaller::system(raw_origin) - }, - _ => - return Err(QuantusError::Generic(format!( - "Invalid origin type: {}. Must be 'signed', 'none', or 'root'", - origin_type - ))), - }; - - let enactment = - quantus_subxt::api::runtime_types::frame_support::traits::schedule::DispatchTime::After( - 10u32, // Execute 10 blocks after approval - ); - - log_print!("🔧 Creating Referenda::submit call..."); - let submit_call = - quantus_subxt::api::tx().referenda().submit(origin_caller, proposal, enactment); - - let tx_hash = submit_transaction(quantus_client, &keypair, submit_call, None).await?; - log_print!( - "✅ {} Referendum proposal submitted! Hash: {:?}", - "SUCCESS".bright_green().bold(), - tx_hash - ); - - log_print!("💡 Use 'quantus referenda list' to see active proposals"); - Ok(()) -} - -/// Submit a proposal using existing preimage hash -async fn submit_proposal( - quantus_client: &crate::chain::client::QuantusClient, - preimage_hash: &str, - from: &str, - password: Option, - password_file: Option, - origin_type: &str, -) -> crate::error::Result<()> { - log_print!("📝 Submitting Proposal to Referenda"); - log_print!(" 🔗 Preimage hash: {}", preimage_hash.bright_cyan()); - log_print!(" 🔑 Submitted by: {}", from.bright_yellow()); - log_print!(" đŸŽ¯ Origin type: {}", origin_type.bright_magenta()); - - // Parse preimage hash - let hash_str = preimage_hash.trim_start_matches("0x"); - let preimage_hash_parsed: sp_core::H256 = sp_core::H256::from_str(hash_str) - .map_err(|_| QuantusError::Generic("Invalid preimage hash format".to_string()))?; - - // Load wallet keypair - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - // Check if preimage exists and get its length - log_print!("🔍 Checking preimage status..."); - let latest_block_hash = quantus_client.get_latest_block().await?; - let storage_at = quantus_client.client().storage().at(latest_block_hash); - - let preimage_status = storage_at - .fetch( - &quantus_subxt::api::storage() - .preimage() - .request_status_for(preimage_hash_parsed), - ) - .await - .map_err(|e| QuantusError::Generic(format!("Failed to fetch preimage status: {:?}", e)))? - .ok_or_else(|| QuantusError::Generic("Preimage not found on chain".to_string()))?; - - let preimage_len = match preimage_status { - quantus_subxt::api::runtime_types::pallet_preimage::RequestStatus::Unrequested { - ticket: _, - len, - } => len, - quantus_subxt::api::runtime_types::pallet_preimage::RequestStatus::Requested { - maybe_ticket: _, - count: _, - maybe_len, - } => match maybe_len { - Some(len) => len, - None => return Err(QuantusError::Generic("Preimage length not available".to_string())), - }, - }; - - log_print!("✅ Preimage found! Length: {} bytes", preimage_len); - - // Build Referenda::submit call - type ProposalBounded = - quantus_subxt::api::runtime_types::frame_support::traits::preimages::Bounded< - quantus_subxt::api::runtime_types::quantus_runtime::RuntimeCall, - quantus_subxt::api::runtime_types::qp_poseidon::PoseidonHasher, - >; - - let preimage_hash_subxt: subxt::utils::H256 = preimage_hash_parsed; - let proposal: ProposalBounded = - ProposalBounded::Lookup { hash: preimage_hash_subxt, len: preimage_len }; - - // Create origin based on origin_type parameter - let account_id_sp = keypair.to_account_id_32(); - let account_id_subxt: subxt::ext::subxt_core::utils::AccountId32 = - subxt::ext::subxt_core::utils::AccountId32(*account_id_sp.as_ref()); - - let origin_caller = match origin_type.to_lowercase().as_str() { - "signed" => { - let raw_origin = - quantus_subxt::api::runtime_types::frame_support::dispatch::RawOrigin::Signed( - account_id_subxt, - ); - quantus_subxt::api::runtime_types::quantus_runtime::OriginCaller::system(raw_origin) - }, - "none" => { - let raw_origin = - quantus_subxt::api::runtime_types::frame_support::dispatch::RawOrigin::None; - quantus_subxt::api::runtime_types::quantus_runtime::OriginCaller::system(raw_origin) - }, - "root" => { - let raw_origin = - quantus_subxt::api::runtime_types::frame_support::dispatch::RawOrigin::Root; - quantus_subxt::api::runtime_types::quantus_runtime::OriginCaller::system(raw_origin) - }, - _ => - return Err(QuantusError::Generic(format!( - "Invalid origin type: {}. Must be 'signed', 'none', or 'root'", - origin_type - ))), - }; - - let enactment = - quantus_subxt::api::runtime_types::frame_support::traits::schedule::DispatchTime::After( - 10u32, - ); - - log_print!("🔧 Creating Referenda::submit call..."); - let submit_call = - quantus_subxt::api::tx().referenda().submit(origin_caller, proposal, enactment); - - let tx_hash = submit_transaction(quantus_client, &keypair, submit_call, None).await?; - log_print!( - "✅ {} Referendum proposal submitted! Hash: {:?}", - "SUCCESS".bright_green().bold(), - tx_hash - ); - - log_print!("💡 Use 'quantus referenda list' to see active proposals"); - Ok(()) -} - -/// List recent Referenda proposals -async fn list_proposals( - quantus_client: &crate::chain::client::QuantusClient, -) -> crate::error::Result<()> { - log_print!("📜 Active Referenda Proposals"); - log_print!(""); - - let addr = quantus_subxt::api::storage().referenda().referendum_count(); - - let latest_block_hash = quantus_client.get_latest_block().await?; - let storage_at = quantus_client.client().storage().at(latest_block_hash); - - let count = storage_at.fetch(&addr).await?; - - if let Some(total) = count { - log_print!("📊 Total referenda created: {}", total); - if total == 0 { - log_print!("📭 No active proposals found"); - return Ok(()); - } - log_print!("🔍 Fetching recent referenda..."); - for i in (0..total).rev().take(10) { - get_proposal_status(quantus_client, i).await?; - log_print!("----------------------------------------"); - } - } else { - log_print!("📭 No referenda found - Referenda may be empty"); - } - - Ok(()) -} - -/// Get details of a specific Referendum -async fn get_proposal_details( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - decode: bool, -) -> crate::error::Result<()> { - use quantus_subxt::api::runtime_types::pallet_referenda::types::ReferendumInfo; - - log_print!("📄 Referendum #{} Details", index); - log_print!(""); - - let addr = quantus_subxt::api::storage().referenda().referendum_info_for(index); - - let latest_block_hash = quantus_client.get_latest_block().await?; - let storage_at = quantus_client.client().storage().at(latest_block_hash); - - let info = storage_at.fetch(&addr).await?; - - if let Some(referendum_info) = info { - if decode { - // Try to decode the proposal - match &referendum_info { - ReferendumInfo::Ongoing(status) => { - log_print!("📊 {} Referendum #{}", "Ongoing".bright_green(), index); - log_print!(" đŸ›¤ī¸ Track: {}", status.track); - log_print!(" 📅 Submitted: Block #{}", status.submitted); - log_print!( - " đŸ—ŗī¸ Tally: Ayes: {}, Nays: {}, Support: {}", - status.tally.ayes, - status.tally.nays, - status.tally.support - ); - log_print!(""); - - // Extract preimage hash and length from proposal - if let quantus_subxt::api::runtime_types::frame_support::traits::preimages::Bounded::Lookup { - hash, - len, - } = &status.proposal - { - log_print!("📝 Proposal Details:"); - log_print!(" 🔗 Preimage Hash: {:?}", hash); - log_print!(" 📏 Length: {} bytes", len); - log_print!(""); - - // Fetch and decode the preimage - match crate::cli::referenda_decode::decode_preimage(quantus_client, hash, *len).await { - Ok(decoded) => { - log_print!("✅ Decoded Proposal:"); - log_print!("{}", decoded); - }, - Err(e) => { - log_print!("âš ī¸ Could not decode proposal: {}", e); - log_print!(" Run 'quantus preimage get --hash {:?} --len {}' to see raw data", hash, len); - }, - } - } else { - log_print!("âš ī¸ Proposal is inline (not a preimage lookup)"); - } - }, - ReferendumInfo::Approved(..) => { - log_print!("📊 {} Referendum #{}", "Approved".green(), index); - log_print!( - " â„šī¸ Proposal details no longer available (referendum finalized)" - ); - }, - ReferendumInfo::Rejected(..) => { - log_print!("📊 {} Referendum #{}", "Rejected".red(), index); - log_print!( - " â„šī¸ Proposal details no longer available (referendum finalized)" - ); - }, - ReferendumInfo::Cancelled(..) => { - log_print!("📊 {} Referendum #{}", "Cancelled".yellow(), index); - log_print!( - " â„šī¸ Proposal details no longer available (referendum finalized)" - ); - }, - ReferendumInfo::TimedOut(..) => { - log_print!("📊 {} Referendum #{}", "TimedOut".dimmed(), index); - log_print!( - " â„šī¸ Proposal details no longer available (referendum finalized)" - ); - }, - ReferendumInfo::Killed(..) => { - log_print!("📊 {} Referendum #{}", "Killed".red().bold(), index); - log_print!(" â„šī¸ Proposal details no longer available (referendum killed)"); - }, - } - } else { - // Raw output (original behavior) - log_print!("📋 Referendum Information (raw):"); - log_print!("{:#?}", referendum_info); - } - } else { - log_print!("📭 Referendum #{} not found", index); - } - Ok(()) -} - -/// Get the status of a Referendum -async fn get_proposal_status( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, -) -> crate::error::Result<()> { - use quantus_subxt::api::runtime_types::pallet_referenda::types::ReferendumInfo; - - log_verbose!("📊 Fetching status for Referendum #{}...", index); - - let addr = quantus_subxt::api::storage().referenda().referendum_info_for(index); - - let latest_block_hash = quantus_client.get_latest_block().await?; - let storage_at = quantus_client.client().storage().at(latest_block_hash); - - let info_res = storage_at.fetch(&addr).await; - - match info_res { - Ok(Some(info)) => { - log_print!("📊 Status for Referendum #{}", index.to_string().bright_yellow()); - match info { - ReferendumInfo::Ongoing(status) => { - log_print!(" - Status: {}", "Ongoing".bright_green()); - log_print!(" - Track: {}", status.track); - log_print!(" - Submitted at: block {}", status.submitted); - log_print!( - " - Tally: Ayes: {}, Nays: {}", - status.tally.ayes, - status.tally.nays - ); - log_verbose!(" - Full status: {:#?}", status); - }, - ReferendumInfo::Approved(submitted, ..) => { - log_print!(" - Status: {}", "Approved".green()); - log_print!(" - Submitted at block: {}", submitted); - }, - ReferendumInfo::Rejected(submitted, ..) => { - log_print!(" - Status: {}", "Rejected".red()); - log_print!(" - Submitted at block: {}", submitted); - }, - ReferendumInfo::Cancelled(submitted, ..) => { - log_print!(" - Status: {}", "Cancelled".yellow()); - log_print!(" - Submitted at block: {}", submitted); - }, - ReferendumInfo::TimedOut(submitted, ..) => { - log_print!(" - Status: {}", "TimedOut".dimmed()); - log_print!(" - Submitted at block: {}", submitted); - }, - ReferendumInfo::Killed(submitted) => { - log_print!(" - Status: {}", "Killed".red().bold()); - log_print!(" - Killed at block: {}", submitted); - }, - } - }, - Ok(None) => log_print!("📭 Referendum #{} not found", index), - Err(e) => log_error!("❌ Failed to fetch referendum #{}: {:?}", index, e), - } - - Ok(()) -} - -/// Place a decision deposit for a Referendum -async fn place_decision_deposit( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("📋 Placing decision deposit for Referendum #{}", index); - log_print!(" 🔑 Placed by: {}", from.bright_yellow()); - - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - let deposit_call = quantus_subxt::api::tx().referenda().place_decision_deposit(index); - let tx_hash = submit_transaction(quantus_client, &keypair, deposit_call, None).await?; - log_success!("✅ Decision deposit placed! Hash: {:?}", tx_hash.to_string().bright_yellow()); - Ok(()) -} - -/// Vote on a Referendum -async fn vote_on_referendum( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - aye: bool, - conviction: u8, - amount: &str, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("đŸ—ŗī¸ Voting on Referendum #{}", index); - log_print!(" 📊 Vote: {}", if aye { "AYE ✅".bright_green() } else { "NAY ❌".bright_red() }); - log_print!(" 💰 Amount: {}", amount.bright_cyan()); - log_print!(" 🔒 Conviction: {}", conviction); - log_print!(" 🔑 Signed by: {}", from.bright_yellow()); - - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - // Parse amount - let amount_value: u128 = (amount - .parse::() - .map_err(|_| QuantusError::Generic("Invalid amount format".to_string()))? - .max(0.0) * - 1_000_000_000_000_000_000.0) as u128; - - // Validate conviction - if conviction > 6 { - return Err(QuantusError::Generic("Invalid conviction (must be 0-6)".to_string())); - } - - // Build vote - let vote = - quantus_subxt::api::runtime_types::pallet_conviction_voting::vote::AccountVote::Standard { - vote: quantus_subxt::api::runtime_types::pallet_conviction_voting::vote::Vote( - if aye { 128 } else { 0 } | conviction, - ), - balance: amount_value, - }; - - let vote_call = quantus_subxt::api::tx().conviction_voting().vote(index, vote); - let tx_hash = submit_transaction(quantus_client, &keypair, vote_call, None).await?; - - log_print!( - "✅ {} Vote transaction submitted! Hash: {:?}", - "SUCCESS".bright_green().bold(), - tx_hash - ); - - log_success!("🎉 {} Vote submitted!", "FINISHED".bright_green().bold()); - Ok(()) -} - -/// Get Referenda configuration -async fn get_config( - quantus_client: &crate::chain::client::QuantusClient, -) -> crate::error::Result<()> { - log_print!("âš™ī¸ Referenda Configuration"); - log_print!(""); - - let constants = quantus_client.client().constants(); - let tracks_addr = quantus_subxt::api::constants().referenda().tracks(); - - match constants.at(&tracks_addr) { - Ok(tracks) => { - log_print!("{}", "📊 Track Configuration:".bold()); - for (id, info) in tracks.iter() { - log_print!(" ------------------------------------"); - log_print!( - " â€ĸ {} #{}: {}", - "Track".bold(), - id, - info.name.to_string().bright_cyan() - ); - log_print!(" â€ĸ Max Deciding: {}", info.max_deciding); - log_print!(" â€ĸ Decision Deposit: {}", info.decision_deposit); - log_print!(" â€ĸ Prepare Period: {} blocks", info.prepare_period); - log_print!(" â€ĸ Decision Period: {} blocks", info.decision_period); - log_print!(" â€ĸ Confirm Period: {} blocks", info.confirm_period); - log_print!(" â€ĸ Min Enactment Period: {} blocks", info.min_enactment_period); - } - log_print!(" ------------------------------------"); - }, - Err(e) => { - log_error!("❌ Failed to decode Tracks constant: {:?}", e); - log_print!("💡 It's possible the Tracks constant is not in the expected format."); - }, - } - - Ok(()) -} - -/// Refund submission deposit for a completed Referendum -async fn refund_submission_deposit( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("💰 Refunding submission deposit for Referendum #{}", index); - log_print!(" 🔑 Refund to: {}", from.bright_yellow()); - - // Load wallet keypair - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - // Create refund_submission_deposit call - let refund_call = quantus_subxt::api::tx().referenda().refund_submission_deposit(index); - - let tx_hash = submit_transaction(quantus_client, &keypair, refund_call, None).await?; - log_print!( - "✅ {} Refund transaction submitted! Hash: {:?}", - "SUCCESS".bright_green().bold(), - tx_hash - ); - - log_print!("💡 Check your balance to confirm the refund"); - Ok(()) -} - -/// Refund decision deposit for a completed Referendum -async fn refund_decision_deposit( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("💰 Refunding decision deposit for Referendum #{}", index); - log_print!(" 🔑 Refund to: {}", from.bright_yellow()); - - // Load wallet keypair - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - // Create refund_decision_deposit call - let refund_call = quantus_subxt::api::tx().referenda().refund_decision_deposit(index); - - let tx_hash = submit_transaction(quantus_client, &keypair, refund_call, None).await?; - log_print!( - "✅ {} Refund transaction submitted! Hash: {:?}", - "SUCCESS".bright_green().bold(), - tx_hash - ); - - log_print!("💡 Check your balance to confirm the refund"); - Ok(()) -} diff --git a/src/cli/referenda_decode.rs b/src/cli/referenda_decode.rs deleted file mode 100644 index 7140fa7..0000000 --- a/src/cli/referenda_decode.rs +++ /dev/null @@ -1,243 +0,0 @@ -//! Decoding utilities for referendum proposals - -use crate::error::QuantusError; -use codec::Decode; -use colored::Colorize; - -/// Decode preimage call data into human-readable format -pub async fn decode_preimage( - quantus_client: &crate::chain::client::QuantusClient, - hash: &subxt::utils::H256, - len: u32, -) -> crate::error::Result { - // Fetch preimage from storage - let latest_block_hash = quantus_client.get_latest_block().await?; - let storage_at = quantus_client.client().storage().at(latest_block_hash); - - let preimage_addr = crate::chain::quantus_subxt::api::storage() - .preimage() - .preimage_for((*hash, len)); - - let preimage_result = storage_at.fetch(&preimage_addr).await; - - let content = match preimage_result { - Ok(Some(bounded_vec)) => bounded_vec.0, - Ok(None) => - return Err(QuantusError::Generic(format!("Preimage not found for hash {:?}", hash))), - Err(e) => return Err(QuantusError::Generic(format!("Error fetching preimage: {:?}", e))), - }; - - // Decode using direct Decode trait (RuntimeCall implements it via DecodeAsType derive) - decode_runtime_call_direct(&content) -} - -/// Decode RuntimeCall directly using Decode trait -fn decode_runtime_call_direct(data: &[u8]) -> crate::error::Result { - // First, let's try to understand the call structure by reading indices - if data.len() < 3 { - return Err(QuantusError::Generic("Call data too short".to_string())); - } - - let pallet_index = data[0]; - let inner_index = data[1]; - let call_index = data[2]; - - match (pallet_index, inner_index, call_index) { - // System pallet (0, 0, X) - // Special case: if call_index looks like Compact (high value like 0xe8), - // it might be remark (call 0) where the call index byte is omitted - (0, 0, idx) if idx > 100 => { - // Likely remark (call 0) with Compact-encoded Vec starting at byte 2 - decode_system_remark_no_index(&data[2..]) - }, - (0, 0, _) => decode_system_call(&data[2..]), - - // TreasuryPallet (18, 5, X) where X is any spend variant (11, 15, 19, etc.) - // Different indices represent different value ranges/encodings - (18, 5, _) => decode_treasury_spend_call(&data[3..]), - - // Unknown - _ => Ok(format!( - " {} {} {} {}\n {} {} bytes\n {}:\n {}", - "Call Indices:".dimmed(), - pallet_index, - inner_index, - call_index, - "Args:".dimmed(), - data.len() - 3, - "Raw Hex".dimmed(), - hex::encode(&data[3..]).bright_green() - )), - } -} - -/// Decode System::remark when call index byte is omitted (call 0) -fn decode_system_remark_no_index(args: &[u8]) -> crate::error::Result { - // args starts directly with Compact-encoded Vec - let mut cursor = args; - let remark_bytes: Vec = Vec::decode(&mut cursor) - .map_err(|e| QuantusError::Generic(format!("Failed to decode remark: {:?}", e)))?; - let remark_str = String::from_utf8_lossy(&remark_bytes); - - Ok(format!( - " {} {}\n {} {}\n {}:\n {} \"{}\"", - "Pallet:".dimmed(), - "System".bright_cyan(), - "Call:".dimmed(), - "remark".bright_yellow(), - "Parameters".dimmed(), - "message:".dimmed(), - remark_str.bright_green() - )) -} - -/// Decode System pallet calls -fn decode_system_call(data_from_call: &[u8]) -> crate::error::Result { - if data_from_call.is_empty() { - return Err(QuantusError::Generic("Empty system call data".to_string())); - } - - let call_index = data_from_call[0]; - let args = &data_from_call[1..]; - - match call_index { - 0 => { - // remark - standard Vec - let mut cursor = args; - let remark_bytes: Vec = Vec::decode(&mut cursor) - .map_err(|e| QuantusError::Generic(format!("Failed to decode remark: {:?}", e)))?; - let remark_str = String::from_utf8_lossy(&remark_bytes); - - Ok(format!( - " {} {}\n {} {}\n {}:\n {} \"{}\"", - "Pallet:".dimmed(), - "System".bright_cyan(), - "Call:".dimmed(), - "remark".bright_yellow(), - "Parameters".dimmed(), - "message:".dimmed(), - remark_str.bright_green() - )) - }, - 1 => { - // remark_with_event - has different encoding, try decoding from byte 1 - let remark_str = if args.len() > 1 { - String::from_utf8_lossy(&args[1..]) - } else { - String::from_utf8_lossy(args) - }; - - Ok(format!( - " {} {}\n {} {}\n {}:\n {} \"{}\"", - "Pallet:".dimmed(), - "System".bright_cyan(), - "Call:".dimmed(), - "remark_with_event".bright_yellow(), - "Parameters".dimmed(), - "message:".dimmed(), - remark_str.bright_green() - )) - }, - 7 => { - // set_code - Ok(format!( - " {} {}\n {} {} {}\n {} {}", - "Pallet:".dimmed(), - "System".bright_cyan(), - "Call:".dimmed(), - "set_code".bright_yellow(), - "(Runtime Upgrade)".dimmed(), - "Parameters:".dimmed(), - "".bright_green() - )) - }, - _ => Ok(format!( - " {} {}\n {} {} (index {})", - "Pallet:".dimmed(), - "System".bright_cyan(), - "Call:".dimmed(), - "unknown".yellow(), - call_index - )), - } -} - -/// Decode TreasuryPallet::spend call arguments -/// The amount is stored as variable-length u128 in little-endian -fn decode_treasury_spend_call(args: &[u8]) -> crate::error::Result { - use sp_core::crypto::Ss58Codec; - - crate::log_verbose!("Decoding treasury spend, args length: {} bytes", args.len()); - crate::log_verbose!("Args hex: {}", hex::encode(args)); - - if args.len() < 34 { - return Err(QuantusError::Generic(format!( - "Args too short for treasury spend: {} bytes (expected 40-42)", - args.len() - ))); - } - - // Structure (discovered through empirical analysis): - // - asset_kind: Box<()> = 0 bytes (unit type has no encoding) - // - amount: u128 = variable bytes (7-8 bytes typically) as little-endian - // - beneficiary: Box = 32 bytes (no variant byte!) - // - valid_from: Option = 1 byte (0x00 for None) - - // The amount length varies based on the value: - // - Small values (< 256TB): 7 bytes - // - Larger values: 8+ bytes - // Total length is typically 40 bytes (7+32+1) or 42 bytes (8+32+1) or similar - - // Calculate amount bytes length: total - 32 (beneficiary) - 1 (valid_from) - let amount_bytes_len = args.len() - 32 - 1; - if !(1..=16).contains(&amount_bytes_len) { - return Err(QuantusError::Generic(format!( - "Invalid amount bytes length: {}", - amount_bytes_len - ))); - } - - // Decode amount: first N bytes as little-endian u128 - let mut amount_bytes_extended = [0u8; 16]; - amount_bytes_extended[..amount_bytes_len].copy_from_slice(&args[..amount_bytes_len]); - let amount = u128::from_le_bytes(amount_bytes_extended); - - // Decode beneficiary: starts after amount bytes, 32 bytes - let beneficiary_start = amount_bytes_len; - let account_bytes: [u8; 32] = args[beneficiary_start..beneficiary_start + 32] - .try_into() - .map_err(|_| QuantusError::Generic("Failed to extract beneficiary bytes".to_string()))?; - let sp_account = sp_core::crypto::AccountId32::from(account_bytes); - let ss58 = sp_account.to_ss58check_with_version(sp_core::crypto::Ss58AddressFormat::custom(42)); - let beneficiary_str = format!("{} ({}...{})", ss58, &ss58[..8], &ss58[ss58.len() - 6..]); - - // Decode valid_from: last byte - let valid_from_byte = args[args.len() - 1]; - let valid_from_str = if valid_from_byte == 0 { - "None (immediate)".to_string() - } else { - format!("Some (byte: 0x{:02x})", valid_from_byte) - }; - - // Format amount in QUAN (1 QUAN = 10^12) - let quan = amount as f64 / 1_000_000_000_000.0; - - Ok(format!( - " {} {}\n {} {}\n {}:\n {} {} {} ({} raw)\n {} {}\n {} {}\n\n {} {}", - "Pallet:".dimmed(), - "TreasuryPallet".bright_cyan(), - "Call:".dimmed(), - "spend".bright_yellow(), - "Parameters".dimmed(), - "amount:".dimmed(), - quan.to_string().bright_green().bold(), - "QUAN".bright_green(), - amount, - "beneficiary:".dimmed(), - beneficiary_str.bright_green(), - "valid_from:".dimmed(), - valid_from_str.bright_green(), - "💡 Info:".cyan(), - "Vote YES if you approve this Treasury spend, NO to reject.".cyan() - )) -} diff --git a/src/cli/tech_referenda.rs b/src/cli/tech_referenda.rs deleted file mode 100644 index 03e5e04..0000000 --- a/src/cli/tech_referenda.rs +++ /dev/null @@ -1,718 +0,0 @@ -//! `quantus tech-referenda` subcommand - manage Tech Referenda proposals -use crate::{ - chain::quantus_subxt, cli::common::submit_transaction, error::QuantusError, log_error, - log_print, log_success, log_verbose, -}; -use clap::Subcommand; -use colored::Colorize; -use std::{path::PathBuf, str::FromStr}; - -/// Tech Referenda management commands -#[derive(Subcommand, Debug)] -pub enum TechReferendaCommands { - /// Submit a runtime upgrade proposal to Tech Referenda (requires existing preimage) - Submit { - /// Preimage hash (must already exist on chain) - #[arg(long)] - preimage_hash: String, - - /// Wallet name to sign with (must be a Tech Collective member or root) - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Submit a runtime upgrade proposal to Tech Referenda (creates preimage first) - SubmitWithPreimage { - /// Path to the runtime WASM file - #[arg(short, long)] - wasm_file: PathBuf, - - /// Wallet name to sign with (must be a Tech Collective member or root) - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// List all active Tech Referenda proposals - List, - - /// Get details of a specific Tech Referendum - Get { - /// Referendum index - #[arg(short, long)] - index: u32, - }, - - /// Check the status of a Tech Referendum - Status { - /// Referendum index - #[arg(short, long)] - index: u32, - }, - - /// Place a decision deposit for a Tech Referendum - PlaceDecisionDeposit { - /// Referendum index - #[arg(short, long)] - index: u32, - - /// Wallet name to sign with - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Cancel a Tech Referendum (requires root permissions) - Cancel { - /// Referendum index to cancel - #[arg(short, long)] - index: u32, - - /// Wallet name to sign with (must have root permissions) - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Kill a Tech Referendum (requires root permissions) - Kill { - /// Referendum index to kill - #[arg(short, long)] - index: u32, - - /// Wallet name to sign with (must have root permissions) - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Nudge a Tech Referendum to next phase (sudo origin) - Nudge { - /// Referendum index to nudge - #[arg(short, long)] - index: u32, - - /// Wallet name to sign with - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Refund submission deposit for a completed Tech Referendum - RefundSubmissionDeposit { - /// Referendum index - #[arg(short, long)] - index: u32, - - /// Wallet name that submitted the referendum - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Refund decision deposit for a completed Tech Referendum - RefundDecisionDeposit { - /// Referendum index - #[arg(short, long)] - index: u32, - - /// Wallet name that placed the decision deposit - #[arg(short, long)] - from: String, - - /// Password for the wallet - #[arg(short, long)] - password: Option, - - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Get Tech Referenda configuration - Config, -} - -/// Handle tech referenda commands -pub async fn handle_tech_referenda_command( - command: TechReferendaCommands, - node_url: &str, -) -> crate::error::Result<()> { - let quantus_client = crate::chain::client::QuantusClient::new(node_url).await?; - - match command { - TechReferendaCommands::Submit { preimage_hash, from, password, password_file } => - submit_runtime_upgrade(&quantus_client, &preimage_hash, &from, password, password_file) - .await, - TechReferendaCommands::SubmitWithPreimage { wasm_file, from, password, password_file } => - submit_runtime_upgrade_with_preimage( - &quantus_client, - &wasm_file, - &from, - password, - password_file, - ) - .await, - TechReferendaCommands::List => list_proposals(&quantus_client).await, - TechReferendaCommands::Get { index } => get_proposal_details(&quantus_client, index).await, - TechReferendaCommands::Status { index } => - get_proposal_status(&quantus_client, index).await, - TechReferendaCommands::PlaceDecisionDeposit { index, from, password, password_file } => - place_decision_deposit(&quantus_client, index, &from, password, password_file).await, - TechReferendaCommands::Cancel { index, from, password, password_file } => - cancel_proposal(&quantus_client, index, &from, password, password_file).await, - TechReferendaCommands::Kill { index, from, password, password_file } => - kill_proposal(&quantus_client, index, &from, password, password_file).await, - TechReferendaCommands::Nudge { index, from, password, password_file } => - nudge_proposal(&quantus_client, index, &from, password, password_file).await, - TechReferendaCommands::RefundSubmissionDeposit { index, from, password, password_file } => - refund_submission_deposit(&quantus_client, index, &from, password, password_file).await, - TechReferendaCommands::RefundDecisionDeposit { index, from, password, password_file } => - refund_decision_deposit(&quantus_client, index, &from, password, password_file).await, - TechReferendaCommands::Config => get_config(&quantus_client).await, - } -} - -/// Submit a runtime upgrade proposal to Tech Referenda (uses existing preimage) -async fn submit_runtime_upgrade( - quantus_client: &crate::chain::client::QuantusClient, - preimage_hash: &str, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("📝 Submitting Runtime Upgrade Proposal to Tech Referenda"); - log_print!(" 🔗 Preimage hash: {}", preimage_hash.bright_cyan()); - log_print!(" 🔑 Submitted by: {}", from.bright_yellow()); - - // Parse preimage hash (trim 0x) - let hash_str = preimage_hash.trim_start_matches("0x"); - let preimage_hash_parsed: sp_core::H256 = sp_core::H256::from_str(hash_str) - .map_err(|_| QuantusError::Generic("Invalid preimage hash format".to_string()))?; - - // Load wallet keypair - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - // Check if preimage exists and get its length - log_print!("🔍 Checking preimage status..."); - let latest_block_hash = quantus_client.get_latest_block().await?; - let storage_at = quantus_client.client().storage().at(latest_block_hash); - - let preimage_status = storage_at - .fetch( - &quantus_subxt::api::storage() - .preimage() - .request_status_for(preimage_hash_parsed), - ) - .await - .map_err(|e| QuantusError::Generic(format!("Failed to fetch preimage status: {:?}", e)))? - .ok_or_else(|| QuantusError::Generic("Preimage not found on chain".to_string()))?; - - let preimage_len = match preimage_status { - quantus_subxt::api::runtime_types::pallet_preimage::RequestStatus::Unrequested { - ticket: _, - len, - } => len, - quantus_subxt::api::runtime_types::pallet_preimage::RequestStatus::Requested { - maybe_ticket: _, - count: _, - maybe_len, - } => match maybe_len { - Some(len) => len, - None => return Err(QuantusError::Generic("Preimage length not available".to_string())), - }, - }; - - log_print!("✅ Preimage found! Length: {} bytes", preimage_len); - - // Build TechReferenda::submit call using Lookup preimage reference - type ProposalBounded = - quantus_subxt::api::runtime_types::frame_support::traits::preimages::Bounded< - quantus_subxt::api::runtime_types::quantus_runtime::RuntimeCall, - quantus_subxt::api::runtime_types::qp_poseidon::PoseidonHasher, - >; - - let preimage_hash_subxt: subxt::utils::H256 = preimage_hash_parsed; - let proposal: ProposalBounded = - ProposalBounded::Lookup { hash: preimage_hash_subxt, len: preimage_len }; - - let raw_origin_root = - quantus_subxt::api::runtime_types::frame_support::dispatch::RawOrigin::Root; - let origin_caller = - quantus_subxt::api::runtime_types::quantus_runtime::OriginCaller::system(raw_origin_root); - - let enactment = - quantus_subxt::api::runtime_types::frame_support::traits::schedule::DispatchTime::After( - 0u32, - ); - - log_print!("🔧 Creating TechReferenda::submit call..."); - let submit_call = - quantus_subxt::api::tx() - .tech_referenda() - .submit(origin_caller, proposal, enactment); - - let tx_hash = submit_transaction(quantus_client, &keypair, submit_call, None).await?; - log_print!( - "✅ {} Runtime upgrade proposal submitted! Hash: {:?}", - "SUCCESS".bright_green().bold(), - tx_hash - ); - - log_print!("💡 Use 'quantus tech-referenda list' to see active proposals"); - Ok(()) -} - -/// Submit a runtime upgrade proposal to Tech Referenda (creates preimage first) -async fn submit_runtime_upgrade_with_preimage( - quantus_client: &crate::chain::client::QuantusClient, - wasm_file: &PathBuf, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - use qp_poseidon::PoseidonHasher; - - log_print!("📝 Submitting Runtime Upgrade Proposal to Tech Referenda"); - log_print!(" 📂 WASM file: {}", wasm_file.display().to_string().bright_cyan()); - log_print!(" 🔑 Submitted by: {}", from.bright_yellow()); - - if !wasm_file.exists() { - return Err(QuantusError::Generic(format!("WASM file not found: {}", wasm_file.display()))); - } - - if let Some(ext) = wasm_file.extension() { - if ext != "wasm" { - log_verbose!("âš ī¸ Warning: File doesn't have .wasm extension"); - } - } - - // Read WASM file - let wasm_code = std::fs::read(wasm_file) - .map_err(|e| QuantusError::Generic(format!("Failed to read WASM file: {}", e)))?; - - log_print!("📊 WASM file size: {} bytes", wasm_code.len()); - - // Load wallet keypair - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - // Build a static payload for System::set_code and encode full call data (pallet + call + args) - let set_code_payload = quantus_subxt::api::tx().system().set_code(wasm_code.clone()); - let metadata = quantus_client.client().metadata(); - let encoded_call = <_ as subxt::tx::Payload>::encode_call_data(&set_code_payload, &metadata) - .map_err(|e| QuantusError::Generic(format!("Failed to encode call data: {:?}", e)))?; - - log_verbose!("📝 Encoded call size: {} bytes", encoded_call.len()); - - // Compute preimage hash using Poseidon (runtime uses PoseidonHasher) - let preimage_hash: sp_core::H256 = - ::hash(&encoded_call); - - log_print!("🔗 Preimage hash: {:?}", preimage_hash); - - // Submit Preimage::note_preimage with bounded bytes - type PreimageBytes = quantus_subxt::api::preimage::calls::types::note_preimage::Bytes; - let bounded_bytes: PreimageBytes = encoded_call.clone(); - - log_print!("📝 Submitting preimage..."); - let note_preimage_tx = quantus_subxt::api::tx().preimage().note_preimage(bounded_bytes); - let preimage_tx_hash = - submit_transaction(quantus_client, &keypair, note_preimage_tx, None).await?; - log_print!("✅ Preimage transaction submitted: {:?}", preimage_tx_hash); - - // Wait for preimage transaction confirmation - log_print!("âŗ Waiting for preimage transaction confirmation..."); - - // Build TechReferenda::submit call using Lookup preimage reference - type ProposalBounded = - quantus_subxt::api::runtime_types::frame_support::traits::preimages::Bounded< - quantus_subxt::api::runtime_types::quantus_runtime::RuntimeCall, - quantus_subxt::api::runtime_types::qp_poseidon::PoseidonHasher, - >; - - let preimage_hash_subxt: subxt::utils::H256 = preimage_hash; - let proposal: ProposalBounded = - ProposalBounded::Lookup { hash: preimage_hash_subxt, len: encoded_call.len() as u32 }; - - let raw_origin_root = - quantus_subxt::api::runtime_types::frame_support::dispatch::RawOrigin::Root; - let origin_caller = - quantus_subxt::api::runtime_types::quantus_runtime::OriginCaller::system(raw_origin_root); - - let enactment = - quantus_subxt::api::runtime_types::frame_support::traits::schedule::DispatchTime::After( - 0u32, - ); - - log_print!("🔧 Creating TechReferenda::submit call..."); - let submit_call = - quantus_subxt::api::tx() - .tech_referenda() - .submit(origin_caller, proposal, enactment); - - let tx_hash = submit_transaction(quantus_client, &keypair, submit_call, None).await?; - log_print!( - "✅ {} Runtime upgrade proposal submitted! Hash: {:?}", - "SUCCESS".bright_green().bold(), - tx_hash - ); - - log_print!("💡 Use 'quantus tech-referenda list' to see active proposals"); - Ok(()) -} - -/// List recent Tech Referenda proposals -async fn list_proposals( - quantus_client: &crate::chain::client::QuantusClient, -) -> crate::error::Result<()> { - log_print!("📜 Active Tech Referenda Proposals"); - log_print!(""); - - let addr = quantus_subxt::api::storage().tech_referenda().referendum_count(); - - // Get the latest block hash to read from the latest state (not finalized) - let latest_block_hash = quantus_client.get_latest_block().await?; - let storage_at = quantus_client.client().storage().at(latest_block_hash); - - let count = storage_at.fetch(&addr).await?; - - if let Some(total) = count { - log_print!("📊 Total referenda created: {}", total); - if total == 0 { - log_print!("📭 No active proposals found"); - return Ok(()); - } - log_print!("🔍 Fetching recent referenda..."); - for i in (0..total).rev().take(10) { - get_proposal_status(quantus_client, i).await?; - log_print!("----------------------------------------"); - } - } else { - log_print!("📭 No referenda found - Tech Referenda may be empty"); - } - - Ok(()) -} - -/// Get details of a specific Tech Referendum -async fn get_proposal_details( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, -) -> crate::error::Result<()> { - log_print!("📄 Tech Referendum #{} Details", index); - log_print!(""); - - let addr = quantus_subxt::api::storage().tech_referenda().referendum_info_for(index); - - // Get the latest block hash to read from the latest state (not finalized) - let latest_block_hash = quantus_client.get_latest_block().await?; - let storage_at = quantus_client.client().storage().at(latest_block_hash); - - let info = storage_at.fetch(&addr).await?; - - if let Some(referendum_info) = info { - log_print!("📋 Referendum Information (raw):"); - log_print!("{:#?}", referendum_info); - } else { - log_print!("📭 Referendum #{} not found", index); - } - Ok(()) -} - -/// Get the status of a Tech Referendum -async fn get_proposal_status( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, -) -> crate::error::Result<()> { - use quantus_subxt::api::runtime_types::pallet_referenda::types::ReferendumInfo; - - log_verbose!("📊 Fetching status for Tech Referendum #{}...", index); - - let addr = quantus_subxt::api::storage().tech_referenda().referendum_info_for(index); - - // Get the latest block hash to read from the latest state (not finalized) - let latest_block_hash = quantus_client.get_latest_block().await?; - let storage_at = quantus_client.client().storage().at(latest_block_hash); - - let info_res = storage_at.fetch(&addr).await; - - match info_res { - Ok(Some(info)) => { - log_print!("📊 Status for Referendum #{}", index.to_string().bright_yellow()); - match info { - ReferendumInfo::Ongoing(status) => { - log_print!(" - Status: {}", "Ongoing".bright_green()); - log_print!(" - Track: {}", status.track); - log_print!(" - Submitted at: block {}", status.submitted); - log_print!( - " - Tally: Ayes: {}, Nays: {}", - status.tally.ayes, - status.tally.nays - ); - log_verbose!(" - Full status: {:#?}", status); - }, - ReferendumInfo::Approved(submitted, ..) => { - log_print!(" - Status: {}", "Approved".green()); - log_print!(" - Submitted at block: {}", submitted); - }, - ReferendumInfo::Rejected(submitted, ..) => { - log_print!(" - Status: {}", "Rejected".red()); - log_print!(" - Submitted at block: {}", submitted); - }, - ReferendumInfo::Cancelled(submitted, ..) => { - log_print!(" - Status: {}", "Cancelled".yellow()); - log_print!(" - Submitted at block: {}", submitted); - }, - ReferendumInfo::TimedOut(submitted, ..) => { - log_print!(" - Status: {}", "TimedOut".dimmed()); - log_print!(" - Submitted at block: {}", submitted); - }, - ReferendumInfo::Killed(submitted) => { - log_print!(" - Status: {}", "Killed".red().bold()); - log_print!(" - Killed at block: {}", submitted); - }, - } - }, - Ok(None) => log_print!("📭 Referendum #{} not found", index), - Err(e) => log_error!("❌ Failed to fetch referendum #{}: {:?}", index, e), - } - - Ok(()) -} - -/// Place a decision deposit for a Tech Referendum -async fn place_decision_deposit( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("📋 Placing decision deposit for Tech Referendum #{}", index); - log_print!(" 🔑 Placed by: {}", from.bright_yellow()); - - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - let deposit_call = quantus_subxt::api::tx().tech_referenda().place_decision_deposit(index); - let tx_hash = submit_transaction(quantus_client, &keypair, deposit_call, None).await?; - log_success!("✅ Decision deposit placed! Hash: {:?}", tx_hash.to_string().bright_yellow()); - Ok(()) -} - -/// Cancel a Tech Referendum (sudo) -async fn cancel_proposal( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("❌ Cancelling Tech Referendum #{}", index); - log_print!(" 🔑 Cancelled by: {}", from.bright_yellow()); - - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - let inner = - quantus_subxt::api::Call::TechReferenda(quantus_subxt::api::tech_referenda::Call::cancel { - index, - }); - let sudo_call = quantus_subxt::api::tx().sudo().sudo(inner); - - let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None).await?; - log_success!("✅ Referendum cancelled! Hash: {:?}", tx_hash.to_string().bright_yellow()); - Ok(()) -} - -/// Kill a Tech Referendum (sudo) -async fn kill_proposal( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("💀 Killing Tech Referendum #{}", index); - log_print!(" 🔑 Killed by: {}", from.bright_yellow()); - - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - let inner = - quantus_subxt::api::Call::TechReferenda(quantus_subxt::api::tech_referenda::Call::kill { - index, - }); - let sudo_call = quantus_subxt::api::tx().sudo().sudo(inner); - - let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None).await?; - log_success!("✅ Referendum killed! Hash: {:?}", tx_hash.to_string().bright_yellow()); - Ok(()) -} - -/// Nudge a Tech Referendum to next phase (sudo) -async fn nudge_proposal( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("🔄 Nudging Tech Referendum #{}", index); - log_print!(" 🔑 Nudged by: {}", from.bright_yellow()); - - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - let inner = quantus_subxt::api::Call::TechReferenda( - quantus_subxt::api::tech_referenda::Call::nudge_referendum { index }, - ); - let sudo_call = quantus_subxt::api::tx().sudo().sudo(inner); - - let tx_hash = submit_transaction(quantus_client, &keypair, sudo_call, None).await?; - log_success!("✅ Referendum nudged! Hash: {:?}", tx_hash.to_string().bright_yellow()); - Ok(()) -} - -/// Get Tech Referenda configuration -async fn get_config( - quantus_client: &crate::chain::client::QuantusClient, -) -> crate::error::Result<()> { - log_print!("âš™ī¸ Tech Referenda Configuration"); - log_print!(""); - - let constants = quantus_client.client().constants(); - let tracks_addr = quantus_subxt::api::constants().tech_referenda().tracks(); - - match constants.at(&tracks_addr) { - Ok(tracks) => { - log_print!("{}", "📊 Track Configuration:".bold()); - for (id, info) in tracks.iter() { - log_print!(" ------------------------------------"); - log_print!( - " â€ĸ {} #{}: {}", - "Track".bold(), - id, - info.name.to_string().bright_cyan() - ); - log_print!(" â€ĸ Max Deciding: {}", info.max_deciding); - log_print!(" â€ĸ Decision Deposit: {}", info.decision_deposit); - log_print!(" â€ĸ Prepare Period: {} blocks", info.prepare_period); - log_print!(" â€ĸ Decision Period: {} blocks", info.decision_period); - log_print!(" â€ĸ Confirm Period: {} blocks", info.confirm_period); - log_print!(" â€ĸ Min Enactment Period: {} blocks", info.min_enactment_period); - } - log_print!(" ------------------------------------"); - }, - Err(e) => { - log_error!("❌ Failed to decode Tracks constant: {:?}", e); - log_print!("💡 It's possible the Tracks constant is not in the expected format."); - }, - } - - Ok(()) -} - -/// Refund submission deposit for a completed Tech Referendum -async fn refund_submission_deposit( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("💰 Refunding submission deposit for Tech Referendum #{}", index); - log_print!(" 🔑 Refund to: {}", from.bright_yellow()); - - // Load wallet keypair - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - // Create refund_submission_deposit call for TechReferenda instance - let refund_call = quantus_subxt::api::tx().tech_referenda().refund_submission_deposit(index); - - let tx_hash = submit_transaction(quantus_client, &keypair, refund_call, None).await?; - log_print!( - "✅ {} Refund transaction submitted! Hash: {:?}", - "SUCCESS".bright_green().bold(), - tx_hash - ); - - log_success!("🎉 {} Submission deposit refunded!", "FINISHED".bright_green().bold()); - log_print!("💡 Check your balance to confirm the refund"); - Ok(()) -} - -/// Refund decision deposit for a completed Tech Referendum -async fn refund_decision_deposit( - quantus_client: &crate::chain::client::QuantusClient, - index: u32, - from: &str, - password: Option, - password_file: Option, -) -> crate::error::Result<()> { - log_print!("💰 Refunding decision deposit for Tech Referendum #{}", index); - log_print!(" 🔑 Refund to: {}", from.bright_yellow()); - - // Load wallet keypair - let keypair = crate::wallet::load_keypair_from_wallet(from, password, password_file)?; - - // Create refund_decision_deposit call for TechReferenda instance - let refund_call = quantus_subxt::api::tx().tech_referenda().refund_decision_deposit(index); - - let tx_hash = submit_transaction(quantus_client, &keypair, refund_call, None).await?; - log_print!( - "✅ {} Refund transaction submitted! Hash: {:?}", - "SUCCESS".bright_green().bold(), - tx_hash - ); - - log_success!("🎉 {} Decision deposit refunded!", "FINISHED".bright_green().bold()); - log_print!("💡 Check your balance to confirm the refund"); - Ok(()) -} From 424236808424c358c12269ee4bd80e2954fab435 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Mon, 17 Nov 2025 20:59:53 +0600 Subject: [PATCH 03/22] Update poseidon deps --- Cargo.lock | 41 ++++------------------------------------- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee03d0c..4484fde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3363,7 +3363,7 @@ checksum = "fb2f13d8793f7a79c42d33e4ebe9d470fe938dc55592ef97ef42d4298aa6a976" dependencies = [ "log", "parity-scale-codec", - "qp-poseidon 1.0.1", + "qp-poseidon", "qp-rusty-crystals-dilithium", "qp-rusty-crystals-hdwallet", "scale-info", @@ -3373,25 +3373,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "qp-poseidon" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33181134496120c212a0a2098215cf45a68d50fe656de6fb30b31e73babe9383" -dependencies = [ - "log", - "p3-field", - "p3-goldilocks", - "parity-scale-codec", - "qp-poseidon-core 0.9.5", - "scale-info", - "serde", - "sp-core", - "sp-runtime", - "sp-storage", - "sp-trie", -] - [[package]] name = "qp-poseidon" version = "1.0.1" @@ -3402,7 +3383,7 @@ dependencies = [ "p3-field", "p3-goldilocks", "parity-scale-codec", - "qp-poseidon-core 1.0.1", + "qp-poseidon-core", "scale-info", "serde", "sp-core", @@ -3424,20 +3405,6 @@ dependencies = [ "rand_chacha 0.9.0", ] -[[package]] -name = "qp-poseidon-core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec326fc2631a929de09a38af2613a3db5230882c12a2f68205693ec632751e8b" -dependencies = [ - "p3-field", - "p3-goldilocks", - "p3-poseidon2", - "p3-symmetric", - "rand 0.9.2", - "rand_chacha 0.9.0", -] - [[package]] name = "qp-poseidon-core" version = "1.0.1" @@ -3474,7 +3441,7 @@ dependencies = [ "hex", "hex-literal", "nam-tiny-hderive", - "qp-poseidon-core 1.0.1", + "qp-poseidon-core", "qp-rusty-crystals-dilithium", "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -3497,7 +3464,7 @@ dependencies = [ "jsonrpsee", "parity-scale-codec", "qp-dilithium-crypto", - "qp-poseidon 0.9.5", + "qp-poseidon", "qp-rusty-crystals-dilithium", "qp-rusty-crystals-hdwallet", "rand 0.9.2", diff --git a/Cargo.toml b/Cargo.toml index bcd74ba..fccefaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ aes-gcm = "0.10" # AES-256-GCM (quantum-safe with 256-bit keys) # Quantus crypto dependencies qp-rusty-crystals-dilithium = { version = "2.0.0" } qp-rusty-crystals-hdwallet = { version = "1.0.0" } -qp-poseidon = { version = "0.9.5", features = [ +qp-poseidon = { version = "1.0.1", features = [ "serde", ] } qp-dilithium-crypto = { version = "0.2.0", features = ["serde"] } From 68a430f2c5c70b2de8a0b8e17a68c6072d4e2990 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Wed, 19 Nov 2025 13:26:49 +0600 Subject: [PATCH 04/22] Update metadata --- src/chain/quantus_subxt.rs | 485 +++++++++++++++++++++++++++++-------- src/quantus_metadata.scale | Bin 165263 -> 166458 bytes 2 files changed, 390 insertions(+), 95 deletions(-) diff --git a/src/chain/quantus_subxt.rs b/src/chain/quantus_subxt.rs index eb76445..f833791 100644 --- a/src/chain/quantus_subxt.rs +++ b/src/chain/quantus_subxt.rs @@ -6,7 +6,7 @@ pub mod api { mod root_mod { pub use super::*; } - pub static PALLETS: [&str; 22usize] = [ + pub static PALLETS: [&str; 23usize] = [ "System", "Timestamp", "Balances", @@ -29,6 +29,7 @@ pub mod api { "Recovery", "Assets", "AssetsHolder", + "Wormhole", ]; pub static RUNTIME_APIS: [&str; 11usize] = [ "Core", @@ -1472,10 +1473,9 @@ pub mod api { "query_call_info", types::QueryCallInfo { call, len }, [ - 166u8, 173u8, 176u8, 212u8, 240u8, 248u8, 215u8, 188u8, 215u8, 21u8, - 209u8, 116u8, 183u8, 186u8, 201u8, 229u8, 28u8, 26u8, 218u8, 247u8, - 99u8, 59u8, 155u8, 235u8, 205u8, 76u8, 165u8, 181u8, 148u8, 21u8, - 122u8, 86u8, + 124u8, 24u8, 108u8, 27u8, 208u8, 239u8, 216u8, 228u8, 57u8, 228u8, + 174u8, 239u8, 59u8, 192u8, 215u8, 42u8, 41u8, 201u8, 169u8, 7u8, 33u8, + 161u8, 23u8, 79u8, 0u8, 57u8, 32u8, 8u8, 13u8, 5u8, 138u8, 98u8, ], ) } @@ -1493,9 +1493,10 @@ pub mod api { "query_call_fee_details", types::QueryCallFeeDetails { call, len }, [ - 18u8, 80u8, 212u8, 196u8, 230u8, 162u8, 108u8, 100u8, 130u8, 14u8, - 44u8, 76u8, 26u8, 143u8, 202u8, 61u8, 26u8, 132u8, 34u8, 112u8, 49u8, - 183u8, 31u8, 51u8, 122u8, 49u8, 37u8, 229u8, 87u8, 43u8, 107u8, 82u8, + 250u8, 80u8, 231u8, 164u8, 228u8, 157u8, 118u8, 66u8, 94u8, 60u8, + 100u8, 68u8, 96u8, 22u8, 100u8, 185u8, 1u8, 160u8, 77u8, 30u8, 126u8, + 180u8, 230u8, 117u8, 99u8, 101u8, 101u8, 49u8, 237u8, 192u8, 219u8, + 41u8, ], ) } @@ -1868,6 +1869,9 @@ pub mod api { pub fn assets(&self) -> assets::constants::ConstantsApi { assets::constants::ConstantsApi } + pub fn wormhole(&self) -> wormhole::constants::ConstantsApi { + wormhole::constants::ConstantsApi + } } pub struct StorageApi; impl StorageApi { @@ -1931,6 +1935,9 @@ pub mod api { pub fn assets_holder(&self) -> assets_holder::storage::StorageApi { assets_holder::storage::StorageApi } + pub fn wormhole(&self) -> wormhole::storage::StorageApi { + wormhole::storage::StorageApi + } } pub struct TransactionApi; impl TransactionApi { @@ -1985,6 +1992,9 @@ pub mod api { pub fn assets(&self) -> assets::calls::TransactionApi { assets::calls::TransactionApi } + pub fn wormhole(&self) -> wormhole::calls::TransactionApi { + wormhole::calls::TransactionApi + } } pub struct ViewFunctionsApi; impl ViewFunctionsApi {} @@ -1997,9 +2007,9 @@ pub mod api { .hash(); runtime_metadata_hash == [ - 194u8, 46u8, 30u8, 103u8, 67u8, 25u8, 224u8, 42u8, 104u8, 224u8, 105u8, 213u8, - 149u8, 58u8, 199u8, 151u8, 221u8, 215u8, 141u8, 247u8, 109u8, 85u8, 204u8, 202u8, - 96u8, 104u8, 173u8, 94u8, 198u8, 124u8, 113u8, 174u8, + 0u8, 63u8, 162u8, 224u8, 195u8, 69u8, 233u8, 104u8, 127u8, 217u8, 171u8, 115u8, + 255u8, 248u8, 177u8, 84u8, 158u8, 190u8, 76u8, 185u8, 144u8, 155u8, 69u8, 210u8, + 153u8, 253u8, 206u8, 43u8, 20u8, 28u8, 169u8, 236u8, ] } pub mod system { @@ -3098,10 +3108,9 @@ pub mod api { "Events", (), [ - 153u8, 144u8, 222u8, 32u8, 219u8, 80u8, 161u8, 232u8, 120u8, 168u8, - 102u8, 147u8, 49u8, 48u8, 3u8, 26u8, 255u8, 126u8, 218u8, 117u8, 254u8, - 217u8, 170u8, 206u8, 182u8, 174u8, 251u8, 53u8, 253u8, 242u8, 26u8, - 74u8, + 19u8, 73u8, 6u8, 2u8, 209u8, 127u8, 197u8, 110u8, 228u8, 146u8, 149u8, + 129u8, 191u8, 123u8, 182u8, 64u8, 160u8, 106u8, 123u8, 149u8, 123u8, + 193u8, 14u8, 100u8, 42u8, 223u8, 34u8, 212u8, 161u8, 98u8, 44u8, 49u8, ], ) } @@ -4616,6 +4625,31 @@ pub mod api { const PALLET: &'static str = "Balances"; const EVENT: &'static str = "TotalIssuanceForced"; } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "Transfer proof was stored."] + pub struct TransferProofStored { + pub transfer_count: transfer_proof_stored::TransferCount, + pub source: transfer_proof_stored::Source, + pub dest: transfer_proof_stored::Dest, + pub funding_amount: transfer_proof_stored::FundingAmount, + } + pub mod transfer_proof_stored { + use super::runtime_types; + pub type TransferCount = ::core::primitive::u64; + pub type Source = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Dest = ::subxt::ext::subxt_core::utils::AccountId32; + pub type FundingAmount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for TransferProofStored { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "TransferProofStored"; + } } pub mod storage { use super::runtime_types; @@ -5463,9 +5497,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 35u8, 97u8, 151u8, 80u8, 160u8, 5u8, 249u8, 161u8, 124u8, 31u8, 46u8, - 45u8, 205u8, 88u8, 85u8, 115u8, 98u8, 172u8, 229u8, 119u8, 45u8, 74u8, - 176u8, 35u8, 216u8, 58u8, 23u8, 103u8, 209u8, 201u8, 15u8, 61u8, + 86u8, 27u8, 250u8, 23u8, 151u8, 9u8, 221u8, 180u8, 232u8, 7u8, 44u8, + 235u8, 50u8, 104u8, 247u8, 184u8, 102u8, 4u8, 48u8, 196u8, 84u8, 123u8, + 30u8, 123u8, 85u8, 124u8, 151u8, 25u8, 83u8, 221u8, 50u8, 226u8, ], ) } @@ -5488,10 +5522,9 @@ pub mod api { weight, }, [ - 129u8, 254u8, 188u8, 113u8, 132u8, 176u8, 63u8, 138u8, 200u8, 84u8, - 62u8, 198u8, 140u8, 161u8, 52u8, 222u8, 184u8, 140u8, 204u8, 144u8, - 247u8, 118u8, 46u8, 126u8, 211u8, 117u8, 140u8, 227u8, 105u8, 74u8, - 162u8, 225u8, + 182u8, 73u8, 169u8, 247u8, 46u8, 137u8, 24u8, 91u8, 219u8, 22u8, 25u8, + 193u8, 10u8, 234u8, 25u8, 205u8, 215u8, 83u8, 83u8, 26u8, 250u8, 195u8, + 164u8, 108u8, 247u8, 77u8, 86u8, 233u8, 185u8, 14u8, 233u8, 6u8, ], ) } @@ -5529,10 +5562,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 174u8, 114u8, 45u8, 150u8, 219u8, 165u8, 118u8, 166u8, 250u8, 85u8, - 15u8, 165u8, 148u8, 17u8, 160u8, 123u8, 198u8, 241u8, 78u8, 198u8, - 206u8, 131u8, 9u8, 107u8, 172u8, 188u8, 83u8, 6u8, 234u8, 14u8, 211u8, - 76u8, + 154u8, 244u8, 161u8, 46u8, 224u8, 242u8, 181u8, 54u8, 246u8, 56u8, + 180u8, 221u8, 178u8, 69u8, 160u8, 158u8, 238u8, 224u8, 137u8, 224u8, + 115u8, 26u8, 218u8, 51u8, 144u8, 218u8, 78u8, 236u8, 165u8, 238u8, 5u8, + 33u8, ], ) } @@ -7610,10 +7643,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 171u8, 151u8, 176u8, 198u8, 154u8, 6u8, 181u8, 56u8, 10u8, 6u8, 38u8, - 136u8, 64u8, 214u8, 145u8, 96u8, 121u8, 125u8, 161u8, 234u8, 247u8, - 156u8, 152u8, 119u8, 122u8, 165u8, 125u8, 238u8, 12u8, 214u8, 135u8, - 21u8, + 125u8, 78u8, 236u8, 0u8, 94u8, 174u8, 252u8, 109u8, 210u8, 132u8, 29u8, + 112u8, 44u8, 65u8, 73u8, 253u8, 86u8, 230u8, 65u8, 52u8, 161u8, 234u8, + 74u8, 178u8, 132u8, 229u8, 110u8, 243u8, 240u8, 3u8, 34u8, 245u8, ], ) } @@ -7655,9 +7687,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 99u8, 222u8, 117u8, 153u8, 121u8, 239u8, 26u8, 216u8, 66u8, 132u8, - 220u8, 8u8, 92u8, 137u8, 253u8, 47u8, 9u8, 8u8, 103u8, 1u8, 116u8, - 133u8, 237u8, 51u8, 73u8, 145u8, 141u8, 64u8, 210u8, 10u8, 74u8, 191u8, + 239u8, 122u8, 34u8, 125u8, 56u8, 62u8, 199u8, 184u8, 247u8, 111u8, + 102u8, 80u8, 111u8, 14u8, 86u8, 113u8, 222u8, 120u8, 142u8, 223u8, + 41u8, 160u8, 217u8, 210u8, 238u8, 4u8, 112u8, 244u8, 52u8, 101u8, 50u8, + 196u8, ], ) } @@ -7696,10 +7729,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 236u8, 32u8, 229u8, 48u8, 43u8, 173u8, 230u8, 106u8, 109u8, 188u8, - 137u8, 151u8, 188u8, 102u8, 252u8, 210u8, 87u8, 146u8, 152u8, 251u8, - 128u8, 10u8, 230u8, 228u8, 168u8, 203u8, 77u8, 24u8, 125u8, 18u8, 52u8, - 201u8, + 254u8, 153u8, 225u8, 60u8, 41u8, 44u8, 134u8, 216u8, 75u8, 142u8, 22u8, + 162u8, 207u8, 33u8, 163u8, 39u8, 155u8, 217u8, 10u8, 86u8, 105u8, + 174u8, 110u8, 14u8, 15u8, 116u8, 55u8, 252u8, 144u8, 174u8, 122u8, + 49u8, ], ) } @@ -7724,9 +7757,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 120u8, 118u8, 201u8, 138u8, 43u8, 75u8, 89u8, 65u8, 107u8, 106u8, 41u8, - 229u8, 55u8, 6u8, 141u8, 24u8, 116u8, 214u8, 215u8, 1u8, 209u8, 67u8, - 157u8, 238u8, 147u8, 31u8, 188u8, 133u8, 21u8, 7u8, 199u8, 202u8, + 220u8, 105u8, 133u8, 190u8, 222u8, 170u8, 54u8, 24u8, 52u8, 74u8, 38u8, + 40u8, 49u8, 202u8, 246u8, 238u8, 114u8, 242u8, 189u8, 247u8, 45u8, + 184u8, 23u8, 60u8, 64u8, 26u8, 173u8, 94u8, 8u8, 121u8, 4u8, 55u8, ], ) } @@ -8103,7 +8136,7 @@ pub mod api { [::core::primitive::u8; 32usize], runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >, ::core::primitive::u32, runtime_types::quantus_runtime::OriginCaller, @@ -8754,10 +8787,9 @@ pub mod api { "batch", types::Batch { calls }, [ - 135u8, 106u8, 152u8, 39u8, 199u8, 163u8, 145u8, 186u8, 129u8, 115u8, - 214u8, 162u8, 12u8, 85u8, 57u8, 122u8, 211u8, 240u8, 143u8, 159u8, - 138u8, 37u8, 114u8, 8u8, 8u8, 236u8, 197u8, 23u8, 114u8, 2u8, 105u8, - 174u8, + 8u8, 14u8, 63u8, 36u8, 47u8, 180u8, 133u8, 150u8, 98u8, 46u8, 251u8, + 65u8, 127u8, 92u8, 106u8, 133u8, 181u8, 255u8, 175u8, 67u8, 153u8, + 238u8, 69u8, 73u8, 66u8, 99u8, 96u8, 13u8, 147u8, 128u8, 96u8, 201u8, ], ) } @@ -8787,9 +8819,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 3u8, 102u8, 237u8, 140u8, 8u8, 207u8, 27u8, 204u8, 155u8, 162u8, 124u8, - 141u8, 172u8, 210u8, 89u8, 239u8, 113u8, 175u8, 41u8, 9u8, 150u8, - 130u8, 205u8, 125u8, 205u8, 199u8, 174u8, 85u8, 24u8, 13u8, 57u8, 19u8, + 240u8, 79u8, 20u8, 90u8, 191u8, 182u8, 34u8, 19u8, 193u8, 234u8, 213u8, + 178u8, 65u8, 218u8, 186u8, 74u8, 118u8, 209u8, 240u8, 129u8, 238u8, + 239u8, 91u8, 252u8, 78u8, 134u8, 163u8, 216u8, 147u8, 98u8, 30u8, 94u8, ], ) } @@ -8815,9 +8847,9 @@ pub mod api { "batch_all", types::BatchAll { calls }, [ - 76u8, 242u8, 205u8, 32u8, 158u8, 24u8, 255u8, 12u8, 97u8, 24u8, 211u8, - 63u8, 119u8, 183u8, 165u8, 217u8, 17u8, 178u8, 254u8, 230u8, 119u8, - 207u8, 207u8, 103u8, 39u8, 226u8, 55u8, 73u8, 233u8, 79u8, 60u8, 218u8, + 222u8, 8u8, 55u8, 135u8, 112u8, 82u8, 66u8, 76u8, 1u8, 9u8, 107u8, + 125u8, 153u8, 254u8, 59u8, 239u8, 61u8, 136u8, 189u8, 46u8, 91u8, 38u8, + 252u8, 97u8, 39u8, 215u8, 145u8, 174u8, 171u8, 47u8, 213u8, 6u8, ], ) } @@ -8840,10 +8872,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 32u8, 108u8, 91u8, 136u8, 200u8, 228u8, 95u8, 44u8, 22u8, 92u8, 34u8, - 234u8, 170u8, 201u8, 4u8, 248u8, 16u8, 209u8, 103u8, 201u8, 207u8, - 160u8, 165u8, 231u8, 152u8, 222u8, 112u8, 63u8, 133u8, 61u8, 220u8, - 24u8, + 220u8, 56u8, 148u8, 222u8, 163u8, 153u8, 156u8, 238u8, 167u8, 7u8, + 58u8, 11u8, 0u8, 102u8, 165u8, 102u8, 104u8, 60u8, 212u8, 73u8, 160u8, + 29u8, 225u8, 115u8, 0u8, 55u8, 189u8, 160u8, 95u8, 119u8, 16u8, 17u8, ], ) } @@ -8869,9 +8900,9 @@ pub mod api { "force_batch", types::ForceBatch { calls }, [ - 26u8, 82u8, 61u8, 185u8, 19u8, 29u8, 151u8, 192u8, 24u8, 41u8, 115u8, - 237u8, 7u8, 38u8, 68u8, 5u8, 159u8, 117u8, 47u8, 138u8, 101u8, 126u8, - 255u8, 137u8, 144u8, 51u8, 244u8, 145u8, 113u8, 21u8, 123u8, 79u8, + 42u8, 74u8, 40u8, 136u8, 212u8, 238u8, 120u8, 35u8, 155u8, 233u8, 90u8, + 11u8, 103u8, 251u8, 234u8, 130u8, 172u8, 5u8, 219u8, 41u8, 231u8, 20u8, + 162u8, 99u8, 204u8, 189u8, 79u8, 21u8, 203u8, 90u8, 170u8, 161u8, ], ) } @@ -8894,10 +8925,10 @@ pub mod api { weight, }, [ - 131u8, 134u8, 250u8, 73u8, 141u8, 137u8, 137u8, 15u8, 206u8, 215u8, - 199u8, 239u8, 24u8, 84u8, 247u8, 50u8, 135u8, 223u8, 110u8, 205u8, - 96u8, 170u8, 74u8, 232u8, 152u8, 135u8, 235u8, 62u8, 110u8, 230u8, - 172u8, 229u8, + 203u8, 125u8, 63u8, 180u8, 29u8, 135u8, 10u8, 130u8, 245u8, 74u8, 95u8, + 40u8, 166u8, 188u8, 185u8, 246u8, 14u8, 191u8, 130u8, 108u8, 188u8, + 93u8, 163u8, 151u8, 253u8, 22u8, 181u8, 237u8, 241u8, 17u8, 245u8, + 61u8, ], ) } @@ -8937,10 +8968,10 @@ pub mod api { fallback: ::subxt::ext::subxt_core::alloc::boxed::Box::new(fallback), }, [ - 195u8, 146u8, 198u8, 20u8, 96u8, 236u8, 218u8, 101u8, 252u8, 17u8, - 41u8, 246u8, 142u8, 116u8, 243u8, 198u8, 237u8, 168u8, 11u8, 211u8, - 236u8, 184u8, 71u8, 173u8, 211u8, 0u8, 129u8, 231u8, 99u8, 189u8, - 229u8, 34u8, + 127u8, 165u8, 98u8, 125u8, 184u8, 176u8, 6u8, 2u8, 146u8, 14u8, 154u8, + 49u8, 52u8, 253u8, 35u8, 127u8, 216u8, 178u8, 115u8, 253u8, 150u8, + 191u8, 55u8, 119u8, 165u8, 206u8, 24u8, 23u8, 106u8, 204u8, 188u8, + 151u8, ], ) } @@ -8963,9 +8994,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 52u8, 4u8, 122u8, 93u8, 231u8, 186u8, 88u8, 129u8, 36u8, 245u8, 176u8, - 117u8, 22u8, 203u8, 94u8, 115u8, 19u8, 27u8, 141u8, 63u8, 184u8, 171u8, - 146u8, 63u8, 124u8, 225u8, 135u8, 73u8, 51u8, 20u8, 60u8, 199u8, + 199u8, 2u8, 66u8, 203u8, 254u8, 202u8, 231u8, 19u8, 158u8, 151u8, + 157u8, 241u8, 252u8, 194u8, 188u8, 185u8, 59u8, 176u8, 72u8, 20u8, + 34u8, 248u8, 151u8, 147u8, 80u8, 251u8, 225u8, 219u8, 240u8, 79u8, + 139u8, 10u8, ], ) } @@ -9174,7 +9206,7 @@ pub mod api { pub type ProposalOrigin = runtime_types::quantus_runtime::OriginCaller; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >; pub type EnactmentMoment = runtime_types::frame_support::traits::schedule::DispatchTime< @@ -9665,7 +9697,7 @@ pub mod api { pub type Track = ::core::primitive::u16; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >; } impl ::subxt::ext::subxt_core::events::StaticEvent for Submitted { @@ -9759,7 +9791,7 @@ pub mod api { pub type Track = ::core::primitive::u16; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >; pub type Tally = runtime_types::pallet_conviction_voting::types::Tally<::core::primitive::u128>; @@ -10016,7 +10048,7 @@ pub mod api { ::core::primitive::u32, runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >, ::core::primitive::u128, runtime_types::pallet_conviction_voting::types::Tally< @@ -10916,7 +10948,7 @@ pub mod api { ::core::primitive::u128, runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >, >; pub type Param0 = ::subxt::ext::subxt_core::utils::H256; @@ -13176,7 +13208,7 @@ pub mod api { pub type ProposalOrigin = runtime_types::quantus_runtime::OriginCaller; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >; pub type EnactmentMoment = runtime_types::frame_support::traits::schedule::DispatchTime< @@ -13667,7 +13699,7 @@ pub mod api { pub type Track = ::core::primitive::u16; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >; } impl ::subxt::ext::subxt_core::events::StaticEvent for Submitted { @@ -13761,7 +13793,7 @@ pub mod api { pub type Track = ::core::primitive::u16; pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >; pub type Tally = runtime_types::pallet_ranked_collective::Tally; } @@ -14012,7 +14044,7 @@ pub mod api { ::core::primitive::u32, runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >, ::core::primitive::u128, runtime_types::pallet_ranked_collective::Tally, @@ -16571,10 +16603,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 60u8, 61u8, 138u8, 19u8, 43u8, 218u8, 179u8, 117u8, 205u8, 143u8, - 128u8, 223u8, 96u8, 166u8, 90u8, 187u8, 255u8, 119u8, 238u8, 209u8, - 140u8, 58u8, 239u8, 44u8, 153u8, 196u8, 218u8, 155u8, 227u8, 228u8, - 210u8, 187u8, + 3u8, 200u8, 160u8, 7u8, 52u8, 80u8, 43u8, 2u8, 39u8, 251u8, 144u8, + 99u8, 69u8, 29u8, 179u8, 239u8, 176u8, 48u8, 100u8, 91u8, 44u8, 249u8, + 176u8, 179u8, 28u8, 21u8, 93u8, 92u8, 26u8, 220u8, 149u8, 183u8, ], ) } @@ -21110,6 +21141,174 @@ pub mod api { } } } + pub mod wormhole { + use super::{root_mod, runtime_types}; + #[doc = "The `Error` enum of this pallet."] + pub type Error = runtime_types::pallet_wormhole::pallet::Error; + #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] + pub type Call = runtime_types::pallet_wormhole::pallet::Call; + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + pub mod types { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + pub struct VerifyWormholeProof { + pub proof_bytes: verify_wormhole_proof::ProofBytes, + pub block_number: verify_wormhole_proof::BlockNumber, + pub header: verify_wormhole_proof::Header, + } + pub mod verify_wormhole_proof { + use super::runtime_types; + pub type ProofBytes = + ::subxt::ext::subxt_core::alloc::vec::Vec<::core::primitive::u8>; + pub type BlockNumber = ::core::primitive::u32; + pub type Header = + runtime_types::sp_runtime::generic::header::Header<::core::primitive::u32>; + } + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for VerifyWormholeProof { + const PALLET: &'static str = "Wormhole"; + const CALL: &'static str = "verify_wormhole_proof"; + } + } + pub struct TransactionApi; + impl TransactionApi { + pub fn verify_wormhole_proof( + &self, + proof_bytes: types::verify_wormhole_proof::ProofBytes, + block_number: types::verify_wormhole_proof::BlockNumber, + header: types::verify_wormhole_proof::Header, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + { + ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + "Wormhole", + "verify_wormhole_proof", + types::VerifyWormholeProof { proof_bytes, block_number, header }, + [ + 162u8, 205u8, 5u8, 181u8, 62u8, 111u8, 128u8, 61u8, 0u8, 236u8, 196u8, + 137u8, 88u8, 33u8, 13u8, 36u8, 251u8, 55u8, 206u8, 185u8, 61u8, 58u8, + 132u8, 180u8, 106u8, 253u8, 232u8, 24u8, 224u8, 220u8, 216u8, 237u8, + ], + ) + } + } + } + #[doc = "The `Event` enum of this pallet"] + pub type Event = runtime_types::pallet_wormhole::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct ProofVerified { + pub exit_amount: proof_verified::ExitAmount, + } + pub mod proof_verified { + use super::runtime_types; + pub type ExitAmount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for ProofVerified { + const PALLET: &'static str = "Wormhole"; + const EVENT: &'static str = "ProofVerified"; + } + } + pub mod storage { + use super::runtime_types; + pub mod types { + use super::runtime_types; + pub mod used_nullifiers { + use super::runtime_types; + pub type UsedNullifiers = ::core::primitive::bool; + pub type Param0 = [::core::primitive::u8; 32usize]; + } + } + pub struct StorageApi; + impl StorageApi { + pub fn used_nullifiers_iter( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::used_nullifiers::UsedNullifiers, + (), + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "Wormhole", + "UsedNullifiers", + (), + [ + 111u8, 222u8, 249u8, 87u8, 31u8, 249u8, 120u8, 32u8, 221u8, 33u8, 86u8, + 103u8, 116u8, 235u8, 16u8, 191u8, 73u8, 183u8, 183u8, 77u8, 229u8, + 255u8, 221u8, 186u8, 29u8, 179u8, 110u8, 138u8, 146u8, 113u8, 241u8, + 222u8, + ], + ) + } + pub fn used_nullifiers( + &self, + _0: types::used_nullifiers::Param0, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::used_nullifiers::Param0, + >, + types::used_nullifiers::UsedNullifiers, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "Wormhole", + "UsedNullifiers", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + [ + 111u8, 222u8, 249u8, 87u8, 31u8, 249u8, 120u8, 32u8, 221u8, 33u8, 86u8, + 103u8, 116u8, 235u8, 16u8, 191u8, 73u8, 183u8, 183u8, 77u8, 229u8, + 255u8, 221u8, 186u8, 29u8, 179u8, 110u8, 138u8, 146u8, 113u8, 241u8, + 222u8, + ], + ) + } + } + } + pub mod constants { + use super::runtime_types; + pub struct ConstantsApi; + impl ConstantsApi { + #[doc = " Account ID used as the \"from\" account when creating transfer proofs for minted tokens"] + pub fn minting_account( + &self, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::subxt::ext::subxt_core::utils::AccountId32, + > { + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( + "Wormhole", + "MintingAccount", + [ + 115u8, 233u8, 13u8, 223u8, 88u8, 20u8, 202u8, 139u8, 153u8, 28u8, + 155u8, 157u8, 224u8, 66u8, 3u8, 250u8, 23u8, 53u8, 88u8, 168u8, 211u8, + 204u8, 122u8, 166u8, 248u8, 23u8, 174u8, 225u8, 99u8, 108u8, 89u8, + 135u8, + ], + ) + } + } + } + } pub mod runtime_types { use super::runtime_types; pub mod bounded_collections { @@ -23388,6 +23587,14 @@ pub mod api { old: ::core::primitive::u128, new: ::core::primitive::u128, }, + #[codec(index = 22)] + #[doc = "Transfer proof was stored."] + TransferProofStored { + transfer_count: ::core::primitive::u64, + source: ::subxt::ext::subxt_core::utils::AccountId32, + dest: ::subxt::ext::subxt_core::utils::AccountId32, + funding_amount: ::core::primitive::u128, + }, } } pub mod types { @@ -24993,7 +25200,7 @@ pub mod api { >, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >, enactment_moment: runtime_types::frame_support::traits::schedule::DispatchTime< @@ -25150,7 +25357,7 @@ pub mod api { track: ::core::primitive::u16, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >, }, #[codec(index = 1)] @@ -25180,7 +25387,7 @@ pub mod api { track: ::core::primitive::u16, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >, tally: runtime_types::pallet_conviction_voting::types::Tally< ::core::primitive::u128, @@ -25273,7 +25480,7 @@ pub mod api { track: ::core::primitive::u16, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >, }, #[codec(index = 1)] @@ -25303,7 +25510,7 @@ pub mod api { track: ::core::primitive::u16, proposal: runtime_types::frame_support::traits::preimages::Bounded< runtime_types::quantus_runtime::RuntimeCall, - runtime_types::quantus_runtime::PoseidonHeaderHasher, + runtime_types::qp_poseidon::PoseidonHasher, >, tally: runtime_types::pallet_ranked_collective::Tally, }, @@ -27239,6 +27446,85 @@ pub mod api { V1, } } + pub mod pallet_wormhole { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] + pub enum Call { + #[codec(index = 0)] + verify_wormhole_proof { + proof_bytes: + ::subxt::ext::subxt_core::alloc::vec::Vec<::core::primitive::u8>, + block_number: ::core::primitive::u32, + header: runtime_types::sp_runtime::generic::header::Header< + ::core::primitive::u32, + >, + }, + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "The `Error` enum of this pallet."] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + ProofDeserializationFailed, + #[codec(index = 2)] + VerificationFailed, + #[codec(index = 3)] + InvalidPublicInputs, + #[codec(index = 4)] + NullifierAlreadyUsed, + #[codec(index = 5)] + VerifierNotAvailable, + #[codec(index = 6)] + InvalidStorageRoot, + #[codec(index = 7)] + StorageRootMismatch, + #[codec(index = 8)] + BlockNotFound, + #[codec(index = 9)] + InvalidBlockNumber, + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "The `Event` enum of this pallet"] + pub enum Event { + #[codec(index = 0)] + ProofVerified { exit_amount: ::core::primitive::u128 }, + } + } + } pub mod primitive_types { use super::runtime_types; #[derive( @@ -27287,6 +27573,17 @@ pub mod api { } } } + pub mod qp_poseidon { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct PoseidonHasher; + } pub mod qp_scheduler { use super::runtime_types; #[derive( @@ -27396,14 +27693,6 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct PoseidonHeaderHasher; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] pub struct Runtime; #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -27447,6 +27736,8 @@ pub mod api { Recovery(runtime_types::pallet_recovery::pallet::Call), #[codec(index = 21)] Assets(runtime_types::pallet_assets::pallet::Call), + #[codec(index = 23)] + Wormhole(runtime_types::pallet_wormhole::pallet::Call), } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -27490,6 +27781,8 @@ pub mod api { Assets(runtime_types::pallet_assets::pallet::Error), #[codec(index = 22)] AssetsHolder(runtime_types::pallet_assets_holder::pallet::Error), + #[codec(index = 23)] + Wormhole(runtime_types::pallet_wormhole::pallet::Error), } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -27539,6 +27832,8 @@ pub mod api { Assets(runtime_types::pallet_assets::pallet::Event), #[codec(index = 22)] AssetsHolder(runtime_types::pallet_assets_holder::pallet::Event), + #[codec(index = 23)] + Wormhole(runtime_types::pallet_wormhole::pallet::Event), } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, diff --git a/src/quantus_metadata.scale b/src/quantus_metadata.scale index ca82fd5affea3364a3f85313a2456d88412f75bd..f17e3cba4c7431e58fa78ad61f5c5d1daeb21422 100644 GIT binary patch delta 6541 zcmb_heOOgxwts(XZ}gyOM+HTNJSdnb8YtRP!6L<^L{K0D7_Qi(8zEPqt-ad?J=XYJ64XPlTFrmC+uUU`$T2kwf8v+=*)BfxjsDS z{n+bW?|RqwT5f;5-*0yI>*LXa4(qX&KA$PL9R8bfCrbCvQpb_n2)roI6=Gy~bDyzl z8}Lh6(}BeB8+}sgFr=3#Ioz+W4adS0`j$`!BorDE{(0XNoC+W6n~Brm&c2gyA)I8H zOcx4+6!<+5t*cIMqFUP$7 z1EwFb#Pwi7ZTQ@674cVCl40w9_r{Jqy(16V{ny9kT*IWq$l5xad8ewS0&3~~n%}jm z`YIbMO#0)HVU86mtAkp=j-OTGUcBL(NAkV6hb4r;276_r&G<{iYqk%U zKUst^Xp!p|A&rMU#?UH{FTx}%AF&{nsSZ}SysLc8GPVRMXfp}Rc?Yq2Q3)0j4(p9& zXaJ7LTNfh%?Rwc_re8e*%L-XVlqfeYL6+Knb$Mb5?xJImH=M!9{cRcRRkTM`r@dQs z%&Dn5#!QE~j;M|~eR*0T8AkP|bFj%vPE_KgzDUFWka7|h`QbSXm5$YT3#ar+E~tHQ zTA$*>a|+JN_x)JQLvaA3ab5-jxSNMJ1Go_v^os#J6Nig(>jtbwr`%bCNzzt>KxF<5 z5801k0}ri_U^2dxe|ZGA;A?5yh)KLE+K6mkv8>W$(?+D`bm5<=X1r;|5#7u-jr49q zL0y_tMTWN46|9g&MHos#$U#2l`DOX`MwAT!Z%_;g{u8RjY8A00r)|Pg43IlEVQBII zQsZX(9$>r}L_!t(Bg`K@kRV^*gyk46ZJT*Wmg_cSto(8dZnme8h(n^6J&ePhLToGo z8NMpb?+Chl-m6=w9*5WIU}LY2z=#wB(@<&Kf*jVH@-0Z_;h`-^N@xM>MODV>oW+{! z-qpcbLZn5Yf42qk$?1gBV$DCt6{vCqD_75UI|6~6(3HsxmQLX&Oq8}qF@=ZHM;UjP zta}vWBTr0-L#oSD<*x8LJev9F1o_pYxD!)l?qishJ++$w(+vjjk1&5ImjwSY*Ye0J z@_43L_>)ECli@w}qmN;yLIu2_cL@P%tJXUIZ|H$FK~ZV+bY%NNT3<_{>7H*aGLEHhR~(zgva#V#eh z@{^E#rcG9D_4vg&|BCuC*2oW-=)hl-3DJ!ZY5JMZ0fpw92 zc_VB}4O!&E9~t#88rcLk%eNabtN&Jlwb19(gxG3q*yJtG!iHM8}c@Bwk*mFo``M^G(y{#9NfQvL+HO-N=TuMv=AkK-Nm};gqKm!ZSz2$q#p9;E+ySi?LH;4@Shc85mnh9PWYf zNEG9-9vF{Yi?RJW8r$Vw#)x)#Y!AlAA2SdiA<@C3YRwcPQJmEK{yUZ_bc*Ek*H}6a zH({7^`iiXfH?cU*%HKD^lX0Fb*{l3)J{5sbRh7>lv=y5v1_ykW3Ufcn)I58+5Er@$ zmruU{OTxt-R9`fRNPy^+2VY?G{8Inq1!NHWzah<7gf6+N88g^#H8x}JlrDo%3zK=7 z)WnEqFnm-O!D3zD^RnIuYl+Weq&y7CkqL?%u@~7CqsZdD7^cQ5m@ixQVu*ZrFUGMi z_|;zArNk)KaOd`s(z*{*a$^o4#1cvjl=H>O2yOp|ZEjLWgy33hc-(wZbcLkWDq`JlE9+4}r_ z48LY;=?B+AegA9T%9Z5@I4DeN!-B|FFCtHVaT-}s^!;ITYLzY{4J?q`euH#|diW3Q zLKe!#KVU2ao99O!#2sVvd$A$!dN$-4Y>;V(kRk6eZtXaTWm6XRI#qW4sj>+3jDdsR zZ^hCc;;@%T#o_27j`9d(qHyqpc%>PmOA-9XC{B13;faua<`8b`&rvcJRwJSek^>Gy zAG1b5{OpkbevJd6$K}0ZDBas)jd}dZS21R6NI?<@vz0ElTOfXw+voH5+Ok$^E_X;4 zyo#Iby*|WgUT3cjYapmq_1a0~DD3h%L-P4ok&;-gz&6*lR&y3i%NDS$t?;c{70`m! z^8Bk9I;huIwxW=yW5w%O zhOP48>)1=R-3*>Yb=`}R^24JTf_ek=isp?^5yH}xQ+AJX>V~p+bY+;g;8je&%A|H zYU*)yT60v;Ej`I_+fD2z62&nCIj=hOly~qeMLnrp$!tG<7o(C-Mc{-u9hq3gS#x3);(U)g%(Py; zpu|P8V*TO&!fxVZlkG=i&)#k2o&Wz<-WgGM)5^`O{!c4!?`h@qWsi3x#6)8ldPIY- zBl?6c{oFZlX?$63_z+tGx#kOGjkHEwW{leHGGkQcDJQV=nnKL7aZ>BTP`ZUh4M=X0sz%@CkBxc;XXI&P?@w@I+3+^8##I z1}z~5nJ6cBvPxyi>Q1a-7yZ{x_OH`r%q85)tNcs2gIBee(9%EGxG;_-FY;u;=Ww$Z zJ@7fJe1ZJ_bENW+@&z9)kTbu)R34Z+vr(wGeu2?_X`w3rbpyM4<&jca-_FH&h#_S_{g{|b)K zO1G=Bz*`jx2E=+r6fX$5-9};J&vSDo=BzFYFcwu5N9z^;0$(uie#Y%s>DEMym>0!k z^c)=bYKwfnpy(s!_gEIX0v;pl7kx!`q^$M@=W;*7$%*Zi)6sIfuTg!ASRs$R$pL4n z-0}@)`sMQEH%PzRq4o^9#5qV{^3prVAf&-fYec85kL-do=kKs+NJs^XkDCCj`EwjWhmk>>SCoB^X_>XX zh_6$7QeS7_?M;4N@p_E z1wSHH&inx$G|QqNF-E@i18(9%@9#fga(YWI?5)>hZ;fDYHI6=7(bnrZJNY$(I0H0g zv9tRzM$yWGJKPJm0eDTS7==4xP|ovqHJq%Ds4t>E{pTf?RC6r#s3O091x>`s`fZef zv-JmQ0=}&Olx}7pF$|Q&23-KkWD|an2en4Q2Dy)Dlo=R<|>RXO?nlYghJV%&}7b&PAD|KXIrmK{YPy*!=8J! z^_J`3D>NpCKzd3n-9r>hdQE@&7sI)J7RT2m=;;IKXW+*i8c6MY?ISnP%Um^2wbBY? z=}%heJ+S}r45l|&9i|T9mQ;cM#t_Q0@G>@uzT*fSlT1x4&3(yC@L_o_nP#9vAATb_ z)nO+|Sm#9hZS#C?XQcY#uE=Ow!f9XUXlmfF_4pWCj#Kh4V~UV=lde zHhsk%^d`_DClt^DoRl9Gu)t2qQFoFLr{(rL=|7dT$`QHbE}A>&eB`kjKlU&yKJ#hc zU9_7s1C#VG4boRojEg@X(=RWedV(gy3+Zj<-O5G$igx1_!(_)I*0z&RmXMuGz3C;i zm~XEuVO2OUzbc_8IW%uArJGoL^p-NZ6){jbcayu8(LT9*F+I-hyv!xEnx!UpE#>d^ z^7K;1abC|_Ms8x=etJ3mz!A5hoGO%LHAVlioCd;>c?BI(S^JJx(tM=LL??~ow`IxM zPAXDz)jV16WO3)~J2c|z@`C>Ez2sLo=;hx>b;OV@^0bGAa8}yAqS7)l-2uoK(RRB;)wV5hZ%WUg{Q0;{-?wEV;jkdSN29M9_zS31U1Q;(Z z8MN#Mlo`jkt8P(a{{F#2`LUNquX51N+h(uUD(@?)(keOf1-P}Pk=1VQm9CBMxX7Am z?%bhywE%}X%8o!3a+S@2I9R=gvd5VaT=Z6I)wDCiTt%8>>!jO9BNJ z8*UDxNxYek%9>{}D!!J_SZ8xTKQ8J12pu9zzU!l0PA05Xbc<5Qaq`Y8*12+tHIxsB zykiahnPOC#;itEhLek`Se%i^tK-L9lrV>)?36N82hps5ypBc!Z3ouVS5OYC_4?Nv=pF?}^wLeN J%}To}{ug?|tdal# delta 5766 zcmb_geOy&_nm^y?9N?l@SLIy@Fck4EKqx4%2(hRTQK3wcu5gq)0$1*fNh=jOm@n%H zUhx@cbjnXsxk*JXo~WqYG(R?JI6F?`6wNv_%%-iSweDw}9de&@4~~%g$NsVRb3XU? za-Q@3J@3Eg_j_x{sBK$D1=s0bhrPEe_&-!!@_(m3fcXb!Yg0(u1sveg4Vd6>37)KV z0nfAJB%=Mtf|IEmd`mFJ`$vT&;;?^O$U-^_?h2+@|Ib2_aKisiNE%N0FNDlQzdz2F zL1)3uAr#|x+U%q}!e4Je)WHvIAvQd6@RxRHsQ(YQCLKH<8y-72aT^`+8?W(_DcU0@{`yHMd z-L1&44UCtN#?!vTIJEnp@0q~we}Z6MG9N|Q#q%~`lJU`etOxcO^A^Ad?Byd1(S|)- zz6cxA_CkwZpnH6^UYoWE9ncEV3D|5Ut2Ctp<_ckjZnvg%N?)E14l6@0_H$7gCQ0Km zn@(;o!^|ilw;_48%j2zd)~|4N0QMqj{d=dzqRZsWu$SXeLbt#4?TNH(&d zyS(}Wy~^dTRuJxW)Ydlk8VQezIOyT0mS6%GFF`tb&Hf6pYX6bgLrc-Dq1UoW?{J$~ z1Is2>KVXwU_ZNZ@FkiqXIO_jNUjiRm2_46cxElNysmEdSxAsNyv{m?+PJr_V5X&*; z2s09D(H|tPbJO`4Bhrn{Do*oWAJ$3}y9N_+hV#~-Jn;-}uw2{%%YvpV``aCeGCo>^ zjbS*;3)iCt1HA0Vn91kY!(;WIlji#$<7sK0YC#6h@f$6;L%RU%4tPD=Ho%T^{`|Ta z&X6d;1=GkyxWr?gMcMevVkEi(MIJ@7+3m_8*!L_J1N_Oeh>QnmVFj+oH8FM&DVidG zO5jgAp-daG6l1v3Y{v3C8!=g$^v#%=9YIPMqU&AmI!A2;L0hC?x@)!Wc6gnx`oB*l z*E#B|9bT8a(V|fzOsq(*+!Sz{-J1|EPV?3##EshzWS6Wqzs`MFcdo4Q&gP{X5yRMw z@aTBLqWQXej?=T+;jOAEsC9TexxQH${QHf_;L6RIg(UWG7SKuDw;59{=_1&^1*5O^ z)3@LOr1H8gm^~}?y3{jFspU@z{82h7@`$Rk$gX5bPqoP_o04N(*n)pjDUbYp6waO7 z5HUBOk_*>*-OhTCvkHYI-X2{O2*-Rvv=x{Nrs&s5JevsF<$6`_-#?nIDETH{1ZS4u zIV!ZU<61Fid=Z74WDb;>{ACLdMf`ay;&@vtrl6SLY{jk8$W#GJIk62HDWxX2v*Ju{ z@a@LnoC4L8Q?jc5>Dp~S0|>EwE-yy4q)$?>dz#D*6D0md{CEpLo)>mwFeFJv6r*x!w}93jLMc*>cMsuB z&=E zAsKAm`-lv4st7Oexz~s{I!*H2$#p8?WKUV{tgV$gV@0h?_Ojtq_A1?3TgSh8A1T=* zUWDoO)gvbC;=HRz%tXsh=yX-rar$8--QA!fajtW%UR`v1rh>$^m97;lJi7M>(~bYz zv;<5Yw;jf9l4lPeM(Q}9iZG|ZC_WKCC`@To{a+l3F(Up2-KyH8+Iap3*(A;#m1NL- zZM6JDv`VfGgh28!@qtZN-)Z)@n(zs{`xxxhrgF&!BpbgvhMxtEZVxC}=~H&8{=Gd3 zyz_)O)gB%=fkJfiw3Eo7J=U8iPf9Z1%kQ1U{ZjnhbP5UR;+dzAER*J{Q#ytWyMLHr zI|A_bGAR3{M>6a*(PGVdbuM*T$SHlem%6R~<~}J~N5c06;8S{s;13Uj?+w8BMJtC* zbQvAB(52=KHBO$wdX;(yE2sOFXLLWW5;KR^j|y@ zV!04qQvKWdZZS5T#WRouANogZ!j-_s6YN%^92}HPo8mi4b$^I z5@!p&4mmj~%A~+sKJ|@MKB-ne`XZK0n4uvvzpBb5b@>n}qTPX_BAtJ75qD#TNgU08 zzKGix7ZJtNFX88-vrO*7#66T83+&5FlI8Qvexa7HDdC*>4dN05xhP+jxK|da)~gqq z1>;Hu(VoV-<*wR%KJqQHD1S)qz_G2+nEf3lhDbto{8dh0#eDnUq;xIi=D#7eyi6Ou zHr=v+G}#fC%X zCi2UJ_yhDnxAS|HNID(-UXFNmeCt(AO|R3m#CsRHb-mcJ+NM1yf@tN)mb$G$a07qj z(-e8cj#-qgH1d;Iv0%JYLt0V2oLKdG?;M9$O3Eg4h4vu2J*{~J-!0m3##>C(k({># zKHN&LN>a-OO}cCA2>rC(sGl}VWV4}mO_4{K%iblmChrDKlMHv2=vMv;R43^x&|gQC zf)3tCl#$vo0)PLF`1>vV{pP37R(6gMXNO1=Bvntq3_Gq1BfFMqv#t@?CgBeXs3E#; zlXvO&X#RLDmanQ5Jo@?-LJr$Cnt|gyTchc6AYG-2ROgsAx=o_+m`3U1{#P_g6UUw! zL}^;1il@0Um=d@th+?%ib?8Ec4+YU=?Wj6*qr!g)qGa@Qd@#+HN^of~EtE>|^lQu_KcGYni#GcPj5&tM~2g5a$WIwIQ<4vmduN!W3pXEMo}B`jF+P*-zLNJ3H0A$ zvp*-&emP3ECdvBU{9Y2>iKE6}lc-t~MO03fT6Tbalj#wukWNmfJyJ^7rqEKUmyf5= zB%Ct7Ng-9kY2&+TbObnIyg7qDgA~m>Zlhm|%+53_76c=W{%W4U(?zZe#OWC{g@ZFF zm87JVLC&~Pb&M*;Q6zp8{Ij%UjddCHGD0I{S}R6k5x<&ANjxu8bU4Y_nn|NnvBppD zpy#w1s$%2UR?<|~v+3WZUM$WbIoug-Idnxsg|THewUQjJ;_^lD?YuglmdWwzlYDvs z&4%Y*nh)9Jj}(X=TDX1=y@E|fY$1&Tb{UiA(qa;2J#|0zppA2i=&_)7b(i{EhK+9L zUl-ACxm;;@fIdN&k^dll1RUkCVmc(s`=D4%bYkZ`a>=n`^*s7eJ+1a|P6^E&d&ZJg z7g@W-eML{LCA3dA#Q^8$OwJ#pAg8=OY<#hRjVKM$0{?~_TCoUO3dPE{H=(4P5=O>oYYh3s!{bSIT>*JOsv;{E6 zE~OeVA3sq+cZ7#vBDab{W3o%mm_jL67!6{K(;VZb z>bSF}DvHG1bB3;Z?w1YDI;9TqE;mgMwrN5C`P(Ai=AnsCEv6m!6x8Tds}`=-tIBn^ zM{YnW$etaTTeNm)#zFS9z|4Jmz3y>(bjq|Sid}BGB6E5hos>BxKp{u2D!qYrOb?8# zyA&Voc&wnt;a;gPay#lhjwWxk`aPLHkkHqwqc0or1@VU^n&hk2XWL`Qg32NJ?t z1j%0Da_eDnYb@?$BW?0ho@{k*d+81}pNjdiS6ro(5BR81E7R=z_%$Cz^5`}65e=&R z=^FZ2Eu_W#;^VYKG|0JY=`Pi&ZQ>`^(yCE;WH(oJYK{EOTDlnCq}jY{3u(&oT36Mo z${JxNv)TBrkqXHCHhUed6VL8mM@hg|y4CURf>j zIBPw&FyC755XD|i;rE`AOlLGp^zY&DXXpv+HMTuN6M# Date: Wed, 19 Nov 2025 20:21:39 +0600 Subject: [PATCH 05/22] Add wormhole command --- Cargo.lock | 256 ++++++++++++++++++++++++-- Cargo.toml | 8 + src/cli/mod.rs | 6 + src/cli/wormhole.rs | 438 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 693 insertions(+), 15 deletions(-) create mode 100644 src/cli/wormhole.rs diff --git a/Cargo.lock b/Cargo.lock index 4484fde..9eaa9b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,6 +69,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", + "const-random", "getrandom 0.3.3", "once_cell", "version_check", @@ -989,6 +990,26 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "tiny-keccak", +] + [[package]] name = "const_format" version = "0.2.34" @@ -1576,6 +1597,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" +[[package]] +name = "fixed-hash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "static_assertions", +] + [[package]] name = "fixed-hash" version = "0.8.0" @@ -1931,6 +1961,7 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", + "serde", ] [[package]] @@ -2266,7 +2297,7 @@ checksum = "803d15461ab0dcc56706adf266158acbc44ccf719bf7d0af30705f58b90a4b8c" dependencies = [ "integer-sqrt", "num-traits", - "uint", + "uint 0.10.0", ] [[package]] @@ -2557,13 +2588,23 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2bd4c29270e724d3eaadf7bdc8700af4221fc0ed771b855eadcd1b98d52851" +dependencies = [ + "primitive-types 0.10.1", + "tiny-keccak", +] + [[package]] name = "keccak-hash" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e1b8590eb6148af2ea2d75f38e7d29f5ca970d5a4df456b3ef19b8b415d0264" dependencies = [ - "primitive-types", + "primitive-types 0.13.1", "tiny-keccak", ] @@ -2793,6 +2834,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -2801,6 +2856,17 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", + "rand 0.8.5", ] [[package]] @@ -2828,6 +2894,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-rational" version = "0.4.2" @@ -3179,6 +3256,16 @@ dependencies = [ "spki", ] +[[package]] +name = "plonky2_maybe_rayon" +version = "1.0.0" +source = "git+https://github.com/Quantus-Network/qp-plonky2#a7f257a234c40d252da33efdcd5f51f1f5a5b647" + +[[package]] +name = "plonky2_util" +version = "1.0.0" +source = "git+https://github.com/Quantus-Network/qp-plonky2#a7f257a234c40d252da33efdcd5f51f1f5a5b647" + [[package]] name = "polkavm-common" version = "0.24.0" @@ -3287,18 +3374,28 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "primitive-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" +dependencies = [ + "fixed-hash 0.7.0", + "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", + "fixed-hash 0.8.0", "impl-codec", "impl-num-traits", "impl-serde", "scale-info", - "uint", + "uint 0.10.0", ] [[package]] @@ -3373,6 +3470,47 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "qp-plonky2" +version = "1.1.1" +source = "git+https://github.com/Quantus-Network/qp-plonky2#a7f257a234c40d252da33efdcd5f51f1f5a5b647" +dependencies = [ + "ahash", + "anyhow", + "hashbrown 0.14.5", + "itertools 0.11.0", + "keccak-hash 0.8.0", + "log", + "num", + "p3-field", + "p3-goldilocks", + "p3-poseidon2", + "p3-symmetric", + "plonky2_maybe_rayon", + "plonky2_util", + "qp-plonky2-field", + "qp-poseidon-constants 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.8.5", + "serde", + "static_assertions", + "unroll", +] + +[[package]] +name = "qp-plonky2-field" +version = "1.1.1" +source = "git+https://github.com/Quantus-Network/qp-plonky2#a7f257a234c40d252da33efdcd5f51f1f5a5b647" +dependencies = [ + "anyhow", + "itertools 0.11.0", + "num", + "plonky2_util", + "rustc_version", + "serde", + "static_assertions", + "unroll", +] + [[package]] name = "qp-poseidon" version = "1.0.1" @@ -3383,7 +3521,7 @@ dependencies = [ "p3-field", "p3-goldilocks", "parity-scale-codec", - "qp-poseidon-core", + "qp-poseidon-core 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "scale-info", "serde", "sp-core", @@ -3405,6 +3543,18 @@ dependencies = [ "rand_chacha 0.9.0", ] +[[package]] +name = "qp-poseidon-constants" +version = "1.0.1" +source = "git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update#57ed5087c8f9a21762ed63af64d6614e8f3194fd" +dependencies = [ + "p3-field", + "p3-goldilocks", + "p3-poseidon2", + "rand 0.9.2", + "rand_chacha 0.9.0", +] + [[package]] name = "qp-poseidon-core" version = "1.0.1" @@ -3415,7 +3565,21 @@ dependencies = [ "p3-goldilocks", "p3-poseidon2", "p3-symmetric", - "qp-poseidon-constants", + "qp-poseidon-constants 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.9.0", +] + +[[package]] +name = "qp-poseidon-core" +version = "1.0.1" +source = "git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update#57ed5087c8f9a21762ed63af64d6614e8f3194fd" +dependencies = [ + "p3-field", + "p3-goldilocks", + "p3-poseidon2", + "p3-symmetric", + "qp-plonky2", + "qp-poseidon-constants 1.0.1 (git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update)", "rand_chacha 0.9.0", ] @@ -3441,7 +3605,7 @@ dependencies = [ "hex", "hex-literal", "nam-tiny-hderive", - "qp-poseidon-core", + "qp-poseidon-core 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "qp-rusty-crystals-dilithium", "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -3450,11 +3614,46 @@ dependencies = [ "thiserror 2.0.16", ] +[[package]] +name = "qp-wormhole-circuit" +version = "0.1.2" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git?branch=feat%2Fblock-header-proof#8edb333d9a92a4279ae5416a5ad96a93864e4375" +dependencies = [ + "anyhow", + "hex", + "qp-plonky2", + "qp-poseidon-core 1.0.1 (git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update)", + "qp-zk-circuits-common", +] + +[[package]] +name = "qp-wormhole-prover" +version = "0.1.2" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git?branch=feat%2Fblock-header-proof#8edb333d9a92a4279ae5416a5ad96a93864e4375" +dependencies = [ + "anyhow", + "qp-plonky2", + "qp-wormhole-circuit", + "qp-zk-circuits-common", +] + +[[package]] +name = "qp-zk-circuits-common" +version = "0.1.2" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git?branch=feat%2Fblock-header-proof#8edb333d9a92a4279ae5416a5ad96a93864e4375" +dependencies = [ + "anyhow", + "qp-plonky2", + "qp-poseidon-core 1.0.1 (git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update)", + "serde", +] + [[package]] name = "quantus-cli" version = "0.3.0" dependencies = [ "aes-gcm", + "anyhow", "argon2", "chrono", "clap", @@ -3464,9 +3663,14 @@ dependencies = [ "jsonrpsee", "parity-scale-codec", "qp-dilithium-crypto", + "qp-plonky2", "qp-poseidon", + "qp-poseidon-core 1.0.1 (git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update)", "qp-rusty-crystals-dilithium", "qp-rusty-crystals-hdwallet", + "qp-wormhole-circuit", + "qp-wormhole-prover", + "qp-zk-circuits-common", "rand 0.9.2", "rpassword", "serde", @@ -3836,7 +4040,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d78196772d25b90a98046794ce0fe2588b39ebdfbdc1e45b4c6c85dd43bebad" dependencies = [ "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "scale-bits", "scale-decode-derive", "scale-type-resolver", @@ -3863,7 +4067,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64901733157f9d25ef86843bd783eda439fac7efb0ad5a615d12d2cf3a29464b" dependencies = [ "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "scale-bits", "scale-encode-derive", "scale-type-resolver", @@ -4433,7 +4637,7 @@ dependencies = [ "parity-scale-codec", "parking_lot", "paste", - "primitive-types", + "primitive-types 0.13.1", "rand 0.8.5", "scale-info", "schnorrkel", @@ -4580,7 +4784,7 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "polkavm-derive", - "primitive-types", + "primitive-types 0.13.1", "sp-externalities", "sp-runtime-interface-proc-macro", "sp-std", @@ -4812,7 +5016,7 @@ dependencies = [ "hex", "jsonrpsee", "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "scale-bits", "scale-decode", "scale-encode", @@ -4866,9 +5070,9 @@ dependencies = [ "hashbrown 0.14.5", "hex", "impl-serde", - "keccak-hash", + "keccak-hash 0.11.0", "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "scale-bits", "scale-decode", "scale-encode", @@ -4944,7 +5148,7 @@ dependencies = [ "impl-serde", "jsonrpsee", "parity-scale-codec", - "primitive-types", + "primitive-types 0.13.1", "serde", "serde_json", "subxt-core", @@ -5443,6 +5647,18 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "uint" version = "0.10.0" @@ -5492,6 +5708,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "unroll" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad948c1cb799b1a70f836077721a92a35ac177d4daddf4c20a633786d4cf618" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index fccefaa..8f99434 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,5 +68,13 @@ jsonrpsee = { version = "0.24", features = ["client"] } # Needed for implementing custom Subxt hasher subxt-metadata = "0.43.0" +# ZK proof generation +anyhow = "1.0" +qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", branch = "feat/block-header-proof", default-features = false } +qp-wormhole-prover = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", branch = "feat/block-header-proof", default-features = false } +qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", branch = "feat/block-header-proof", default-features = false } +plonky2 = { package = "qp-plonky2", git = "https://github.com/Quantus-Network/qp-plonky2", default-features = false, features = ["no_random"] } +qp-poseidon-core = { git = "https://github.com/Quantus-Network/qp-poseidon.git", branch = "feat/plonky2-update", default-features = false, features = ["p3"] } + [dev-dependencies] tempfile = "3.8" diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 162b1f7..9d8c6ba 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -21,6 +21,7 @@ pub mod system; pub mod tech_collective; pub mod treasury; pub mod wallet; +pub mod wormhole; /// Main CLI commands #[derive(Subcommand, Debug)] @@ -221,6 +222,10 @@ pub enum Commands { /// Block management and analysis commands #[command(subcommand)] Block(block::BlockCommands), + + /// Wormhole proof generation and verification + #[command(subcommand)] + Wormhole(wormhole::WormholeCommands), } /// Developer subcommands @@ -343,6 +348,7 @@ pub async fn execute_command( }, Commands::CompatibilityCheck => handle_compatibility_check(node_url).await, Commands::Block(block_cmd) => block::handle_block_command(block_cmd, node_url).await, + Commands::Wormhole(wormhole_cmd) => wormhole::handle_wormhole_command(wormhole_cmd, node_url).await, } } diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs new file mode 100644 index 0000000..55a4281 --- /dev/null +++ b/src/cli/wormhole.rs @@ -0,0 +1,438 @@ +use crate::chain::client::{ChainConfig, QuantusClient}; +use crate::chain::quantus_subxt as quantus_node; +use crate::chain::quantus_subxt::api::balances; +use crate::cli::common::submit_transaction; +use crate::wallet::QuantumKeyPair; +use crate::{log_print, log_success, log_verbose}; +use anyhow::anyhow; +use clap::Subcommand; +use plonky2::plonk::circuit_data::CircuitConfig; +use plonky2::plonk::proof::ProofWithPublicInputs; +use qp_poseidon::PoseidonHasher; +use qp_wormhole_circuit::inputs::{CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs}; +use qp_wormhole_circuit::nullifier::Nullifier; +use qp_wormhole_prover::WormholeProver; +use qp_zk_circuits_common::utils::{BytesDigest, Digest}; +use sp_core::crypto::{AccountId32, Ss58Codec}; +use sp_core::Hasher; +use subxt::backend::legacy::rpc_methods::{Bytes, ReadProof}; +use subxt::blocks::Block; +use subxt::ext::codec::Encode; +use subxt::ext::jsonrpsee::core::client::ClientT; +use subxt::ext::jsonrpsee::rpc_params; +use subxt::utils::{to_hex, AccountId32 as SubxtAccountId}; +use subxt::OnlineClient; + +#[derive(Subcommand, Debug)] +pub enum WormholeCommands { + /// Generate a wormhole proof + Generate { + /// Secret (32-byte hex string) + #[arg(long)] + secret: String, + + /// Funding amount to transfer + #[arg(long)] + amount: u128, + + /// Exit account (where funds will be withdrawn) + #[arg(long)] + exit_account: String, + + /// Wallet name to fund from + #[arg(short, long)] + from: String, + + /// Password for the wallet + #[arg(short, long)] + password: Option, + + /// Read password from file + #[arg(long)] + password_file: Option, + + /// Output file for the proof (default: proof.hex) + #[arg(short, long, default_value = "proof.hex")] + output: String, + }, +} + +pub async fn handle_wormhole_command( + command: WormholeCommands, + node_url: &str, +) -> crate::error::Result<()> { + match command { + WormholeCommands::Generate { + secret, + amount, + exit_account, + from, + password, + password_file, + output, + } => { + generate_proof( + secret, + amount, + exit_account, + from, + password, + password_file, + output, + node_url, + ) + .await + }, + } +} + +async fn generate_proof( + secret_hex: String, + funding_amount: u128, + exit_account_str: String, + from_wallet: String, + password: Option, + password_file: Option, + output_file: String, + node_url: &str, +) -> crate::error::Result<()> { + log_print!("Generating wormhole proof..."); + + // Parse secret + let secret_bytes = hex::decode(secret_hex.trim_start_matches("0x")) + .map_err(|e| crate::error::QuantusError::Generic(format!("Invalid secret hex: {}", e)))?; + if secret_bytes.len() != 32 { + return Err(crate::error::QuantusError::Generic( + "Secret must be exactly 32 bytes".to_string(), + )); + } + let secret_array: [u8; 32] = secret_bytes + .try_into() + .map_err(|_| crate::error::QuantusError::Generic("Failed to convert secret".to_string()))?; + let secret: BytesDigest = secret_array.try_into().map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to convert secret: {:?}", e)) + })?; + + // Parse exit account + let exit_account_id = if exit_account_str.starts_with("0x") { + let exit_account_bytes = hex::decode(&exit_account_str[2..]).map_err(|e| { + crate::error::QuantusError::Generic(format!("Invalid exit account hex: {}", e)) + })?; + if exit_account_bytes.len() != 32 { + return Err(crate::error::QuantusError::Generic( + "Exit account must be 32 bytes".to_string(), + )); + } + SubxtAccountId(exit_account_bytes.try_into().map_err(|_| { + crate::error::QuantusError::Generic("Failed to convert exit account".to_string()) + })?) + } else { + // Assume it's a wallet name, resolve it + let resolved = crate::cli::common::resolve_address(&exit_account_str)?; + let account_id = AccountId32::from_ss58check(&resolved).map_err(|e| { + crate::error::QuantusError::Generic(format!("Invalid SS58 address: {}", e)) + })?; + let bytes: [u8; 32] = account_id.into(); + SubxtAccountId(bytes) + }; + + // Load keypair + let keypair = crate::wallet::load_keypair_from_wallet(&from_wallet, password, password_file)?; + + // Connect to node + let quantus_client = QuantusClient::new(node_url) + .await + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to connect: {}", e)))?; + let client = quantus_client.client(); + + log_verbose!("Connected to node"); + + let funding_account = AccountId32::new(PoseidonHasher::hash(keypair.public_key.as_ref()).0); + + // Generate unspendable account + let unspendable_account = + qp_wormhole_circuit::unspendable_account::UnspendableAccount::from_secret(secret) + .account_id; + let unspendable_account_bytes_digest = + qp_zk_circuits_common::utils::digest_felts_to_bytes(unspendable_account); + let unspendable_account_bytes: [u8; 32] = unspendable_account_bytes_digest + .as_ref() + .try_into() + .expect("BytesDigest is always 32 bytes"); + let unspendable_account_id = SubxtAccountId(unspendable_account_bytes); + + log_verbose!("Unspendable account: {:?}", &unspendable_account_id); + log_verbose!("Exit account: {:?}", &exit_account_id); + + // Transfer to unspendable account + let transfer_tx = quantus_node::api::tx().balances().transfer_keep_alive( + subxt::ext::subxt_core::utils::MultiAddress::Id(unspendable_account_id.clone()), + funding_amount, + ); + + log_verbose!("Submitting transfer to unspendable account..."); + + let blocks = at_best_block(&quantus_client) + .await + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + let block_hash_pre = blocks.hash(); + + let storage_api = client.storage().at(block_hash_pre); + let transfer_count_previous = storage_api + .fetch(&quantus_node::api::storage().balances().transfer_count()) + .await + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))? + .unwrap_or_default(); + + let quantum_keypair = QuantumKeyPair { + public_key: keypair.public_key.clone(), + private_key: keypair.private_key.clone(), + }; + + submit_transaction(&quantus_client, &quantum_keypair, transfer_tx, None) + .await + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + + let blocks = at_best_block(&quantus_client) + .await + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + let block_hash = blocks.hash(); + + log_success!("Transfer included in block: {:?}", block_hash); + + let events_api = client + .events() + .at(block_hash) + .await + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + + let event = events_api + .find::() + .next() + .ok_or_else(|| { + crate::error::QuantusError::Generic("No TransferProofStored event found".to_string()) + })? + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + + let storage_api = client.storage().at(block_hash); + let transfer_count = storage_api + .fetch(&quantus_node::api::storage().balances().transfer_count()) + .await + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))? + .unwrap_or_default(); + + if transfer_count <= transfer_count_previous { + return Err(crate::error::QuantusError::Generic( + "Transfer count was not incremented".to_string(), + )); + } + + // Get storage proof + let leaf_hash = qp_poseidon::PoseidonHasher::hash_storage::( + &(event.transfer_count, event.source.clone(), event.dest.clone(), event.funding_amount) + .encode(), + ); + let proof_address = quantus_node::api::storage().balances().transfer_proof(( + event.transfer_count, + event.source.clone(), + event.dest.clone(), + event.funding_amount, + )); + let mut final_key = proof_address.to_root_bytes(); + final_key.extend_from_slice(&leaf_hash); + let val = storage_api + .fetch_raw(final_key.clone()) + .await + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + if val.is_none() { + return Err(crate::error::QuantusError::Generic("Storage key not found".to_string())); + } + + let proof_params = rpc_params![vec![to_hex(&final_key)], block_hash]; + let read_proof: ReadProof = quantus_client + .rpc_client() + .request("state_getReadProof", proof_params) + .await + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + + let header = blocks.header(); + + let state_root = BytesDigest::try_from(header.state_root.as_bytes()) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + let parent_hash = BytesDigest::try_from(header.parent_hash.as_bytes()) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + let extrinsics_root = BytesDigest::try_from(header.extrinsics_root.as_bytes()) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + let digest = + header.digest.encode().try_into().map_err(|_| { + crate::error::QuantusError::Generic("Failed to encode digest".to_string()) + })?; + + let block_number = header.number; + + // Prepare storage proof + let processed_storage_proof = + prepare_proof_for_circuit(read_proof.proof, hex::encode(header.state_root.0), leaf_hash) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + + let inputs = CircuitInputs { + private: PrivateCircuitInputs { + secret, + transfer_count: event.transfer_count, + funding_account: BytesDigest::try_from(funding_account.as_ref() as &[u8]) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?, + storage_proof: processed_storage_proof, + unspendable_account: Digest::from(unspendable_account).into(), + state_root, + extrinsics_root, + digest, + }, + public: PublicCircuitInputs { + funding_amount, + nullifier: Nullifier::from_preimage(secret, event.transfer_count).hash.into(), + exit_account: BytesDigest::try_from(exit_account_id.as_ref() as &[u8]) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?, + block_hash: BytesDigest::try_from(block_hash.as_ref()) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?, + parent_hash, + block_number, + }, + }; + + log_verbose!("Generating ZK proof..."); + let config = CircuitConfig::standard_recursion_config(); + let prover = WormholeProver::new(config); + let prover_next = prover + .commit(&inputs) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + let proof: ProofWithPublicInputs<_, _, 2> = prover_next.prove().map_err(|e| { + crate::error::QuantusError::Generic(format!("Proof generation failed: {}", e)) + })?; + + let public_inputs = PublicCircuitInputs::try_from(&proof) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + + let proof_hex = hex::encode(proof.to_bytes()); + std::fs::write(&output_file, proof_hex).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to write proof: {}", e)) + })?; + + log_success!("Proof generated successfully!"); + log_success!("Output: {}", output_file); + log_verbose!("Public inputs: {:?}", public_inputs); + + Ok(()) +} + +async fn at_best_block( + quantus_client: &QuantusClient, +) -> anyhow::Result>> { + let best_block = quantus_client.get_latest_block().await?; + let block = quantus_client.client().blocks().at(best_block).await?; + Ok(block) +} + +// Utility functions from proof-utils.rs +fn hash_node_with_poseidon_padded(node_bytes: &[u8]) -> [u8; 32] { + use qp_poseidon_core::{hash_padded_bytes, FIELD_ELEMENT_PREIMAGE_PADDING_LEN}; + hash_padded_bytes::(node_bytes) +} + +fn prepare_proof_for_circuit( + proof: Vec, + state_root: String, + leaf_hash: [u8; 32], +) -> anyhow::Result { + let mut node_map: std::collections::HashMap, String)> = + std::collections::HashMap::new(); + for (idx, node) in proof.iter().enumerate() { + let hash = hash_node_with_poseidon_padded(&node.0); + let hash_hex = hex::encode(hash); + let node_hex = hex::encode(&node.0); + node_map.insert(hash_hex.clone(), (idx, node.0.clone(), node_hex)); + } + + let state_root_hex = state_root.trim_start_matches("0x").to_string(); + + let root_hash = if node_map.contains_key(&state_root_hex) { + state_root_hex.clone() + } else { + anyhow::bail!("No node hashes to state root!"); + }; + + let root_entry = node_map + .get(&root_hash) + .ok_or_else(|| anyhow!("Failed to get root entry from map"))?; + + let mut ordered_nodes = vec![root_entry.1.clone()]; + let mut current_node_hex = root_entry.2.clone(); + + const HASH_LENGTH_PREFIX: &str = "2000000000000000"; + + loop { + let mut found_child = None; + for (child_hash, (_, child_bytes, _)) in &node_map { + let hash_with_prefix = format!("{}{}", HASH_LENGTH_PREFIX, child_hash); + if current_node_hex.contains(&hash_with_prefix) { + if !ordered_nodes.iter().any(|n| n == child_bytes) { + found_child = Some((child_hash.clone(), child_bytes.clone())); + break; + } + } + } + + if let Some((_, child_bytes)) = found_child { + ordered_nodes.push(child_bytes.clone()); + current_node_hex = hex::encode(ordered_nodes.last().unwrap()); + } else { + break; + } + } + + let mut indices = Vec::::new(); + + for i in 0..ordered_nodes.len() - 1 { + let current_hex = hex::encode(&ordered_nodes[i]); + let next_node = &ordered_nodes[i + 1]; + let next_hash = hex::encode(hash_node_with_poseidon_padded(next_node)); + + if let Some(hex_idx) = current_hex.find(&next_hash) { + indices.push(hex_idx); + } else { + anyhow::bail!("Could not find child hash in ordered node {}", i); + } + } + + let (found, last_idx) = check_leaf(&leaf_hash, ordered_nodes.last().unwrap().clone()); + if !found { + anyhow::bail!("Leaf hash suffix not found in leaf node!"); + } + + indices.push(last_idx); + + if indices.len() != ordered_nodes.len() { + log_verbose!( + "Warning: indices.len() = {}, ordered_nodes.len() = {}", + indices.len(), + ordered_nodes.len() + ); + } + + qp_wormhole_circuit::storage_proof::ProcessedStorageProof::new(ordered_nodes, indices) +} + +fn check_leaf(leaf_hash: &[u8; 32], leaf_node: Vec) -> (bool, usize) { + let hash_suffix = &leaf_hash[8..32]; + let mut last_idx = 0usize; + let mut found = false; + + for i in 0..=leaf_node.len().saturating_sub(hash_suffix.len()) { + if &leaf_node[i..i + hash_suffix.len()] == hash_suffix { + last_idx = i; + found = true; + break; + } + } + + (found, (last_idx * 2).saturating_sub(16)) +} From ee136fed5f0c2cff6584d0e5952d13c9e223f6fb Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Wed, 19 Nov 2025 20:29:01 +0600 Subject: [PATCH 06/22] fmt --- src/cli/mod.rs | 3 ++- src/cli/wormhole.rs | 53 ++++++++++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 9d8c6ba..f44b594 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -348,7 +348,8 @@ pub async fn execute_command( }, Commands::CompatibilityCheck => handle_compatibility_check(node_url).await, Commands::Block(block_cmd) => block::handle_block_command(block_cmd, node_url).await, - Commands::Wormhole(wormhole_cmd) => wormhole::handle_wormhole_command(wormhole_cmd, node_url).await, + Commands::Wormhole(wormhole_cmd) => + wormhole::handle_wormhole_command(wormhole_cmd, node_url).await, } } diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index 55a4281..11d5dcb 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -1,27 +1,37 @@ -use crate::chain::client::{ChainConfig, QuantusClient}; -use crate::chain::quantus_subxt as quantus_node; -use crate::chain::quantus_subxt::api::balances; -use crate::cli::common::submit_transaction; -use crate::wallet::QuantumKeyPair; -use crate::{log_print, log_success, log_verbose}; +use crate::{ + chain::{ + client::{ChainConfig, QuantusClient}, + quantus_subxt as quantus_node, + quantus_subxt::api::balances, + }, + cli::common::submit_transaction, + log_print, log_success, log_verbose, + wallet::QuantumKeyPair, +}; use anyhow::anyhow; use clap::Subcommand; -use plonky2::plonk::circuit_data::CircuitConfig; -use plonky2::plonk::proof::ProofWithPublicInputs; +use plonky2::plonk::{circuit_data::CircuitConfig, proof::ProofWithPublicInputs}; use qp_poseidon::PoseidonHasher; -use qp_wormhole_circuit::inputs::{CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs}; -use qp_wormhole_circuit::nullifier::Nullifier; +use qp_wormhole_circuit::{ + inputs::{CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs}, + nullifier::Nullifier, +}; use qp_wormhole_prover::WormholeProver; use qp_zk_circuits_common::utils::{BytesDigest, Digest}; -use sp_core::crypto::{AccountId32, Ss58Codec}; -use sp_core::Hasher; -use subxt::backend::legacy::rpc_methods::{Bytes, ReadProof}; -use subxt::blocks::Block; -use subxt::ext::codec::Encode; -use subxt::ext::jsonrpsee::core::client::ClientT; -use subxt::ext::jsonrpsee::rpc_params; -use subxt::utils::{to_hex, AccountId32 as SubxtAccountId}; -use subxt::OnlineClient; +use sp_core::{ + crypto::{AccountId32, Ss58Codec}, + Hasher, +}; +use subxt::{ + backend::legacy::rpc_methods::{Bytes, ReadProof}, + blocks::Block, + ext::{ + codec::Encode, + jsonrpsee::{core::client::ClientT, rpc_params}, + }, + utils::{to_hex, AccountId32 as SubxtAccountId}, + OnlineClient, +}; #[derive(Subcommand, Debug)] pub enum WormholeCommands { @@ -70,7 +80,7 @@ pub async fn handle_wormhole_command( password, password_file, output, - } => { + } => generate_proof( secret, amount, @@ -81,8 +91,7 @@ pub async fn handle_wormhole_command( output, node_url, ) - .await - }, + .await, } } From f9037fab4687583634c8ac4bb1123c4e108fdebb Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Fri, 12 Dec 2025 13:51:18 +0600 Subject: [PATCH 07/22] Update metadata --- Cargo.lock | 60 ++-- Cargo.toml | 11 +- src/chain/quantus_subxt.rs | 647 +++++++++++++++++++++++-------------- src/cli/wormhole.rs | 148 ++------- src/quantus_metadata.scale | Bin 166458 -> 167060 bytes 5 files changed, 462 insertions(+), 404 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9eaa9b8..96a188f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3259,12 +3259,14 @@ dependencies = [ [[package]] name = "plonky2_maybe_rayon" version = "1.0.0" -source = "git+https://github.com/Quantus-Network/qp-plonky2#a7f257a234c40d252da33efdcd5f51f1f5a5b647" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1e554181dc95243b8d9948ae7bae5759c7fb2502fed28f671f95ef38079406" [[package]] name = "plonky2_util" version = "1.0.0" -source = "git+https://github.com/Quantus-Network/qp-plonky2#a7f257a234c40d252da33efdcd5f51f1f5a5b647" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c32c137808ca984ab2458b612b7eb0462d853ee041a3136e83d54b96074c7610" [[package]] name = "polkavm-common" @@ -3472,8 +3474,9 @@ dependencies = [ [[package]] name = "qp-plonky2" -version = "1.1.1" -source = "git+https://github.com/Quantus-Network/qp-plonky2#a7f257a234c40d252da33efdcd5f51f1f5a5b647" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39530b02faa85964bba211e030afa2d54995b403b0022f88e984c4c65679c4bc" dependencies = [ "ahash", "anyhow", @@ -3489,7 +3492,7 @@ dependencies = [ "plonky2_maybe_rayon", "plonky2_util", "qp-plonky2-field", - "qp-poseidon-constants 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "qp-poseidon-constants 1.0.1", "rand 0.8.5", "serde", "static_assertions", @@ -3498,8 +3501,9 @@ dependencies = [ [[package]] name = "qp-plonky2-field" -version = "1.1.1" -source = "git+https://github.com/Quantus-Network/qp-plonky2#a7f257a234c40d252da33efdcd5f51f1f5a5b647" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8d52dadf3bb92708c309922b62d7f3f2587d3047f9fe05a0c9f587e2890526" dependencies = [ "anyhow", "itertools 0.11.0", @@ -3521,7 +3525,7 @@ dependencies = [ "p3-field", "p3-goldilocks", "parity-scale-codec", - "qp-poseidon-core 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "qp-poseidon-core 1.0.3", "scale-info", "serde", "sp-core", @@ -3545,8 +3549,8 @@ dependencies = [ [[package]] name = "qp-poseidon-constants" -version = "1.0.1" -source = "git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update#57ed5087c8f9a21762ed63af64d6614e8f3194fd" +version = "1.0.2" +source = "git+https://github.com/Quantus-Network/qp-poseidon?branch=feat%2Ftransfer-proof-asset-id#9ae96dea18464d6ea43de5c78a066f9d1f17b801" dependencies = [ "p3-field", "p3-goldilocks", @@ -3557,29 +3561,30 @@ dependencies = [ [[package]] name = "qp-poseidon-core" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e658a373a7fb22babeda9ffcc8af0a894e6e3c008272ed735509eccb7769ead3" +version = "1.0.2" +source = "git+https://github.com/Quantus-Network/qp-poseidon?branch=feat%2Ftransfer-proof-asset-id#9ae96dea18464d6ea43de5c78a066f9d1f17b801" dependencies = [ "p3-field", "p3-goldilocks", "p3-poseidon2", "p3-symmetric", - "qp-poseidon-constants 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "qp-plonky2", + "qp-poseidon-constants 1.0.2", "rand_chacha 0.9.0", ] [[package]] name = "qp-poseidon-core" -version = "1.0.1" -source = "git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update#57ed5087c8f9a21762ed63af64d6614e8f3194fd" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52c70df221c356b3ce63afabfae623aae632c27d3e078cd20eec4348096c2d7" dependencies = [ "p3-field", "p3-goldilocks", "p3-poseidon2", "p3-symmetric", "qp-plonky2", - "qp-poseidon-constants 1.0.1 (git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update)", + "qp-poseidon-constants 1.0.1", "rand_chacha 0.9.0", ] @@ -3605,7 +3610,7 @@ dependencies = [ "hex", "hex-literal", "nam-tiny-hderive", - "qp-poseidon-core 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "qp-poseidon-core 1.0.3", "qp-rusty-crystals-dilithium", "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -3616,20 +3621,20 @@ dependencies = [ [[package]] name = "qp-wormhole-circuit" -version = "0.1.2" -source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git?branch=feat%2Fblock-header-proof#8edb333d9a92a4279ae5416a5ad96a93864e4375" +version = "0.1.4" +source = "git+https://github.com/Quantus-Network/zk-circuits?branch=feat%2Fasset-id-wormhole#b97f33e7db8d4f07d6817883e434c86565959046" dependencies = [ "anyhow", "hex", "qp-plonky2", - "qp-poseidon-core 1.0.1 (git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update)", + "qp-poseidon-core 1.0.3", "qp-zk-circuits-common", ] [[package]] name = "qp-wormhole-prover" -version = "0.1.2" -source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git?branch=feat%2Fblock-header-proof#8edb333d9a92a4279ae5416a5ad96a93864e4375" +version = "0.1.4" +source = "git+https://github.com/Quantus-Network/zk-circuits?branch=feat%2Fasset-id-wormhole#b97f33e7db8d4f07d6817883e434c86565959046" dependencies = [ "anyhow", "qp-plonky2", @@ -3639,12 +3644,13 @@ dependencies = [ [[package]] name = "qp-zk-circuits-common" -version = "0.1.2" -source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git?branch=feat%2Fblock-header-proof#8edb333d9a92a4279ae5416a5ad96a93864e4375" +version = "0.1.4" +source = "git+https://github.com/Quantus-Network/zk-circuits?branch=feat%2Fasset-id-wormhole#b97f33e7db8d4f07d6817883e434c86565959046" dependencies = [ "anyhow", + "hex", "qp-plonky2", - "qp-poseidon-core 1.0.1 (git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update)", + "qp-poseidon-core 1.0.3", "serde", ] @@ -3665,7 +3671,7 @@ dependencies = [ "qp-dilithium-crypto", "qp-plonky2", "qp-poseidon", - "qp-poseidon-core 1.0.1 (git+https://github.com/Quantus-Network/qp-poseidon.git?branch=feat%2Fplonky2-update)", + "qp-poseidon-core 1.0.2", "qp-rusty-crystals-dilithium", "qp-rusty-crystals-hdwallet", "qp-wormhole-circuit", diff --git a/Cargo.toml b/Cargo.toml index 8f99434..ffb5d8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ path = "src/lib.rs" name = "quantus" path = "src/main.rs" - [dependencies] # CLI and async runtime clap = { version = "4.5", features = ["derive"] } @@ -70,11 +69,11 @@ subxt-metadata = "0.43.0" # ZK proof generation anyhow = "1.0" -qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", branch = "feat/block-header-proof", default-features = false } -qp-wormhole-prover = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", branch = "feat/block-header-proof", default-features = false } -qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", branch = "feat/block-header-proof", default-features = false } -plonky2 = { package = "qp-plonky2", git = "https://github.com/Quantus-Network/qp-plonky2", default-features = false, features = ["no_random"] } -qp-poseidon-core = { git = "https://github.com/Quantus-Network/qp-poseidon.git", branch = "feat/plonky2-update", default-features = false, features = ["p3"] } +qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/zk-circuits", branch = "feat/asset-id-wormhole", default-features = false } +qp-wormhole-prover = { git = "https://github.com/Quantus-Network/zk-circuits", branch = "feat/asset-id-wormhole", default-features = false } +qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/zk-circuits", branch = "feat/asset-id-wormhole", default-features = false } +qp-plonky2 = { version = "1.1.3", default-features = false, features = ["no_random"] } +qp-poseidon-core = { git = "https://github.com/Quantus-Network/qp-poseidon", branch = "feat/transfer-proof-asset-id", default-features = false, features = ["p2", "p3"] } [dev-dependencies] tempfile = "3.8" diff --git a/src/chain/quantus_subxt.rs b/src/chain/quantus_subxt.rs index f833791..c8aa097 100644 --- a/src/chain/quantus_subxt.rs +++ b/src/chain/quantus_subxt.rs @@ -145,9 +145,10 @@ pub mod api { "execute_block", types::ExecuteBlock { block }, [ - 133u8, 135u8, 228u8, 65u8, 106u8, 27u8, 85u8, 158u8, 112u8, 254u8, - 93u8, 26u8, 102u8, 201u8, 118u8, 216u8, 249u8, 247u8, 91u8, 74u8, 56u8, - 208u8, 231u8, 115u8, 131u8, 29u8, 209u8, 6u8, 65u8, 57u8, 214u8, 125u8, + 81u8, 130u8, 143u8, 72u8, 156u8, 15u8, 28u8, 87u8, 117u8, 10u8, 192u8, + 249u8, 117u8, 214u8, 184u8, 13u8, 148u8, 224u8, 167u8, 170u8, 101u8, + 194u8, 229u8, 140u8, 199u8, 115u8, 73u8, 99u8, 183u8, 205u8, 98u8, + 33u8, ], ) } @@ -164,9 +165,9 @@ pub mod api { "initialize_block", types::InitializeBlock { header }, [ - 132u8, 169u8, 113u8, 112u8, 80u8, 139u8, 113u8, 35u8, 41u8, 81u8, 36u8, - 35u8, 37u8, 202u8, 29u8, 207u8, 205u8, 229u8, 145u8, 7u8, 133u8, 94u8, - 25u8, 108u8, 233u8, 86u8, 234u8, 29u8, 236u8, 57u8, 56u8, 186u8, + 112u8, 139u8, 92u8, 30u8, 37u8, 99u8, 47u8, 83u8, 221u8, 31u8, 204u8, + 129u8, 102u8, 92u8, 144u8, 80u8, 3u8, 98u8, 157u8, 5u8, 20u8, 31u8, + 110u8, 105u8, 86u8, 91u8, 173u8, 19u8, 140u8, 246u8, 60u8, 223u8, ], ) } @@ -194,7 +195,7 @@ pub mod api { pub struct Version {} pub mod execute_block { use super::runtime_types; - pub type Block = runtime_types :: sp_runtime :: generic :: block :: Block < runtime_types :: sp_runtime :: generic :: header :: Header < :: core :: primitive :: u32 > , :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension ,) > > ; + pub type Block = runtime_types :: sp_runtime :: generic :: block :: Block < runtime_types :: qp_header :: Header < :: core :: primitive :: u32 > , :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > > ; pub mod output { use super::runtime_types; pub type Output = (); @@ -216,8 +217,7 @@ pub mod api { } pub mod initialize_block { use super::runtime_types; - pub type Header = - runtime_types::sp_runtime::generic::header::Header<::core::primitive::u32>; + pub type Header = runtime_types::qp_header::Header<::core::primitive::u32>; pub mod output { use super::runtime_types; pub type Output = runtime_types::sp_runtime::ExtrinsicInclusionMode; @@ -412,9 +412,9 @@ pub mod api { "finalize_block", types::FinalizeBlock {}, [ - 244u8, 207u8, 24u8, 33u8, 13u8, 69u8, 9u8, 249u8, 145u8, 143u8, 122u8, - 96u8, 197u8, 55u8, 64u8, 111u8, 238u8, 224u8, 34u8, 201u8, 27u8, 146u8, - 232u8, 99u8, 191u8, 30u8, 114u8, 16u8, 32u8, 220u8, 58u8, 62u8, + 135u8, 81u8, 28u8, 123u8, 19u8, 171u8, 129u8, 82u8, 85u8, 96u8, 238u8, + 155u8, 211u8, 153u8, 243u8, 31u8, 189u8, 82u8, 91u8, 225u8, 78u8, 48u8, + 241u8, 236u8, 143u8, 65u8, 91u8, 167u8, 114u8, 146u8, 31u8, 197u8, ], ) } @@ -452,10 +452,10 @@ pub mod api { "check_inherents", types::CheckInherents { block, data }, [ - 153u8, 134u8, 1u8, 215u8, 139u8, 11u8, 53u8, 51u8, 210u8, 175u8, 197u8, - 28u8, 38u8, 209u8, 175u8, 247u8, 142u8, 157u8, 50u8, 151u8, 164u8, - 191u8, 181u8, 118u8, 80u8, 97u8, 160u8, 248u8, 110u8, 217u8, 181u8, - 234u8, + 44u8, 230u8, 134u8, 154u8, 73u8, 173u8, 160u8, 231u8, 223u8, 148u8, + 247u8, 104u8, 214u8, 168u8, 43u8, 202u8, 204u8, 14u8, 148u8, 154u8, + 9u8, 103u8, 239u8, 45u8, 186u8, 21u8, 97u8, 136u8, 200u8, 108u8, 205u8, + 167u8, ], ) } @@ -464,7 +464,7 @@ pub mod api { use super::runtime_types; pub mod apply_extrinsic { use super::runtime_types; - pub type Extrinsic = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension ,) > ; + pub type Extrinsic = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > ; pub mod output { use super::runtime_types; pub type Output = :: core :: result :: Result < :: core :: result :: Result < () , runtime_types :: sp_runtime :: DispatchError > , runtime_types :: sp_runtime :: transaction_validity :: TransactionValidityError > ; @@ -488,9 +488,7 @@ pub mod api { use super::runtime_types; pub mod output { use super::runtime_types; - pub type Output = runtime_types::sp_runtime::generic::header::Header< - ::core::primitive::u32, - >; + pub type Output = runtime_types::qp_header::Header<::core::primitive::u32>; } } #[derive( @@ -510,7 +508,7 @@ pub mod api { pub type Inherent = runtime_types::sp_inherents::InherentData; pub mod output { use super::runtime_types; - pub type Output = :: subxt :: ext :: subxt_core :: alloc :: vec :: Vec < :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension ,) > > ; + pub type Output = :: subxt :: ext :: subxt_core :: alloc :: vec :: Vec < :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > > ; } } #[derive( @@ -529,7 +527,7 @@ pub mod api { } pub mod check_inherents { use super::runtime_types; - pub type Block = runtime_types :: sp_runtime :: generic :: block :: Block < runtime_types :: sp_runtime :: generic :: header :: Header < :: core :: primitive :: u32 > , :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension ,) > > ; + pub type Block = runtime_types :: sp_runtime :: generic :: block :: Block < runtime_types :: qp_header :: Header < :: core :: primitive :: u32 > , :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > > ; pub type Data = runtime_types::sp_inherents::InherentData; pub mod output { use super::runtime_types; @@ -595,7 +593,7 @@ pub mod api { use super::runtime_types; pub type Source = runtime_types::sp_runtime::transaction_validity::TransactionSource; - pub type Tx = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension ,) > ; + pub type Tx = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > ; pub type BlockHash = ::subxt::ext::subxt_core::utils::H256; pub mod output { use super::runtime_types; @@ -638,9 +636,10 @@ pub mod api { "offchain_worker", types::OffchainWorker { header }, [ - 10u8, 135u8, 19u8, 153u8, 33u8, 216u8, 18u8, 242u8, 33u8, 140u8, 4u8, - 223u8, 200u8, 130u8, 103u8, 118u8, 137u8, 24u8, 19u8, 127u8, 161u8, - 29u8, 184u8, 111u8, 222u8, 111u8, 253u8, 73u8, 45u8, 31u8, 79u8, 60u8, + 131u8, 199u8, 206u8, 86u8, 209u8, 109u8, 229u8, 152u8, 235u8, 155u8, + 35u8, 252u8, 70u8, 180u8, 47u8, 173u8, 84u8, 182u8, 176u8, 164u8, + 107u8, 88u8, 249u8, 181u8, 85u8, 174u8, 240u8, 226u8, 254u8, 189u8, + 167u8, 155u8, ], ) } @@ -649,8 +648,7 @@ pub mod api { use super::runtime_types; pub mod offchain_worker { use super::runtime_types; - pub type Header = - runtime_types::sp_runtime::generic::header::Header<::core::primitive::u32>; + pub type Header = runtime_types::qp_header::Header<::core::primitive::u32>; pub mod output { use super::runtime_types; pub type Output = (); @@ -1356,7 +1354,7 @@ pub mod api { use super::runtime_types; pub mod query_info { use super::runtime_types; - pub type Uxt = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension ,) > ; + pub type Uxt = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > ; pub type Len = ::core::primitive::u32; pub mod output { use super::runtime_types; @@ -1384,7 +1382,7 @@ pub mod api { } pub mod query_fee_details { use super::runtime_types; - pub type Uxt = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension ,) > ; + pub type Uxt = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > ; pub type Len = ::core::primitive::u32; pub mod output { use super::runtime_types; @@ -1473,9 +1471,9 @@ pub mod api { "query_call_info", types::QueryCallInfo { call, len }, [ - 124u8, 24u8, 108u8, 27u8, 208u8, 239u8, 216u8, 228u8, 57u8, 228u8, - 174u8, 239u8, 59u8, 192u8, 215u8, 42u8, 41u8, 201u8, 169u8, 7u8, 33u8, - 161u8, 23u8, 79u8, 0u8, 57u8, 32u8, 8u8, 13u8, 5u8, 138u8, 98u8, + 86u8, 229u8, 66u8, 90u8, 9u8, 192u8, 94u8, 166u8, 53u8, 95u8, 117u8, + 12u8, 3u8, 4u8, 189u8, 7u8, 73u8, 230u8, 139u8, 35u8, 5u8, 109u8, + 158u8, 162u8, 231u8, 1u8, 128u8, 220u8, 143u8, 156u8, 31u8, 122u8, ], ) } @@ -1493,10 +1491,9 @@ pub mod api { "query_call_fee_details", types::QueryCallFeeDetails { call, len }, [ - 250u8, 80u8, 231u8, 164u8, 228u8, 157u8, 118u8, 66u8, 94u8, 60u8, - 100u8, 68u8, 96u8, 22u8, 100u8, 185u8, 1u8, 160u8, 77u8, 30u8, 126u8, - 180u8, 230u8, 117u8, 99u8, 101u8, 101u8, 49u8, 237u8, 192u8, 219u8, - 41u8, + 181u8, 7u8, 183u8, 151u8, 247u8, 92u8, 240u8, 27u8, 40u8, 192u8, 150u8, + 16u8, 176u8, 113u8, 208u8, 17u8, 253u8, 72u8, 92u8, 180u8, 153u8, + 179u8, 32u8, 229u8, 61u8, 136u8, 33u8, 123u8, 48u8, 172u8, 216u8, 8u8, ], ) } @@ -2007,9 +2004,9 @@ pub mod api { .hash(); runtime_metadata_hash == [ - 0u8, 63u8, 162u8, 224u8, 195u8, 69u8, 233u8, 104u8, 127u8, 217u8, 171u8, 115u8, - 255u8, 248u8, 177u8, 84u8, 158u8, 190u8, 76u8, 185u8, 144u8, 155u8, 69u8, 210u8, - 153u8, 253u8, 206u8, 43u8, 20u8, 28u8, 169u8, 236u8, + 92u8, 199u8, 247u8, 245u8, 15u8, 124u8, 69u8, 52u8, 138u8, 213u8, 161u8, 230u8, + 234u8, 254u8, 189u8, 183u8, 200u8, 237u8, 73u8, 35u8, 183u8, 80u8, 71u8, 120u8, + 128u8, 234u8, 140u8, 160u8, 131u8, 172u8, 255u8, 32u8, ] } pub mod system { @@ -3108,9 +3105,10 @@ pub mod api { "Events", (), [ - 19u8, 73u8, 6u8, 2u8, 209u8, 127u8, 197u8, 110u8, 228u8, 146u8, 149u8, - 129u8, 191u8, 123u8, 182u8, 64u8, 160u8, 106u8, 123u8, 149u8, 123u8, - 193u8, 14u8, 100u8, 42u8, 223u8, 34u8, 212u8, 161u8, 98u8, 44u8, 49u8, + 233u8, 203u8, 207u8, 158u8, 57u8, 161u8, 88u8, 160u8, 148u8, 0u8, + 176u8, 254u8, 251u8, 206u8, 46u8, 94u8, 178u8, 136u8, 154u8, 109u8, + 197u8, 147u8, 125u8, 17u8, 120u8, 246u8, 69u8, 50u8, 48u8, 172u8, 81u8, + 34u8, ], ) } @@ -4625,31 +4623,6 @@ pub mod api { const PALLET: &'static str = "Balances"; const EVENT: &'static str = "TotalIssuanceForced"; } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Transfer proof was stored."] - pub struct TransferProofStored { - pub transfer_count: transfer_proof_stored::TransferCount, - pub source: transfer_proof_stored::Source, - pub dest: transfer_proof_stored::Dest, - pub funding_amount: transfer_proof_stored::FundingAmount, - } - pub mod transfer_proof_stored { - use super::runtime_types; - pub type TransferCount = ::core::primitive::u64; - pub type Source = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Dest = ::subxt::ext::subxt_core::utils::AccountId32; - pub type FundingAmount = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TransferProofStored { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "TransferProofStored"; - } } pub mod storage { use super::runtime_types; @@ -4709,20 +4682,6 @@ pub mod api { >; pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; } - pub mod transfer_proof { - use super::runtime_types; - pub type TransferProof = (); - pub type Param0 = ( - ::core::primitive::u64, - ::subxt::ext::subxt_core::utils::AccountId32, - ::subxt::ext::subxt_core::utils::AccountId32, - ::core::primitive::u128, - ); - } - pub mod transfer_count { - use super::runtime_types; - pub type TransferCount = ::core::primitive::u64; - } } pub struct StorageApi; impl StorageApi { @@ -5050,74 +5009,6 @@ pub mod api { ], ) } - #[doc = " Transfer proofs for a wormhole transfers"] - pub fn transfer_proof_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::transfer_proof::TransferProof, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Balances", - "TransferProof", - (), - [ - 210u8, 54u8, 36u8, 79u8, 12u8, 123u8, 227u8, 172u8, 23u8, 232u8, 200u8, - 138u8, 130u8, 99u8, 12u8, 186u8, 77u8, 74u8, 208u8, 111u8, 137u8, - 159u8, 169u8, 112u8, 227u8, 111u8, 65u8, 127u8, 232u8, 57u8, 166u8, - 14u8, - ], - ) - } - #[doc = " Transfer proofs for a wormhole transfers"] - pub fn transfer_proof( - &self, - _0: types::transfer_proof::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::transfer_proof::Param0, - >, - types::transfer_proof::TransferProof, - ::subxt::ext::subxt_core::utils::Yes, - (), - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Balances", - "TransferProof", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 210u8, 54u8, 36u8, 79u8, 12u8, 123u8, 227u8, 172u8, 23u8, 232u8, 200u8, - 138u8, 130u8, 99u8, 12u8, 186u8, 77u8, 74u8, 208u8, 111u8, 137u8, - 159u8, 169u8, 112u8, 227u8, 111u8, 65u8, 127u8, 232u8, 57u8, 166u8, - 14u8, - ], - ) - } - pub fn transfer_count( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::transfer_count::TransferCount, - ::subxt::ext::subxt_core::utils::Yes, - ::subxt::ext::subxt_core::utils::Yes, - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Balances", - "TransferCount", - (), - [ - 105u8, 10u8, 160u8, 118u8, 193u8, 131u8, 207u8, 188u8, 78u8, 238u8, - 252u8, 99u8, 31u8, 72u8, 159u8, 128u8, 159u8, 215u8, 110u8, 101u8, - 27u8, 132u8, 12u8, 59u8, 182u8, 107u8, 98u8, 77u8, 189u8, 100u8, 51u8, - 209u8, - ], - ) - } } } pub mod constants { @@ -5497,9 +5388,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 86u8, 27u8, 250u8, 23u8, 151u8, 9u8, 221u8, 180u8, 232u8, 7u8, 44u8, - 235u8, 50u8, 104u8, 247u8, 184u8, 102u8, 4u8, 48u8, 196u8, 84u8, 123u8, - 30u8, 123u8, 85u8, 124u8, 151u8, 25u8, 83u8, 221u8, 50u8, 226u8, + 203u8, 72u8, 88u8, 39u8, 226u8, 214u8, 8u8, 216u8, 109u8, 243u8, 223u8, + 189u8, 193u8, 191u8, 45u8, 189u8, 20u8, 195u8, 62u8, 97u8, 210u8, + 214u8, 151u8, 193u8, 31u8, 108u8, 69u8, 46u8, 140u8, 222u8, 228u8, + 169u8, ], ) } @@ -5522,9 +5414,9 @@ pub mod api { weight, }, [ - 182u8, 73u8, 169u8, 247u8, 46u8, 137u8, 24u8, 91u8, 219u8, 22u8, 25u8, - 193u8, 10u8, 234u8, 25u8, 205u8, 215u8, 83u8, 83u8, 26u8, 250u8, 195u8, - 164u8, 108u8, 247u8, 77u8, 86u8, 233u8, 185u8, 14u8, 233u8, 6u8, + 64u8, 94u8, 77u8, 108u8, 78u8, 248u8, 236u8, 53u8, 252u8, 34u8, 135u8, + 22u8, 131u8, 225u8, 167u8, 100u8, 56u8, 83u8, 244u8, 9u8, 173u8, 199u8, + 88u8, 108u8, 230u8, 56u8, 106u8, 54u8, 86u8, 235u8, 180u8, 228u8, ], ) } @@ -5562,10 +5454,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 154u8, 244u8, 161u8, 46u8, 224u8, 242u8, 181u8, 54u8, 246u8, 56u8, - 180u8, 221u8, 178u8, 69u8, 160u8, 158u8, 238u8, 224u8, 137u8, 224u8, - 115u8, 26u8, 218u8, 51u8, 144u8, 218u8, 78u8, 236u8, 165u8, 238u8, 5u8, - 33u8, + 8u8, 102u8, 80u8, 179u8, 244u8, 71u8, 31u8, 51u8, 95u8, 97u8, 65u8, + 110u8, 217u8, 40u8, 207u8, 195u8, 130u8, 247u8, 148u8, 175u8, 138u8, + 222u8, 176u8, 210u8, 200u8, 53u8, 95u8, 253u8, 149u8, 73u8, 173u8, + 153u8, ], ) } @@ -7643,9 +7535,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 125u8, 78u8, 236u8, 0u8, 94u8, 174u8, 252u8, 109u8, 210u8, 132u8, 29u8, - 112u8, 44u8, 65u8, 73u8, 253u8, 86u8, 230u8, 65u8, 52u8, 161u8, 234u8, - 74u8, 178u8, 132u8, 229u8, 110u8, 243u8, 240u8, 3u8, 34u8, 245u8, + 90u8, 168u8, 100u8, 250u8, 215u8, 75u8, 141u8, 146u8, 204u8, 225u8, + 150u8, 231u8, 151u8, 205u8, 65u8, 240u8, 45u8, 2u8, 98u8, 5u8, 141u8, + 255u8, 9u8, 53u8, 135u8, 131u8, 137u8, 181u8, 188u8, 200u8, 250u8, + 108u8, ], ) } @@ -7687,10 +7580,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 239u8, 122u8, 34u8, 125u8, 56u8, 62u8, 199u8, 184u8, 247u8, 111u8, - 102u8, 80u8, 111u8, 14u8, 86u8, 113u8, 222u8, 120u8, 142u8, 223u8, - 41u8, 160u8, 217u8, 210u8, 238u8, 4u8, 112u8, 244u8, 52u8, 101u8, 50u8, - 196u8, + 254u8, 116u8, 223u8, 77u8, 222u8, 118u8, 131u8, 7u8, 35u8, 246u8, + 214u8, 44u8, 105u8, 203u8, 31u8, 211u8, 208u8, 85u8, 63u8, 237u8, 34u8, + 103u8, 3u8, 229u8, 78u8, 119u8, 199u8, 193u8, 131u8, 128u8, 154u8, + 27u8, ], ) } @@ -7729,10 +7622,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 254u8, 153u8, 225u8, 60u8, 41u8, 44u8, 134u8, 216u8, 75u8, 142u8, 22u8, - 162u8, 207u8, 33u8, 163u8, 39u8, 155u8, 217u8, 10u8, 86u8, 105u8, - 174u8, 110u8, 14u8, 15u8, 116u8, 55u8, 252u8, 144u8, 174u8, 122u8, - 49u8, + 67u8, 98u8, 234u8, 203u8, 198u8, 87u8, 76u8, 191u8, 8u8, 128u8, 225u8, + 169u8, 148u8, 200u8, 47u8, 118u8, 216u8, 229u8, 197u8, 38u8, 8u8, 28u8, + 164u8, 63u8, 208u8, 100u8, 156u8, 29u8, 99u8, 179u8, 75u8, 209u8, ], ) } @@ -7757,9 +7649,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 220u8, 105u8, 133u8, 190u8, 222u8, 170u8, 54u8, 24u8, 52u8, 74u8, 38u8, - 40u8, 49u8, 202u8, 246u8, 238u8, 114u8, 242u8, 189u8, 247u8, 45u8, - 184u8, 23u8, 60u8, 64u8, 26u8, 173u8, 94u8, 8u8, 121u8, 4u8, 55u8, + 147u8, 123u8, 83u8, 248u8, 110u8, 162u8, 244u8, 115u8, 186u8, 216u8, + 98u8, 153u8, 83u8, 198u8, 255u8, 53u8, 20u8, 221u8, 154u8, 224u8, 11u8, + 226u8, 188u8, 40u8, 247u8, 251u8, 57u8, 137u8, 101u8, 147u8, 35u8, + 137u8, ], ) } @@ -8787,9 +8680,9 @@ pub mod api { "batch", types::Batch { calls }, [ - 8u8, 14u8, 63u8, 36u8, 47u8, 180u8, 133u8, 150u8, 98u8, 46u8, 251u8, - 65u8, 127u8, 92u8, 106u8, 133u8, 181u8, 255u8, 175u8, 67u8, 153u8, - 238u8, 69u8, 73u8, 66u8, 99u8, 96u8, 13u8, 147u8, 128u8, 96u8, 201u8, + 247u8, 255u8, 73u8, 140u8, 94u8, 73u8, 225u8, 12u8, 45u8, 234u8, 39u8, + 94u8, 64u8, 54u8, 195u8, 173u8, 213u8, 184u8, 159u8, 251u8, 73u8, 9u8, + 74u8, 229u8, 19u8, 77u8, 36u8, 70u8, 173u8, 166u8, 126u8, 156u8, ], ) } @@ -8819,9 +8712,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 240u8, 79u8, 20u8, 90u8, 191u8, 182u8, 34u8, 19u8, 193u8, 234u8, 213u8, - 178u8, 65u8, 218u8, 186u8, 74u8, 118u8, 209u8, 240u8, 129u8, 238u8, - 239u8, 91u8, 252u8, 78u8, 134u8, 163u8, 216u8, 147u8, 98u8, 30u8, 94u8, + 141u8, 234u8, 46u8, 19u8, 175u8, 133u8, 239u8, 49u8, 92u8, 144u8, 18u8, + 166u8, 50u8, 108u8, 96u8, 72u8, 121u8, 82u8, 37u8, 35u8, 128u8, 50u8, + 159u8, 197u8, 203u8, 245u8, 252u8, 230u8, 206u8, 120u8, 145u8, 228u8, ], ) } @@ -8847,9 +8740,10 @@ pub mod api { "batch_all", types::BatchAll { calls }, [ - 222u8, 8u8, 55u8, 135u8, 112u8, 82u8, 66u8, 76u8, 1u8, 9u8, 107u8, - 125u8, 153u8, 254u8, 59u8, 239u8, 61u8, 136u8, 189u8, 46u8, 91u8, 38u8, - 252u8, 97u8, 39u8, 215u8, 145u8, 174u8, 171u8, 47u8, 213u8, 6u8, + 197u8, 249u8, 16u8, 146u8, 49u8, 44u8, 209u8, 110u8, 241u8, 172u8, + 211u8, 117u8, 251u8, 137u8, 219u8, 157u8, 77u8, 198u8, 95u8, 118u8, + 219u8, 117u8, 174u8, 119u8, 1u8, 103u8, 213u8, 59u8, 201u8, 35u8, 47u8, + 246u8, ], ) } @@ -8872,9 +8766,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 220u8, 56u8, 148u8, 222u8, 163u8, 153u8, 156u8, 238u8, 167u8, 7u8, - 58u8, 11u8, 0u8, 102u8, 165u8, 102u8, 104u8, 60u8, 212u8, 73u8, 160u8, - 29u8, 225u8, 115u8, 0u8, 55u8, 189u8, 160u8, 95u8, 119u8, 16u8, 17u8, + 126u8, 91u8, 53u8, 68u8, 190u8, 43u8, 235u8, 28u8, 47u8, 103u8, 238u8, + 171u8, 70u8, 123u8, 143u8, 153u8, 155u8, 125u8, 45u8, 164u8, 41u8, + 200u8, 56u8, 163u8, 249u8, 150u8, 158u8, 87u8, 125u8, 137u8, 88u8, + 81u8, ], ) } @@ -8900,9 +8795,9 @@ pub mod api { "force_batch", types::ForceBatch { calls }, [ - 42u8, 74u8, 40u8, 136u8, 212u8, 238u8, 120u8, 35u8, 155u8, 233u8, 90u8, - 11u8, 103u8, 251u8, 234u8, 130u8, 172u8, 5u8, 219u8, 41u8, 231u8, 20u8, - 162u8, 99u8, 204u8, 189u8, 79u8, 21u8, 203u8, 90u8, 170u8, 161u8, + 113u8, 196u8, 193u8, 13u8, 222u8, 221u8, 108u8, 232u8, 210u8, 14u8, + 195u8, 2u8, 179u8, 155u8, 190u8, 186u8, 109u8, 98u8, 99u8, 58u8, 59u8, + 133u8, 145u8, 32u8, 186u8, 12u8, 198u8, 85u8, 230u8, 85u8, 247u8, 52u8, ], ) } @@ -8925,10 +8820,9 @@ pub mod api { weight, }, [ - 203u8, 125u8, 63u8, 180u8, 29u8, 135u8, 10u8, 130u8, 245u8, 74u8, 95u8, - 40u8, 166u8, 188u8, 185u8, 246u8, 14u8, 191u8, 130u8, 108u8, 188u8, - 93u8, 163u8, 151u8, 253u8, 22u8, 181u8, 237u8, 241u8, 17u8, 245u8, - 61u8, + 78u8, 208u8, 22u8, 102u8, 235u8, 74u8, 42u8, 190u8, 137u8, 216u8, 66u8, + 115u8, 20u8, 245u8, 101u8, 199u8, 156u8, 250u8, 122u8, 200u8, 65u8, + 43u8, 78u8, 60u8, 46u8, 65u8, 119u8, 31u8, 33u8, 170u8, 27u8, 229u8, ], ) } @@ -8968,10 +8862,10 @@ pub mod api { fallback: ::subxt::ext::subxt_core::alloc::boxed::Box::new(fallback), }, [ - 127u8, 165u8, 98u8, 125u8, 184u8, 176u8, 6u8, 2u8, 146u8, 14u8, 154u8, - 49u8, 52u8, 253u8, 35u8, 127u8, 216u8, 178u8, 115u8, 253u8, 150u8, - 191u8, 55u8, 119u8, 165u8, 206u8, 24u8, 23u8, 106u8, 204u8, 188u8, - 151u8, + 223u8, 119u8, 179u8, 217u8, 241u8, 14u8, 29u8, 115u8, 177u8, 237u8, + 205u8, 6u8, 227u8, 113u8, 89u8, 101u8, 97u8, 82u8, 22u8, 191u8, 14u8, + 205u8, 13u8, 198u8, 165u8, 175u8, 152u8, 231u8, 190u8, 54u8, 15u8, + 124u8, ], ) } @@ -8994,10 +8888,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 199u8, 2u8, 66u8, 203u8, 254u8, 202u8, 231u8, 19u8, 158u8, 151u8, - 157u8, 241u8, 252u8, 194u8, 188u8, 185u8, 59u8, 176u8, 72u8, 20u8, - 34u8, 248u8, 151u8, 147u8, 80u8, 251u8, 225u8, 219u8, 240u8, 79u8, - 139u8, 10u8, + 135u8, 83u8, 250u8, 68u8, 40u8, 246u8, 6u8, 82u8, 241u8, 47u8, 39u8, + 197u8, 248u8, 48u8, 173u8, 141u8, 28u8, 152u8, 58u8, 51u8, 84u8, 207u8, + 164u8, 66u8, 250u8, 88u8, 12u8, 170u8, 18u8, 81u8, 181u8, 70u8, ], ) } @@ -16603,9 +16496,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 3u8, 200u8, 160u8, 7u8, 52u8, 80u8, 43u8, 2u8, 39u8, 251u8, 144u8, - 99u8, 69u8, 29u8, 179u8, 239u8, 176u8, 48u8, 100u8, 91u8, 44u8, 249u8, - 176u8, 179u8, 28u8, 21u8, 93u8, 92u8, 26u8, 220u8, 149u8, 183u8, + 136u8, 165u8, 225u8, 86u8, 177u8, 169u8, 20u8, 142u8, 186u8, 42u8, + 170u8, 86u8, 16u8, 67u8, 250u8, 64u8, 121u8, 164u8, 33u8, 84u8, 193u8, + 32u8, 144u8, 184u8, 87u8, 18u8, 71u8, 81u8, 107u8, 193u8, 232u8, 170u8, ], ) } @@ -21165,39 +21058,130 @@ pub mod api { )] pub struct VerifyWormholeProof { pub proof_bytes: verify_wormhole_proof::ProofBytes, - pub block_number: verify_wormhole_proof::BlockNumber, - pub header: verify_wormhole_proof::Header, } pub mod verify_wormhole_proof { use super::runtime_types; pub type ProofBytes = ::subxt::ext::subxt_core::alloc::vec::Vec<::core::primitive::u8>; - pub type BlockNumber = ::core::primitive::u32; - pub type Header = - runtime_types::sp_runtime::generic::header::Header<::core::primitive::u32>; } impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for VerifyWormholeProof { const PALLET: &'static str = "Wormhole"; const CALL: &'static str = "verify_wormhole_proof"; } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "Transfer native tokens and store proof for wormhole"] + pub struct TransferNative { + pub dest: transfer_native::Dest, + #[codec(compact)] + pub amount: transfer_native::Amount, + } + pub mod transfer_native { + use super::runtime_types; + pub type Dest = ::subxt::ext::subxt_core::utils::MultiAddress< + ::subxt::ext::subxt_core::utils::AccountId32, + (), + >; + pub type Amount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for TransferNative { + const PALLET: &'static str = "Wormhole"; + const CALL: &'static str = "transfer_native"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "Transfer asset tokens and store proof for wormhole"] + pub struct TransferAsset { + pub asset_id: transfer_asset::AssetId, + pub dest: transfer_asset::Dest, + #[codec(compact)] + pub amount: transfer_asset::Amount, + } + pub mod transfer_asset { + use super::runtime_types; + pub type AssetId = ::core::primitive::u32; + pub type Dest = ::subxt::ext::subxt_core::utils::MultiAddress< + ::subxt::ext::subxt_core::utils::AccountId32, + (), + >; + pub type Amount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for TransferAsset { + const PALLET: &'static str = "Wormhole"; + const CALL: &'static str = "transfer_asset"; + } } pub struct TransactionApi; impl TransactionApi { pub fn verify_wormhole_proof( &self, proof_bytes: types::verify_wormhole_proof::ProofBytes, - block_number: types::verify_wormhole_proof::BlockNumber, - header: types::verify_wormhole_proof::Header, ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( "Wormhole", "verify_wormhole_proof", - types::VerifyWormholeProof { proof_bytes, block_number, header }, + types::VerifyWormholeProof { proof_bytes }, [ - 162u8, 205u8, 5u8, 181u8, 62u8, 111u8, 128u8, 61u8, 0u8, 236u8, 196u8, - 137u8, 88u8, 33u8, 13u8, 36u8, 251u8, 55u8, 206u8, 185u8, 61u8, 58u8, - 132u8, 180u8, 106u8, 253u8, 232u8, 24u8, 224u8, 220u8, 216u8, 237u8, + 242u8, 232u8, 238u8, 253u8, 96u8, 217u8, 86u8, 251u8, 216u8, 200u8, + 103u8, 7u8, 182u8, 218u8, 118u8, 149u8, 120u8, 244u8, 124u8, 33u8, + 133u8, 50u8, 150u8, 163u8, 187u8, 19u8, 37u8, 76u8, 73u8, 48u8, 213u8, + 193u8, + ], + ) + } + #[doc = "Transfer native tokens and store proof for wormhole"] + pub fn transfer_native( + &self, + dest: types::transfer_native::Dest, + amount: types::transfer_native::Amount, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + { + ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + "Wormhole", + "transfer_native", + types::TransferNative { dest, amount }, + [ + 108u8, 65u8, 158u8, 226u8, 204u8, 38u8, 41u8, 193u8, 72u8, 15u8, 175u8, + 111u8, 213u8, 47u8, 70u8, 113u8, 235u8, 77u8, 160u8, 118u8, 210u8, + 134u8, 44u8, 76u8, 24u8, 231u8, 234u8, 50u8, 44u8, 75u8, 99u8, 215u8, + ], + ) + } + #[doc = "Transfer asset tokens and store proof for wormhole"] + pub fn transfer_asset( + &self, + asset_id: types::transfer_asset::AssetId, + dest: types::transfer_asset::Dest, + amount: types::transfer_asset::Amount, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + { + ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + "Wormhole", + "transfer_asset", + types::TransferAsset { asset_id, dest, amount }, + [ + 49u8, 152u8, 37u8, 165u8, 177u8, 50u8, 177u8, 190u8, 98u8, 23u8, 130u8, + 61u8, 91u8, 175u8, 20u8, 208u8, 21u8, 95u8, 21u8, 10u8, 229u8, 132u8, + 118u8, 155u8, 74u8, 212u8, 103u8, 247u8, 138u8, 49u8, 157u8, 214u8, ], ) } @@ -21225,6 +21209,56 @@ pub mod api { const PALLET: &'static str = "Wormhole"; const EVENT: &'static str = "ProofVerified"; } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct NativeTransferred { + pub from: native_transferred::From, + pub to: native_transferred::To, + pub amount: native_transferred::Amount, + pub transfer_count: native_transferred::TransferCount, + } + pub mod native_transferred { + use super::runtime_types; + pub type From = ::subxt::ext::subxt_core::utils::AccountId32; + pub type To = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Amount = ::core::primitive::u128; + pub type TransferCount = ::core::primitive::u64; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for NativeTransferred { + const PALLET: &'static str = "Wormhole"; + const EVENT: &'static str = "NativeTransferred"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct AssetTransferred { + pub asset_id: asset_transferred::AssetId, + pub from: asset_transferred::From, + pub to: asset_transferred::To, + pub amount: asset_transferred::Amount, + pub transfer_count: asset_transferred::TransferCount, + } + pub mod asset_transferred { + use super::runtime_types; + pub type AssetId = ::core::primitive::u32; + pub type From = ::subxt::ext::subxt_core::utils::AccountId32; + pub type To = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Amount = ::core::primitive::u128; + pub type TransferCount = ::core::primitive::u64; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for AssetTransferred { + const PALLET: &'static str = "Wormhole"; + const EVENT: &'static str = "AssetTransferred"; + } } pub mod storage { use super::runtime_types; @@ -21235,6 +21269,21 @@ pub mod api { pub type UsedNullifiers = ::core::primitive::bool; pub type Param0 = [::core::primitive::u8; 32usize]; } + pub mod transfer_proof { + use super::runtime_types; + pub type TransferProof = (); + pub type Param0 = ( + ::core::primitive::u32, + ::core::primitive::u64, + ::subxt::ext::subxt_core::utils::AccountId32, + ::subxt::ext::subxt_core::utils::AccountId32, + ::core::primitive::u128, + ); + } + pub mod transfer_count { + use super::runtime_types; + pub type TransferCount = ::core::primitive::u64; + } } pub struct StorageApi; impl StorageApi { @@ -21283,6 +21332,73 @@ pub mod api { ], ) } + #[doc = " Transfer proofs for wormhole transfers (both native and assets)"] + pub fn transfer_proof_iter( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::transfer_proof::TransferProof, + (), + (), + ::subxt::ext::subxt_core::utils::Yes, + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "Wormhole", + "TransferProof", + (), + [ + 162u8, 38u8, 220u8, 3u8, 188u8, 47u8, 138u8, 210u8, 217u8, 129u8, 26u8, + 172u8, 96u8, 61u8, 145u8, 79u8, 185u8, 128u8, 39u8, 11u8, 94u8, 231u8, + 163u8, 227u8, 139u8, 18u8, 42u8, 47u8, 138u8, 192u8, 119u8, 84u8, + ], + ) + } + #[doc = " Transfer proofs for wormhole transfers (both native and assets)"] + pub fn transfer_proof( + &self, + _0: types::transfer_proof::Param0, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::transfer_proof::Param0, + >, + types::transfer_proof::TransferProof, + ::subxt::ext::subxt_core::utils::Yes, + (), + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "Wormhole", + "TransferProof", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + [ + 162u8, 38u8, 220u8, 3u8, 188u8, 47u8, 138u8, 210u8, 217u8, 129u8, 26u8, + 172u8, 96u8, 61u8, 145u8, 79u8, 185u8, 128u8, 39u8, 11u8, 94u8, 231u8, + 163u8, 227u8, 139u8, 18u8, 42u8, 47u8, 138u8, 192u8, 119u8, 84u8, + ], + ) + } + #[doc = " Transfer count for all wormhole transfers"] + pub fn transfer_count( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::transfer_count::TransferCount, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "Wormhole", + "TransferCount", + (), + [ + 105u8, 10u8, 160u8, 118u8, 193u8, 131u8, 207u8, 188u8, 78u8, 238u8, + 252u8, 99u8, 31u8, 72u8, 159u8, 128u8, 159u8, 215u8, 110u8, 101u8, + 27u8, 132u8, 12u8, 59u8, 182u8, 107u8, 98u8, 77u8, 189u8, 100u8, 51u8, + 209u8, + ], + ) + } } } pub mod constants { @@ -23587,14 +23703,6 @@ pub mod api { old: ::core::primitive::u128, new: ::core::primitive::u128, }, - #[codec(index = 22)] - #[doc = "Transfer proof was stored."] - TransferProofStored { - transfer_count: ::core::primitive::u64, - source: ::subxt::ext::subxt_core::utils::AccountId32, - dest: ::subxt::ext::subxt_core::utils::AccountId32, - funding_amount: ::core::primitive::u128, - }, } } pub mod types { @@ -27467,10 +27575,27 @@ pub mod api { verify_wormhole_proof { proof_bytes: ::subxt::ext::subxt_core::alloc::vec::Vec<::core::primitive::u8>, - block_number: ::core::primitive::u32, - header: runtime_types::sp_runtime::generic::header::Header< - ::core::primitive::u32, + }, + #[codec(index = 1)] + #[doc = "Transfer native tokens and store proof for wormhole"] + transfer_native { + dest: ::subxt::ext::subxt_core::utils::MultiAddress< + ::subxt::ext::subxt_core::utils::AccountId32, + (), >, + #[codec(compact)] + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + #[doc = "Transfer asset tokens and store proof for wormhole"] + transfer_asset { + asset_id: ::core::primitive::u32, + dest: ::subxt::ext::subxt_core::utils::MultiAddress< + ::subxt::ext::subxt_core::utils::AccountId32, + (), + >, + #[codec(compact)] + amount: ::core::primitive::u128, }, } #[derive( @@ -27506,6 +27631,10 @@ pub mod api { BlockNotFound, #[codec(index = 9)] InvalidBlockNumber, + #[codec(index = 10)] + AssetNotFound, + #[codec(index = 11)] + SelfTransfer, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -27522,6 +27651,21 @@ pub mod api { pub enum Event { #[codec(index = 0)] ProofVerified { exit_amount: ::core::primitive::u128 }, + #[codec(index = 1)] + NativeTransferred { + from: ::subxt::ext::subxt_core::utils::AccountId32, + to: ::subxt::ext::subxt_core::utils::AccountId32, + amount: ::core::primitive::u128, + transfer_count: ::core::primitive::u64, + }, + #[codec(index = 2)] + AssetTransferred { + asset_id: ::core::primitive::u32, + from: ::subxt::ext::subxt_core::utils::AccountId32, + to: ::subxt::ext::subxt_core::utils::AccountId32, + amount: ::core::primitive::u128, + transfer_count: ::core::primitive::u64, + }, } } } @@ -27573,6 +27717,23 @@ pub mod api { } } } + pub mod qp_header { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct Header<_0> { + pub parent_hash: ::subxt::ext::subxt_core::utils::H256, + pub number: _0, + pub state_root: ::subxt::ext::subxt_core::utils::H256, + pub extrinsics_root: ::subxt::ext::subxt_core::utils::H256, + pub digest: runtime_types::sp_runtime::generic::digest::Digest, + } + } pub mod qp_poseidon { use super::runtime_types; #[derive( @@ -27676,6 +27837,18 @@ pub mod api { crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] pub struct ReversibleTransactionExtension; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + pub struct WormholeProofRecorderExtension; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -28586,28 +28759,6 @@ pub mod api { Mortal255(::core::primitive::u8), } } - pub mod header { - use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - pub struct Header<_0> { - pub parent_hash: ::subxt::ext::subxt_core::utils::H256, - #[codec(compact)] - pub number: _0, - pub state_root: ::subxt::ext::subxt_core::utils::H256, - pub extrinsics_root: ::subxt::ext::subxt_core::utils::H256, - pub digest: runtime_types::sp_runtime::generic::digest::Digest, - } - } } pub mod proving_trie { use super::runtime_types; diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index 11d5dcb..f4f4278 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -2,13 +2,12 @@ use crate::{ chain::{ client::{ChainConfig, QuantusClient}, quantus_subxt as quantus_node, - quantus_subxt::api::balances, + quantus_subxt::api::wormhole, }, cli::common::submit_transaction, log_print, log_success, log_verbose, wallet::QuantumKeyPair, }; -use anyhow::anyhow; use clap::Subcommand; use plonky2::plonk::{circuit_data::CircuitConfig, proof::ProofWithPublicInputs}; use qp_poseidon::PoseidonHasher; @@ -17,13 +16,16 @@ use qp_wormhole_circuit::{ nullifier::Nullifier, }; use qp_wormhole_prover::WormholeProver; -use qp_zk_circuits_common::utils::{BytesDigest, Digest}; +use qp_zk_circuits_common::{ + storage_proof::prepare_proof_for_circuit, + utils::{BytesDigest, Digest}, +}; use sp_core::{ crypto::{AccountId32, Ss58Codec}, Hasher, }; use subxt::{ - backend::legacy::rpc_methods::{Bytes, ReadProof}, + backend::legacy::rpc_methods::ReadProof, blocks::Block, ext::{ codec::Encode, @@ -80,7 +82,7 @@ pub async fn handle_wormhole_command( password, password_file, output, - } => + } => { generate_proof( secret, amount, @@ -91,7 +93,8 @@ pub async fn handle_wormhole_command( output, node_url, ) - .await, + .await + }, } } @@ -188,7 +191,7 @@ async fn generate_proof( let storage_api = client.storage().at(block_hash_pre); let transfer_count_previous = storage_api - .fetch(&quantus_node::api::storage().balances().transfer_count()) + .fetch(&quantus_node::api::storage().wormhole().transfer_count()) .await .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))? .unwrap_or_default(); @@ -216,7 +219,7 @@ async fn generate_proof( .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; let event = events_api - .find::() + .find::() .next() .ok_or_else(|| { crate::error::QuantusError::Generic("No TransferProofStored event found".to_string()) @@ -225,7 +228,7 @@ async fn generate_proof( let storage_api = client.storage().at(block_hash); let transfer_count = storage_api - .fetch(&quantus_node::api::storage().balances().transfer_count()) + .fetch(&quantus_node::api::storage().wormhole().transfer_count()) .await .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))? .unwrap_or_default(); @@ -238,14 +241,14 @@ async fn generate_proof( // Get storage proof let leaf_hash = qp_poseidon::PoseidonHasher::hash_storage::( - &(event.transfer_count, event.source.clone(), event.dest.clone(), event.funding_amount) - .encode(), + &(event.transfer_count, event.from.clone(), event.to.clone(), event.amount).encode(), ); - let proof_address = quantus_node::api::storage().balances().transfer_proof(( + let proof_address = quantus_node::api::storage().wormhole().transfer_proof(( + 0, event.transfer_count, - event.source.clone(), - event.dest.clone(), - event.funding_amount, + event.from.clone(), + event.to.clone(), + event.amount, )); let mut final_key = proof_address.to_root_bytes(); final_key.extend_from_slice(&leaf_hash); @@ -280,9 +283,12 @@ async fn generate_proof( let block_number = header.number; // Prepare storage proof - let processed_storage_proof = - prepare_proof_for_circuit(read_proof.proof, hex::encode(header.state_root.0), leaf_hash) - .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + let processed_storage_proof = prepare_proof_for_circuit( + read_proof.proof.iter().map(|proof| proof.0.clone()).collect(), + hex::encode(header.state_root.0), + leaf_hash, + ) + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; let inputs = CircuitInputs { private: PrivateCircuitInputs { @@ -305,6 +311,7 @@ async fn generate_proof( .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?, parent_hash, block_number, + asset_id: 0, }, }; @@ -340,108 +347,3 @@ async fn at_best_block( let block = quantus_client.client().blocks().at(best_block).await?; Ok(block) } - -// Utility functions from proof-utils.rs -fn hash_node_with_poseidon_padded(node_bytes: &[u8]) -> [u8; 32] { - use qp_poseidon_core::{hash_padded_bytes, FIELD_ELEMENT_PREIMAGE_PADDING_LEN}; - hash_padded_bytes::(node_bytes) -} - -fn prepare_proof_for_circuit( - proof: Vec, - state_root: String, - leaf_hash: [u8; 32], -) -> anyhow::Result { - let mut node_map: std::collections::HashMap, String)> = - std::collections::HashMap::new(); - for (idx, node) in proof.iter().enumerate() { - let hash = hash_node_with_poseidon_padded(&node.0); - let hash_hex = hex::encode(hash); - let node_hex = hex::encode(&node.0); - node_map.insert(hash_hex.clone(), (idx, node.0.clone(), node_hex)); - } - - let state_root_hex = state_root.trim_start_matches("0x").to_string(); - - let root_hash = if node_map.contains_key(&state_root_hex) { - state_root_hex.clone() - } else { - anyhow::bail!("No node hashes to state root!"); - }; - - let root_entry = node_map - .get(&root_hash) - .ok_or_else(|| anyhow!("Failed to get root entry from map"))?; - - let mut ordered_nodes = vec![root_entry.1.clone()]; - let mut current_node_hex = root_entry.2.clone(); - - const HASH_LENGTH_PREFIX: &str = "2000000000000000"; - - loop { - let mut found_child = None; - for (child_hash, (_, child_bytes, _)) in &node_map { - let hash_with_prefix = format!("{}{}", HASH_LENGTH_PREFIX, child_hash); - if current_node_hex.contains(&hash_with_prefix) { - if !ordered_nodes.iter().any(|n| n == child_bytes) { - found_child = Some((child_hash.clone(), child_bytes.clone())); - break; - } - } - } - - if let Some((_, child_bytes)) = found_child { - ordered_nodes.push(child_bytes.clone()); - current_node_hex = hex::encode(ordered_nodes.last().unwrap()); - } else { - break; - } - } - - let mut indices = Vec::::new(); - - for i in 0..ordered_nodes.len() - 1 { - let current_hex = hex::encode(&ordered_nodes[i]); - let next_node = &ordered_nodes[i + 1]; - let next_hash = hex::encode(hash_node_with_poseidon_padded(next_node)); - - if let Some(hex_idx) = current_hex.find(&next_hash) { - indices.push(hex_idx); - } else { - anyhow::bail!("Could not find child hash in ordered node {}", i); - } - } - - let (found, last_idx) = check_leaf(&leaf_hash, ordered_nodes.last().unwrap().clone()); - if !found { - anyhow::bail!("Leaf hash suffix not found in leaf node!"); - } - - indices.push(last_idx); - - if indices.len() != ordered_nodes.len() { - log_verbose!( - "Warning: indices.len() = {}, ordered_nodes.len() = {}", - indices.len(), - ordered_nodes.len() - ); - } - - qp_wormhole_circuit::storage_proof::ProcessedStorageProof::new(ordered_nodes, indices) -} - -fn check_leaf(leaf_hash: &[u8; 32], leaf_node: Vec) -> (bool, usize) { - let hash_suffix = &leaf_hash[8..32]; - let mut last_idx = 0usize; - let mut found = false; - - for i in 0..=leaf_node.len().saturating_sub(hash_suffix.len()) { - if &leaf_node[i..i + hash_suffix.len()] == hash_suffix { - last_idx = i; - found = true; - break; - } - } - - (found, (last_idx * 2).saturating_sub(16)) -} diff --git a/src/quantus_metadata.scale b/src/quantus_metadata.scale index f17e3cba4c7431e58fa78ad61f5c5d1daeb21422..b0c4f05f1457a99ebd9620348d85a34a0c73b4d8 100644 GIT binary patch delta 3519 zcma)94Nz5O8vdU59^i_YS3!O+c|kN$BS1?iXd=bwW`Y7z{uCYI5O;uk@%|u~){^1x zn$Quyp_P&uQQ3`l$Axd)}Y>+WzSM-O-VaT2OV24o3dNhOdu*X$z3j1H3F(ZAXgU9yv!j0UVO* z86@iOL}t(sEm?e=0j9y$Iyhi8)h@vOAt7n9=>(0%-BP65y@H`XBE_>YRXi3ho?8vgMQ zy6?`X!qXQgMBN%zkRF@A7@hj^{7iIh3*{T3e0&v`7*o-#`8~C*RhxYN#yVevR@LP9 z`Dzu}R)WN-LKFo3sy9%p`K!EYP~W#|mVDfa=<@9Q)dtmDt(DdmRNO0|yjL+U=3+5V zv*rr=>NRh`rFv^zfuPT?xhz;$tFI#K|S^GEa`S4?SZ95=JQQEkn-DW zJ6O^`WCOiw>oRo8-e7un2v7!&`^r}&HIRy>sG>z9$B&-vyFFGVjIwF zl$0R^^vSo&(TQGJS%K}@eNYn1v_PmKXjdxG52YA`fZbkNuZVsK{>2pg{fZdmIbZ!U zW;F^hAl<7mn+Kmc49c$6$Vy;wJ2IMlfnb%#TkGow9Bv-<-g(J5VQOYLDzTO@q_28C z-PrpGo&u5N1wzZZXH2zKC&Ai#Zt4pF2BKo_qotMh#~j{zbM?*!7OH z@p67W-lGp7i#|cJOsYhTF|z^ZBAD8@Tud_J{n%~8N3u7B79NtDk&bh+uo;!EbFdd| z45{8=C{X1Od4rxt%~=*6O>ds>QjuW1+l-wt_(Ya(Lme*2$DT!&ytoa4@cbnnzI_%y z;^FCbTiwH=F<&w+zhR7(4HIB-cXYD|*39Hsc&JZCpuhICv(a&)ui4Jt~7K#V-K z9a*tUODyhA5Y4aEIP}k^Ez+|;oVxfrS*v}lWj5}sxclx2$tC71KKA=8;!eEf^>O;G zhn@Q8({l6w2dD7^FiGgEZcW42a>@>@o<7FRB9P!qD0YWKM9AO{ti>ex{tm>aP9h~{ ziEk5|gefEx!8c*uB1lY=v=i$wLspqXl6+$)=J1fS8(Dd&Bw~>0HB@GLzNkyjAcQfqm^6YNR3)?qCI`&}l z#5`vY9%Qy}*@Jr*=3KY?PSb9_3F}7rB=}-q6_P^~^2}!EPj*pcT-t-5+NhZHvlJ%> z_F=|yH)RyJ1pOXwz*EiXl4CTnPE%_%znhTwfHf1Ct4)Xmx(IodT6Mv-MXbG>>=_%I zs^p?lEQLdEF2x$+%*%Ti&JHX?(gKw<@=zmfq*mHWZPZSCsgr~%A9^0ihTe&nV&%t& zk(u@Ics^cfrsHtfYkuB~vnu=5q%Hrt*d*RSbRRg%CsEpmjQAc>%GqMk$6A}}ae5X# zq?fKwkcayChzjMe`;axYm*6bZ)PT<$5TZByefklkPwF!vdr0&%WKR6RINIP1XaiyC zpB#ZJwve3Tc^ZlAF}tUxP@Xx0%t?bL%m9fK7R=B%%&8k-hDiT3IbC{=;+EJ8_%6%^ zx%()RC!I23hDZ!sFsH|1MsI*QeH|ulnU5mQku5}`SR!*bV)RR`CqMwYc|RfkENaH(okglrqbZ8Cj~bHPUG9^(x|vSEzM)0p9#uuZ}59PYT>X;XKek0^So zk}R*<$bllmp-`U!SrSk0aN`u8K%FQyjwMi(0;lnd6v|iF(-&vb74*x$yQrW2 z(ve1492ak<(OhF$I%O$bjYD(j5l%E`=1>ntjE39jFHx+t5XM7y&@67hjHV*`rGg$~ z_A*L|zzL&hIsMzlZA^YCt-_G8rR?d+!xR;X z4~)%^Qjoh129Q;VC~QvqIf|%3lqHJl!O`@JhdLp z9{?0mT&7}+CgRRYw%pFrYGuD76yQKQ&6q#Yu)2cdO>V$7cY`ljH__{wO|I3H1~O%4 zI;AXBj=3ffT~@nb^}XD&UF&_XLkaAKz-9S`pZ1ln;Z3h8V|5kTO2>Dxf~`%OE5xR_ zJYK80R-e#B0+%%<;;TQcB1J6VfQxa&B|2Rha~H@L19WC#%l|JYowR>}V+ptEF;4zF zU=|p0yWAS2LKMr_gS6P@rbp%FAf4n)^m2%b6-{v*mOl?syfL|%UI0Au$R^rPZjuEp zbdRl7>5`jUs6M)w9NaUgt;#O>SquF$Zm(hwwydDJ8ybAo^;LChpl(s8@ntJ5A#-is z7TUt>II)G&!0hydVU%A3~k1svF{m5;Re|F**5wD Xwqd2)IMhy$ndG^;lk#92QN(`%aV8*t delta 3133 zcmZuz3vg7`89v{?C&?0{-H6qHIrW%LPNz-_XV{|gQ<1j70Mtrp@b;?v*8Fj?AR?+@>HbpdzX%{Nyx zCf2H(1Z+)uD161Nr#a$p^7%J4Xl*8l11{cGskLf;hL|K<%#(A>qn%sKvz^j*P8TT6mZ{`pi&D$#J2V?p(s>g7jofH!<|@6%c1_$iPh*<&0Z8z z57e2L;Z~#PF_DF}J(aKi?u8e9>P!b_80(f{FVJtCS&j%WpjOr*ihlJ$E%v(yARR08 zP^2|%m30_|tilLjwR$&8F$lq5R#h-4#R${<52|0(p&Uc%&O^vmAJ-w9Y1Cr|M%2uD zluqV7Rupdugu)Fze{*0EuvK#(%bJzP_QaAIzpBR?qEV>bZ=fjlk2zV!^{dc^$zy

I6mR(Wn%Yi->TH-=X8rIc+g3eh5UW;Zn#A~B@!ynAqBN0z3GM-Xo z{GuXF%0ObARAhooDiWtu$tLW>E5`9n_!r?7)qfZMhSSEO&5-GM%Xn}rer>@!>V^o~ zxjPoYbo^Dl6v0aFuG@xbbQbEB^Kcj&wqbu3K2&FaiWZzxpX^1cx_d7|N%|4)I``o| z?y@^D7oV!d9k@w;4m_N2HTClj*yvNl0!0q>dX4@%J&2t7g(R}z@UvxWt%U?rkU4=Z zdQc1d0{)9r#ci6uNn_{Qk>F7e9AeP>WbSnw|`Qa+aCMuY+Sb51RswlRn(ryeKL6-&9%Gm|Gs_lfmGK%7= z_HfYW5BVB78nCTja$HB!aRprZw=AJ3!Lw3tEWfyEq2Y~U117sP(#c0{w3T+yJ+y~9 z=qL$IWyg?boOuY3|heUq@)NLO~;SFAfH(>I6aw@1G6-nXX zYg&Cx6>9V2D9Ic&F$PEsr7%WP7$+{n7*U-AD4TK)-^Dn`v4!Kg>iY~iSBVoQ)Ch^u z6x3J>>f~imV@as^72?F{5)_HJ`gj1dCZ04A$4H#wUfSG3I1J|#SR+wk>^hE(Ssd-( zeF`jUud(4B+{{s5^}LH}qu^P9u43mXhRv_F>Dh*B47;XquwnMu#!GMG0YW^rCvNW9 zm6?{37Gz9&5BsL7<6of&F7@hHcu&20fy2dW_4x(dj`iw?U!!EDCZ!|k2c|c!m$2II z2>5k2I9qL?O_yT5OvG57`7VXzPL9Yv=1oN8PG(L8WM7imr=I;9x1mj0zu^P7s@dPL zEj;rziqxiW@IFuQ^7QUj@*>jxG|j+{?)Pa{*$ye4m32W~uhF(x<&RN8awR-$Sobh$ zqMz{2B;3{h7Cp!TX|Wd8ggBVMSI>iPbRQijcT`?3c+|ulFL^Y% zbt%zt&SPH^&A6p!+za(y`9i(POPd|_u^S`=^z=*7uhv>^yH|eLSOA7g@vrcId%5iJXZ|fW9x8++%T->$D ztid4MPV;RNpV41L-DPS2!O9GpsB)XQGAsD=7s1v&e89ND31mDB18+E(o-MOo9>9Tw)&cV zdN2e?l1|o-z)=X!zvsjB;M96^Vlrn1nRfoonLy*yVUCudNF&BZ4pZdMS@6Z#zv=*S6CfXvWfZ8V2;A?WC^E zC}fLsiO=r~#XiyPYIrA2vqWT6y|$A!XI7JqbE_7S9jba4eUf`nTEp!% Date: Wed, 17 Dec 2025 18:20:02 +0600 Subject: [PATCH 08/22] Fix submit transaction --- src/cli/wormhole.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index f4f4278..3bb6e30 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -82,7 +82,7 @@ pub async fn handle_wormhole_command( password, password_file, output, - } => { + } => generate_proof( secret, amount, @@ -93,8 +93,7 @@ pub async fn handle_wormhole_command( output, node_url, ) - .await - }, + .await, } } @@ -201,7 +200,7 @@ async fn generate_proof( private_key: keypair.private_key.clone(), }; - submit_transaction(&quantus_client, &quantum_keypair, transfer_tx, None) + submit_transaction(&quantus_client, &quantum_keypair, transfer_tx, None, false) .await .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; From 08fdc0cedd9f48660420fafeecaed4bd29691a7a Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:22:21 +0600 Subject: [PATCH 09/22] taplo fmt --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2d83d3f..7ce8f2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,7 @@ qp-rusty-crystals-hdwallet = { version = "1.0.0" } qp-poseidon = { version = "1.0.1", features = [ "serde", ] } +qp-poseidon-core = { version = "1.0.4", default-features = false, features = ["p2", "p3"] } qp-dilithium-crypto = { version = "0.2.0", features = ["serde"] } # Blockchain and RPC client @@ -75,7 +76,6 @@ qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/zk-circuits", qp-wormhole-prover = { git = "https://github.com/Quantus-Network/zk-circuits", branch = "feat/asset-id-wormhole", default-features = false } qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/zk-circuits", branch = "feat/asset-id-wormhole", default-features = false } qp-plonky2 = { version = "1.1.3", default-features = false, features = ["no_random"] } -qp-poseidon-core = { git = "https://github.com/Quantus-Network/qp-poseidon", branch = "feat/transfer-proof-asset-id", default-features = false, features = ["p2", "p3"] } [dev-dependencies] tempfile = "3.8" From 6c849c1cbc50c1576bd3a19ea4fd85728f27455f Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:22:39 +0600 Subject: [PATCH 10/22] Version bumps --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7ce8f2b..a984ad3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ aes-gcm = "0.10" # AES-256-GCM (quantum-safe with 256-bit keys) # Quantus crypto dependencies qp-rusty-crystals-dilithium = { version = "2.0.0" } qp-rusty-crystals-hdwallet = { version = "1.0.0" } -qp-poseidon = { version = "1.0.1", features = [ +qp-poseidon = { version = "1.0.4", features = [ "serde", ] } qp-poseidon-core = { version = "1.0.4", default-features = false, features = ["p2", "p3"] } From b5a03977223392718ff5bca04aacb90a8ac9ae7c Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Thu, 18 Dec 2025 12:05:47 +0600 Subject: [PATCH 11/22] Update Cargo.lock --- Cargo.lock | 48 +++++++++++------------------------------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55835b9..1c54eb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3754,7 +3754,7 @@ dependencies = [ "plonky2_maybe_rayon", "plonky2_util", "qp-plonky2-field", - "qp-poseidon-constants 1.0.1", + "qp-poseidon-constants", "rand 0.8.5", "serde", "static_assertions", @@ -3779,15 +3779,15 @@ dependencies = [ [[package]] name = "qp-poseidon" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0353086f7af1df7d45a1ecb995cf84b583c8211d7122f542044b37388b5effcd" +checksum = "f124a93e98e6f1b42b18728c80d529e353b4ed09665477693026fdbb7bc8b523" dependencies = [ "log", "p3-field", "p3-goldilocks", "parity-scale-codec", - "qp-poseidon-core 1.0.3", + "qp-poseidon-core", "scale-info", "serde", "sp-core", @@ -3809,44 +3809,18 @@ dependencies = [ "rand_chacha 0.9.0", ] -[[package]] -name = "qp-poseidon-constants" -version = "1.0.2" -source = "git+https://github.com/Quantus-Network/qp-poseidon?branch=feat%2Ftransfer-proof-asset-id#9ae96dea18464d6ea43de5c78a066f9d1f17b801" -dependencies = [ - "p3-field", - "p3-goldilocks", - "p3-poseidon2", - "rand 0.9.2", - "rand_chacha 0.9.0", -] - [[package]] name = "qp-poseidon-core" -version = "1.0.2" -source = "git+https://github.com/Quantus-Network/qp-poseidon?branch=feat%2Ftransfer-proof-asset-id#9ae96dea18464d6ea43de5c78a066f9d1f17b801" -dependencies = [ - "p3-field", - "p3-goldilocks", - "p3-poseidon2", - "p3-symmetric", - "qp-plonky2", - "qp-poseidon-constants 1.0.2", - "rand_chacha 0.9.0", -] - -[[package]] -name = "qp-poseidon-core" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52c70df221c356b3ce63afabfae623aae632c27d3e078cd20eec4348096c2d7" +checksum = "9e513413affb8c745e368503b50b629e4b2f764e15b1622b8980eec20fbfccfd" dependencies = [ "p3-field", "p3-goldilocks", "p3-poseidon2", "p3-symmetric", "qp-plonky2", - "qp-poseidon-constants 1.0.1", + "qp-poseidon-constants", "rand_chacha 0.9.0", ] @@ -3872,7 +3846,7 @@ dependencies = [ "hex", "hex-literal", "nam-tiny-hderive", - "qp-poseidon-core 1.0.3", + "qp-poseidon-core", "qp-rusty-crystals-dilithium", "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -3889,7 +3863,7 @@ dependencies = [ "anyhow", "hex", "qp-plonky2", - "qp-poseidon-core 1.0.3", + "qp-poseidon-core", "qp-zk-circuits-common", ] @@ -3912,7 +3886,7 @@ dependencies = [ "anyhow", "hex", "qp-plonky2", - "qp-poseidon-core 1.0.3", + "qp-poseidon-core", "serde", ] @@ -3935,7 +3909,7 @@ dependencies = [ "qp-dilithium-crypto", "qp-plonky2", "qp-poseidon", - "qp-poseidon-core 1.0.2", + "qp-poseidon-core", "qp-rusty-crystals-dilithium", "qp-rusty-crystals-hdwallet", "qp-wormhole-circuit", From 66ba31de67b6585028720da90145398510d4f79e Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Thu, 18 Dec 2025 16:53:41 +0600 Subject: [PATCH 12/22] clippy --- src/cli/wormhole.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index 3bb6e30..8029188 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -82,7 +82,7 @@ pub async fn handle_wormhole_command( password, password_file, output, - } => + } => { generate_proof( secret, amount, @@ -93,7 +93,8 @@ pub async fn handle_wormhole_command( output, node_url, ) - .await, + .await + }, } } @@ -125,8 +126,8 @@ async fn generate_proof( })?; // Parse exit account - let exit_account_id = if exit_account_str.starts_with("0x") { - let exit_account_bytes = hex::decode(&exit_account_str[2..]).map_err(|e| { + let exit_account_id = if let Some(exit_account) = exit_account_str.strip_prefix("0x") { + let exit_account_bytes = hex::decode(exit_account).map_err(|e| { crate::error::QuantusError::Generic(format!("Invalid exit account hex: {}", e)) })?; if exit_account_bytes.len() != 32 { From 056b448d2c2f3f463c4cce0a71a5c12da0fa2f26 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Thu, 18 Dec 2025 16:57:11 +0600 Subject: [PATCH 13/22] Bump versions, fix lock file --- Cargo.lock | 8 ++++---- Cargo.toml | 4 ++-- src/cli/wormhole.rs | 5 ++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c54eb5..584ab37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3779,9 +3779,9 @@ dependencies = [ [[package]] name = "qp-poseidon" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f124a93e98e6f1b42b18728c80d529e353b4ed09665477693026fdbb7bc8b523" +checksum = "5029d1c8223c0312a0247ebc745c5b09622dcbebe104f0fdb9de358b87ef032a" dependencies = [ "log", "p3-field", @@ -3811,9 +3811,9 @@ dependencies = [ [[package]] name = "qp-poseidon-core" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e513413affb8c745e368503b50b629e4b2f764e15b1622b8980eec20fbfccfd" +checksum = "71dd1bf5d2997abf70247fcd23c8f04d7093b1faf33b775a42fb00c07e0a0e05" dependencies = [ "p3-field", "p3-goldilocks", diff --git a/Cargo.toml b/Cargo.toml index a984ad3..83313a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,10 +51,10 @@ aes-gcm = "0.10" # AES-256-GCM (quantum-safe with 256-bit keys) # Quantus crypto dependencies qp-rusty-crystals-dilithium = { version = "2.0.0" } qp-rusty-crystals-hdwallet = { version = "1.0.0" } -qp-poseidon = { version = "1.0.4", features = [ +qp-poseidon = { version = "1.0.5", features = [ "serde", ] } -qp-poseidon-core = { version = "1.0.4", default-features = false, features = ["p2", "p3"] } +qp-poseidon-core = { version = "1.0.5", default-features = false, features = ["p2", "p3"] } qp-dilithium-crypto = { version = "0.2.0", features = ["serde"] } # Blockchain and RPC client diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index 8029188..2386964 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -82,7 +82,7 @@ pub async fn handle_wormhole_command( password, password_file, output, - } => { + } => generate_proof( secret, amount, @@ -93,8 +93,7 @@ pub async fn handle_wormhole_command( output, node_url, ) - .await - }, + .await, } } From b7d6b1ea197dc5ba6ea6c8f8bdf056aafe47d421 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Sat, 10 Jan 2026 21:58:26 +0600 Subject: [PATCH 14/22] Bump versions for crates --- Cargo.lock | 15 +++++++++------ Cargo.toml | 6 +++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 584ab37..9104ee9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3857,8 +3857,9 @@ dependencies = [ [[package]] name = "qp-wormhole-circuit" -version = "0.1.4" -source = "git+https://github.com/Quantus-Network/zk-circuits?branch=feat%2Fasset-id-wormhole#b97f33e7db8d4f07d6817883e434c86565959046" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcbccee20e314a1c52f36d8e78b1fa8205da46050c18da60d4964f41875bd4f6" dependencies = [ "anyhow", "hex", @@ -3869,8 +3870,9 @@ dependencies = [ [[package]] name = "qp-wormhole-prover" -version = "0.1.4" -source = "git+https://github.com/Quantus-Network/zk-circuits?branch=feat%2Fasset-id-wormhole#b97f33e7db8d4f07d6817883e434c86565959046" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd377a2fa936e6edb069ffecbf41afe10803b342e5cda8ff3aab199f77fde5d" dependencies = [ "anyhow", "qp-plonky2", @@ -3880,8 +3882,9 @@ dependencies = [ [[package]] name = "qp-zk-circuits-common" -version = "0.1.4" -source = "git+https://github.com/Quantus-Network/zk-circuits?branch=feat%2Fasset-id-wormhole#b97f33e7db8d4f07d6817883e434c86565959046" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445cc21c39959d1b553c4d8ea94d058ceab84cd70e5d47ec82b11535494cec46" dependencies = [ "anyhow", "hex", diff --git a/Cargo.toml b/Cargo.toml index 83313a2..230b43b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,9 +72,9 @@ subxt-metadata = "0.43.0" # ZK proof generation anyhow = "1.0" -qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/zk-circuits", branch = "feat/asset-id-wormhole", default-features = false } -qp-wormhole-prover = { git = "https://github.com/Quantus-Network/zk-circuits", branch = "feat/asset-id-wormhole", default-features = false } -qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/zk-circuits", branch = "feat/asset-id-wormhole", default-features = false } +qp-wormhole-circuit = { version = "0.1.7", default-features = false } +qp-wormhole-prover = { version = "0.1.7", default-features = false } +qp-zk-circuits-common = { version = "0.1.7", default-features = false } qp-plonky2 = { version = "1.1.3", default-features = false, features = ["no_random"] } [dev-dependencies] From 94fd940efc2218415b420bd857143164ec2c9958 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Fri, 16 Jan 2026 23:32:07 +0600 Subject: [PATCH 15/22] Fix merge conflicts --- src/cli/wormhole.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index 2386964..0ab84d9 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -1,10 +1,9 @@ use crate::{ chain::{ client::{ChainConfig, QuantusClient}, - quantus_subxt as quantus_node, - quantus_subxt::api::wormhole, + quantus_subxt::{self as quantus_node, api::wormhole}, }, - cli::common::submit_transaction, + cli::common::{submit_transaction, ExecutionMode}, log_print, log_success, log_verbose, wallet::QuantumKeyPair, }; @@ -200,9 +199,15 @@ async fn generate_proof( private_key: keypair.private_key.clone(), }; - submit_transaction(&quantus_client, &quantum_keypair, transfer_tx, None, false) - .await - .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + submit_transaction( + &quantus_client, + &quantum_keypair, + transfer_tx, + None, + ExecutionMode { finalized: false, wait_for_transaction: true }, + ) + .await + .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; let blocks = at_best_block(&quantus_client) .await From aa55a0867d69e483a196b47cd141f3c4b0bcd572 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Sat, 17 Jan 2026 01:28:28 +0600 Subject: [PATCH 16/22] Add verify command --- .gitignore | 3 +- Cargo.lock | 8 +- Cargo.toml | 4 +- src/chain/quantus_subxt.rs | 244 +++++++++++++++++++++++-------------- src/cli/wormhole.rs | 93 +++++++++++++- src/quantus_metadata.scale | Bin 167060 -> 167504 bytes 6 files changed, 249 insertions(+), 103 deletions(-) diff --git a/.gitignore b/.gitignore index 2a0038a..1b9cbf1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target -.idea \ No newline at end of file +.idea +*.hex diff --git a/Cargo.lock b/Cargo.lock index 9104ee9..1947458 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3779,9 +3779,9 @@ dependencies = [ [[package]] name = "qp-poseidon" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5029d1c8223c0312a0247ebc745c5b09622dcbebe104f0fdb9de358b87ef032a" +checksum = "fef3bb816fc51b4ffc4524fa03376037d2531b17e2349ef6489a417cef029b3a" dependencies = [ "log", "p3-field", @@ -3811,9 +3811,9 @@ dependencies = [ [[package]] name = "qp-poseidon-core" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71dd1bf5d2997abf70247fcd23c8f04d7093b1faf33b775a42fb00c07e0a0e05" +checksum = "e33b3fb9032ac9b197265da8fc8bdedd21ba76592ceefbf4a591286d47baec2d" dependencies = [ "p3-field", "p3-goldilocks", diff --git a/Cargo.toml b/Cargo.toml index 230b43b..8e7b3f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,10 +51,10 @@ aes-gcm = "0.10" # AES-256-GCM (quantum-safe with 256-bit keys) # Quantus crypto dependencies qp-rusty-crystals-dilithium = { version = "2.0.0" } qp-rusty-crystals-hdwallet = { version = "1.0.0" } -qp-poseidon = { version = "1.0.5", features = [ +qp-poseidon = { version = "1.0.6", features = [ "serde", ] } -qp-poseidon-core = { version = "1.0.5", default-features = false, features = ["p2", "p3"] } +qp-poseidon-core = { version = "1.0.6", default-features = false, features = ["p2", "p3"] } qp-dilithium-crypto = { version = "0.2.0", features = ["serde"] } # Blockchain and RPC client diff --git a/src/chain/quantus_subxt.rs b/src/chain/quantus_subxt.rs index c8aa097..05e2ec8 100644 --- a/src/chain/quantus_subxt.rs +++ b/src/chain/quantus_subxt.rs @@ -1471,9 +1471,9 @@ pub mod api { "query_call_info", types::QueryCallInfo { call, len }, [ - 86u8, 229u8, 66u8, 90u8, 9u8, 192u8, 94u8, 166u8, 53u8, 95u8, 117u8, - 12u8, 3u8, 4u8, 189u8, 7u8, 73u8, 230u8, 139u8, 35u8, 5u8, 109u8, - 158u8, 162u8, 231u8, 1u8, 128u8, 220u8, 143u8, 156u8, 31u8, 122u8, + 144u8, 69u8, 76u8, 20u8, 225u8, 168u8, 95u8, 163u8, 136u8, 202u8, 72u8, + 27u8, 234u8, 2u8, 87u8, 1u8, 106u8, 223u8, 192u8, 30u8, 20u8, 233u8, + 167u8, 128u8, 112u8, 225u8, 153u8, 125u8, 248u8, 228u8, 53u8, 167u8, ], ) } @@ -1491,9 +1491,10 @@ pub mod api { "query_call_fee_details", types::QueryCallFeeDetails { call, len }, [ - 181u8, 7u8, 183u8, 151u8, 247u8, 92u8, 240u8, 27u8, 40u8, 192u8, 150u8, - 16u8, 176u8, 113u8, 208u8, 17u8, 253u8, 72u8, 92u8, 180u8, 153u8, - 179u8, 32u8, 229u8, 61u8, 136u8, 33u8, 123u8, 48u8, 172u8, 216u8, 8u8, + 86u8, 238u8, 23u8, 213u8, 191u8, 145u8, 151u8, 110u8, 183u8, 238u8, + 148u8, 145u8, 134u8, 41u8, 240u8, 193u8, 187u8, 232u8, 19u8, 217u8, + 179u8, 188u8, 8u8, 191u8, 23u8, 18u8, 155u8, 52u8, 12u8, 169u8, 221u8, + 101u8, ], ) } @@ -2004,9 +2005,9 @@ pub mod api { .hash(); runtime_metadata_hash == [ - 92u8, 199u8, 247u8, 245u8, 15u8, 124u8, 69u8, 52u8, 138u8, 213u8, 161u8, 230u8, - 234u8, 254u8, 189u8, 183u8, 200u8, 237u8, 73u8, 35u8, 183u8, 80u8, 71u8, 120u8, - 128u8, 234u8, 140u8, 160u8, 131u8, 172u8, 255u8, 32u8, + 188u8, 39u8, 127u8, 207u8, 32u8, 174u8, 40u8, 37u8, 8u8, 103u8, 134u8, 90u8, 25u8, + 13u8, 113u8, 231u8, 42u8, 35u8, 1u8, 219u8, 62u8, 142u8, 175u8, 90u8, 219u8, 204u8, + 82u8, 53u8, 187u8, 156u8, 226u8, 105u8, ] } pub mod system { @@ -5388,10 +5389,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 203u8, 72u8, 88u8, 39u8, 226u8, 214u8, 8u8, 216u8, 109u8, 243u8, 223u8, - 189u8, 193u8, 191u8, 45u8, 189u8, 20u8, 195u8, 62u8, 97u8, 210u8, - 214u8, 151u8, 193u8, 31u8, 108u8, 69u8, 46u8, 140u8, 222u8, 228u8, - 169u8, + 168u8, 100u8, 48u8, 116u8, 163u8, 192u8, 242u8, 52u8, 119u8, 87u8, + 194u8, 233u8, 96u8, 99u8, 148u8, 199u8, 189u8, 152u8, 42u8, 69u8, + 195u8, 93u8, 2u8, 53u8, 139u8, 85u8, 19u8, 63u8, 251u8, 30u8, 244u8, + 30u8, ], ) } @@ -5414,9 +5415,10 @@ pub mod api { weight, }, [ - 64u8, 94u8, 77u8, 108u8, 78u8, 248u8, 236u8, 53u8, 252u8, 34u8, 135u8, - 22u8, 131u8, 225u8, 167u8, 100u8, 56u8, 83u8, 244u8, 9u8, 173u8, 199u8, - 88u8, 108u8, 230u8, 56u8, 106u8, 54u8, 86u8, 235u8, 180u8, 228u8, + 181u8, 252u8, 48u8, 252u8, 226u8, 4u8, 157u8, 205u8, 114u8, 223u8, + 86u8, 149u8, 228u8, 170u8, 164u8, 255u8, 152u8, 191u8, 239u8, 205u8, + 149u8, 126u8, 209u8, 188u8, 197u8, 250u8, 24u8, 208u8, 212u8, 168u8, + 66u8, 131u8, ], ) } @@ -5454,10 +5456,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 8u8, 102u8, 80u8, 179u8, 244u8, 71u8, 31u8, 51u8, 95u8, 97u8, 65u8, - 110u8, 217u8, 40u8, 207u8, 195u8, 130u8, 247u8, 148u8, 175u8, 138u8, - 222u8, 176u8, 210u8, 200u8, 53u8, 95u8, 253u8, 149u8, 73u8, 173u8, - 153u8, + 158u8, 186u8, 229u8, 16u8, 76u8, 224u8, 81u8, 198u8, 111u8, 234u8, + 112u8, 64u8, 248u8, 191u8, 138u8, 69u8, 111u8, 215u8, 204u8, 69u8, + 43u8, 60u8, 173u8, 141u8, 200u8, 113u8, 143u8, 75u8, 33u8, 84u8, 108u8, + 149u8, ], ) } @@ -7535,10 +7537,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 90u8, 168u8, 100u8, 250u8, 215u8, 75u8, 141u8, 146u8, 204u8, 225u8, - 150u8, 231u8, 151u8, 205u8, 65u8, 240u8, 45u8, 2u8, 98u8, 5u8, 141u8, - 255u8, 9u8, 53u8, 135u8, 131u8, 137u8, 181u8, 188u8, 200u8, 250u8, - 108u8, + 98u8, 56u8, 162u8, 148u8, 112u8, 249u8, 195u8, 138u8, 14u8, 208u8, + 216u8, 29u8, 136u8, 77u8, 22u8, 170u8, 181u8, 92u8, 215u8, 105u8, + 123u8, 64u8, 0u8, 48u8, 135u8, 65u8, 103u8, 121u8, 222u8, 161u8, 220u8, + 252u8, ], ) } @@ -7580,10 +7582,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 254u8, 116u8, 223u8, 77u8, 222u8, 118u8, 131u8, 7u8, 35u8, 246u8, - 214u8, 44u8, 105u8, 203u8, 31u8, 211u8, 208u8, 85u8, 63u8, 237u8, 34u8, - 103u8, 3u8, 229u8, 78u8, 119u8, 199u8, 193u8, 131u8, 128u8, 154u8, - 27u8, + 199u8, 176u8, 11u8, 253u8, 206u8, 181u8, 22u8, 109u8, 121u8, 2u8, + 189u8, 149u8, 188u8, 210u8, 81u8, 219u8, 147u8, 140u8, 252u8, 149u8, + 128u8, 248u8, 171u8, 106u8, 7u8, 152u8, 32u8, 65u8, 61u8, 121u8, 175u8, + 153u8, ], ) } @@ -7622,9 +7624,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 67u8, 98u8, 234u8, 203u8, 198u8, 87u8, 76u8, 191u8, 8u8, 128u8, 225u8, - 169u8, 148u8, 200u8, 47u8, 118u8, 216u8, 229u8, 197u8, 38u8, 8u8, 28u8, - 164u8, 63u8, 208u8, 100u8, 156u8, 29u8, 99u8, 179u8, 75u8, 209u8, + 241u8, 149u8, 155u8, 185u8, 58u8, 107u8, 11u8, 188u8, 177u8, 36u8, + 106u8, 40u8, 178u8, 137u8, 85u8, 190u8, 46u8, 56u8, 244u8, 20u8, 150u8, + 238u8, 73u8, 111u8, 151u8, 150u8, 2u8, 133u8, 218u8, 189u8, 95u8, + 109u8, ], ) } @@ -7649,10 +7652,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 147u8, 123u8, 83u8, 248u8, 110u8, 162u8, 244u8, 115u8, 186u8, 216u8, - 98u8, 153u8, 83u8, 198u8, 255u8, 53u8, 20u8, 221u8, 154u8, 224u8, 11u8, - 226u8, 188u8, 40u8, 247u8, 251u8, 57u8, 137u8, 101u8, 147u8, 35u8, - 137u8, + 130u8, 87u8, 248u8, 189u8, 84u8, 139u8, 26u8, 139u8, 35u8, 18u8, 102u8, + 95u8, 127u8, 218u8, 144u8, 149u8, 65u8, 134u8, 86u8, 98u8, 195u8, + 192u8, 79u8, 154u8, 7u8, 232u8, 76u8, 179u8, 255u8, 188u8, 29u8, 191u8, ], ) } @@ -8680,9 +8682,9 @@ pub mod api { "batch", types::Batch { calls }, [ - 247u8, 255u8, 73u8, 140u8, 94u8, 73u8, 225u8, 12u8, 45u8, 234u8, 39u8, - 94u8, 64u8, 54u8, 195u8, 173u8, 213u8, 184u8, 159u8, 251u8, 73u8, 9u8, - 74u8, 229u8, 19u8, 77u8, 36u8, 70u8, 173u8, 166u8, 126u8, 156u8, + 143u8, 230u8, 160u8, 33u8, 51u8, 78u8, 98u8, 70u8, 24u8, 252u8, 53u8, + 95u8, 142u8, 254u8, 85u8, 220u8, 208u8, 135u8, 35u8, 223u8, 159u8, 9u8, + 252u8, 220u8, 43u8, 167u8, 49u8, 44u8, 89u8, 178u8, 227u8, 192u8, ], ) } @@ -8712,9 +8714,10 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 141u8, 234u8, 46u8, 19u8, 175u8, 133u8, 239u8, 49u8, 92u8, 144u8, 18u8, - 166u8, 50u8, 108u8, 96u8, 72u8, 121u8, 82u8, 37u8, 35u8, 128u8, 50u8, - 159u8, 197u8, 203u8, 245u8, 252u8, 230u8, 206u8, 120u8, 145u8, 228u8, + 214u8, 237u8, 32u8, 195u8, 191u8, 195u8, 55u8, 60u8, 99u8, 181u8, + 242u8, 109u8, 51u8, 83u8, 103u8, 100u8, 4u8, 196u8, 130u8, 130u8, + 190u8, 179u8, 224u8, 200u8, 67u8, 61u8, 214u8, 118u8, 5u8, 91u8, 104u8, + 72u8, ], ) } @@ -8740,10 +8743,9 @@ pub mod api { "batch_all", types::BatchAll { calls }, [ - 197u8, 249u8, 16u8, 146u8, 49u8, 44u8, 209u8, 110u8, 241u8, 172u8, - 211u8, 117u8, 251u8, 137u8, 219u8, 157u8, 77u8, 198u8, 95u8, 118u8, - 219u8, 117u8, 174u8, 119u8, 1u8, 103u8, 213u8, 59u8, 201u8, 35u8, 47u8, - 246u8, + 181u8, 57u8, 166u8, 110u8, 27u8, 199u8, 129u8, 206u8, 52u8, 238u8, + 32u8, 165u8, 37u8, 48u8, 103u8, 144u8, 138u8, 34u8, 41u8, 94u8, 246u8, + 41u8, 110u8, 214u8, 14u8, 114u8, 86u8, 44u8, 95u8, 14u8, 201u8, 175u8, ], ) } @@ -8766,10 +8768,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 126u8, 91u8, 53u8, 68u8, 190u8, 43u8, 235u8, 28u8, 47u8, 103u8, 238u8, - 171u8, 70u8, 123u8, 143u8, 153u8, 155u8, 125u8, 45u8, 164u8, 41u8, - 200u8, 56u8, 163u8, 249u8, 150u8, 158u8, 87u8, 125u8, 137u8, 88u8, - 81u8, + 10u8, 157u8, 57u8, 66u8, 109u8, 65u8, 72u8, 193u8, 5u8, 242u8, 129u8, + 169u8, 57u8, 0u8, 3u8, 210u8, 146u8, 49u8, 26u8, 109u8, 117u8, 2u8, + 189u8, 69u8, 186u8, 28u8, 163u8, 235u8, 225u8, 210u8, 111u8, 177u8, ], ) } @@ -8795,9 +8796,9 @@ pub mod api { "force_batch", types::ForceBatch { calls }, [ - 113u8, 196u8, 193u8, 13u8, 222u8, 221u8, 108u8, 232u8, 210u8, 14u8, - 195u8, 2u8, 179u8, 155u8, 190u8, 186u8, 109u8, 98u8, 99u8, 58u8, 59u8, - 133u8, 145u8, 32u8, 186u8, 12u8, 198u8, 85u8, 230u8, 85u8, 247u8, 52u8, + 236u8, 54u8, 180u8, 85u8, 81u8, 119u8, 70u8, 224u8, 73u8, 103u8, 169u8, + 41u8, 191u8, 56u8, 138u8, 114u8, 255u8, 207u8, 13u8, 219u8, 217u8, + 35u8, 131u8, 51u8, 220u8, 168u8, 191u8, 5u8, 98u8, 225u8, 50u8, 137u8, ], ) } @@ -8820,9 +8821,10 @@ pub mod api { weight, }, [ - 78u8, 208u8, 22u8, 102u8, 235u8, 74u8, 42u8, 190u8, 137u8, 216u8, 66u8, - 115u8, 20u8, 245u8, 101u8, 199u8, 156u8, 250u8, 122u8, 200u8, 65u8, - 43u8, 78u8, 60u8, 46u8, 65u8, 119u8, 31u8, 33u8, 170u8, 27u8, 229u8, + 253u8, 207u8, 162u8, 133u8, 214u8, 66u8, 111u8, 171u8, 181u8, 86u8, + 82u8, 24u8, 121u8, 127u8, 80u8, 92u8, 21u8, 81u8, 255u8, 176u8, 61u8, + 95u8, 195u8, 109u8, 197u8, 42u8, 54u8, 204u8, 148u8, 107u8, 212u8, + 236u8, ], ) } @@ -8862,10 +8864,9 @@ pub mod api { fallback: ::subxt::ext::subxt_core::alloc::boxed::Box::new(fallback), }, [ - 223u8, 119u8, 179u8, 217u8, 241u8, 14u8, 29u8, 115u8, 177u8, 237u8, - 205u8, 6u8, 227u8, 113u8, 89u8, 101u8, 97u8, 82u8, 22u8, 191u8, 14u8, - 205u8, 13u8, 198u8, 165u8, 175u8, 152u8, 231u8, 190u8, 54u8, 15u8, - 124u8, + 251u8, 49u8, 108u8, 91u8, 215u8, 66u8, 153u8, 50u8, 76u8, 22u8, 82u8, + 115u8, 88u8, 37u8, 50u8, 69u8, 92u8, 225u8, 34u8, 143u8, 59u8, 13u8, + 222u8, 29u8, 130u8, 66u8, 25u8, 162u8, 78u8, 5u8, 113u8, 244u8, ], ) } @@ -8888,9 +8889,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 135u8, 83u8, 250u8, 68u8, 40u8, 246u8, 6u8, 82u8, 241u8, 47u8, 39u8, - 197u8, 248u8, 48u8, 173u8, 141u8, 28u8, 152u8, 58u8, 51u8, 84u8, 207u8, - 164u8, 66u8, 250u8, 88u8, 12u8, 170u8, 18u8, 81u8, 181u8, 70u8, + 20u8, 7u8, 177u8, 85u8, 1u8, 244u8, 203u8, 254u8, 2u8, 41u8, 209u8, + 209u8, 100u8, 23u8, 237u8, 67u8, 162u8, 62u8, 226u8, 220u8, 77u8, + 112u8, 238u8, 124u8, 247u8, 247u8, 153u8, 8u8, 19u8, 82u8, 84u8, 163u8, ], ) } @@ -16496,9 +16497,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 136u8, 165u8, 225u8, 86u8, 177u8, 169u8, 20u8, 142u8, 186u8, 42u8, - 170u8, 86u8, 16u8, 67u8, 250u8, 64u8, 121u8, 164u8, 33u8, 84u8, 193u8, - 32u8, 144u8, 184u8, 87u8, 18u8, 71u8, 81u8, 107u8, 193u8, 232u8, 170u8, + 62u8, 111u8, 80u8, 232u8, 188u8, 15u8, 202u8, 50u8, 77u8, 223u8, 96u8, + 15u8, 232u8, 213u8, 143u8, 185u8, 200u8, 40u8, 119u8, 120u8, 195u8, + 183u8, 193u8, 129u8, 198u8, 43u8, 220u8, 26u8, 149u8, 14u8, 92u8, 42u8, ], ) } @@ -21128,6 +21129,30 @@ pub mod api { const PALLET: &'static str = "Wormhole"; const CALL: &'static str = "transfer_asset"; } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "Verify an aggregated wormhole proof and process all transfers in the batch"] + pub struct VerifyAggregatedProof { + pub proof_bytes: verify_aggregated_proof::ProofBytes, + } + pub mod verify_aggregated_proof { + use super::runtime_types; + pub type ProofBytes = + ::subxt::ext::subxt_core::alloc::vec::Vec<::core::primitive::u8>; + } + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for VerifyAggregatedProof { + const PALLET: &'static str = "Wormhole"; + const CALL: &'static str = "verify_aggregated_proof"; + } } pub struct TransactionApi; impl TransactionApi { @@ -21185,6 +21210,25 @@ pub mod api { ], ) } + #[doc = "Verify an aggregated wormhole proof and process all transfers in the batch"] + pub fn verify_aggregated_proof( + &self, + proof_bytes: types::verify_aggregated_proof::ProofBytes, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload< + types::VerifyAggregatedProof, + > { + ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + "Wormhole", + "verify_aggregated_proof", + types::VerifyAggregatedProof { proof_bytes }, + [ + 122u8, 42u8, 194u8, 153u8, 22u8, 66u8, 199u8, 173u8, 19u8, 107u8, + 232u8, 147u8, 77u8, 40u8, 115u8, 208u8, 183u8, 77u8, 46u8, 149u8, 56u8, + 225u8, 146u8, 168u8, 49u8, 248u8, 42u8, 195u8, 180u8, 91u8, 75u8, + 102u8, + ], + ) + } } } #[doc = "The `Event` enum of this pallet"] @@ -21198,24 +21242,6 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct ProofVerified { - pub exit_amount: proof_verified::ExitAmount, - } - pub mod proof_verified { - use super::runtime_types; - pub type ExitAmount = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for ProofVerified { - const PALLET: &'static str = "Wormhole"; - const EVENT: &'static str = "ProofVerified"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] pub struct NativeTransferred { pub from: native_transferred::From, pub to: native_transferred::To, @@ -21259,6 +21285,24 @@ pub mod api { const PALLET: &'static str = "Wormhole"; const EVENT: &'static str = "AssetTransferred"; } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct ProofVerified { + pub exit_amount: proof_verified::ExitAmount, + } + pub mod proof_verified { + use super::runtime_types; + pub type ExitAmount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for ProofVerified { + const PALLET: &'static str = "Wormhole"; + const EVENT: &'static str = "ProofVerified"; + } } pub mod storage { use super::runtime_types; @@ -21347,9 +21391,10 @@ pub mod api { "TransferProof", (), [ - 162u8, 38u8, 220u8, 3u8, 188u8, 47u8, 138u8, 210u8, 217u8, 129u8, 26u8, - 172u8, 96u8, 61u8, 145u8, 79u8, 185u8, 128u8, 39u8, 11u8, 94u8, 231u8, - 163u8, 227u8, 139u8, 18u8, 42u8, 47u8, 138u8, 192u8, 119u8, 84u8, + 114u8, 93u8, 194u8, 180u8, 234u8, 160u8, 121u8, 23u8, 201u8, 229u8, + 249u8, 211u8, 159u8, 188u8, 127u8, 128u8, 32u8, 26u8, 209u8, 25u8, + 176u8, 192u8, 221u8, 140u8, 46u8, 26u8, 47u8, 223u8, 210u8, 37u8, + 137u8, 90u8, ], ) } @@ -21371,9 +21416,10 @@ pub mod api { "TransferProof", ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 162u8, 38u8, 220u8, 3u8, 188u8, 47u8, 138u8, 210u8, 217u8, 129u8, 26u8, - 172u8, 96u8, 61u8, 145u8, 79u8, 185u8, 128u8, 39u8, 11u8, 94u8, 231u8, - 163u8, 227u8, 139u8, 18u8, 42u8, 47u8, 138u8, 192u8, 119u8, 84u8, + 114u8, 93u8, 194u8, 180u8, 234u8, 160u8, 121u8, 23u8, 201u8, 229u8, + 249u8, 211u8, 159u8, 188u8, 127u8, 128u8, 32u8, 26u8, 209u8, 25u8, + 176u8, 192u8, 221u8, 140u8, 46u8, 26u8, 47u8, 223u8, 210u8, 37u8, + 137u8, 90u8, ], ) } @@ -27597,6 +27643,12 @@ pub mod api { #[codec(compact)] amount: ::core::primitive::u128, }, + #[codec(index = 3)] + #[doc = "Verify an aggregated wormhole proof and process all transfers in the batch"] + verify_aggregated_proof { + proof_bytes: + ::subxt::ext::subxt_core::alloc::vec::Vec<::core::primitive::u8>, + }, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -27635,6 +27687,14 @@ pub mod api { AssetNotFound, #[codec(index = 11)] SelfTransfer, + #[codec(index = 12)] + AggregatedVerifierNotAvailable, + #[codec(index = 13)] + AggregatedProofDeserializationFailed, + #[codec(index = 14)] + AggregatedVerificationFailed, + #[codec(index = 15)] + InvalidAggregatedPublicInputs, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -27650,15 +27710,13 @@ pub mod api { #[doc = "The `Event` enum of this pallet"] pub enum Event { #[codec(index = 0)] - ProofVerified { exit_amount: ::core::primitive::u128 }, - #[codec(index = 1)] NativeTransferred { from: ::subxt::ext::subxt_core::utils::AccountId32, to: ::subxt::ext::subxt_core::utils::AccountId32, amount: ::core::primitive::u128, transfer_count: ::core::primitive::u64, }, - #[codec(index = 2)] + #[codec(index = 1)] AssetTransferred { asset_id: ::core::primitive::u32, from: ::subxt::ext::subxt_core::utils::AccountId32, @@ -27666,6 +27724,8 @@ pub mod api { amount: ::core::primitive::u128, transfer_count: ::core::primitive::u64, }, + #[codec(index = 2)] + ProofVerified { exit_amount: ::core::primitive::u128 }, } } } diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index 0ab84d9..a43b10a 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -34,6 +34,9 @@ use subxt::{ OnlineClient, }; +/// Native asset id +const NATIVE_ASSET_ID: u32 = 0; + #[derive(Subcommand, Debug)] pub enum WormholeCommands { /// Generate a wormhole proof @@ -66,6 +69,12 @@ pub enum WormholeCommands { #[arg(short, long, default_value = "proof.hex")] output: String, }, + /// Verify a wormhole proof on-chain + Verify { + /// Path to the proof file (hex-encoded) + #[arg(short, long, default_value = "proof.hex")] + proof: String, + }, } pub async fn handle_wormhole_command( @@ -93,9 +102,12 @@ pub async fn handle_wormhole_command( node_url, ) .await, + WormholeCommands::Verify { proof } => verify_proof(proof, node_url).await, } } +pub type TransferProofKey = (u32, u64, AccountId32, AccountId32, u128); + async fn generate_proof( secret_hex: String, funding_amount: u128, @@ -244,11 +256,18 @@ async fn generate_proof( } // Get storage proof - let leaf_hash = qp_poseidon::PoseidonHasher::hash_storage::( - &(event.transfer_count, event.from.clone(), event.to.clone(), event.amount).encode(), + let leaf_hash = qp_poseidon::PoseidonHasher::hash_storage::( + &( + NATIVE_ASSET_ID, + event.transfer_count, + event.from.clone(), + event.to.clone(), + event.amount, + ) + .encode(), ); let proof_address = quantus_node::api::storage().wormhole().transfer_proof(( - 0, + NATIVE_ASSET_ID, event.transfer_count, event.from.clone(), event.to.clone(), @@ -315,7 +334,7 @@ async fn generate_proof( .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?, parent_hash, block_number, - asset_id: 0, + asset_id: NATIVE_ASSET_ID, }, }; @@ -351,3 +370,69 @@ async fn at_best_block( let block = quantus_client.client().blocks().at(best_block).await?; Ok(block) } + +async fn verify_proof(proof_file: String, node_url: &str) -> crate::error::Result<()> { + use subxt::tx::TxStatus; + + log_print!("Verifying wormhole proof on-chain..."); + + // Read proof from file + let proof_hex = std::fs::read_to_string(&proof_file).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to read proof file: {}", e)) + })?; + + let proof_bytes = hex::decode(proof_hex.trim()) + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to decode hex: {}", e)))?; + + log_verbose!("Proof size: {} bytes", proof_bytes.len()); + + // Connect to node + let quantus_client = QuantusClient::new(node_url) + .await + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to connect: {}", e)))?; + + log_verbose!("Connected to node"); + + // Create the verify transaction payload + let verify_tx = quantus_node::api::tx().wormhole().verify_wormhole_proof(proof_bytes); + + log_verbose!("Submitting unsigned verification transaction..."); + + // Submit as unsigned extrinsic + let unsigned_tx = quantus_client.client().tx().create_unsigned(&verify_tx).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to create unsigned tx: {}", e)) + })?; + + let mut tx_progress = unsigned_tx + .submit_and_watch() + .await + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to submit tx: {}", e)))?; + + // Wait for transaction inclusion + while let Some(Ok(status)) = tx_progress.next().await { + log_verbose!("Transaction status: {:?}", status); + match status { + TxStatus::InBestBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + log_success!("Proof verified successfully on-chain!"); + log_verbose!("Included in block: {:?}", block_hash); + return Ok(()); + }, + TxStatus::InFinalizedBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + log_success!("Proof verified successfully on-chain!"); + log_verbose!("Finalized in block: {:?}", block_hash); + return Ok(()); + }, + TxStatus::Error { message } | TxStatus::Invalid { message } => { + return Err(crate::error::QuantusError::Generic(format!( + "Transaction failed: {}", + message + ))); + }, + _ => continue, + } + } + + Err(crate::error::QuantusError::Generic("Transaction stream ended unexpectedly".to_string())) +} diff --git a/src/quantus_metadata.scale b/src/quantus_metadata.scale index b0c4f05f1457a99ebd9620348d85a34a0c73b4d8..a4a9a4e257c4ecd9fdeffc1f89e98c45c2d1744f 100644 GIT binary patch delta 478 zcmaixL2DC16oBWgp_HJeRVhLhANJCM*V?O*QizbIAX*PLGTD8b3{Ga^%xtuR;3<0% zEJRp^o+{$0H(?L{2`%x^AJB_`pqGYrla}nUx5xXw%lF=wZ^b{m#gD&WP=%TFUlpFf zjh9_ABHVt(n@vMa?kGr(s&H@pN?{3}j}dZ(ImNfyv|Cydc8u0x27}S$leNgDL}$3N zAsLH8p=%K~xbs{6H$T==s=@z<$%h`y!`J@)_q(%Y-`A0Hm4Lyt)9ifPe>!`se`l|h z$QTxYCC5EjzRXWv#IWLJa;*ms($6tGj^NSHgA;&f@5+;~agHFfu3fpyh2#xM>?+&I zjg3*#D%q@?OYxpNq19SuQoydUPVOZzgq!!TGgndFObl|e5jCXnE2yf|fkhr$4B*+Yy72<^6Y)W!)!r?Jgn6AFhRNoSFi NuY;^2{T+FSb7#zvtLp#& delta 132 zcmV-~0DJ$?oC=hg3V^f$)J*{lx7AGnN&%B`rAD{pPXX#Smr95MECK)km(GR(8x6l^?|6KtBx6pM0C; Date: Tue, 20 Jan 2026 16:29:20 +0800 Subject: [PATCH 17/22] fix wormhole command --- src/cli/wormhole.rs | 64 +++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index a43b10a..e799096 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -37,6 +37,9 @@ use subxt::{ /// Native asset id const NATIVE_ASSET_ID: u32 = 0; +/// Scale down factor for quantizing amounts (10^10 to go from 12 to 2 decimal places) +const SCALE_DOWN_FACTOR: u128 = 10_000_000_000; + #[derive(Subcommand, Debug)] pub enum WormholeCommands { /// Generate a wormhole proof @@ -90,7 +93,7 @@ pub async fn handle_wormhole_command( password, password_file, output, - } => + } => { generate_proof( secret, amount, @@ -101,7 +104,8 @@ pub async fn handle_wormhole_command( output, node_url, ) - .await, + .await + }, WormholeCommands::Verify { proof } => verify_proof(proof, node_url).await, } } @@ -186,26 +190,14 @@ async fn generate_proof( log_verbose!("Unspendable account: {:?}", &unspendable_account_id); log_verbose!("Exit account: {:?}", &exit_account_id); - // Transfer to unspendable account - let transfer_tx = quantus_node::api::tx().balances().transfer_keep_alive( + // Transfer to unspendable account using wormhole pallet + let transfer_tx = quantus_node::api::tx().wormhole().transfer_native( subxt::ext::subxt_core::utils::MultiAddress::Id(unspendable_account_id.clone()), funding_amount, ); log_verbose!("Submitting transfer to unspendable account..."); - let blocks = at_best_block(&quantus_client) - .await - .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; - let block_hash_pre = blocks.hash(); - - let storage_api = client.storage().at(block_hash_pre); - let transfer_count_previous = storage_api - .fetch(&quantus_node::api::storage().wormhole().transfer_count()) - .await - .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))? - .unwrap_or_default(); - let quantum_keypair = QuantumKeyPair { public_key: keypair.public_key.clone(), private_key: keypair.private_key.clone(), @@ -238,30 +230,29 @@ async fn generate_proof( .find::() .next() .ok_or_else(|| { - crate::error::QuantusError::Generic("No TransferProofStored event found".to_string()) + crate::error::QuantusError::Generic("No NativeTransferred event found".to_string()) })? .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + log_verbose!( + "Transfer event: amount={}, transfer_count={}", + event.amount, + event.transfer_count + ); + + // Get storage proof let storage_api = client.storage().at(block_hash); - let transfer_count = storage_api - .fetch(&quantus_node::api::storage().wormhole().transfer_count()) - .await - .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))? - .unwrap_or_default(); - if transfer_count <= transfer_count_previous { - return Err(crate::error::QuantusError::Generic( - "Transfer count was not incremented".to_string(), - )); - } + // Convert subxt AccountId32 to sp_core AccountId32 for hash_storage + let from_account = AccountId32::new(event.from.0); + let to_account = AccountId32::new(event.to.0); - // Get storage proof let leaf_hash = qp_poseidon::PoseidonHasher::hash_storage::( &( NATIVE_ASSET_ID, event.transfer_count, - event.from.clone(), - event.to.clone(), + from_account.clone(), + to_account.clone(), event.amount, ) .encode(), @@ -313,6 +304,17 @@ async fn generate_proof( ) .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; + // Quantize the funding amount (from 12 decimal places to 2) + // Note: The circuit expects u32 internally but the crates.io version of + // qp-wormhole-circuit still uses u128 in PublicCircuitInputs. + // The actual quantized value must fit in u32. + let funding_amount_quantized: u128 = funding_amount / SCALE_DOWN_FACTOR; + if funding_amount_quantized > u32::MAX as u128 { + return Err(crate::error::QuantusError::Generic( + "Funding amount too large after quantization".to_string(), + )); + } + let inputs = CircuitInputs { private: PrivateCircuitInputs { secret, @@ -326,7 +328,7 @@ async fn generate_proof( digest, }, public: PublicCircuitInputs { - funding_amount, + funding_amount: funding_amount_quantized, nullifier: Nullifier::from_preimage(secret, event.transfer_count).hash.into(), exit_account: BytesDigest::try_from(exit_account_id.as_ref() as &[u8]) .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?, From bebfeac3f8d947adb2f9facf31c4eaf24cb2d471 Mon Sep 17 00:00:00 2001 From: illuzen Date: Tue, 20 Jan 2026 16:57:15 +0800 Subject: [PATCH 18/22] fix ci and add quantization to zk proofs --- .github/workflows/ci.yml | 8 +- Cargo.lock | 107 +++++++++- Cargo.toml | 12 +- src/cli/wormhole.rs | 427 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 521 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4fe258..65107d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,6 +59,8 @@ jobs: - name: Install dependencies (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | + sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list + sudo rm -f /etc/apt/sources.list.d/azure-cli.list sudo apt-get update -yqq sudo apt-get install -yqq --no-install-recommends \ libclang-dev \ @@ -86,6 +88,8 @@ jobs: components: clippy, rust-src - name: Install dependencies run: | + sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list + sudo rm -f /etc/apt/sources.list.d/azure-cli.list sudo apt-get update -yqq sudo apt-get install -yqq --no-install-recommends \ libclang-dev \ @@ -120,6 +124,8 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Install dependencies run: | + sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list + sudo rm -f /etc/apt/sources.list.d/azure-cli.list sudo apt-get update -yqq sudo apt-get install -yqq --no-install-recommends \ libclang-dev \ @@ -133,4 +139,4 @@ jobs: example_name=$(basename "$example" .rs) echo "Checking example: $example_name" cargo check --example "$example_name" --locked - done \ No newline at end of file + done diff --git a/Cargo.lock b/Cargo.lock index 1947458..75c9e0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1112,6 +1112,25 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.12" @@ -1940,8 +1959,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -2090,6 +2111,7 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", + "rayon", "serde", ] @@ -3482,6 +3504,9 @@ name = "plonky2_maybe_rayon" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1e554181dc95243b8d9948ae7bae5759c7fb2502fed28f671f95ef38079406" +dependencies = [ + "rayon", +] [[package]] name = "plonky2_util" @@ -3742,6 +3767,7 @@ checksum = "39530b02faa85964bba211e030afa2d54995b403b0022f88e984c4c65679c4bc" dependencies = [ "ahash", "anyhow", + "getrandom 0.2.16", "hashbrown 0.14.5", "itertools 0.11.0", "keccak-hash 0.8.0", @@ -3756,9 +3782,11 @@ dependencies = [ "qp-plonky2-field", "qp-poseidon-constants", "rand 0.8.5", + "rand_chacha 0.3.1", "serde", "static_assertions", "unroll", + "web-time", ] [[package]] @@ -3771,6 +3799,7 @@ dependencies = [ "itertools 0.11.0", "num", "plonky2_util", + "rand 0.8.5", "rustc_version", "serde", "static_assertions", @@ -3779,9 +3808,9 @@ dependencies = [ [[package]] name = "qp-poseidon" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef3bb816fc51b4ffc4524fa03376037d2531b17e2349ef6489a417cef029b3a" +checksum = "4214ec389bff0c21c6ef815cf0ff00656586344dbe20f6441d23a1a6a7f56e84" dependencies = [ "log", "p3-field", @@ -3811,9 +3840,9 @@ dependencies = [ [[package]] name = "qp-poseidon-core" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b3fb9032ac9b197265da8fc8bdedd21ba76592ceefbf4a591286d47baec2d" +checksum = "0f65766d6de64eff741c7f402002a3322f5e563d53e0e9040aeab4921ff24f2b" dependencies = [ "p3-field", "p3-goldilocks", @@ -3855,24 +3884,47 @@ dependencies = [ "thiserror 2.0.16", ] +[[package]] +name = "qp-wormhole-aggregator" +version = "0.1.7" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" +dependencies = [ + "anyhow", + "qp-plonky2", + "qp-wormhole-circuit", + "qp-wormhole-prover", + "qp-wormhole-verifier", + "qp-zk-circuits-common", + "rayon", + "test-helpers", +] + [[package]] name = "qp-wormhole-circuit" version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbccee20e314a1c52f36d8e78b1fa8205da46050c18da60d4964f41875bd4f6" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" dependencies = [ "anyhow", "hex", "qp-plonky2", - "qp-poseidon-core", "qp-zk-circuits-common", ] [[package]] name = "qp-wormhole-prover" version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd377a2fa936e6edb069ffecbf41afe10803b342e5cda8ff3aab199f77fde5d" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" +dependencies = [ + "anyhow", + "qp-plonky2", + "qp-wormhole-circuit", + "qp-zk-circuits-common", +] + +[[package]] +name = "qp-wormhole-verifier" +version = "0.1.7" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" dependencies = [ "anyhow", "qp-plonky2", @@ -3883,8 +3935,7 @@ dependencies = [ [[package]] name = "qp-zk-circuits-common" version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445cc21c39959d1b553c4d8ea94d058ceab84cd70e5d47ec82b11535494cec46" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" dependencies = [ "anyhow", "hex", @@ -3915,8 +3966,10 @@ dependencies = [ "qp-poseidon-core", "qp-rusty-crystals-dilithium", "qp-rusty-crystals-hdwallet", + "qp-wormhole-aggregator", "qp-wormhole-circuit", "qp-wormhole-prover", + "qp-wormhole-verifier", "qp-zk-circuits-common", "rand 0.9.2", "rpassword", @@ -4013,6 +4066,26 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.17" @@ -5610,6 +5683,18 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "test-helpers" +version = "0.1.7" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" +dependencies = [ + "anyhow", + "hex", + "qp-plonky2", + "qp-wormhole-circuit", + "qp-zk-circuits-common", +] + [[package]] name = "thiserror" version = "1.0.69" diff --git a/Cargo.toml b/Cargo.toml index 8e7b3f5..cd6bcfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,10 +51,10 @@ aes-gcm = "0.10" # AES-256-GCM (quantum-safe with 256-bit keys) # Quantus crypto dependencies qp-rusty-crystals-dilithium = { version = "2.0.0" } qp-rusty-crystals-hdwallet = { version = "1.0.0" } -qp-poseidon = { version = "1.0.6", features = [ +qp-poseidon = { version = "1.0.7", features = [ "serde", ] } -qp-poseidon-core = { version = "1.0.6", default-features = false, features = ["p2", "p3"] } +qp-poseidon-core = { version = "1.0.7", default-features = false, features = ["p2", "p3"] } qp-dilithium-crypto = { version = "0.2.0", features = ["serde"] } # Blockchain and RPC client @@ -72,9 +72,11 @@ subxt-metadata = "0.43.0" # ZK proof generation anyhow = "1.0" -qp-wormhole-circuit = { version = "0.1.7", default-features = false } -qp-wormhole-prover = { version = "0.1.7", default-features = false } -qp-zk-circuits-common = { version = "0.1.7", default-features = false } +qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-wormhole-circuit", default-features = false, features = ["std"] } +qp-wormhole-prover = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-wormhole-prover", default-features = false, features = ["std"] } +qp-wormhole-verifier = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-wormhole-verifier", default-features = false, features = ["std"] } +qp-wormhole-aggregator = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-wormhole-aggregator", default-features = false, features = ["std", "rayon"] } +qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-zk-circuits-common", default-features = false, features = ["std"] } qp-plonky2 = { version = "1.1.3", default-features = false, features = ["no_random"] } [dev-dependencies] diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index e799096..db37709 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -10,12 +10,14 @@ use crate::{ use clap::Subcommand; use plonky2::plonk::{circuit_data::CircuitConfig, proof::ProofWithPublicInputs}; use qp_poseidon::PoseidonHasher; -use qp_wormhole_circuit::{ - inputs::{CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs}, - nullifier::Nullifier, +use qp_wormhole_circuit::inputs::{ + AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, }; +use qp_wormhole_circuit::nullifier::Nullifier; use qp_wormhole_prover::WormholeProver; +use qp_wormhole_verifier::WormholeVerifier; use qp_zk_circuits_common::{ + circuit::{C, D, F}, storage_proof::prepare_proof_for_circuit, utils::{BytesDigest, Digest}, }; @@ -35,10 +37,98 @@ use subxt::{ }; /// Native asset id -const NATIVE_ASSET_ID: u32 = 0; +pub const NATIVE_ASSET_ID: u32 = 0; /// Scale down factor for quantizing amounts (10^10 to go from 12 to 2 decimal places) -const SCALE_DOWN_FACTOR: u128 = 10_000_000_000; +pub const SCALE_DOWN_FACTOR: u128 = 10_000_000_000; + +/// Parse a hex-encoded secret string into a 32-byte array +pub fn parse_secret_hex(secret_hex: &str) -> Result<[u8; 32], String> { + let secret_bytes = hex::decode(secret_hex.trim_start_matches("0x")) + .map_err(|e| format!("Invalid secret hex: {}", e))?; + + if secret_bytes.len() != 32 { + return Err(format!("Secret must be exactly 32 bytes, got {} bytes", secret_bytes.len())); + } + + secret_bytes + .try_into() + .map_err(|_| "Failed to convert secret to 32-byte array".to_string()) +} + +/// Parse an exit account from either hex or SS58 format +pub fn parse_exit_account(exit_account_str: &str) -> Result<[u8; 32], String> { + if let Some(hex_str) = exit_account_str.strip_prefix("0x") { + let bytes = hex::decode(hex_str).map_err(|e| format!("Invalid exit account hex: {}", e))?; + + if bytes.len() != 32 { + return Err(format!("Exit account must be 32 bytes, got {} bytes", bytes.len())); + } + + bytes.try_into().map_err(|_| "Failed to convert exit account".to_string()) + } else { + // Try to parse as SS58 + let account_id = AccountId32::from_ss58check(exit_account_str) + .map_err(|e| format!("Invalid SS58 address: {}", e))?; + + Ok(account_id.into()) + } +} + +/// Quantize a funding amount from 12 decimal places to 2 decimal places +/// Returns an error if the quantized value doesn't fit in u32 +pub fn quantize_funding_amount(amount: u128) -> Result { + let quantized = amount / SCALE_DOWN_FACTOR; + + quantized + .try_into() + .map_err(|_| format!("Funding amount {} too large after quantization", quantized)) +} + +/// Read and decode a hex-encoded proof file +pub fn read_proof_file(path: &str) -> Result, String> { + let proof_hex = + std::fs::read_to_string(path).map_err(|e| format!("Failed to read proof file: {}", e))?; + + hex::decode(proof_hex.trim()).map_err(|e| format!("Failed to decode proof hex: {}", e)) +} + +/// Write a proof to a hex-encoded file +pub fn write_proof_file(path: &str, proof_bytes: &[u8]) -> Result<(), String> { + let proof_hex = hex::encode(proof_bytes); + std::fs::write(path, proof_hex).map_err(|e| format!("Failed to write proof file: {}", e)) +} + +/// Validate aggregation parameters +pub fn validate_aggregation_params( + num_proofs: usize, + depth: usize, + branching_factor: usize, +) -> Result { + if num_proofs == 0 { + return Err("No proofs provided".to_string()); + } + + if branching_factor < 2 { + return Err("Branching factor must be at least 2".to_string()); + } + + if depth == 0 { + return Err("Depth must be at least 1".to_string()); + } + + // Calculate max leaf proofs for given depth and branching factor + let max_leaf_proofs = branching_factor.pow(depth as u32); + + if num_proofs > max_leaf_proofs { + return Err(format!( + "Too many proofs: {} provided, max {} for depth={} branching_factor={}", + num_proofs, max_leaf_proofs, depth, branching_factor + )); + } + + Ok(max_leaf_proofs) +} #[derive(Subcommand, Debug)] pub enum WormholeCommands { @@ -72,12 +162,36 @@ pub enum WormholeCommands { #[arg(short, long, default_value = "proof.hex")] output: String, }, - /// Verify a wormhole proof on-chain + /// Verify a single wormhole proof on-chain Verify { /// Path to the proof file (hex-encoded) #[arg(short, long, default_value = "proof.hex")] proof: String, }, + /// Aggregate multiple wormhole proofs into a single proof + Aggregate { + /// Input proof files (hex-encoded) + #[arg(short, long, num_args = 1..)] + proofs: Vec, + + /// Output file for the aggregated proof (default: aggregated_proof.hex) + #[arg(short, long, default_value = "aggregated_proof.hex")] + output: String, + + /// Tree depth for aggregation (default: 1) + #[arg(long, default_value = "1")] + depth: usize, + + /// Branching factor for aggregation tree (default: 2) + #[arg(long, default_value = "2")] + branching_factor: usize, + }, + /// Verify an aggregated wormhole proof on-chain + VerifyAggregated { + /// Path to the aggregated proof file (hex-encoded) + #[arg(short, long, default_value = "aggregated_proof.hex")] + proof: String, + }, } pub async fn handle_wormhole_command( @@ -107,6 +221,12 @@ pub async fn handle_wormhole_command( .await }, WormholeCommands::Verify { proof } => verify_proof(proof, node_url).await, + WormholeCommands::Aggregate { proofs, output, depth, branching_factor } => { + aggregate_proofs(proofs, output, depth, branching_factor).await + }, + WormholeCommands::VerifyAggregated { proof } => { + verify_aggregated_proof(proof, node_url).await + }, } } @@ -305,15 +425,13 @@ async fn generate_proof( .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?; // Quantize the funding amount (from 12 decimal places to 2) - // Note: The circuit expects u32 internally but the crates.io version of - // qp-wormhole-circuit still uses u128 in PublicCircuitInputs. - // The actual quantized value must fit in u32. - let funding_amount_quantized: u128 = funding_amount / SCALE_DOWN_FACTOR; - if funding_amount_quantized > u32::MAX as u128 { - return Err(crate::error::QuantusError::Generic( - "Funding amount too large after quantization".to_string(), - )); - } + // The circuit expects a u32 value. + let funding_amount_quantized: u32 = + (funding_amount / SCALE_DOWN_FACTOR).try_into().map_err(|_| { + crate::error::QuantusError::Generic( + "Funding amount too large after quantization".to_string(), + ) + })?; let inputs = CircuitInputs { private: PrivateCircuitInputs { @@ -341,7 +459,7 @@ async fn generate_proof( }; log_verbose!("Generating ZK proof..."); - let config = CircuitConfig::standard_recursion_config(); + let config = CircuitConfig::standard_recursion_zk_config(); let prover = WormholeProver::new(config); let prover_next = prover .commit(&inputs) @@ -373,6 +491,283 @@ async fn at_best_block( Ok(block) } +async fn aggregate_proofs( + proof_files: Vec, + output_file: String, + depth: usize, + branching_factor: usize, +) -> crate::error::Result<()> { + use qp_wormhole_aggregator::{ + aggregator::WormholeProofAggregator, circuits::tree::TreeAggregationConfig, + }; + + log_print!("Aggregating {} proofs...", proof_files.len()); + + if proof_files.is_empty() { + return Err(crate::error::QuantusError::Generic("No proof files provided".to_string())); + } + + // Build the wormhole verifier to get circuit data for parsing proofs + let config = CircuitConfig::standard_recursion_zk_config(); + let verifier = WormholeVerifier::new(config.clone(), None); + let common_data = verifier.circuit_data.common.clone(); + + // Configure aggregation + let aggregation_config = TreeAggregationConfig::new(branching_factor, depth as u32); + + log_verbose!( + "Aggregation config: branching_factor={}, depth={}, num_leaf_proofs={}", + aggregation_config.tree_branching_factor, + aggregation_config.tree_depth, + aggregation_config.num_leaf_proofs + ); + + if proof_files.len() > aggregation_config.num_leaf_proofs { + return Err(crate::error::QuantusError::Generic(format!( + "Too many proofs: {} provided, max {} for depth={} branching_factor={}", + proof_files.len(), + aggregation_config.num_leaf_proofs, + depth, + branching_factor + ))); + } + + // Create aggregator + let mut aggregator = + WormholeProofAggregator::new(verifier.circuit_data).with_config(aggregation_config); + + // Load and add proofs + for (idx, proof_file) in proof_files.iter().enumerate() { + log_verbose!("Loading proof {}/{}: {}", idx + 1, proof_files.len(), proof_file); + + let proof_hex = std::fs::read_to_string(proof_file).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to read {}: {}", proof_file, e)) + })?; + + let proof_bytes = hex::decode(proof_hex.trim()).map_err(|e| { + crate::error::QuantusError::Generic(format!( + "Failed to decode hex from {}: {}", + proof_file, e + )) + })?; + + let proof = ProofWithPublicInputs::::from_bytes(proof_bytes, &common_data) + crate::error::QuantusError::Generic(format!( + "Failed to deserialize proof from {}: {}", + proof_file, e + )) + })?; + + aggregator.push_proof(proof).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to add proof: {}", e)) + })?; + } + + log_print!("Running aggregation..."); + let aggregated_proof = aggregator + .aggregate() + .map_err(|e| crate::error::QuantusError::Generic(format!("Aggregation failed: {}", e)))?; + + // Parse and display aggregated public inputs + let aggregated_public_inputs = AggregatedPublicCircuitInputs::try_from_slice( + aggregated_proof.proof.public_inputs.as_slice(), + ) + .map_err(|e| { + crate::error::QuantusError::Generic(format!( + "Failed to parse aggregated public inputs: {}", + e + )) + })?; + + log_verbose!("Aggregated public inputs: {:#?}", aggregated_public_inputs); + + // Verify the aggregated proof locally + log_verbose!("Verifying aggregated proof locally..."); + aggregated_proof + .circuit_data + .verify(aggregated_proof.proof.clone()) + .map_err(|e| { + crate::error::QuantusError::Generic(format!( + "Aggregated proof verification failed: {}", + e + )) + })?; + + // Save aggregated proof + let proof_hex = hex::encode(aggregated_proof.proof.to_bytes()); + std::fs::write(&output_file, proof_hex).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to write proof: {}", e)) + })?; + + log_success!("Aggregation complete!"); + log_success!("Output: {}", output_file); + log_print!( + "Aggregated {} proofs into 1 proof with {} exit accounts", + proof_files.len(), + aggregated_public_inputs.account_data.len() + ); + + Ok(()) +} + +async fn verify_aggregated_proof(proof_file: String, node_url: &str) -> crate::error::Result<()> { + use subxt::tx::TxStatus; + + log_print!("Verifying aggregated wormhole proof on-chain..."); + + // Read proof from file + let proof_hex = std::fs::read_to_string(&proof_file).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to read proof file: {}", e)) + })?; + + let proof_bytes = hex::decode(proof_hex.trim()) + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to decode hex: {}", e)))?; + + log_verbose!("Aggregated proof size: {} bytes", proof_bytes.len()); + + // Connect to node + let quantus_client = QuantusClient::new(node_url) + .await + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to connect: {}", e)))?; + + log_verbose!("Connected to node"); + + // Create the verify_aggregated_proof transaction payload + let verify_tx = quantus_node::api::tx().wormhole().verify_aggregated_proof(proof_bytes); + + log_verbose!("Submitting unsigned aggregated verification transaction..."); + + // Submit as unsigned extrinsic + let unsigned_tx = quantus_client.client().tx().create_unsigned(&verify_tx).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to create unsigned tx: {}", e)) + })?; + + let mut tx_progress = unsigned_tx + .submit_and_watch() + .await + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to submit tx: {}", e)))?; + + // Wait for transaction inclusion + while let Some(Ok(status)) = tx_progress.next().await { + log_verbose!("Transaction status: {:?}", status); + match status { + TxStatus::InBestBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + log_success!("Aggregated proof verified successfully on-chain!"); + log_verbose!("Included in block: {:?}", block_hash); + return Ok(()); + }, + TxStatus::InFinalizedBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + log_success!("Aggregated proof verified successfully on-chain!"); + log_verbose!("Finalized in block: {:?}", block_hash); + return Ok(()); + }, + TxStatus::Error { message } | TxStatus::Invalid { message } => { + return Err(crate::error::QuantusError::Generic(format!( + "Transaction failed: {}", + message + ))); + }, + _ => continue, + } + } + + Err(crate::error::QuantusError::Generic("Transaction stream ended unexpectedly".to_string())) +} + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::NamedTempFile; + + #[test] + fn test_parse_secret_hex() { + // Valid hex with and without 0x prefix + let secret = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + assert!(parse_secret_hex(secret).is_ok()); + assert!(parse_secret_hex(&format!("0x{}", secret)).is_ok()); + + // Wrong length + assert!(parse_secret_hex("0123456789abcdef").unwrap_err().contains("32 bytes")); + + // Invalid hex characters + assert!(parse_secret_hex("ghij".repeat(16).as_str()) + .unwrap_err() + .contains("Invalid secret hex")); + } + + #[test] + fn test_parse_exit_account() { + // Valid hex account + let hex = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + assert!(parse_exit_account(hex).is_ok()); + + // Wrong length + assert!(parse_exit_account("0x0123456789abcdef").unwrap_err().contains("32 bytes")); + + // Invalid SS58 + assert!(parse_exit_account("not_valid").unwrap_err().contains("Invalid SS58")); + } + + #[test] + fn test_quantize_funding_amount() { + // Basic quantization: 1 token (12 decimals) -> 100 (2 decimals) + assert_eq!(quantize_funding_amount(1_000_000_000_000).unwrap(), 100); + + // Zero and small amounts + assert_eq!(quantize_funding_amount(0).unwrap(), 0); + assert_eq!(quantize_funding_amount(5_000_000_000).unwrap(), 0); // < 10^10 + + // Max valid and overflow + let max_valid = (u32::MAX as u128) * SCALE_DOWN_FACTOR; + assert_eq!(quantize_funding_amount(max_valid).unwrap(), u32::MAX); + assert!(quantize_funding_amount(max_valid + SCALE_DOWN_FACTOR) + .unwrap_err() + .contains("too large")); + } + + #[test] + fn test_validate_aggregation_params() { + // Valid configurations + assert_eq!(validate_aggregation_params(2, 1, 2).unwrap(), 2); + assert_eq!(validate_aggregation_params(9, 2, 3).unwrap(), 9); // 3^2 = 9 + + // Invalid: no proofs, bad branching factor, zero depth + assert!(validate_aggregation_params(0, 1, 2).unwrap_err().contains("No proofs")); + assert!(validate_aggregation_params(2, 1, 1).unwrap_err().contains("Branching factor")); + assert!(validate_aggregation_params(2, 0, 2).unwrap_err().contains("Depth")); + + // Too many proofs for tree size + assert!(validate_aggregation_params(3, 1, 2).unwrap_err().contains("Too many proofs")); + } + + #[test] + fn test_proof_file_roundtrip() { + let temp_file = NamedTempFile::new().unwrap(); + let path = temp_file.path().to_str().unwrap(); + let proof_bytes = vec![0x01, 0x02, 0x03, 0xaa, 0xbb, 0xcc]; + + write_proof_file(path, &proof_bytes).unwrap(); + assert_eq!(read_proof_file(path).unwrap(), proof_bytes); + } + + #[test] + fn test_read_proof_file_errors() { + // File not found + assert!(read_proof_file("/nonexistent/path/proof.hex") + .unwrap_err() + .contains("Failed to read")); + + // Invalid hex content + let temp_file = NamedTempFile::new().unwrap(); + std::fs::write(temp_file.path(), "not valid hex!").unwrap(); + assert!(read_proof_file(temp_file.path().to_str().unwrap()) + .unwrap_err() + .contains("Failed to decode")); + } +} + async fn verify_proof(proof_file: String, node_url: &str) -> crate::error::Result<()> { use subxt::tx::TxStatus; From 88024b7a68cbd5f227e1108e0329b2f9a2509622 Mon Sep 17 00:00:00 2001 From: illuzen Date: Wed, 21 Jan 2026 01:19:39 +0800 Subject: [PATCH 19/22] handle volume fee --- Cargo.lock | 19 +- Cargo.toml | 13 +- src/cli/wormhole.rs | 410 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 422 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75c9e0f..ec4e088 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3886,8 +3886,7 @@ dependencies = [ [[package]] name = "qp-wormhole-aggregator" -version = "0.1.7" -source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" +version = "0.1.8" dependencies = [ "anyhow", "qp-plonky2", @@ -3901,8 +3900,7 @@ dependencies = [ [[package]] name = "qp-wormhole-circuit" -version = "0.1.7" -source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" +version = "0.1.8" dependencies = [ "anyhow", "hex", @@ -3912,8 +3910,7 @@ dependencies = [ [[package]] name = "qp-wormhole-prover" -version = "0.1.7" -source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" +version = "0.1.8" dependencies = [ "anyhow", "qp-plonky2", @@ -3923,8 +3920,7 @@ dependencies = [ [[package]] name = "qp-wormhole-verifier" -version = "0.1.7" -source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" +version = "0.1.8" dependencies = [ "anyhow", "qp-plonky2", @@ -3934,8 +3930,7 @@ dependencies = [ [[package]] name = "qp-zk-circuits-common" -version = "0.1.7" -source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" +version = "0.1.8" dependencies = [ "anyhow", "hex", @@ -3981,6 +3976,7 @@ dependencies = [ "subxt", "subxt-metadata", "tempfile", + "test-helpers", "thiserror 2.0.16", "tokio", "toml 0.9.5", @@ -5685,8 +5681,7 @@ dependencies = [ [[package]] name = "test-helpers" -version = "0.1.7" -source = "git+https://github.com/Quantus-Network/qp-zk-circuits.git#e164f3703293c4cdcd97608252b9c4fac358e8bf" +version = "0.1.8" dependencies = [ "anyhow", "hex", diff --git a/Cargo.toml b/Cargo.toml index cd6bcfa..d5715fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,12 +72,13 @@ subxt-metadata = "0.43.0" # ZK proof generation anyhow = "1.0" -qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-wormhole-circuit", default-features = false, features = ["std"] } -qp-wormhole-prover = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-wormhole-prover", default-features = false, features = ["std"] } -qp-wormhole-verifier = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-wormhole-verifier", default-features = false, features = ["std"] } -qp-wormhole-aggregator = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-wormhole-aggregator", default-features = false, features = ["std", "rayon"] } -qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/qp-zk-circuits.git", package = "qp-zk-circuits-common", default-features = false, features = ["std"] } -qp-plonky2 = { version = "1.1.3", default-features = false, features = ["no_random"] } +qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-circuit", default-features = false, features = ["std"] } +qp-wormhole-prover = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-prover", default-features = false, features = ["std"] } +qp-wormhole-verifier = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-verifier", default-features = false, features = ["std"] } +qp-wormhole-aggregator = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-aggregator", default-features = false, features = ["std", "rayon"] } +qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-zk-circuits-common", default-features = false, features = ["std"] } +qp-plonky2 = { version = "1.1.3", default-features = false, features = ["std"] } [dev-dependencies] tempfile = "3.8" +qp-wormhole-test-helpers = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "test-helpers" } diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index db37709..3498b45 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -42,6 +42,16 @@ pub const NATIVE_ASSET_ID: u32 = 0; /// Scale down factor for quantizing amounts (10^10 to go from 12 to 2 decimal places) pub const SCALE_DOWN_FACTOR: u128 = 10_000_000_000; +/// Volume fee rate in basis points (10 bps = 0.1%) +/// This must match the on-chain VolumeFeeRateBps configuration +pub const VOLUME_FEE_BPS: u32 = 10; + +/// Compute output amount after fee deduction +/// output = input * (10000 - fee_bps) / 10000 +pub fn compute_output_amount(input_amount: u32, fee_bps: u32) -> u32 { + ((input_amount as u64) * (10000 - fee_bps as u64) / 10000) as u32 +} + /// Parse a hex-encoded secret string into a 32-byte array pub fn parse_secret_hex(secret_hex: &str) -> Result<[u8; 32], String> { let secret_bytes = hex::decode(secret_hex.trim_start_matches("0x")) @@ -426,13 +436,16 @@ async fn generate_proof( // Quantize the funding amount (from 12 decimal places to 2) // The circuit expects a u32 value. - let funding_amount_quantized: u32 = + let input_amount_quantized: u32 = (funding_amount / SCALE_DOWN_FACTOR).try_into().map_err(|_| { crate::error::QuantusError::Generic( "Funding amount too large after quantization".to_string(), ) })?; + // Calculate output amount after fee deduction + let output_amount_quantized = compute_output_amount(input_amount_quantized, VOLUME_FEE_BPS); + let inputs = CircuitInputs { private: PrivateCircuitInputs { secret, @@ -444,9 +457,11 @@ async fn generate_proof( state_root, extrinsics_root, digest, + input_amount: input_amount_quantized, }, public: PublicCircuitInputs { - funding_amount: funding_amount_quantized, + output_amount: output_amount_quantized, + volume_fee_bps: VOLUME_FEE_BPS, nullifier: Nullifier::from_preimage(secret, event.transfer_count).hash.into(), exit_account: BytesDigest::try_from(exit_account_id.as_ref() as &[u8]) .map_err(|e| crate::error::QuantusError::Generic(e.to_string()))?, @@ -552,6 +567,7 @@ async fn aggregate_proofs( })?; let proof = ProofWithPublicInputs::::from_bytes(proof_bytes, &common_data) + .map_err(|e| { crate::error::QuantusError::Generic(format!( "Failed to deserialize proof from {}: {}", proof_file, e @@ -679,8 +695,39 @@ async fn verify_aggregated_proof(proof_file: String, node_url: &str) -> crate::e #[cfg(test)] mod tests { use super::*; + use plonky2::plonk::circuit_data::CircuitConfig; + use qp_wormhole_circuit::inputs::{ + AggregatedPublicCircuitInputs, CircuitInputs, PublicCircuitInputs, + }; + use qp_wormhole_prover::WormholeProver; + use qp_wormhole_test_helpers::TestInputs; + use qp_wormhole_verifier::WormholeVerifier; use tempfile::NamedTempFile; + /// Helper to get a standard circuit config for tests + fn test_circuit_config() -> CircuitConfig { + CircuitConfig::standard_recursion_zk_config() + } + + #[test] + fn test_compute_output_amount() { + // 0.1% fee (10 bps): output = input * 9990 / 10000 + assert_eq!(compute_output_amount(1000, 10), 999); + assert_eq!(compute_output_amount(10000, 10), 9990); + + // 1% fee (100 bps): output = input * 9900 / 10000 + assert_eq!(compute_output_amount(1000, 100), 990); + assert_eq!(compute_output_amount(10000, 100), 9900); + + // 0% fee + assert_eq!(compute_output_amount(1000, 0), 1000); + + // Edge cases + assert_eq!(compute_output_amount(0, 10), 0); + assert_eq!(compute_output_amount(1, 10), 0); // rounds down + assert_eq!(compute_output_amount(100, 10), 99); + } + #[test] fn test_parse_secret_hex() { // Valid hex with and without 0x prefix @@ -766,6 +813,365 @@ mod tests { .unwrap_err() .contains("Failed to decode")); } + + #[test] + fn test_fee_calculation_edge_cases() { + // Test the circuit fee constraint: output_amount * 10000 <= input_amount * (10000 - volume_fee_bps) + // This is equivalent to: output <= input * (1 - fee_rate) + + // Small amounts where fee rounds to zero + let input_small: u32 = 100; + let output_small = compute_output_amount(input_small, VOLUME_FEE_BPS); + assert_eq!(output_small, 99); + // Verify constraint: 99 * 10000 = 990000 <= 100 * 9990 = 999000 ✓ + assert!( + (output_small as u64) * 10000 <= (input_small as u64) * (10000 - VOLUME_FEE_BPS as u64) + ); + + // Medium amounts + let input_medium: u32 = 10000; + let output_medium = compute_output_amount(input_medium, VOLUME_FEE_BPS); + assert_eq!(output_medium, 9990); + assert!( + (output_medium as u64) * 10000 + <= (input_medium as u64) * (10000 - VOLUME_FEE_BPS as u64) + ); + + // Large amounts near u32::MAX + let input_large: u32 = u32::MAX / 2; + let output_large = compute_output_amount(input_large, VOLUME_FEE_BPS); + assert!( + (output_large as u64) * 10000 <= (input_large as u64) * (10000 - VOLUME_FEE_BPS as u64) + ); + + // Test with different fee rates + for fee_bps in [0u32, 1, 10, 50, 100, 500, 1000] { + let input: u32 = 100000; + let output = compute_output_amount(input, fee_bps); + assert!( + (output as u64) * 10000 <= (input as u64) * (10000 - fee_bps as u64), + "Fee constraint violated for fee_bps={}: {} * 10000 > {} * {}", + fee_bps, + output, + input, + 10000 - fee_bps + ); + } + } + + #[test] + fn test_nullifier_determinism() { + use qp_wormhole_circuit::nullifier::Nullifier; + use qp_zk_circuits_common::utils::BytesDigest; + + let secret: BytesDigest = [1u8; 32].try_into().expect("valid secret"); + let transfer_count = 42u64; + + // Generate nullifier multiple times - should be identical + let nullifier1 = Nullifier::from_preimage(secret, transfer_count); + let nullifier2 = Nullifier::from_preimage(secret, transfer_count); + let nullifier3 = Nullifier::from_preimage(secret, transfer_count); + + assert_eq!(nullifier1.hash, nullifier2.hash); + assert_eq!(nullifier2.hash, nullifier3.hash); + + // Different transfer count should produce different nullifier + let nullifier_different = Nullifier::from_preimage(secret, transfer_count + 1); + assert_ne!(nullifier1.hash, nullifier_different.hash); + + // Different secret should produce different nullifier + let different_secret: BytesDigest = [2u8; 32].try_into().expect("valid secret"); + let nullifier_different_secret = Nullifier::from_preimage(different_secret, transfer_count); + assert_ne!(nullifier1.hash, nullifier_different_secret.hash); + } + + #[test] + fn test_unspendable_account_determinism() { + use qp_wormhole_circuit::unspendable_account::UnspendableAccount; + use qp_zk_circuits_common::utils::BytesDigest; + + let secret: BytesDigest = [1u8; 32].try_into().expect("valid secret"); + + // Generate unspendable account multiple times - should be identical + let account1 = UnspendableAccount::from_secret(secret); + let account2 = UnspendableAccount::from_secret(secret); + + assert_eq!(account1.account_id, account2.account_id); + + // Different secret should produce different account + let different_secret: BytesDigest = [2u8; 32].try_into().expect("valid secret"); + let account_different = UnspendableAccount::from_secret(different_secret); + assert_ne!(account1.account_id, account_different.account_id); + } + + /// Integration test: Generate a real ZK proof using test fixtures and verify it + #[test] + #[ignore] // This test is slow (~30s) - run with `cargo test -- --ignored` + fn test_full_proof_generation_and_verification() { + // Use test fixtures from qp-wormhole-test-helpers + let inputs = CircuitInputs::test_inputs_0(); + + // Verify the test inputs have correct fee configuration + assert_eq!(inputs.public.volume_fee_bps, VOLUME_FEE_BPS); + assert_eq!(inputs.public.asset_id, NATIVE_ASSET_ID); + + // Verify fee constraint is satisfied in test inputs + let input_amount = inputs.private.input_amount; + let output_amount = inputs.public.output_amount; + assert!( + (output_amount as u64) * 10000 + <= (input_amount as u64) * (10000 - VOLUME_FEE_BPS as u64), + "Test inputs violate fee constraint" + ); + + // Create prover and generate proof + let config = test_circuit_config(); + let prover = WormholeProver::new(config.clone()); + let prover_committed = prover.commit(&inputs).expect("Failed to commit inputs"); + let proof = prover_committed.prove().expect("Failed to generate proof"); + + // Parse and verify public inputs from proof + let parsed_public_inputs = + PublicCircuitInputs::try_from(&proof).expect("Failed to parse public inputs"); + + assert_eq!(parsed_public_inputs.asset_id, inputs.public.asset_id); + assert_eq!(parsed_public_inputs.output_amount, inputs.public.output_amount); + assert_eq!(parsed_public_inputs.volume_fee_bps, inputs.public.volume_fee_bps); + assert_eq!(parsed_public_inputs.nullifier, inputs.public.nullifier); + assert_eq!(parsed_public_inputs.exit_account, inputs.public.exit_account); + assert_eq!(parsed_public_inputs.block_hash, inputs.public.block_hash); + assert_eq!(parsed_public_inputs.parent_hash, inputs.public.parent_hash); + assert_eq!(parsed_public_inputs.block_number, inputs.public.block_number); + + // Create verifier and verify proof + let verifier = WormholeVerifier::new(config, None); + verifier.verify(proof).expect("Proof verification failed"); + } + + /// Integration test: Generate proof, serialize/deserialize, then verify + #[test] + #[ignore] // This test is slow - run with `cargo test -- --ignored` + fn test_proof_serialization_roundtrip() { + let inputs = CircuitInputs::test_inputs_0(); + let config = test_circuit_config(); + + // Generate proof + let prover = WormholeProver::new(config.clone()); + let proof = prover.commit(&inputs).unwrap().prove().unwrap(); + + // Serialize to bytes + let proof_bytes = proof.to_bytes(); + + // Write to temp file and read back + let temp_file = NamedTempFile::new().unwrap(); + let path = temp_file.path().to_str().unwrap(); + write_proof_file(path, &proof_bytes).unwrap(); + let read_bytes = read_proof_file(path).unwrap(); + + assert_eq!(proof_bytes, read_bytes, "Proof bytes should match after file roundtrip"); + + // Deserialize and verify + let verifier = WormholeVerifier::new(config, None); + let deserialized_proof = plonky2::plonk::proof::ProofWithPublicInputs::< + qp_zk_circuits_common::circuit::F, + qp_zk_circuits_common::circuit::C, + { qp_zk_circuits_common::circuit::D }, + >::from_bytes(read_bytes, &verifier.circuit_data.common) + .expect("Failed to deserialize proof"); + + verifier + .verify(deserialized_proof) + .expect("Deserialized proof verification failed"); + } + + /// Integration test: Generate multiple proofs with different inputs + #[test] + #[ignore] // This test is slow - run with `cargo test -- --ignored` + fn test_multiple_proof_generation() { + let config = test_circuit_config(); + + // Generate proofs for both test input sets + let inputs_0 = CircuitInputs::test_inputs_0(); + let inputs_1 = CircuitInputs::test_inputs_1(); + + let prover_0 = WormholeProver::new(config.clone()); + let proof_0 = prover_0.commit(&inputs_0).unwrap().prove().unwrap(); + + let prover_1 = WormholeProver::new(config.clone()); + let proof_1 = prover_1.commit(&inputs_1).unwrap().prove().unwrap(); + + // Verify both proofs + let verifier = WormholeVerifier::new(config, None); + verifier.verify(proof_0.clone()).expect("Proof 0 verification failed"); + verifier.verify(proof_1.clone()).expect("Proof 1 verification failed"); + + // Verify public inputs are different (different nullifiers, etc.) + let public_0 = PublicCircuitInputs::try_from(&proof_0).unwrap(); + let public_1 = PublicCircuitInputs::try_from(&proof_1).unwrap(); + + assert_ne!(public_0.nullifier, public_1.nullifier, "Nullifiers should be different"); + assert_ne!(public_0.block_hash, public_1.block_hash, "Block hashes should be different"); + } + + /// Integration test: Aggregate proofs and verify aggregated proof + #[test] + #[ignore] // This test is slow (~60s) - run with `cargo test -- --ignored` + fn test_proof_aggregation() { + use qp_wormhole_aggregator::aggregator::WormholeProofAggregator; + + let config = test_circuit_config(); + + // Generate a proof + let inputs = CircuitInputs::test_inputs_0(); + let prover = WormholeProver::new(config.clone()); + let proof = prover.commit(&inputs).unwrap().prove().unwrap(); + + // Create aggregator with default config (branching_factor=2, depth=1) + let verifier = WormholeVerifier::new(config, None); + let mut aggregator = WormholeProofAggregator::new(verifier.circuit_data); + + // Add proof to aggregator + aggregator.push_proof(proof.clone()).expect("Failed to push proof"); + + // Aggregate + let aggregated_result = aggregator.aggregate().expect("Aggregation failed"); + + // Parse aggregated public inputs + let aggregated_public_inputs = AggregatedPublicCircuitInputs::try_from_slice( + aggregated_result.proof.public_inputs.as_slice(), + ) + .expect("Failed to parse aggregated public inputs"); + + // Verify aggregated proof structure + assert_eq!(aggregated_public_inputs.asset_id, NATIVE_ASSET_ID, "Asset ID should be native"); + assert_eq!( + aggregated_public_inputs.volume_fee_bps, VOLUME_FEE_BPS, + "Volume fee BPS should match" + ); + assert!( + !aggregated_public_inputs.nullifiers.is_empty(), + "Should have at least one nullifier" + ); + assert!( + !aggregated_public_inputs.account_data.is_empty(), + "Should have at least one account" + ); + + // Verify the aggregated proof locally + aggregated_result + .circuit_data + .verify(aggregated_result.proof) + .expect("Aggregated proof verification failed"); + } + + /// Integration test: Aggregate multiple proofs with different exit accounts + #[test] + #[ignore] // This test is very slow (~120s) - run with `cargo test -- --ignored` + fn test_proof_aggregation_multiple_accounts() { + use qp_wormhole_aggregator::aggregator::WormholeProofAggregator; + + let config = test_circuit_config(); + + // Generate proofs with different inputs (different exit accounts) + let inputs_0 = CircuitInputs::test_inputs_0(); + let inputs_1 = CircuitInputs::test_inputs_1(); + + let prover_0 = WormholeProver::new(config.clone()); + let proof_0 = prover_0.commit(&inputs_0).unwrap().prove().unwrap(); + + let prover_1 = WormholeProver::new(config.clone()); + let proof_1 = prover_1.commit(&inputs_1).unwrap().prove().unwrap(); + + // Create aggregator + let verifier = WormholeVerifier::new(config, None); + let mut aggregator = WormholeProofAggregator::new(verifier.circuit_data); + + // Add both proofs + aggregator.push_proof(proof_0).expect("Failed to push proof 0"); + aggregator.push_proof(proof_1).expect("Failed to push proof 1"); + + // Aggregate + let aggregated_result = aggregator.aggregate().expect("Aggregation failed"); + + // Parse aggregated public inputs + let aggregated_public_inputs = AggregatedPublicCircuitInputs::try_from_slice( + aggregated_result.proof.public_inputs.as_slice(), + ) + .expect("Failed to parse aggregated public inputs"); + + // Verify we have 2 nullifiers (one per proof) + assert_eq!( + aggregated_public_inputs.nullifiers.len(), + 2, + "Should have 2 nullifiers for 2 proofs" + ); + + // Verify all nullifiers are unique + assert_ne!( + aggregated_public_inputs.nullifiers[0], aggregated_public_inputs.nullifiers[1], + "Nullifiers should be unique" + ); + + // Verify the aggregated proof + aggregated_result + .circuit_data + .verify(aggregated_result.proof) + .expect("Aggregated proof verification failed"); + } + + /// Test that public inputs parsing matches expected structure + #[test] + fn test_public_inputs_structure() { + use qp_wormhole_circuit::inputs::{ + ASSET_ID_INDEX, BLOCK_HASH_END_INDEX, BLOCK_HASH_START_INDEX, BLOCK_NUMBER_INDEX, + EXIT_ACCOUNT_END_INDEX, EXIT_ACCOUNT_START_INDEX, NULLIFIER_END_INDEX, + NULLIFIER_START_INDEX, OUTPUT_AMOUNT_INDEX, PARENT_HASH_END_INDEX, + PARENT_HASH_START_INDEX, PUBLIC_INPUTS_FELTS_LEN, VOLUME_FEE_BPS_INDEX, + }; + + // Verify expected public inputs layout + assert_eq!(PUBLIC_INPUTS_FELTS_LEN, 20, "Public inputs should be 20 field elements"); + assert_eq!(ASSET_ID_INDEX, 0, "Asset ID should be first"); + assert_eq!(OUTPUT_AMOUNT_INDEX, 1, "Output amount should be second"); + assert_eq!(VOLUME_FEE_BPS_INDEX, 2, "Volume fee BPS should be third"); + assert_eq!(NULLIFIER_START_INDEX, 3, "Nullifier should start at index 3"); + assert_eq!(NULLIFIER_END_INDEX, 7, "Nullifier should end at index 7"); + assert_eq!(EXIT_ACCOUNT_START_INDEX, 7, "Exit account should start at index 7"); + assert_eq!(EXIT_ACCOUNT_END_INDEX, 11, "Exit account should end at index 11"); + assert_eq!(BLOCK_HASH_START_INDEX, 11, "Block hash should start at index 11"); + assert_eq!(BLOCK_HASH_END_INDEX, 15, "Block hash should end at index 15"); + assert_eq!(PARENT_HASH_START_INDEX, 15, "Parent hash should start at index 15"); + assert_eq!(PARENT_HASH_END_INDEX, 19, "Parent hash should end at index 19"); + assert_eq!(BLOCK_NUMBER_INDEX, 19, "Block number should be at index 19"); + } + + /// Test that constants match expected on-chain configuration + #[test] + fn test_constants_match_chain_config() { + // Volume fee rate should be 10 bps (0.1%) + assert_eq!(VOLUME_FEE_BPS, 10, "Volume fee should be 10 bps"); + + // Native asset ID should be 0 + assert_eq!(NATIVE_ASSET_ID, 0, "Native asset ID should be 0"); + + // Scale down factor should be 10^10 (12 decimals -> 2 decimals) + assert_eq!(SCALE_DOWN_FACTOR, 10_000_000_000, "Scale down factor should be 10^10"); + + // Verify scale down: 1 token with 12 decimals = 10^12 units + // After quantization: 10^12 / 10^10 = 100 (which is 1.00 in 2 decimal places) + let one_token_12_decimals: u128 = 1_000_000_000_000; + let quantized = quantize_funding_amount(one_token_12_decimals).unwrap(); + assert_eq!(quantized, 100, "1 token should quantize to 100 (1.00 with 2 decimals)"); + } + + #[test] + fn test_volume_fee_bps_constant() { + // Ensure VOLUME_FEE_BPS matches expected value (10 bps = 0.1%) + assert_eq!(VOLUME_FEE_BPS, 10); + + // Verify it's a reasonable value (less than 100% = 10000 bps) + assert!(VOLUME_FEE_BPS < 10000); + } } async fn verify_proof(proof_file: String, node_url: &str) -> crate::error::Result<()> { From c75ad95805c971621199f6d339b5a8a3c77efc99 Mon Sep 17 00:00:00 2001 From: illuzen Date: Wed, 21 Jan 2026 03:10:38 +0800 Subject: [PATCH 20/22] integration tests pass --- Cargo.lock | 1187 +++++++++++++++++---------------- Cargo.toml | 3 +- tests/wormhole_integration.rs | 1064 +++++++++++++++++++++++++++++ 3 files changed, 1681 insertions(+), 573 deletions(-) create mode 100644 tests/wormhole_integration.rs diff --git a/Cargo.lock b/Cargo.lock index ec4e088..029bcd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -70,7 +70,7 @@ checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "const-random", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -102,9 +102,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -117,9 +117,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -132,29 +132,29 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "aquamarine" @@ -167,7 +167,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -324,7 +324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -350,7 +350,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -425,7 +425,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -464,9 +464,9 @@ dependencies = [ [[package]] name = "ark-vrf" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9501da18569b2afe0eb934fb7afd5a247d238b94116155af4dd068f319adfe6d" +checksum = "0d63e9780640021b74d02b32895d8cec1b4abe8e5547b560a6bda6b14b78c6da" dependencies = [ "ark-bls12-381 0.5.0", "ark-ec 0.5.0", @@ -536,9 +536,9 @@ dependencies = [ [[package]] name = "async-fs" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f7e37c0ed80b2a977691c47dae8625cfb21e205827106c64f7c588766b2e50" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" dependencies = [ "async-lock", "blocking", @@ -547,11 +547,11 @@ dependencies = [ [[package]] name = "async-io" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock", + "autocfg", "cfg-if", "concurrent-queue", "futures-io", @@ -560,14 +560,14 @@ dependencies = [ "polling", "rustix", "slab", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener", "event-listener-strategy", @@ -587,9 +587,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ "async-channel", "async-io", @@ -605,9 +605,9 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" dependencies = [ "async-io", "async-lock", @@ -618,7 +618,7 @@ dependencies = [ "rustix", "signal-hook-registry", "slab", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -635,7 +635,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -658,9 +658,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -668,7 +668,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -691,15 +691,15 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.0" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "binary-merkle-tree" -version = "16.0.0" +version = "16.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "181f5380e435b8ba6d901f8b16fc8908c6f0f8bea8973113d1c8718d89bb1809" +checksum = "95c9f6900c9fd344d53fbdfb36e1343429079d73f4168c8ef48884bf15616dbd" dependencies = [ "hash-db", "log", @@ -708,11 +708,11 @@ dependencies = [ [[package]] name = "bip39" -version = "2.2.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d193de1f7487df1914d3a568b772458861d33f9c54249612cc2893d6915054" +checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.14.1", ] [[package]] @@ -728,7 +728,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" dependencies = [ "bitcoin-internals", - "hex-conservative", + "hex-conservative 0.1.2", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" +dependencies = [ + "hex-conservative 0.2.2", ] [[package]] @@ -739,9 +748,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.4" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bitvec" @@ -776,13 +785,13 @@ dependencies = [ [[package]] name = "blake2b_simd" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e903a20b159e944f91ec8499fe1e55651480c541ea0a584f5d967c49ad9d99" +checksum = "b79834656f71332577234b50bfc009996f7449e0c056884e6a02492ded0ca2f3" dependencies = [ "arrayref", "arrayvec 0.7.6", - "constant_time_eq 0.3.1", + "constant_time_eq 0.4.2", ] [[package]] @@ -839,9 +848,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "byte-slice-cast" @@ -857,15 +866,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cc" -version = "1.2.36" +version = "1.2.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" +checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932" dependencies = [ "find-msvc-tools", "shlex", @@ -888,9 +897,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chacha20" @@ -905,16 +914,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" dependencies = [ "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -929,9 +938,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.47" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -939,9 +948,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.47" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -951,21 +960,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" [[package]] name = "colorchoice" @@ -975,11 +984,11 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "colored" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1041,16 +1050,16 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "once_cell", "tiny-keccak", ] [[package]] name = "const_format" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ "const_format_proc_macros", ] @@ -1074,15 +1083,15 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "convert_case" -version = "0.7.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ "unicode-segmentation", ] @@ -1166,9 +1175,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -1218,7 +1227,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1242,7 +1251,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1253,7 +1262,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1269,9 +1278,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", ] @@ -1295,7 +1304,7 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1306,7 +1315,7 @@ checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1320,11 +1329,11 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "derive_more-impl 2.0.1", + "derive_more-impl 2.1.1", ] [[package]] @@ -1335,19 +1344,20 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 2.0.106", + "rustc_version", + "syn 2.0.114", "unicode-xid", ] @@ -1390,7 +1400,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -1401,7 +1411,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1425,7 +1435,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.106", + "syn 2.0.114", "termcolor", "toml 0.8.23", "walkdir", @@ -1507,7 +1517,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1544,22 +1554,22 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "enum-ordinalize" -version = "4.3.0" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" dependencies = [ "enum-ordinalize-derive", ] [[package]] name = "enum-ordinalize-derive" -version = "4.3.1" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1581,7 +1591,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -1617,7 +1627,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1654,9 +1664,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.1" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" +checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" [[package]] name = "fixed-hash" @@ -1716,9 +1726,9 @@ dependencies = [ [[package]] name = "frame-metadata" -version = "23.0.0" +version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8c26fcb0454397c522c05fdad5380c4e622f8a875638af33bff5a320d1fc965" +checksum = "9ba5be0edbdb824843a0f9c6f0906ecfc66c5316218d74457003218b24909ed0" dependencies = [ "cfg-if", "parity-scale-codec", @@ -1728,9 +1738,9 @@ dependencies = [ [[package]] name = "frame-support" -version = "41.0.0" +version = "41.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00861648586bca196780b311ca1f345752ee5d971fa1a027f3213955bc493434" +checksum = "9162e30a146eabaa72feaf67a79b32d4adbebfc0566b5544937e44786734ac7b" dependencies = [ "aquamarine", "array-bytes", @@ -1786,7 +1796,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1799,7 +1809,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1810,7 +1820,7 @@ checksum = "ed971c6435503a099bdac99fe4c5bea08981709e5b5a0a8535a1856f48561191" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1898,7 +1908,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1954,27 +1964,27 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.5+wasi-0.2.4", + "wasip2", ] [[package]] @@ -1999,9 +2009,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "gloo-net" @@ -2062,9 +2072,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -2127,6 +2137,12 @@ dependencies = [ "serde", ] +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + [[package]] name = "heck" version = "0.5.0" @@ -2151,6 +2167,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec 0.7.6", +] + [[package]] name = "hex-literal" version = "0.4.1" @@ -2189,12 +2214,11 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -2235,9 +2259,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ "atomic-waker", "bytes", @@ -2275,9 +2299,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" dependencies = [ "bytes", "futures-channel", @@ -2296,9 +2320,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2320,9 +2344,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -2333,9 +2357,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -2346,11 +2370,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -2361,42 +2384,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -2468,7 +2487,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -2492,12 +2511,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -2531,22 +2550,11 @@ dependencies = [ "num-traits", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", -] - [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -2586,9 +2594,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jni" @@ -2614,9 +2622,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.78" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ "once_cell", "wasm-bindgen", @@ -2624,9 +2632,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b26c20e2178756451cfeb0661fb74c47dd5988cb7e3939de7e9241fd604d42" +checksum = "e281ae70cc3b98dac15fced3366a880949e65fc66e345ce857a5682d152f3e62" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", @@ -2638,9 +2646,9 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bacb85abf4117092455e1573625e21b8f8ef4dec8aff13361140b2dc266cdff2" +checksum = "cc4280b709ac3bb5e16cf3bad5056a0ec8df55fa89edfe996361219aadc2c7ea" dependencies = [ "base64", "futures-channel", @@ -2663,9 +2671,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456196007ca3a14db478346f58c7238028d55ee15c1df15115596e411ff27925" +checksum = "348ee569eaed52926b5e740aae20863762b16596476e943c9e415a6479021622" dependencies = [ "async-trait", "bytes", @@ -2688,9 +2696,9 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c872b6c9961a4ccc543e321bb5b89f6b2d2c7fe8b61906918273a3333c95400c" +checksum = "f50c389d6e6a52eb7c3548a6600c90cf74d9b71cb5912209833f00a5479e9a01" dependencies = [ "async-trait", "base64", @@ -2713,9 +2721,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a8e70baf945b6b5752fc8eb38c918a48f1234daf11355e07106d963f860089" +checksum = "b0f05e0028e55b15dbd2107163b3c744cd3bb4474f193f95d9708acbf5677e44" dependencies = [ "http", "serde", @@ -2725,9 +2733,9 @@ dependencies = [ [[package]] name = "jsonrpsee-wasm-client" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6558a9586cad43019dafd0b6311d0938f46efc116b34b28c74778bc11a2edf6" +checksum = "e9d745e4f543fc10fc0e2b11aa1f3be506b1e475d412167e7191a65ecd239f1c" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", @@ -2736,9 +2744,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b3323d890aa384f12148e8d2a1fd18eb66e9e7e825f9de4fa53bcc19b93eef" +checksum = "78fc744f17e7926d57f478cf9ca6e1ee5d8332bf0514860b1a3cdf1742e614cc" dependencies = [ "http", "jsonrpsee-client-transport", @@ -2799,9 +2807,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.175" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libm" @@ -2811,11 +2819,11 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "libc", ] @@ -2875,25 +2883,24 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "lru" @@ -2913,7 +2920,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -2927,7 +2934,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -2938,7 +2945,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -2949,7 +2956,7 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -2963,9 +2970,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memory-db" @@ -2978,12 +2985,6 @@ dependencies = [ "hashbrown 0.15.5", ] -[[package]] -name = "memzero" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93c0d11ac30a033511ae414355d80f70d9f29a44a49140face477117a1ee90db" - [[package]] name = "merlin" version = "3.0.0" @@ -3007,13 +3008,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -3024,15 +3025,15 @@ checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" [[package]] name = "nam-tiny-hderive" -version = "0.3.1-nam.0" +version = "0.3.1-nam.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dfd77f274636f722e966c394b381a70233ed4c25150864a4c53d398028a6818" +checksum = "b2cd44792ed5cd84dc9dedc3d572242ac00e76c244e85eb4bf34da2c6239ce30" dependencies = [ "base58", "hmac 0.12.1", "k256", - "memzero", "sha2 0.10.9", + "zeroize", ] [[package]] @@ -3058,11 +3059,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3174,9 +3175,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -3189,9 +3190,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "opaque-debug" @@ -3201,9 +3202,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" [[package]] name = "option-ext" @@ -3333,7 +3334,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.13.0", "rand 0.8.5", "rand_core 0.6.4", "serde", @@ -3366,7 +3367,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -3383,9 +3384,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -3393,15 +3394,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -3463,7 +3464,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -3538,7 +3539,7 @@ dependencies = [ "polkavm-common", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -3548,21 +3549,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba0ef0f17ad81413ea1ca5b1b67553aedf5650c88269b673d3ba015c83bc2651" dependencies = [ "polkavm-derive-impl", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "polling" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", "rustix", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3590,15 +3591,15 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -3625,7 +3626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -3654,11 +3655,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit", + "toml_edit 0.23.10+spec-1.0.0", ] [[package]] @@ -3704,7 +3705,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -3715,14 +3716,14 @@ checksum = "75eea531cfcd120e0851a3f8aed42c4841f78c889eefafd96339c72677ae42c3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" dependencies = [ "unicode-ident", ] @@ -3767,7 +3768,7 @@ checksum = "39530b02faa85964bba211e030afa2d54995b403b0022f88e984c4c65679c4bc" dependencies = [ "ahash", "anyhow", - "getrandom 0.2.16", + "getrandom 0.2.17", "hashbrown 0.14.5", "itertools 0.11.0", "keccak-hash 0.8.0", @@ -3827,9 +3828,9 @@ dependencies = [ [[package]] name = "qp-poseidon-constants" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d56b56652e9f44a43de9593e75d7c3e0c3a352e10675cf3024e5b3175711cd3" +checksum = "15005ef7ac88e170a9461990130619855284bd524e8ad059491ed291222d1553" dependencies = [ "p3-field", "p3-goldilocks", @@ -3878,15 +3879,16 @@ dependencies = [ "qp-poseidon-core", "qp-rusty-crystals-dilithium", "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", "serde", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] name = "qp-wormhole-aggregator" version = "0.1.8" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits?branch=illuzen%2Fagg-fees#9aa2ad658544500432cf2180ac3c2a341b8daaea" dependencies = [ "anyhow", "qp-plonky2", @@ -3901,6 +3903,7 @@ dependencies = [ [[package]] name = "qp-wormhole-circuit" version = "0.1.8" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits?branch=illuzen%2Fagg-fees#9aa2ad658544500432cf2180ac3c2a341b8daaea" dependencies = [ "anyhow", "hex", @@ -3911,6 +3914,7 @@ dependencies = [ [[package]] name = "qp-wormhole-prover" version = "0.1.8" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits?branch=illuzen%2Fagg-fees#9aa2ad658544500432cf2180ac3c2a341b8daaea" dependencies = [ "anyhow", "qp-plonky2", @@ -3921,6 +3925,7 @@ dependencies = [ [[package]] name = "qp-wormhole-verifier" version = "0.1.8" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits?branch=illuzen%2Fagg-fees#9aa2ad658544500432cf2180ac3c2a341b8daaea" dependencies = [ "anyhow", "qp-plonky2", @@ -3931,6 +3936,7 @@ dependencies = [ [[package]] name = "qp-zk-circuits-common" version = "0.1.8" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits?branch=illuzen%2Fagg-fees#9aa2ad658544500432cf2180ac3c2a341b8daaea" dependencies = [ "anyhow", "hex", @@ -3970,6 +3976,7 @@ dependencies = [ "rpassword", "serde", "serde_json", + "serial_test", "sha2 0.10.9", "sp-core", "sp-runtime", @@ -3977,16 +3984,16 @@ dependencies = [ "subxt-metadata", "tempfile", "test-helpers", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio", - "toml 0.9.5", + "toml 0.9.11+spec-1.1.0", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" dependencies = [ "proc-macro2", ] @@ -4021,7 +4028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -4041,7 +4048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -4050,16 +4057,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] @@ -4084,11 +4091,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", ] [[package]] @@ -4097,36 +4104,36 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] name = "ref-cast" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -4136,9 +4143,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -4147,9 +4154,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rfc6979" @@ -4169,7 +4176,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -4198,9 +4205,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" @@ -4225,22 +4232,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "log", "once_cell", @@ -4253,9 +4260,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -4265,9 +4272,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "zeroize", ] @@ -4301,9 +4308,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ "ring", "rustls-pki-types", @@ -4318,15 +4325,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ruzstd" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3640bec8aad418d7d03c72ea2de10d5c646a598f9883c7babc160d91e3c1b26c" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "e5ff0cc5e135c8870a775d3320910cd9b564ec036b4dc0b8741629020be63f01" [[package]] name = "same-file" @@ -4351,9 +4352,9 @@ dependencies = [ [[package]] name = "scale-decode" -version = "0.16.0" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d78196772d25b90a98046794ce0fe2588b39ebdfbdc1e45b4c6c85dd43bebad" +checksum = "8d6ed61699ad4d54101ab5a817169259b5b0efc08152f8632e61482d8a27ca3d" dependencies = [ "parity-scale-codec", "primitive-types 0.13.1", @@ -4361,26 +4362,26 @@ dependencies = [ "scale-decode-derive", "scale-type-resolver", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] name = "scale-decode-derive" -version = "0.16.0" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4b54a1211260718b92832b661025d1f1a4b6930fbadd6908e00edd265fa5f7" +checksum = "65cb245f7fdb489e7ba43a616cbd34427fe3ba6fe0edc1d0d250085e6c84f3ec" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "scale-encode" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64901733157f9d25ef86843bd783eda439fac7efb0ad5a615d12d2cf3a29464b" +checksum = "f2a976d73564a59e482b74fd5d95f7518b79ca8c8ca5865398a4d629dd15ee50" dependencies = [ "parity-scale-codec", "primitive-types 0.13.1", @@ -4388,20 +4389,20 @@ dependencies = [ "scale-encode-derive", "scale-type-resolver", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] name = "scale-encode-derive" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a3993a13b4eafa89350604672c8757b7ea84c7c5947d4b3691e3169c96379b" +checksum = "17020f2d59baabf2ddcdc20a4e567f8210baf089b8a8d4785f5fd5e716f92038" dependencies = [ "darling", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -4427,7 +4428,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -4449,15 +4450,15 @@ dependencies = [ "proc-macro2", "quote", "scale-info", - "syn 2.0.106", - "thiserror 2.0.16", + "syn 2.0.114", + "thiserror 2.0.18", ] [[package]] name = "scale-value" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca8b26b451ecb7fd7b62b259fa28add63d12ec49bbcac0e01fcb4b5ae0c09aa" +checksum = "884aab179aba344c67ddcd1d7dd8e3f8fee202f2e570d97ec34ec8688442a5b3" dependencies = [ "base58", "blake2", @@ -4468,17 +4469,26 @@ dependencies = [ "scale-encode", "scale-type-resolver", "serde", - "thiserror 2.0.16", + "thiserror 2.0.18", "yap", ] +[[package]] +name = "scc" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" +dependencies = [ + "sdd", +] + [[package]] name = "schannel" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -4517,6 +4527,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sdd" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" + [[package]] name = "sec1" version = "0.7.3" @@ -4561,11 +4577,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.4.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b369d18893388b345804dc0007963c99b7d665ae71d275812d828c6f089640" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "core-foundation", "core-foundation-sys", "libc", @@ -4584,9 +4600,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "send_wrapper" @@ -4596,43 +4612,55 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.17" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -4646,11 +4674,11 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -4663,6 +4691,32 @@ dependencies = [ "serde", ] +[[package]] +name = "serial_test" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" +dependencies = [ + "futures-executor", + "futures-util", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "sha1" version = "0.10.6" @@ -4725,10 +4779,11 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -4798,7 +4853,7 @@ dependencies = [ "bs58", "chacha20", "crossbeam-queue", - "derive_more 2.0.1", + "derive_more 2.1.1", "ed25519-zebra", "either", "event-listener", @@ -4848,7 +4903,7 @@ dependencies = [ "base64", "blake2-rfc", "bs58", - "derive_more 2.0.1", + "derive_more 2.1.1", "either", "event-listener", "fnv", @@ -4875,12 +4930,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -4933,7 +4988,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -5035,7 +5090,7 @@ checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -5046,7 +5101,7 @@ checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -5128,9 +5183,9 @@ dependencies = [ [[package]] name = "sp-metadata-ir" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2319040b39b9614c35c7faaf548172f4d9a3b44b6992bbae534b096d5cdb4f79" +checksum = "15c327d0340a18979aa242f2ad3ad8a6f5fa76c03cc7ca5b50c4770573fd8191" dependencies = [ "frame-metadata", "parity-scale-codec", @@ -5208,7 +5263,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -5331,7 +5386,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -5394,9 +5449,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -5452,9 +5507,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "subxt" -version = "0.43.0" +version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74791ddeaaa6de42e7cc8a715c83eb73303f513f90af701fd07eb2caad92ed84" +checksum = "f8c6dc0f90e23c521465b8f7e026af04a48cc6f00c51d88a8d313d33096149de" dependencies = [ "async-trait", "derive-where", @@ -5478,7 +5533,7 @@ dependencies = [ "subxt-macro", "subxt-metadata", "subxt-rpcs", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio", "tokio-util", "tracing", @@ -5500,8 +5555,8 @@ dependencies = [ "scale-info", "scale-typegen", "subxt-metadata", - "syn 2.0.106", - "thiserror 2.0.16", + "syn 2.0.114", + "thiserror 2.0.18", ] [[package]] @@ -5530,7 +5585,7 @@ dependencies = [ "serde_json", "sp-crypto-hashing", "subxt-metadata", - "thiserror 2.0.16", + "thiserror 2.0.18", "tracing", ] @@ -5545,7 +5600,7 @@ dependencies = [ "serde", "serde_json", "smoldot-light", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", @@ -5553,9 +5608,9 @@ dependencies = [ [[package]] name = "subxt-macro" -version = "0.43.0" +version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69516e8ff0e9340a0f21b8398da7f997571af4734ee81deada5150a2668c8443" +checksum = "c269228a2e5de4c0c61ed872b701967ee761df0f167d5b91ecec1185bca65793" dependencies = [ "darling", "parity-scale-codec", @@ -5565,7 +5620,7 @@ dependencies = [ "subxt-codegen", "subxt-metadata", "subxt-utils-fetchmetadata", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -5580,7 +5635,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-crypto-hashing", - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] @@ -5601,7 +5656,7 @@ dependencies = [ "serde_json", "subxt-core", "subxt-lightclient", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio-util", "tracing", "url", @@ -5615,7 +5670,7 @@ checksum = "8c4fb8fd6b16ecd3537a29d70699f329a68c1e47f70ed1a46d64f76719146563" dependencies = [ "hex", "parity-scale-codec", - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] @@ -5631,9 +5686,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -5648,7 +5703,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -5659,15 +5714,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.22.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -5682,6 +5737,7 @@ dependencies = [ [[package]] name = "test-helpers" version = "0.1.8" +source = "git+https://github.com/Quantus-Network/qp-zk-circuits?branch=illuzen%2Fagg-fees#9aa2ad658544500432cf2180ac3c2a341b8daaea" dependencies = [ "anyhow", "hex", @@ -5701,11 +5757,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.16", + "thiserror-impl 2.0.18", ] [[package]] @@ -5716,18 +5772,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -5741,29 +5797,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.43" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" +checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" dependencies = [ "num-conv", "time-core", @@ -5780,9 +5837,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -5805,40 +5862,37 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -5846,9 +5900,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -5857,9 +5911,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -5878,19 +5932,19 @@ dependencies = [ "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", - "toml_edit", + "toml_edit 0.22.27", ] [[package]] name = "toml" -version = "0.9.5" +version = "0.9.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" +checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" dependencies = [ "indexmap", - "serde", - "serde_spanned 1.0.0", - "toml_datetime 0.7.0", + "serde_core", + "serde_spanned 1.0.4", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", "winnow", @@ -5907,11 +5961,11 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.0" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -5928,11 +5982,23 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.23.10+spec-1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +dependencies = [ + "indexmap", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "winnow", +] + [[package]] name = "toml_parser" -version = "1.0.2" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" dependencies = [ "winnow", ] @@ -5945,9 +6011,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.0.2" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "tower" @@ -5978,9 +6044,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -5990,20 +6056,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -6022,9 +6088,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "matchers", "nu-ansi-term", @@ -6108,9 +6174,9 @@ checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "uint" @@ -6138,9 +6204,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" @@ -6197,9 +6263,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -6324,29 +6390,20 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.5+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4" -dependencies = [ - "wasip2", -] - [[package]] name = "wasip2" -version = "1.0.0+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.101" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", "once_cell", @@ -6355,27 +6412,14 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.106", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.51" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -6384,9 +6428,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.101" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6394,22 +6438,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.101" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.106", - "wasm-bindgen-backend", + "syn 2.0.114", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.101" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ "unicode-ident", ] @@ -6461,14 +6505,14 @@ version = "0.221.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d06bfa36ab3ac2be0dee563380147a5b81ba10dd8885d7fbbc9eb574be67d185" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", ] [[package]] name = "web-sys" -version = "0.3.78" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -6490,14 +6534,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" dependencies = [ - "webpki-root-certs 1.0.2", + "webpki-root-certs 1.0.5", ] [[package]] name = "webpki-root-certs" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" dependencies = [ "rustls-pki-types", ] @@ -6524,7 +6568,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -6535,67 +6579,61 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.1.3", + "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "windows-link" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - -[[package]] -name = "windows-link" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -6631,16 +6669,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -6676,19 +6714,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -6705,9 +6743,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -6723,9 +6761,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -6741,9 +6779,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -6753,9 +6791,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -6771,9 +6809,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -6789,9 +6827,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -6807,9 +6845,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -6825,30 +6863,30 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen" -version = "0.45.1" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wyz" @@ -6879,11 +6917,10 @@ checksum = "bfe269e7b803a5e8e20cbd97860e136529cd83bf2c9c6d37b142467e7e1f051f" [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -6891,34 +6928,34 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -6938,35 +6975,35 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -6975,9 +7012,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -6986,11 +7023,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] + +[[package]] +name = "zmij" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65" diff --git a/Cargo.toml b/Cargo.toml index d5715fb..3a864d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,8 +77,9 @@ qp-wormhole-prover = { git = "https://github.com/Quantus-Network/qp-zk-circuits" qp-wormhole-verifier = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-verifier", default-features = false, features = ["std"] } qp-wormhole-aggregator = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-aggregator", default-features = false, features = ["std", "rayon"] } qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-zk-circuits-common", default-features = false, features = ["std"] } -qp-plonky2 = { version = "1.1.3", default-features = false, features = ["std"] } +qp-plonky2 = { version = "1.1.3", default-features = false } [dev-dependencies] tempfile = "3.8" +serial_test = "3.1" qp-wormhole-test-helpers = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "test-helpers" } diff --git a/tests/wormhole_integration.rs b/tests/wormhole_integration.rs new file mode 100644 index 0000000..6fedc3f --- /dev/null +++ b/tests/wormhole_integration.rs @@ -0,0 +1,1064 @@ +//! Integration tests for wormhole proof verification on-chain +//! +//! These tests require a local Quantus node running at ws://127.0.0.1:9944 +//! with funded developer accounts (crystal_alice, crystal_bob, crystal_charlie). +//! +//! Run with: `cargo test --test wormhole_integration -- --ignored --nocapture` +//! +//! The tests verify the full end-to-end flow: +//! 1. Fund an unspendable account via wormhole transfer +//! 2. Generate a ZK proof of the transfer +//! 3. Submit the proof for on-chain verification +//! 4. For aggregated proofs: generate multiple proofs and aggregate them +//! +//! Note: For aggregation, proofs must be from the same block or consecutive blocks +//! with valid parent hash linkage. We use batch transfers to ensure same-block proofs. + +use plonky2::plonk::{circuit_data::CircuitConfig, proof::ProofWithPublicInputs}; +use qp_wormhole_circuit::inputs::{ + AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, +}; +use qp_wormhole_circuit::nullifier::Nullifier; +use qp_wormhole_prover::WormholeProver; +use qp_wormhole_verifier::WormholeVerifier; +use qp_zk_circuits_common::{ + circuit::{C, D, F}, + storage_proof::prepare_proof_for_circuit, + utils::{BytesDigest, Digest}, +}; +use quantus_cli::{ + chain::{ + client::QuantusClient, + quantus_subxt::{self as quantus_node, api::wormhole}, + }, + wallet::{QuantumKeyPair, WalletManager}, +}; +use rand::{rng, RngCore}; +use serial_test::serial; +use sp_core::{ + crypto::{AccountId32, Ss58Codec}, + Hasher, +}; +use std::time::Duration; +use subxt::{ + backend::legacy::rpc_methods::ReadProof, + ext::{codec::Encode, jsonrpsee::core::client::ClientT}, + tx::TxStatus, + utils::{to_hex, AccountId32 as SubxtAccountId}, +}; + +/// Default local node URL for testing +const LOCAL_NODE_URL: &str = "ws://127.0.0.1:9944"; + +/// Native asset ID (matches chain configuration) +const NATIVE_ASSET_ID: u32 = 0; + +/// Scale down factor for quantizing amounts (10^10 to go from 12 to 2 decimal places) +const SCALE_DOWN_FACTOR: u128 = 10_000_000_000; + +/// Volume fee rate in basis points (10 bps = 0.1%) +const VOLUME_FEE_BPS: u32 = 10; + +/// Type alias for transfer proof storage key +type TransferProofKey = (u32, u64, AccountId32, AccountId32, u128); + +/// Compute output amount after fee deduction +fn compute_output_amount(input_amount: u32, fee_bps: u32) -> u32 { + ((input_amount as u64) * (10000 - fee_bps as u64) / 10000) as u32 +} + +/// Generate a random 32-byte secret +fn generate_random_secret() -> [u8; 32] { + let mut secret = [0u8; 32]; + rng().fill_bytes(&mut secret); + secret +} + +/// Helper struct to hold proof generation context +struct ProofContext { + proof: ProofWithPublicInputs, + proof_bytes: Vec, + public_inputs: PublicCircuitInputs, +} + +/// Helper struct to hold aggregated proof context +struct AggregatedProofContext { + proof_bytes: Vec, + public_inputs: AggregatedPublicCircuitInputs, +} + +/// Data collected from a transfer, needed to generate proof later +struct TransferData { + secret: [u8; 32], + exit_account_bytes: [u8; 32], + funding_amount: u128, + transfer_count: u64, + from_account: SubxtAccountId, + to_account: SubxtAccountId, + amount: u128, + funding_account: AccountId32, + unspendable_account: qp_zk_circuits_common::utils::Digest, +} + +/// Submit a transaction and return the block hash where it was included +async fn submit_and_get_block_hash( + quantus_client: &QuantusClient, + keypair: &QuantumKeyPair, + call: Call, +) -> Result +where + Call: subxt::tx::Payload, +{ + let client = quantus_client.client(); + + let signer = keypair + .to_subxt_signer() + .map_err(|e| format!("Failed to convert keypair: {}", e))?; + + // Get fresh nonce + let (from_account_id, _version) = + AccountId32::from_ss58check_with_version(&keypair.to_account_id_ss58check()) + .map_err(|e| format!("Invalid from address: {:?}", e))?; + let nonce = quantus_client + .get_account_nonce_from_best_block(&from_account_id) + .await + .map_err(|e| format!("Failed to get nonce: {}", e))?; + + // Build transaction params + use subxt::config::DefaultExtrinsicParamsBuilder; + let params = DefaultExtrinsicParamsBuilder::new().mortal(256).nonce(nonce).build(); + + // Submit and watch for the block hash where it's included + let mut tx_progress = client + .tx() + .sign_and_submit_then_watch(&call, &signer, params) + .await + .map_err(|e| format!("Failed to submit transaction: {}", e))?; + + // Wait for transaction to be included and get the block hash + loop { + match tx_progress.next().await { + Some(Ok(TxStatus::InBestBlock(tx_in_block))) => { + return Ok(tx_in_block.block_hash()); + }, + Some(Ok(TxStatus::InFinalizedBlock(tx_in_block))) => { + return Ok(tx_in_block.block_hash()); + }, + Some(Ok(TxStatus::Error { message })) | Some(Ok(TxStatus::Invalid { message })) => { + return Err(format!("Transaction failed: {}", message)); + }, + Some(Err(e)) => { + return Err(format!("Transaction progress error: {}", e)); + }, + None => { + return Err("Transaction stream ended unexpectedly".to_string()); + }, + _ => continue, + } + } +} + +/// Setup developer wallet for testing +/// Creates the wallet if it doesn't exist +async fn setup_developer_wallet(wallet_name: &str) -> QuantumKeyPair { + let wallet_manager = WalletManager::new().expect("Failed to create wallet manager"); + + // Try to load existing wallet, or create if doesn't exist + // get_wallet returns Ok(Some(...)) if wallet exists, Ok(None) if it doesn't + match wallet_manager.get_wallet(wallet_name, Some("")) { + Ok(Some(_wallet_info)) => { + // Wallet exists, load the keypair (developer wallets use empty password) + let wallet_data = + wallet_manager.load_wallet(wallet_name, "").expect("Failed to load wallet data"); + wallet_data.keypair + }, + Ok(None) | Err(_) => { + // Wallet doesn't exist, create developer wallet (pre-funded on dev chains) + println!(" Creating developer wallet '{}'...", wallet_name); + wallet_manager + .create_developer_wallet(wallet_name) + .await + .expect("Failed to create developer wallet"); + + let wallet_data = + wallet_manager.load_wallet(wallet_name, "").expect("Failed to load wallet data"); + wallet_data.keypair + }, + } +} + +/// Generate a wormhole proof by funding an unspendable account +async fn generate_wormhole_proof( + quantus_client: &QuantusClient, + keypair: &QuantumKeyPair, + funding_amount: u128, + exit_account_bytes: [u8; 32], + secret: [u8; 32], +) -> Result { + // First submit the transfer and collect transfer data + let transfer_data = submit_wormhole_transfer( + quantus_client, + keypair, + funding_amount, + exit_account_bytes, + secret, + ) + .await?; + + // Wait a moment then get the latest block to use for proof generation + tokio::time::sleep(Duration::from_millis(500)).await; + let block_hash = quantus_client + .get_latest_block() + .await + .map_err(|e| format!("Failed to get latest block: {}", e))?; + + // Generate proof from the transfer data using this block + generate_proof_from_transfer(quantus_client, &transfer_data, block_hash).await +} + +/// Submit a wormhole transfer and return the transfer data needed for proof generation +async fn submit_wormhole_transfer( + quantus_client: &QuantusClient, + keypair: &QuantumKeyPair, + funding_amount: u128, + exit_account_bytes: [u8; 32], + secret: [u8; 32], +) -> Result { + let secret_digest: BytesDigest = + secret.try_into().map_err(|e| format!("Failed to convert secret: {:?}", e))?; + + let client = quantus_client.client(); + let funding_account = + AccountId32::new(qp_poseidon::PoseidonHasher::hash(keypair.public_key.as_ref()).0); + + // Generate unspendable account from secret + let unspendable_account = + qp_wormhole_circuit::unspendable_account::UnspendableAccount::from_secret(secret_digest) + .account_id; + let unspendable_account_bytes_digest = + qp_zk_circuits_common::utils::digest_felts_to_bytes(unspendable_account); + let unspendable_account_bytes: [u8; 32] = unspendable_account_bytes_digest + .as_ref() + .try_into() + .expect("BytesDigest is always 32 bytes"); + let unspendable_account_id = SubxtAccountId(unspendable_account_bytes); + + println!(" Unspendable account: 0x{}", hex::encode(&unspendable_account_bytes)); + println!(" Exit account: 0x{}", hex::encode(&exit_account_bytes)); + + // Create and submit transfer to unspendable account + let transfer_tx = quantus_node::api::tx().wormhole().transfer_native( + subxt::ext::subxt_core::utils::MultiAddress::Id(unspendable_account_id.clone()), + funding_amount, + ); + + println!(" Submitting transfer to unspendable account..."); + + let quantum_keypair = QuantumKeyPair { + public_key: keypair.public_key.clone(), + private_key: keypair.private_key.clone(), + }; + + // Submit transaction and get the actual block hash where it was included + let block_hash = submit_and_get_block_hash(quantus_client, &quantum_keypair, transfer_tx) + .await + .map_err(|e| format!("Transfer failed: {}", e))?; + + println!(" Transfer included in block: {:?}", block_hash); + + // Find the NativeTransferred event that matches our unspendable account + let events_api = client + .events() + .at(block_hash) + .await + .map_err(|e| format!("Failed to get events: {}", e))?; + + // Find the event that matches our specific unspendable account + let mut matching_event = None; + for event_result in events_api.find::() { + let event = event_result.map_err(|e| format!("Failed to decode event: {}", e))?; + // Check if this event is for our unspendable account + if event.to.0 == unspendable_account_bytes { + matching_event = Some(event); + break; + } + } + + let event = matching_event.ok_or_else(|| { + "No NativeTransferred event found for our unspendable account".to_string() + })?; + + println!(" Transfer event: amount={}, transfer_count={}", event.amount, event.transfer_count); + + Ok(TransferData { + secret, + exit_account_bytes, + funding_amount, + transfer_count: event.transfer_count, + from_account: event.from, + to_account: event.to, + amount: event.amount, + funding_account, + unspendable_account, + }) +} + +/// Generate a proof from transfer data using a specific block for the storage proof +async fn generate_proof_from_transfer( + quantus_client: &QuantusClient, + transfer_data: &TransferData, + block_hash: subxt::utils::H256, +) -> Result { + let client = quantus_client.client(); + + let secret_digest: BytesDigest = transfer_data + .secret + .try_into() + .map_err(|e| format!("Failed to convert secret: {:?}", e))?; + + let blocks = client + .blocks() + .at(block_hash) + .await + .map_err(|e| format!("Failed to get block: {}", e))?; + + // Get storage proof + let from_account = AccountId32::new(transfer_data.from_account.0); + let to_account = AccountId32::new(transfer_data.to_account.0); + + let leaf_hash = qp_poseidon::PoseidonHasher::hash_storage::( + &( + NATIVE_ASSET_ID, + transfer_data.transfer_count, + from_account.clone(), + to_account.clone(), + transfer_data.amount, + ) + .encode(), + ); + + let proof_address = quantus_node::api::storage().wormhole().transfer_proof(( + NATIVE_ASSET_ID, + transfer_data.transfer_count, + transfer_data.from_account.clone(), + transfer_data.to_account.clone(), + transfer_data.amount, + )); + + let mut final_key = proof_address.to_root_bytes(); + final_key.extend_from_slice(&leaf_hash); + + let storage_api = client.storage().at(block_hash); + let val = storage_api + .fetch_raw(final_key.clone()) + .await + .map_err(|e| format!("Failed to fetch storage: {}", e))?; + + if val.is_none() { + return Err("Storage key not found".to_string()); + } + + // Get read proof via RPC + let proof_params = subxt::ext::jsonrpsee::rpc_params![vec![to_hex(&final_key)], block_hash]; + let read_proof: ReadProof = quantus_client + .rpc_client() + .request("state_getReadProof", proof_params) + .await + .map_err(|e| format!("Failed to get read proof: {}", e))?; + + let header = blocks.header(); + + let state_root = BytesDigest::try_from(header.state_root.as_bytes()) + .map_err(|e| format!("Failed to convert state root: {}", e))?; + let parent_hash = BytesDigest::try_from(header.parent_hash.as_bytes()) + .map_err(|e| format!("Failed to convert parent hash: {}", e))?; + let extrinsics_root = BytesDigest::try_from(header.extrinsics_root.as_bytes()) + .map_err(|e| format!("Failed to convert extrinsics root: {}", e))?; + let digest = header + .digest + .encode() + .try_into() + .map_err(|_| "Failed to encode digest".to_string())?; + + let block_number = header.number; + + // Prepare storage proof for circuit + let processed_storage_proof = prepare_proof_for_circuit( + read_proof.proof.iter().map(|proof| proof.0.clone()).collect(), + hex::encode(header.state_root.0), + leaf_hash, + ) + .map_err(|e| format!("Failed to prepare storage proof: {}", e))?; + + // Quantize the funding amount + let input_amount_quantized: u32 = (transfer_data.funding_amount / SCALE_DOWN_FACTOR) + .try_into() + .map_err(|_| "Funding amount too large after quantization".to_string())?; + + let output_amount_quantized = compute_output_amount(input_amount_quantized, VOLUME_FEE_BPS); + + let exit_account_digest = BytesDigest::try_from(&transfer_data.exit_account_bytes[..]) + .map_err(|e| format!("Failed to convert exit account: {}", e))?; + + let inputs = CircuitInputs { + private: PrivateCircuitInputs { + secret: secret_digest, + transfer_count: transfer_data.transfer_count, + funding_account: BytesDigest::try_from(transfer_data.funding_account.as_ref() as &[u8]) + .map_err(|e| format!("Failed to convert funding account: {}", e))?, + storage_proof: processed_storage_proof, + unspendable_account: Digest::from(transfer_data.unspendable_account).into(), + state_root, + extrinsics_root, + digest, + input_amount: input_amount_quantized, + }, + public: PublicCircuitInputs { + output_amount: output_amount_quantized, + volume_fee_bps: VOLUME_FEE_BPS, + nullifier: Nullifier::from_preimage(secret_digest, transfer_data.transfer_count) + .hash + .into(), + exit_account: exit_account_digest, + block_hash: BytesDigest::try_from(block_hash.as_ref()) + .map_err(|e| format!("Failed to convert block hash: {}", e))?, + parent_hash, + block_number, + asset_id: NATIVE_ASSET_ID, + }, + }; + + println!(" Generating ZK proof (this may take ~30s)..."); + let config = CircuitConfig::standard_recursion_zk_config(); + let prover = WormholeProver::new(config); + let prover_next = prover.commit(&inputs).map_err(|e| format!("Failed to commit: {}", e))?; + let proof: ProofWithPublicInputs<_, _, 2> = + prover_next.prove().map_err(|e| format!("Proof generation failed: {}", e))?; + + let public_inputs = PublicCircuitInputs::try_from(&proof) + .map_err(|e| format!("Failed to parse public inputs: {}", e))?; + + let proof_bytes = proof.to_bytes(); + println!(" Proof generated! Size: {} bytes", proof_bytes.len()); + + Ok(ProofContext { proof, proof_bytes, public_inputs }) +} + +/// Submit a single proof for on-chain verification +async fn submit_single_proof_for_verification( + quantus_client: &QuantusClient, + proof_bytes: Vec, +) -> Result<(), String> { + println!(" Submitting single proof for on-chain verification..."); + + let verify_tx = quantus_node::api::tx().wormhole().verify_wormhole_proof(proof_bytes); + + let unsigned_tx = quantus_client + .client() + .tx() + .create_unsigned(&verify_tx) + .map_err(|e| format!("Failed to create unsigned tx: {}", e))?; + + let mut tx_progress = unsigned_tx + .submit_and_watch() + .await + .map_err(|e| format!("Failed to submit tx: {}", e))?; + + while let Some(Ok(status)) = tx_progress.next().await { + match status { + TxStatus::InBestBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + println!(" ✅ Single proof verified on-chain! Block: {:?}", block_hash); + return Ok(()); + }, + TxStatus::InFinalizedBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + println!( + " ✅ Single proof verified on-chain (finalized)! Block: {:?}", + block_hash + ); + return Ok(()); + }, + TxStatus::Error { message } | TxStatus::Invalid { message } => { + return Err(format!("Transaction failed: {}", message)); + }, + _ => continue, + } + } + + Err("Transaction stream ended unexpectedly".to_string()) +} + +/// Aggregate multiple proofs into one +fn aggregate_proofs( + proof_contexts: Vec, + depth: usize, + branching_factor: usize, +) -> Result { + use qp_wormhole_aggregator::{ + aggregator::WormholeProofAggregator, circuits::tree::TreeAggregationConfig, + }; + + println!( + " Aggregating {} proofs (depth={}, branching_factor={})...", + proof_contexts.len(), + depth, + branching_factor + ); + + let config = CircuitConfig::standard_recursion_zk_config(); + let verifier = WormholeVerifier::new(config.clone(), None); + + let aggregation_config = TreeAggregationConfig::new(branching_factor, depth as u32); + + if proof_contexts.len() > aggregation_config.num_leaf_proofs { + return Err(format!( + "Too many proofs: {} provided, max {} for depth={} branching_factor={}", + proof_contexts.len(), + aggregation_config.num_leaf_proofs, + depth, + branching_factor + )); + } + + let mut aggregator = + WormholeProofAggregator::new(verifier.circuit_data).with_config(aggregation_config); + + for (idx, ctx) in proof_contexts.into_iter().enumerate() { + println!(" Adding proof {} to aggregator...", idx + 1); + println!(" Public inputs:"); + println!(" asset_id: {}", ctx.public_inputs.asset_id); + println!(" output_amount: {}", ctx.public_inputs.output_amount); + println!(" volume_fee_bps: {}", ctx.public_inputs.volume_fee_bps); + println!(" nullifier: {:?}", ctx.public_inputs.nullifier); + println!(" exit_account: {:?}", ctx.public_inputs.exit_account); + println!(" block_hash: {:?}", ctx.public_inputs.block_hash); + println!(" parent_hash: {:?}", ctx.public_inputs.parent_hash); + println!(" block_number: {}", ctx.public_inputs.block_number); + aggregator + .push_proof(ctx.proof) + .map_err(|e| format!("Failed to push proof: {}", e))?; + } + + println!(" Running aggregation (this may take ~60s)..."); + let aggregated_result = + aggregator.aggregate().map_err(|e| format!("Aggregation failed: {}", e))?; + + let public_inputs = AggregatedPublicCircuitInputs::try_from_slice( + aggregated_result.proof.public_inputs.as_slice(), + ) + .map_err(|e| format!("Failed to parse aggregated public inputs: {}", e))?; + + // Verify locally first + println!(" Verifying aggregated proof locally..."); + aggregated_result + .circuit_data + .verify(aggregated_result.proof.clone()) + .map_err(|e| format!("Local verification failed: {}", e))?; + + let proof_bytes = aggregated_result.proof.to_bytes(); + println!( + " Aggregation complete! Size: {} bytes, {} nullifiers", + proof_bytes.len(), + public_inputs.nullifiers.len() + ); + + Ok(AggregatedProofContext { proof_bytes, public_inputs }) +} + +/// Submit an aggregated proof for on-chain verification +async fn submit_aggregated_proof_for_verification( + quantus_client: &QuantusClient, + proof_bytes: Vec, +) -> Result<(), String> { + println!(" Submitting aggregated proof for on-chain verification..."); + + let verify_tx = quantus_node::api::tx().wormhole().verify_aggregated_proof(proof_bytes); + + let unsigned_tx = quantus_client + .client() + .tx() + .create_unsigned(&verify_tx) + .map_err(|e| format!("Failed to create unsigned tx: {}", e))?; + + let mut tx_progress = unsigned_tx + .submit_and_watch() + .await + .map_err(|e| format!("Failed to submit tx: {}", e))?; + + while let Some(Ok(status)) = tx_progress.next().await { + match status { + TxStatus::InBestBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + println!(" ✅ Aggregated proof verified on-chain! Block: {:?}", block_hash); + return Ok(()); + }, + TxStatus::InFinalizedBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + println!( + " ✅ Aggregated proof verified on-chain (finalized)! Block: {:?}", + block_hash + ); + return Ok(()); + }, + TxStatus::Error { message } | TxStatus::Invalid { message } => { + return Err(format!("Transaction failed: {}", message)); + }, + _ => continue, + } + } + + Err("Transaction stream ended unexpectedly".to_string()) +} + +/// Integration test: Generate and verify a single wormhole proof on-chain +/// +/// This test: +/// 1. Connects to a local Quantus node +/// 2. Uses a developer wallet (crystal_alice) to fund an unspendable account +/// 3. Generates a ZK proof of the transfer +/// 4. Submits the proof for on-chain verification +#[tokio::test] +#[serial] +#[ignore] // Requires running local node - run with `cargo test -- --ignored` +async fn test_single_proof_on_chain_verification() { + println!("\n=== Single Proof On-Chain Verification Test ===\n"); + + // Connect to local node + println!("1. Connecting to local node at {}...", LOCAL_NODE_URL); + let quantus_client = QuantusClient::new(LOCAL_NODE_URL) + .await + .expect("Failed to connect to local node"); + println!(" Connected!"); + + // Setup developer wallet + println!("2. Setting up developer wallet (crystal_alice)..."); + let keypair = setup_developer_wallet("crystal_alice").await; + println!(" Wallet address: {}", keypair.to_account_id_ss58check()); + + // Generate random secret and exit account + let secret = generate_random_secret(); + let mut exit_account = [0u8; 32]; + rng().fill_bytes(&mut exit_account); + + // Use a small funding amount (1 token = 10^12 units) + let funding_amount: u128 = 1_000_000_000_000; // 1 token + + println!("3. Generating wormhole proof..."); + println!(" Funding amount: {} units (1 token)", funding_amount); + println!(" Secret: 0x{}", hex::encode(&secret)); + + let proof_context = + generate_wormhole_proof(&quantus_client, &keypair, funding_amount, exit_account, secret) + .await + .expect("Failed to generate proof"); + + println!( + " Public inputs - output_amount: {}, nullifier: {:?}", + proof_context.public_inputs.output_amount, proof_context.public_inputs.nullifier + ); + + // Submit for on-chain verification + println!("4. Verifying proof on-chain..."); + submit_single_proof_for_verification(&quantus_client, proof_context.proof_bytes) + .await + .expect("On-chain verification failed"); + + println!("\n=== Single Proof Test PASSED ===\n"); +} + +/// Integration test: Generate, aggregate, and verify multiple wormhole proofs on-chain +/// +/// This test: +/// 1. Connects to a local Quantus node +/// 2. Uses developer wallets to fund multiple unspendable accounts +/// 3. Generates ZK proofs for each transfer (all from the same block for aggregation) +/// 4. Aggregates the proofs into a single proof +/// 5. Submits the aggregated proof for on-chain verification +#[tokio::test] +#[serial] +#[ignore] // Requires running local node - run with `cargo test -- --ignored` +async fn test_aggregated_proof_on_chain_verification() { + println!("\n=== Aggregated Proof On-Chain Verification Test ===\n"); + + // Connect to local node + println!("1. Connecting to local node at {}...", LOCAL_NODE_URL); + let quantus_client = QuantusClient::new(LOCAL_NODE_URL) + .await + .expect("Failed to connect to local node"); + println!(" Connected!"); + + // Setup developer wallets - use different wallets for different proofs to avoid nonce issues + println!("2. Setting up developer wallets..."); + let keypair_alice = setup_developer_wallet("crystal_alice").await; + let keypair_bob = setup_developer_wallet("crystal_bob").await; + println!(" Alice address: {}", keypair_alice.to_account_id_ss58check()); + println!(" Bob address: {}", keypair_bob.to_account_id_ss58check()); + + let keypairs = [&keypair_alice, &keypair_bob]; + let mut transfer_data_list = Vec::new(); + + // Phase 1: Submit all transfers first + println!("3. Submitting wormhole transfers..."); + for (i, keypair) in keypairs.iter().enumerate() { + println!("\n --- Transfer {} ---", i + 1); + + let secret = generate_random_secret(); + let mut exit_account = [0u8; 32]; + rng().fill_bytes(&mut exit_account); + + // Use a small funding amount (0.5 tokens each) + let funding_amount: u128 = 500_000_000_000; // 0.5 tokens + + println!(" Funding amount: {} units (0.5 tokens)", funding_amount); + println!(" Secret: 0x{}", hex::encode(&secret)); + + let transfer_data = submit_wormhole_transfer( + &quantus_client, + keypair, + funding_amount, + exit_account, + secret, + ) + .await + .expect("Failed to submit transfer"); + + transfer_data_list.push(transfer_data); + } + + // Wait for all transfers to be available in storage + println!("\n Waiting for transfers to be confirmed..."); + tokio::time::sleep(Duration::from_secs(2)).await; + + // Phase 2: Get a common block hash and generate all proofs from it + let common_block_hash = + quantus_client.get_latest_block().await.expect("Failed to get latest block"); + println!(" Using common block for all proofs: {:?}", common_block_hash); + + let mut proof_contexts = Vec::new(); + println!("\n4. Generating proofs from common block..."); + for (i, transfer_data) in transfer_data_list.iter().enumerate() { + println!("\n --- Proof {} ---", i + 1); + + let proof_context = + generate_proof_from_transfer(&quantus_client, transfer_data, common_block_hash) + .await + .expect("Failed to generate proof"); + + println!( + " Public inputs - output_amount: {}, nullifier: {:?}", + proof_context.public_inputs.output_amount, proof_context.public_inputs.nullifier + ); + + proof_contexts.push(proof_context); + } + + // Aggregate proofs + println!("\n4. Aggregating {} proofs...", proof_contexts.len()); + let aggregated_context = aggregate_proofs( + proof_contexts, + 1, // depth + 2, // branching_factor (2^1 = 2 max proofs) + ) + .expect("Failed to aggregate proofs"); + + println!( + " Aggregated {} nullifiers, {} account entries", + aggregated_context.public_inputs.nullifiers.len(), + aggregated_context.public_inputs.account_data.len() + ); + + // Verify aggregated proof on-chain + println!("5. Verifying aggregated proof on-chain..."); + submit_aggregated_proof_for_verification(&quantus_client, aggregated_context.proof_bytes) + .await + .expect("On-chain aggregated verification failed"); + + println!("\n=== Aggregated Proof Test PASSED ===\n"); +} + +/// Integration test: Test single proof with specific exit account +/// +/// This test verifies that the exit account in the proof matches what we specified. +#[tokio::test] +#[serial] +#[ignore] // Requires running local node - run with `cargo test -- --ignored` +async fn test_single_proof_exit_account_verification() { + println!("\n=== Exit Account Verification Test ===\n"); + + // Connect to local node + println!("1. Connecting to local node..."); + let quantus_client = QuantusClient::new(LOCAL_NODE_URL) + .await + .expect("Failed to connect to local node"); + + // Setup developer wallet + println!("2. Setting up developer wallet..."); + let keypair = setup_developer_wallet("crystal_alice").await; + + // Generate random secret + let secret = generate_random_secret(); + + // Use Bob's address as the exit account + let keypair_bob = setup_developer_wallet("crystal_bob").await; + let bob_account = keypair_bob.to_account_id_ss58check(); + println!(" Using Bob's address as exit account: {}", bob_account); + + // Convert Bob's address to bytes (use from_ss58check_with_version for Quantus SS58 format) + let (bob_account_id, _version) = + AccountId32::from_ss58check_with_version(&bob_account).expect("Invalid SS58"); + let exit_account_bytes: [u8; 32] = bob_account_id.into(); + + let funding_amount: u128 = 1_000_000_000_000; + + println!("3. Generating wormhole proof with specific exit account..."); + let proof_context = generate_wormhole_proof( + &quantus_client, + &keypair, + funding_amount, + exit_account_bytes, + secret, + ) + .await + .expect("Failed to generate proof"); + + // Verify the exit account in public inputs matches what we specified + let exit_account_from_proof: [u8; 32] = proof_context + .public_inputs + .exit_account + .as_ref() + .try_into() + .expect("Exit account should be 32 bytes"); + + assert_eq!( + exit_account_bytes, exit_account_from_proof, + "Exit account in proof should match specified account" + ); + println!(" ✅ Exit account verification passed!"); + + // Submit for on-chain verification + println!("4. Verifying proof on-chain..."); + submit_single_proof_for_verification(&quantus_client, proof_context.proof_bytes) + .await + .expect("On-chain verification failed"); + + println!("\n=== Exit Account Verification Test PASSED ===\n"); +} + +/// Integration test: Verify nullifier uniqueness across proofs +/// +/// This test ensures that different secrets produce different nullifiers, +/// which is critical for preventing double-spending. +#[tokio::test] +#[serial] +#[ignore] // Requires running local node - run with `cargo test -- --ignored` +async fn test_nullifier_uniqueness() { + println!("\n=== Nullifier Uniqueness Test ===\n"); + + // Connect to local node + println!("1. Connecting to local node..."); + let quantus_client = QuantusClient::new(LOCAL_NODE_URL) + .await + .expect("Failed to connect to local node"); + + // Setup developer wallet + println!("2. Setting up developer wallet..."); + let keypair = setup_developer_wallet("crystal_alice").await; + + // Generate two proofs with different secrets + let secret1 = generate_random_secret(); + let secret2 = generate_random_secret(); + assert_ne!(secret1, secret2, "Secrets should be different"); + + let mut exit_account = [0u8; 32]; + rng().fill_bytes(&mut exit_account); + + let funding_amount: u128 = 500_000_000_000; + + println!("3. Generating first proof..."); + let proof1 = + generate_wormhole_proof(&quantus_client, &keypair, funding_amount, exit_account, secret1) + .await + .expect("Failed to generate first proof"); + + // Wait for nonce to update + tokio::time::sleep(Duration::from_secs(2)).await; + + println!("4. Generating second proof..."); + let proof2 = + generate_wormhole_proof(&quantus_client, &keypair, funding_amount, exit_account, secret2) + .await + .expect("Failed to generate second proof"); + + // Verify nullifiers are different + assert_ne!( + proof1.public_inputs.nullifier, proof2.public_inputs.nullifier, + "Nullifiers from different secrets should be different" + ); + println!(" ✅ Nullifiers are unique!"); + println!(" Nullifier 1: {:?}", proof1.public_inputs.nullifier); + println!(" Nullifier 2: {:?}", proof2.public_inputs.nullifier); + + // Verify both proofs on-chain + println!("5. Verifying first proof on-chain..."); + submit_single_proof_for_verification(&quantus_client, proof1.proof_bytes) + .await + .expect("First proof verification failed"); + + println!("6. Verifying second proof on-chain..."); + submit_single_proof_for_verification(&quantus_client, proof2.proof_bytes) + .await + .expect("Second proof verification failed"); + + println!("\n=== Nullifier Uniqueness Test PASSED ===\n"); +} + +/// Integration test: Full end-to-end workflow with multiple aggregated proofs +/// +/// This is a comprehensive test that exercises the full wormhole workflow: +/// 1. Multiple transfers from different accounts +/// 2. Multiple proof generations +/// 3. Proof aggregation +/// 4. On-chain verification of aggregated proof +#[tokio::test] +#[serial] +#[ignore] // Requires running local node - run with `cargo test -- --ignored` +async fn test_full_wormhole_workflow() { + println!("\n=== Full Wormhole Workflow Test ===\n"); + + // Connect to local node + println!("1. Connecting to local node at {}...", LOCAL_NODE_URL); + let quantus_client = QuantusClient::new(LOCAL_NODE_URL) + .await + .expect("Failed to connect to local node"); + println!(" Connected!"); + + // Setup developer wallet + println!("2. Setting up developer wallet..."); + let keypair = setup_developer_wallet("crystal_alice").await; + println!(" Address: {}", keypair.to_account_id_ss58check()); + + // Step 1: Generate and verify a single proof + println!("\n--- Step 1: Single Proof ---"); + let secret1 = generate_random_secret(); + let mut exit1 = [0u8; 32]; + rng().fill_bytes(&mut exit1); + + let proof1 = generate_wormhole_proof( + &quantus_client, + &keypair, + 1_000_000_000_000, // 1 token + exit1, + secret1, + ) + .await + .expect("Failed to generate proof 1"); + + println!(" Generated proof 1, verifying on-chain..."); + submit_single_proof_for_verification(&quantus_client, proof1.proof_bytes.clone()) + .await + .expect("Proof 1 verification failed"); + + // Wait for state to settle + tokio::time::sleep(Duration::from_secs(2)).await; + + // Step 2: Submit multiple transfers for aggregation + println!("\n--- Step 2: Submitting Transfers for Aggregation ---"); + let mut transfer_data_list = Vec::new(); + + for i in 0..2 { + println!(" Submitting transfer {}...", i + 1); + let secret = generate_random_secret(); + let mut exit = [0u8; 32]; + rng().fill_bytes(&mut exit); + + let transfer_data = submit_wormhole_transfer( + &quantus_client, + &keypair, + 500_000_000_000, // 0.5 tokens + exit, + secret, + ) + .await + .expect(&format!("Failed to submit transfer {}", i + 1)); + + transfer_data_list.push(transfer_data); + } + + // Wait for transfers to be confirmed and get a common block + println!(" Waiting for transfers to be confirmed..."); + tokio::time::sleep(Duration::from_secs(2)).await; + + let common_block_hash = + quantus_client.get_latest_block().await.expect("Failed to get latest block"); + println!(" Using common block for all proofs: {:?}", common_block_hash); + + // Generate all proofs from the common block + let mut proofs_for_aggregation = Vec::new(); + for (i, transfer_data) in transfer_data_list.iter().enumerate() { + println!(" Generating proof {}...", i + 1); + let proof = generate_proof_from_transfer(&quantus_client, transfer_data, common_block_hash) + .await + .expect(&format!("Failed to generate proof {}", i + 1)); + proofs_for_aggregation.push(proof); + } + + // Step 3: Aggregate and verify + println!("\n--- Step 3: Aggregation ---"); + let aggregated = + aggregate_proofs(proofs_for_aggregation, 1, 2).expect("Failed to aggregate proofs"); + + println!(" Verifying aggregated proof on-chain..."); + submit_aggregated_proof_for_verification(&quantus_client, aggregated.proof_bytes) + .await + .expect("Aggregated proof verification failed"); + + println!("\n=== Full Wormhole Workflow Test PASSED ===\n"); +} + +/// Test that the fee calculation is correct +#[test] +fn test_fee_calculation_consistency() { + // Test various amounts and verify the fee calculation + let test_cases = [ + (1000u32, 10u32, 999u32), // 1000 * 0.999 = 999 + (10000, 10, 9990), // 10000 * 0.999 = 9990 + (100, 10, 99), // 100 * 0.999 = 99 + (1, 10, 0), // 1 * 0.999 = 0 (rounds down) + (0, 10, 0), // 0 * 0.999 = 0 + (1000, 100, 990), // 1% fee: 1000 * 0.99 = 990 + (1000, 0, 1000), // 0% fee: no deduction + ]; + + for (input, fee_bps, expected_output) in test_cases { + let output = compute_output_amount(input, fee_bps); + assert_eq!( + output, expected_output, + "Fee calculation failed for input={}, fee_bps={}: got {}, expected {}", + input, fee_bps, output, expected_output + ); + } + + println!("Fee calculation test passed!"); +} + +/// Test that secrets generate deterministic nullifiers +#[test] +fn test_nullifier_determinism() { + let secret: BytesDigest = [42u8; 32].try_into().expect("valid secret"); + let transfer_count = 123u64; + + let nullifier1 = Nullifier::from_preimage(secret, transfer_count); + let nullifier2 = Nullifier::from_preimage(secret, transfer_count); + + assert_eq!(nullifier1.hash, nullifier2.hash, "Same inputs should produce same nullifier"); + + // Different transfer count should produce different nullifier + let nullifier3 = Nullifier::from_preimage(secret, transfer_count + 1); + assert_ne!( + nullifier1.hash, nullifier3.hash, + "Different transfer counts should produce different nullifiers" + ); + + println!("Nullifier determinism test passed!"); +} From 696dd8cfc921367409bb8699781022394ed25c85 Mon Sep 17 00:00:00 2001 From: Ethan Date: Tue, 20 Jan 2026 20:25:21 -0600 Subject: [PATCH 21/22] fmt --- Cargo.toml | 2 +- src/cli/wormhole.rs | 178 +++++++++++++++++----------------- tests/wormhole_integration.rs | 20 ++-- 3 files changed, 99 insertions(+), 101 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3a864d3..25bd0d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,7 +75,7 @@ anyhow = "1.0" qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-circuit", default-features = false, features = ["std"] } qp-wormhole-prover = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-prover", default-features = false, features = ["std"] } qp-wormhole-verifier = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-verifier", default-features = false, features = ["std"] } -qp-wormhole-aggregator = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-aggregator", default-features = false, features = ["std", "rayon"] } +qp-wormhole-aggregator = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-aggregator", default-features = false, features = ["rayon", "std"] } qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-zk-circuits-common", default-features = false, features = ["std"] } qp-plonky2 = { version = "1.1.3", default-features = false } diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index e08b468..390df75 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -10,10 +10,12 @@ use crate::{ use clap::Subcommand; use plonky2::plonk::{circuit_data::CircuitConfig, proof::ProofWithPublicInputs}; use qp_poseidon::PoseidonHasher; -use qp_wormhole_circuit::inputs::{ - AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, +use qp_wormhole_circuit::{ + inputs::{ + AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, + }, + nullifier::Nullifier, }; -use qp_wormhole_circuit::nullifier::Nullifier; use qp_wormhole_prover::WormholeProver; use qp_wormhole_verifier::WormholeVerifier; use qp_zk_circuits_common::{ @@ -217,7 +219,7 @@ pub async fn handle_wormhole_command( password, password_file, output, - } => { + } => generate_proof( secret, amount, @@ -228,15 +230,12 @@ pub async fn handle_wormhole_command( output, node_url, ) - .await - }, + .await, WormholeCommands::Verify { proof } => verify_proof(proof, node_url).await, - WormholeCommands::Aggregate { proofs, output, depth, branching_factor } => { - aggregate_proofs(proofs, output, depth, branching_factor).await - }, - WormholeCommands::VerifyAggregated { proof } => { - verify_aggregated_proof(proof, node_url).await - }, + WormholeCommands::Aggregate { proofs, output, depth, branching_factor } => + aggregate_proofs(proofs, output, depth, branching_factor).await, + WormholeCommands::VerifyAggregated { proof } => + verify_aggregated_proof(proof, node_url).await, } } @@ -256,14 +255,14 @@ async fn generate_proof( // Parse secret using helper function let secret_array = - parse_secret_hex(&secret_hex).map_err(|e| crate::error::QuantusError::Generic(e))?; + parse_secret_hex(&secret_hex).map_err(crate::error::QuantusError::Generic)?; let secret: BytesDigest = secret_array.try_into().map_err(|e| { crate::error::QuantusError::Generic(format!("Failed to convert secret: {:?}", e)) })?; // Parse exit account using helper function let exit_account_bytes = parse_exit_account(&exit_account_str) - .map_err(|e| crate::error::QuantusError::Generic(e))?; + .map_err(crate::error::QuantusError::Generic)?; let exit_account_id = SubxtAccountId(exit_account_bytes); // Load keypair @@ -410,7 +409,7 @@ async fn generate_proof( // Quantize the funding amount using helper function let input_amount_quantized: u32 = quantize_funding_amount(funding_amount) - .map_err(|e| crate::error::QuantusError::Generic(e))?; + .map_err(crate::error::QuantusError::Generic)?; // Calculate output amount after fee deduction let output_amount_quantized = compute_output_amount(input_amount_quantized, VOLUME_FEE_BPS); @@ -489,7 +488,7 @@ async fn aggregate_proofs( // Validate aggregation parameters using helper function let max_leaf_proofs = validate_aggregation_params(proof_files.len(), depth, branching_factor) - .map_err(|e| crate::error::QuantusError::Generic(e))?; + .map_err(crate::error::QuantusError::Generic)?; // Build the wormhole verifier to get circuit data for parsing proofs let config = CircuitConfig::standard_recursion_zk_config(); @@ -643,6 +642,72 @@ async fn verify_aggregated_proof(proof_file: String, node_url: &str) -> crate::e Err(crate::error::QuantusError::Generic("Transaction stream ended unexpectedly".to_string())) } +async fn verify_proof(proof_file: String, node_url: &str) -> crate::error::Result<()> { + use subxt::tx::TxStatus; + + log_print!("Verifying wormhole proof on-chain..."); + + // Read proof from file + let proof_hex = std::fs::read_to_string(&proof_file).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to read proof file: {}", e)) + })?; + + let proof_bytes = hex::decode(proof_hex.trim()) + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to decode hex: {}", e)))?; + + log_verbose!("Proof size: {} bytes", proof_bytes.len()); + + // Connect to node + let quantus_client = QuantusClient::new(node_url) + .await + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to connect: {}", e)))?; + + log_verbose!("Connected to node"); + + // Create the verify transaction payload + let verify_tx = quantus_node::api::tx().wormhole().verify_wormhole_proof(proof_bytes); + + log_verbose!("Submitting unsigned verification transaction..."); + + // Submit as unsigned extrinsic + let unsigned_tx = quantus_client.client().tx().create_unsigned(&verify_tx).map_err(|e| { + crate::error::QuantusError::Generic(format!("Failed to create unsigned tx: {}", e)) + })?; + + let mut tx_progress = unsigned_tx + .submit_and_watch() + .await + .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to submit tx: {}", e)))?; + + // Wait for transaction inclusion + while let Some(Ok(status)) = tx_progress.next().await { + log_verbose!("Transaction status: {:?}", status); + match status { + TxStatus::InBestBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + log_success!("Proof verified successfully on-chain!"); + log_verbose!("Included in block: {:?}", block_hash); + return Ok(()); + }, + TxStatus::InFinalizedBlock(tx_in_block) => { + let block_hash = tx_in_block.block_hash(); + log_success!("Proof verified successfully on-chain!"); + log_verbose!("Finalized in block: {:?}", block_hash); + return Ok(()); + }, + TxStatus::Error { message } | TxStatus::Invalid { message } => { + return Err(crate::error::QuantusError::Generic(format!( + "Transaction failed: {}", + message + ))); + }, + _ => continue, + } + } + + Err(crate::error::QuantusError::Generic("Transaction stream ended unexpectedly".to_string())) +} + #[cfg(test)] mod tests { use super::*; @@ -767,8 +832,8 @@ mod tests { #[test] fn test_fee_calculation_edge_cases() { - // Test the circuit fee constraint: output_amount * 10000 <= input_amount * (10000 - volume_fee_bps) - // This is equivalent to: output <= input * (1 - fee_rate) + // Test the circuit fee constraint: output_amount * 10000 <= input_amount * (10000 - + // volume_fee_bps) This is equivalent to: output <= input * (1 - fee_rate) // Small amounts where fee rounds to zero let input_small: u32 = 100; @@ -784,8 +849,8 @@ mod tests { let output_medium = compute_output_amount(input_medium, VOLUME_FEE_BPS); assert_eq!(output_medium, 9990); assert!( - (output_medium as u64) * 10000 - <= (input_medium as u64) * (10000 - VOLUME_FEE_BPS as u64) + (output_medium as u64) * 10000 <= + (input_medium as u64) * (10000 - VOLUME_FEE_BPS as u64) ); // Large amounts near u32::MAX @@ -870,8 +935,8 @@ mod tests { let input_amount = inputs.private.input_amount; let output_amount = inputs.public.output_amount; assert!( - (output_amount as u64) * 10000 - <= (input_amount as u64) * (10000 - VOLUME_FEE_BPS as u64), + (output_amount as u64) * 10000 <= + (input_amount as u64) * (10000 - VOLUME_FEE_BPS as u64), "Test inputs violate fee constraint" ); @@ -1119,74 +1184,5 @@ mod tests { fn test_volume_fee_bps_constant() { // Ensure VOLUME_FEE_BPS matches expected value (10 bps = 0.1%) assert_eq!(VOLUME_FEE_BPS, 10); - - // Verify it's a reasonable value (less than 100% = 10000 bps) - assert!(VOLUME_FEE_BPS < 10000); - } -} - -async fn verify_proof(proof_file: String, node_url: &str) -> crate::error::Result<()> { - use subxt::tx::TxStatus; - - log_print!("Verifying wormhole proof on-chain..."); - - // Read proof from file - let proof_hex = std::fs::read_to_string(&proof_file).map_err(|e| { - crate::error::QuantusError::Generic(format!("Failed to read proof file: {}", e)) - })?; - - let proof_bytes = hex::decode(proof_hex.trim()) - .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to decode hex: {}", e)))?; - - log_verbose!("Proof size: {} bytes", proof_bytes.len()); - - // Connect to node - let quantus_client = QuantusClient::new(node_url) - .await - .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to connect: {}", e)))?; - - log_verbose!("Connected to node"); - - // Create the verify transaction payload - let verify_tx = quantus_node::api::tx().wormhole().verify_wormhole_proof(proof_bytes); - - log_verbose!("Submitting unsigned verification transaction..."); - - // Submit as unsigned extrinsic - let unsigned_tx = quantus_client.client().tx().create_unsigned(&verify_tx).map_err(|e| { - crate::error::QuantusError::Generic(format!("Failed to create unsigned tx: {}", e)) - })?; - - let mut tx_progress = unsigned_tx - .submit_and_watch() - .await - .map_err(|e| crate::error::QuantusError::Generic(format!("Failed to submit tx: {}", e)))?; - - // Wait for transaction inclusion - while let Some(Ok(status)) = tx_progress.next().await { - log_verbose!("Transaction status: {:?}", status); - match status { - TxStatus::InBestBlock(tx_in_block) => { - let block_hash = tx_in_block.block_hash(); - log_success!("Proof verified successfully on-chain!"); - log_verbose!("Included in block: {:?}", block_hash); - return Ok(()); - }, - TxStatus::InFinalizedBlock(tx_in_block) => { - let block_hash = tx_in_block.block_hash(); - log_success!("Proof verified successfully on-chain!"); - log_verbose!("Finalized in block: {:?}", block_hash); - return Ok(()); - }, - TxStatus::Error { message } | TxStatus::Invalid { message } => { - return Err(crate::error::QuantusError::Generic(format!( - "Transaction failed: {}", - message - ))); - }, - _ => continue, - } } - - Err(crate::error::QuantusError::Generic("Transaction stream ended unexpectedly".to_string())) } diff --git a/tests/wormhole_integration.rs b/tests/wormhole_integration.rs index 6fedc3f..31f4a80 100644 --- a/tests/wormhole_integration.rs +++ b/tests/wormhole_integration.rs @@ -15,10 +15,12 @@ //! with valid parent hash linkage. We use batch transfers to ensure same-block proofs. use plonky2::plonk::{circuit_data::CircuitConfig, proof::ProofWithPublicInputs}; -use qp_wormhole_circuit::inputs::{ - AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, +use qp_wormhole_circuit::{ + inputs::{ + AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, + }, + nullifier::Nullifier, }; -use qp_wormhole_circuit::nullifier::Nullifier; use qp_wormhole_prover::WormholeProver; use qp_wormhole_verifier::WormholeVerifier; use qp_zk_circuits_common::{ @@ -243,8 +245,8 @@ async fn submit_wormhole_transfer( .expect("BytesDigest is always 32 bytes"); let unspendable_account_id = SubxtAccountId(unspendable_account_bytes); - println!(" Unspendable account: 0x{}", hex::encode(&unspendable_account_bytes)); - println!(" Exit account: 0x{}", hex::encode(&exit_account_bytes)); + println!(" Unspendable account: 0x{}", hex::encode(unspendable_account_bytes)); + println!(" Exit account: 0x{}", hex::encode(exit_account_bytes)); // Create and submit transfer to unspendable account let transfer_tx = quantus_node::api::tx().wormhole().transfer_native( @@ -646,7 +648,7 @@ async fn test_single_proof_on_chain_verification() { println!("3. Generating wormhole proof..."); println!(" Funding amount: {} units (1 token)", funding_amount); - println!(" Secret: 0x{}", hex::encode(&secret)); + println!(" Secret: 0x{}", hex::encode(secret)); let proof_context = generate_wormhole_proof(&quantus_client, &keypair, funding_amount, exit_account, secret) @@ -711,7 +713,7 @@ async fn test_aggregated_proof_on_chain_verification() { let funding_amount: u128 = 500_000_000_000; // 0.5 tokens println!(" Funding amount: {} units (0.5 tokens)", funding_amount); - println!(" Secret: 0x{}", hex::encode(&secret)); + println!(" Secret: 0x{}", hex::encode(secret)); let transfer_data = submit_wormhole_transfer( &quantus_client, @@ -980,7 +982,7 @@ async fn test_full_wormhole_workflow() { secret, ) .await - .expect(&format!("Failed to submit transfer {}", i + 1)); + .unwrap_or_else(|_| panic!("Failed to submit transfer {}", i + 1)); transfer_data_list.push(transfer_data); } @@ -999,7 +1001,7 @@ async fn test_full_wormhole_workflow() { println!(" Generating proof {}...", i + 1); let proof = generate_proof_from_transfer(&quantus_client, transfer_data, common_block_hash) .await - .expect(&format!("Failed to generate proof {}", i + 1)); + .unwrap_or_else(|_| panic!("Failed to generate proof {}", i + 1)); proofs_for_aggregation.push(proof); } From 5304a034342b8bd519571029f16205f3e1f01cfc Mon Sep 17 00:00:00 2001 From: illuzen Date: Wed, 21 Jan 2026 18:58:01 +0800 Subject: [PATCH 22/22] fmt --- Cargo.toml | 2 +- src/cli/wormhole.rs | 35 +++++++++++++++++------------------ tests/wormhole_integration.rs | 8 +++++--- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3a864d3..25bd0d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,7 +75,7 @@ anyhow = "1.0" qp-wormhole-circuit = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-circuit", default-features = false, features = ["std"] } qp-wormhole-prover = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-prover", default-features = false, features = ["std"] } qp-wormhole-verifier = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-verifier", default-features = false, features = ["std"] } -qp-wormhole-aggregator = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-aggregator", default-features = false, features = ["std", "rayon"] } +qp-wormhole-aggregator = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-wormhole-aggregator", default-features = false, features = ["rayon", "std"] } qp-zk-circuits-common = { git = "https://github.com/Quantus-Network/qp-zk-circuits", branch = "illuzen/agg-fees", package = "qp-zk-circuits-common", default-features = false, features = ["std"] } qp-plonky2 = { version = "1.1.3", default-features = false } diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index e08b468..724cba8 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -10,10 +10,12 @@ use crate::{ use clap::Subcommand; use plonky2::plonk::{circuit_data::CircuitConfig, proof::ProofWithPublicInputs}; use qp_poseidon::PoseidonHasher; -use qp_wormhole_circuit::inputs::{ - AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, +use qp_wormhole_circuit::{ + inputs::{ + AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, + }, + nullifier::Nullifier, }; -use qp_wormhole_circuit::nullifier::Nullifier; use qp_wormhole_prover::WormholeProver; use qp_wormhole_verifier::WormholeVerifier; use qp_zk_circuits_common::{ @@ -217,7 +219,7 @@ pub async fn handle_wormhole_command( password, password_file, output, - } => { + } => generate_proof( secret, amount, @@ -228,15 +230,12 @@ pub async fn handle_wormhole_command( output, node_url, ) - .await - }, + .await, WormholeCommands::Verify { proof } => verify_proof(proof, node_url).await, - WormholeCommands::Aggregate { proofs, output, depth, branching_factor } => { - aggregate_proofs(proofs, output, depth, branching_factor).await - }, - WormholeCommands::VerifyAggregated { proof } => { - verify_aggregated_proof(proof, node_url).await - }, + WormholeCommands::Aggregate { proofs, output, depth, branching_factor } => + aggregate_proofs(proofs, output, depth, branching_factor).await, + WormholeCommands::VerifyAggregated { proof } => + verify_aggregated_proof(proof, node_url).await, } } @@ -767,8 +766,8 @@ mod tests { #[test] fn test_fee_calculation_edge_cases() { - // Test the circuit fee constraint: output_amount * 10000 <= input_amount * (10000 - volume_fee_bps) - // This is equivalent to: output <= input * (1 - fee_rate) + // Test the circuit fee constraint: output_amount * 10000 <= input_amount * (10000 - + // volume_fee_bps) This is equivalent to: output <= input * (1 - fee_rate) // Small amounts where fee rounds to zero let input_small: u32 = 100; @@ -784,8 +783,8 @@ mod tests { let output_medium = compute_output_amount(input_medium, VOLUME_FEE_BPS); assert_eq!(output_medium, 9990); assert!( - (output_medium as u64) * 10000 - <= (input_medium as u64) * (10000 - VOLUME_FEE_BPS as u64) + (output_medium as u64) * 10000 <= + (input_medium as u64) * (10000 - VOLUME_FEE_BPS as u64) ); // Large amounts near u32::MAX @@ -870,8 +869,8 @@ mod tests { let input_amount = inputs.private.input_amount; let output_amount = inputs.public.output_amount; assert!( - (output_amount as u64) * 10000 - <= (input_amount as u64) * (10000 - VOLUME_FEE_BPS as u64), + (output_amount as u64) * 10000 <= + (input_amount as u64) * (10000 - VOLUME_FEE_BPS as u64), "Test inputs violate fee constraint" ); diff --git a/tests/wormhole_integration.rs b/tests/wormhole_integration.rs index 6fedc3f..0f452e0 100644 --- a/tests/wormhole_integration.rs +++ b/tests/wormhole_integration.rs @@ -15,10 +15,12 @@ //! with valid parent hash linkage. We use batch transfers to ensure same-block proofs. use plonky2::plonk::{circuit_data::CircuitConfig, proof::ProofWithPublicInputs}; -use qp_wormhole_circuit::inputs::{ - AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, +use qp_wormhole_circuit::{ + inputs::{ + AggregatedPublicCircuitInputs, CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs, + }, + nullifier::Nullifier, }; -use qp_wormhole_circuit::nullifier::Nullifier; use qp_wormhole_prover::WormholeProver; use qp_wormhole_verifier::WormholeVerifier; use qp_zk_circuits_common::{