From 247dea54102528efbe3f63755603baf79ceceea7 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Sun, 11 Jan 2026 23:11:51 +0600 Subject: [PATCH 1/5] Apply ToFelts changes to wormhole --- Cargo.lock | 8 +- Cargo.toml | 4 +- pallets/wormhole/src/lib.rs | 106 ++++++++++++++------------ runtime/src/configs/mod.rs | 3 +- runtime/src/transaction_extensions.rs | 16 ++-- 5 files changed, 75 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9bfabe60..35ec3be9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8984,9 +8984,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", @@ -9016,9 +9016,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 4878ed36..b954d7e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -149,8 +149,8 @@ sp-consensus-qpow = { path = "./primitives/consensus/qpow", default-features = f # Quantus network dependencies qp-plonky2 = { version = "1.1.3", default-features = false } -qp-poseidon = { version = "1.0.5", default-features = false } -qp-poseidon-core = { version = "1.0.5", default-features = false, features = ["p2", "p3"] } +qp-poseidon = { version = "1.0.6", default-features = false } +qp-poseidon-core = { version = "1.0.6", default-features = false, features = ["p2", "p3"] } qp-rusty-crystals-dilithium = { version = "2.0.0", default-features = false } qp-rusty-crystals-hdwallet = { version = "1.0.0" } qp-wormhole-circuit = { version = "0.1.7", default-features = false } diff --git a/pallets/wormhole/src/lib.rs b/pallets/wormhole/src/lib.rs index ec635407..d1349474 100644 --- a/pallets/wormhole/src/lib.rs +++ b/pallets/wormhole/src/lib.rs @@ -4,11 +4,11 @@ extern crate alloc; use core::marker::PhantomData; -use codec::{Decode, Encode, MaxEncodedLen}; +use codec::{Decode, MaxEncodedLen}; use frame_support::StorageHasher; use lazy_static::lazy_static; pub use pallet::*; -use qp_poseidon::PoseidonHasher as PoseidonCore; +pub use qp_poseidon::{PoseidonHasher as PoseidonCore, ToFelts}; use qp_wormhole_verifier::WormholeVerifier; #[cfg(test)] @@ -35,17 +35,16 @@ pub fn get_wormhole_verifier() -> Result<&'static WormholeVerifier, &'static str WORMHOLE_VERIFIER.as_ref().ok_or("Wormhole verifier not available") } -pub struct PoseidonStorageHasher(PhantomData); +// We use a generic struct so we can pass the specific Key type to the hasher +pub struct PoseidonStorageHasher(PhantomData); -impl StorageHasher - for PoseidonStorageHasher -{ +impl StorageHasher for PoseidonStorageHasher { // We are lying here, but maybe it's ok because it's just metadata const METADATA: StorageHasherIR = StorageHasherIR::Identity; type Output = [u8; 32]; fn hash(x: &[u8]) -> Self::Output { - PoseidonCore::hash_storage::(x) + PoseidonCore::hash_storage::(x) } fn max_len() -> usize { @@ -55,7 +54,7 @@ impl StorageHasher #[frame_support::pallet] pub mod pallet { - use crate::{PoseidonStorageHasher, WeightInfo}; + use crate::{PoseidonStorageHasher, ToFelts, WeightInfo}; use alloc::vec::Vec; use codec::Decode; use frame_support::{ @@ -73,7 +72,7 @@ pub mod pallet { use qp_wormhole_verifier::ProofWithPublicInputs; use qp_zk_circuits_common::circuit::{C, D, F}; use sp_runtime::{ - traits::{Saturating, StaticLookup, Zero}, + traits::{MaybeDisplay, Saturating, StaticLookup, Zero}, Perbill, }; @@ -87,25 +86,33 @@ pub mod pallet { >>::Balance; pub type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; + pub type TransferProofKey = ( + AssetIdOf, + ::TransferCount, + ::AccountId, + ::AccountId, + BalanceOf, + ); + #[pallet::pallet] pub struct Pallet(_); #[pallet::config] pub trait Config: frame_system::Config where - AssetIdOf: Default + From + Clone, - BalanceOf: Default, + AssetIdOf: Default + From + Clone + ToFelts, + BalanceOf: Default + ToFelts, AssetBalanceOf: Into> + From>, { /// Currency type used for native token transfers and minting - type Currency: Mutate> - + Unbalanced - + Currency; + type Currency: Mutate<::AccountId, Balance = BalanceOf> + + Unbalanced<::AccountId> + + Currency<::AccountId>; /// Assets type used for managing fungible assets - type Assets: fungibles::Inspect - + fungibles::Mutate - + fungibles::Create; + type Assets: fungibles::Inspect<::AccountId> + + fungibles::Mutate<::AccountId> + + fungibles::Create<::AccountId>; /// Transfer count type used in storage type TransferCount: Parameter @@ -113,16 +120,29 @@ pub mod pallet { + Default + Saturating + Copy - + sp_runtime::traits::One; + + sp_runtime::traits::One + + ToFelts; /// Account ID used as the "from" account when creating transfer proofs for minted tokens #[pallet::constant] - type MintingAccount: Get; + type MintingAccount: Get<::AccountId>; /// Weight information for pallet operations. type WeightInfo: WeightInfo; type WeightToFee: WeightToFee>; + + /// Override system AccountId to make it felts encodable + type AccountId: Parameter + + Member + + MaybeSerializeDeserialize + + core::fmt::Debug + + MaybeDisplay + + Ord + + MaxEncodedLen + + ToFelts + + Into<::AccountId> + + From<::AccountId>; } #[pallet::storage] @@ -135,8 +155,8 @@ pub mod pallet { #[pallet::getter(fn transfer_proof)] pub type TransferProof = StorageMap< _, - PoseidonStorageHasher, - (AssetIdOf, T::TransferCount, T::AccountId, T::AccountId, BalanceOf), /* (asset_id, tx_count, from, to, amount) */ + PoseidonStorageHasher>, + TransferProofKey, (), OptionQuery, >; @@ -149,22 +169,7 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - ProofVerified { - exit_amount: BalanceOf, - }, - NativeTransferred { - from: T::AccountId, - to: T::AccountId, - amount: BalanceOf, - transfer_count: T::TransferCount, - }, - AssetTransferred { - asset_id: AssetIdOf, - from: T::AccountId, - to: T::AccountId, - amount: AssetBalanceOf, - transfer_count: T::TransferCount, - }, + ProofVerified { exit_amount: BalanceOf }, } #[pallet::error] @@ -246,8 +251,9 @@ pub mod pallet { // Decode exit account from public inputs let exit_account_bytes = *public_inputs.exit_account; - let exit_account = T::AccountId::decode(&mut &exit_account_bytes[..]) - .map_err(|_| Error::::InvalidPublicInputs)?; + let exit_account = + ::AccountId::decode(&mut &exit_account_bytes[..]) + .map_err(|_| Error::::InvalidPublicInputs)?; // Extract asset_id from public inputs let asset_id_u32 = public_inputs.asset_id; @@ -305,7 +311,12 @@ pub mod pallet { // Create a transfer proof for the minted tokens let mint_account = T::MintingAccount::get(); - Self::record_transfer(asset_id, mint_account, exit_account, exit_balance)?; + Self::record_transfer( + asset_id, + mint_account.into(), + exit_account.into(), + exit_balance, + )?; // Emit event Self::deposit_event(Event::ProofVerified { exit_amount: exit_balance }); @@ -331,7 +342,7 @@ pub mod pallet { >::transfer(&source, &dest, amount, Preservation::Expendable)?; // Store proof with asset_id = Default (0 for native) - Self::record_transfer(AssetIdOf::::default(), source, dest, amount)?; + Self::record_transfer(AssetIdOf::::default(), source.into(), dest.into(), amount)?; Ok(()) } @@ -367,7 +378,7 @@ pub mod pallet { )?; // Store proof - Self::record_transfer(asset_id, source, dest, amount.into())?; + Self::record_transfer(asset_id, source.into(), dest.into(), amount.into())?; Ok(()) } @@ -379,8 +390,8 @@ pub mod pallet { /// This should be called by transaction extensions or other runtime components pub fn record_transfer( asset_id: AssetIdOf, - from: T::AccountId, - to: T::AccountId, + from: ::AccountId, + to: ::AccountId, amount: BalanceOf, ) -> DispatchResult { let current_count = TransferCount::::get(); @@ -395,15 +406,16 @@ pub mod pallet { } // Implement the TransferProofRecorder trait for other pallets to use - impl qp_wormhole::TransferProofRecorder, BalanceOf> + impl + qp_wormhole::TransferProofRecorder<::AccountId, AssetIdOf, BalanceOf> for Pallet { type Error = DispatchError; fn record_transfer_proof( asset_id: Option>, - from: T::AccountId, - to: T::AccountId, + from: ::AccountId, + to: ::AccountId, amount: BalanceOf, ) -> Result<(), Self::Error> { let asset_id_value = asset_id.unwrap_or_default(); diff --git a/runtime/src/configs/mod.rs b/runtime/src/configs/mod.rs index c50898d8..b191d0ad 100644 --- a/runtime/src/configs/mod.rs +++ b/runtime/src/configs/mod.rs @@ -57,7 +57,7 @@ use qp_poseidon::PoseidonHasher; use qp_scheduler::BlockNumberOrTimestamp; use sp_runtime::{ traits::{AccountIdConversion, ConvertInto, One}, - FixedU128, Perbill, Permill, + AccountId32, FixedU128, Perbill, Permill, }; use sp_version::RuntimeVersion; @@ -635,5 +635,6 @@ impl pallet_wormhole::Config for Runtime { type Currency = Balances; type Assets = Assets; type TransferCount = u64; + type AccountId = AccountId32; type WeightToFee = IdentityFee; } diff --git a/runtime/src/transaction_extensions.rs b/runtime/src/transaction_extensions.rs index 6216b96d..92114394 100644 --- a/runtime/src/transaction_extensions.rs +++ b/runtime/src/transaction_extensions.rs @@ -72,11 +72,11 @@ impl match call { RuntimeCall::ReversibleTransfers( pallet_reversible_transfers::Call::schedule_transfer { .. }, - ) | - RuntimeCall::ReversibleTransfers( + ) + | RuntimeCall::ReversibleTransfers( pallet_reversible_transfers::Call::schedule_asset_transfer { .. }, - ) | - RuntimeCall::ReversibleTransfers(pallet_reversible_transfers::Call::cancel { + ) + | RuntimeCall::ReversibleTransfers(pallet_reversible_transfers::Call::cancel { .. }) => { return Ok((ValidTransaction::default(), (), origin)); @@ -193,10 +193,10 @@ impl TransactionEx fn weight(&self, call: &RuntimeCall) -> Weight { // Account for proof recording in post_dispatch match call { - RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { .. }) | - RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) | - RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) | - RuntimeCall::Assets(pallet_assets::Call::transfer_keep_alive { .. }) => { + RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { .. }) + | RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) + | RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) + | RuntimeCall::Assets(pallet_assets::Call::transfer_keep_alive { .. }) => { // 2 writes: TransferProof insert + TransferCount update // 1 read: TransferCount get T::DbWeight::get().reads_writes(1, 2) From 4d1f7c8817b8ce2d2e6772f4821da51ce4bb2707 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:21:52 +0600 Subject: [PATCH 2/5] Fix checks --- pallets/wormhole/src/lib.rs | 37 +++++++++++++++++++++++++-- pallets/wormhole/src/mock.rs | 1 + pallets/wormhole/src/tests.rs | 7 +++-- runtime/src/transaction_extensions.rs | 16 ++++++------ 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/pallets/wormhole/src/lib.rs b/pallets/wormhole/src/lib.rs index d1349474..af1766a4 100644 --- a/pallets/wormhole/src/lib.rs +++ b/pallets/wormhole/src/lib.rs @@ -58,6 +58,7 @@ pub mod pallet { use alloc::vec::Vec; use codec::Decode; use frame_support::{ + dispatch::DispatchResult, pallet_prelude::*, traits::{ fungible::{Mutate, Unbalanced}, @@ -169,7 +170,22 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - ProofVerified { exit_amount: BalanceOf }, + NativeTransferred { + from: ::AccountId, + to: ::AccountId, + amount: BalanceOf, + transfer_count: T::TransferCount, + }, + AssetTransferred { + asset_id: AssetIdOf, + from: ::AccountId, + to: ::AccountId, + amount: AssetBalanceOf, + transfer_count: T::TransferCount, + }, + ProofVerified { + exit_amount: BalanceOf, + }, } #[pallet::error] @@ -396,11 +412,28 @@ pub mod pallet { ) -> DispatchResult { let current_count = TransferCount::::get(); TransferProof::::insert( - (asset_id, current_count, from.clone(), to.clone(), amount), + (asset_id.clone(), current_count, from.clone(), to.clone(), amount), (), ); TransferCount::::put(current_count.saturating_add(T::TransferCount::one())); + if asset_id == AssetIdOf::::default() { + Self::deposit_event(Event::::NativeTransferred { + from: from.into(), + to: to.into(), + amount, + transfer_count: current_count, + }); + } else { + Self::deposit_event(Event::::AssetTransferred { + from: from.into(), + to: to.into(), + asset_id, + amount: amount.into(), + transfer_count: current_count, + }); + } + Ok(()) } } diff --git a/pallets/wormhole/src/mock.rs b/pallets/wormhole/src/mock.rs index 7f0a4024..ca63aa37 100644 --- a/pallets/wormhole/src/mock.rs +++ b/pallets/wormhole/src/mock.rs @@ -127,6 +127,7 @@ impl pallet_wormhole::Config for Test { type Assets = Assets; type TransferCount = u64; type MintingAccount = MintingAccount; + type AccountId = AccountId; } // Helper function to build a genesis configuration diff --git a/pallets/wormhole/src/tests.rs b/pallets/wormhole/src/tests.rs index 74054d08..871c4d4e 100644 --- a/pallets/wormhole/src/tests.rs +++ b/pallets/wormhole/src/tests.rs @@ -73,9 +73,9 @@ mod wormhole_tests { let event_transfer_count = 0u64; - let leaf_hash = PoseidonHasher::hash_storage::( + let leaf_hash = PoseidonHasher::hash_storage::>( &( - 0u32, + 0u32, // AssetId (native) event_transfer_count, alice.clone(), unspendable_account_id.clone(), @@ -91,8 +91,7 @@ mod wormhole_tests { unspendable_account_id.clone(), funding_amount, )); - let mut storage_key = proof_address; - storage_key.extend_from_slice(&leaf_hash); + let storage_key = proof_address; let header = System::finalize(); let state_root = *header.state_root(); diff --git a/runtime/src/transaction_extensions.rs b/runtime/src/transaction_extensions.rs index 92114394..6216b96d 100644 --- a/runtime/src/transaction_extensions.rs +++ b/runtime/src/transaction_extensions.rs @@ -72,11 +72,11 @@ impl match call { RuntimeCall::ReversibleTransfers( pallet_reversible_transfers::Call::schedule_transfer { .. }, - ) - | RuntimeCall::ReversibleTransfers( + ) | + RuntimeCall::ReversibleTransfers( pallet_reversible_transfers::Call::schedule_asset_transfer { .. }, - ) - | RuntimeCall::ReversibleTransfers(pallet_reversible_transfers::Call::cancel { + ) | + RuntimeCall::ReversibleTransfers(pallet_reversible_transfers::Call::cancel { .. }) => { return Ok((ValidTransaction::default(), (), origin)); @@ -193,10 +193,10 @@ impl TransactionEx fn weight(&self, call: &RuntimeCall) -> Weight { // Account for proof recording in post_dispatch match call { - RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { .. }) - | RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) - | RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) - | RuntimeCall::Assets(pallet_assets::Call::transfer_keep_alive { .. }) => { + RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { .. }) | + RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { .. }) | + RuntimeCall::Assets(pallet_assets::Call::transfer { .. }) | + RuntimeCall::Assets(pallet_assets::Call::transfer_keep_alive { .. }) => { // 2 writes: TransferProof insert + TransferCount update // 1 read: TransferCount get T::DbWeight::get().reads_writes(1, 2) From 38d96182d758012e544b2232c63be9db663d04d7 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:24:34 +0600 Subject: [PATCH 3/5] Passing tests --- pallets/wormhole/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/wormhole/src/tests.rs b/pallets/wormhole/src/tests.rs index 871c4d4e..1a18eb14 100644 --- a/pallets/wormhole/src/tests.rs +++ b/pallets/wormhole/src/tests.rs @@ -75,7 +75,7 @@ mod wormhole_tests { let leaf_hash = PoseidonHasher::hash_storage::>( &( - 0u32, // AssetId (native) + 0u32, event_transfer_count, alice.clone(), unspendable_account_id.clone(), From d8a70c88b04463eceb8b5b2ca05effef48436426 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Tue, 13 Jan 2026 22:13:25 +0600 Subject: [PATCH 4/5] Revert unit test line --- pallets/wormhole/src/tests.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pallets/wormhole/src/tests.rs b/pallets/wormhole/src/tests.rs index 1a18eb14..2a706be8 100644 --- a/pallets/wormhole/src/tests.rs +++ b/pallets/wormhole/src/tests.rs @@ -91,7 +91,8 @@ mod wormhole_tests { unspendable_account_id.clone(), funding_amount, )); - let storage_key = proof_address; + let mut storage_key = proof_address; + storage_key.extend_from_slice(&leaf_hash); let header = System::finalize(); let state_root = *header.state_root(); From 3ff51d98576123960da495057b9edfffe0f01358 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Tue, 13 Jan 2026 23:13:51 +0600 Subject: [PATCH 5/5] Rename explicit AccountId --- pallets/wormhole/src/lib.rs | 21 ++++++++++++--------- pallets/wormhole/src/mock.rs | 2 +- runtime/src/configs/mod.rs | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/pallets/wormhole/src/lib.rs b/pallets/wormhole/src/lib.rs index af1766a4..2abd1cb2 100644 --- a/pallets/wormhole/src/lib.rs +++ b/pallets/wormhole/src/lib.rs @@ -90,8 +90,8 @@ pub mod pallet { pub type TransferProofKey = ( AssetIdOf, ::TransferCount, - ::AccountId, - ::AccountId, + ::WormholeAccountId, + ::WormholeAccountId, BalanceOf, ); @@ -134,7 +134,7 @@ pub mod pallet { type WeightToFee: WeightToFee>; /// Override system AccountId to make it felts encodable - type AccountId: Parameter + type WormholeAccountId: Parameter + Member + MaybeSerializeDeserialize + core::fmt::Debug @@ -406,8 +406,8 @@ pub mod pallet { /// This should be called by transaction extensions or other runtime components pub fn record_transfer( asset_id: AssetIdOf, - from: ::AccountId, - to: ::AccountId, + from: ::WormholeAccountId, + to: ::WormholeAccountId, amount: BalanceOf, ) -> DispatchResult { let current_count = TransferCount::::get(); @@ -440,15 +440,18 @@ pub mod pallet { // Implement the TransferProofRecorder trait for other pallets to use impl - qp_wormhole::TransferProofRecorder<::AccountId, AssetIdOf, BalanceOf> - for Pallet + qp_wormhole::TransferProofRecorder< + ::WormholeAccountId, + AssetIdOf, + BalanceOf, + > for Pallet { type Error = DispatchError; fn record_transfer_proof( asset_id: Option>, - from: ::AccountId, - to: ::AccountId, + from: ::WormholeAccountId, + to: ::WormholeAccountId, amount: BalanceOf, ) -> Result<(), Self::Error> { let asset_id_value = asset_id.unwrap_or_default(); diff --git a/pallets/wormhole/src/mock.rs b/pallets/wormhole/src/mock.rs index ca63aa37..8527f4ff 100644 --- a/pallets/wormhole/src/mock.rs +++ b/pallets/wormhole/src/mock.rs @@ -127,7 +127,7 @@ impl pallet_wormhole::Config for Test { type Assets = Assets; type TransferCount = u64; type MintingAccount = MintingAccount; - type AccountId = AccountId; + type WormholeAccountId = AccountId; } // Helper function to build a genesis configuration diff --git a/runtime/src/configs/mod.rs b/runtime/src/configs/mod.rs index b191d0ad..5b2e7ec8 100644 --- a/runtime/src/configs/mod.rs +++ b/runtime/src/configs/mod.rs @@ -635,6 +635,6 @@ impl pallet_wormhole::Config for Runtime { type Currency = Balances; type Assets = Assets; type TransferCount = u64; - type AccountId = AccountId32; + type WormholeAccountId = AccountId32; type WeightToFee = IdentityFee; }