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..2abd1cb2 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,10 +54,11 @@ 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::{ + dispatch::DispatchResult, pallet_prelude::*, traits::{ fungible::{Mutate, Unbalanced}, @@ -73,7 +73,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 +87,33 @@ pub mod pallet { >>::Balance; pub type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; + pub type TransferProofKey = ( + AssetIdOf, + ::TransferCount, + ::WormholeAccountId, + ::WormholeAccountId, + 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 +121,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 WormholeAccountId: Parameter + + Member + + MaybeSerializeDeserialize + + core::fmt::Debug + + MaybeDisplay + + Ord + + MaxEncodedLen + + ToFelts + + Into<::AccountId> + + From<::AccountId>; } #[pallet::storage] @@ -135,8 +156,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 +170,22 @@ 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, + from: ::AccountId, + to: ::AccountId, amount: BalanceOf, transfer_count: T::TransferCount, }, AssetTransferred { asset_id: AssetIdOf, - from: T::AccountId, - to: T::AccountId, + from: ::AccountId, + to: ::AccountId, amount: AssetBalanceOf, transfer_count: T::TransferCount, }, + ProofVerified { + exit_amount: BalanceOf, + }, } #[pallet::error] @@ -246,8 +267,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 +327,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 +358,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 +394,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,31 +406,52 @@ 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: ::WormholeAccountId, + to: ::WormholeAccountId, amount: BalanceOf, ) -> 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(()) } } // Implement the TransferProofRecorder trait for other pallets to use - impl qp_wormhole::TransferProofRecorder, BalanceOf> - for Pallet + impl + qp_wormhole::TransferProofRecorder< + ::WormholeAccountId, + AssetIdOf, + BalanceOf, + > for Pallet { type Error = DispatchError; fn record_transfer_proof( asset_id: Option>, - from: T::AccountId, - to: T::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 7f0a4024..8527f4ff 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 WormholeAccountId = AccountId; } // Helper function to build a genesis configuration diff --git a/pallets/wormhole/src/tests.rs b/pallets/wormhole/src/tests.rs index 74054d08..2a706be8 100644 --- a/pallets/wormhole/src/tests.rs +++ b/pallets/wormhole/src/tests.rs @@ -73,7 +73,7 @@ mod wormhole_tests { let event_transfer_count = 0u64; - let leaf_hash = PoseidonHasher::hash_storage::( + let leaf_hash = PoseidonHasher::hash_storage::>( &( 0u32, event_transfer_count, diff --git a/runtime/src/configs/mod.rs b/runtime/src/configs/mod.rs index c50898d8..5b2e7ec8 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 WormholeAccountId = AccountId32; type WeightToFee = IdentityFee; }