From d045acc4334ba0cfa4e4adef3bc048842d83f7c5 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Fri, 28 Nov 2025 14:43:31 +0600 Subject: [PATCH 1/4] No pad hasher header (#327) * no circuit padding hasher for block header * *use custom hasher for header that encodes the pre-image in a felt aligned manner. * *bespoke header hasher * *patch bug with hash header fall back * *replace custom poseidon header hasher on generic header with a fork of header that has a custom hasher that overrides default on the header trait. * *rmv commented out impl of prior hash method * Update primitives/header/src/lib.rs Co-authored-by: Dastan <88332432+dastansam@users.noreply.github.com> * fixed tests * Use inherent struct method * Update Cargo.toml --------- Co-authored-by: Ethan Co-authored-by: illuzen --- Cargo.lock | 19 ++ Cargo.toml | 4 + primitives/header/Cargo.toml | 40 +++ primitives/header/src/lib.rs | 346 ++++++++++++++++++++++++++ runtime/Cargo.toml | 3 +- runtime/src/genesis_config_presets.rs | 1 + runtime/src/lib.rs | 5 +- 7 files changed, 414 insertions(+), 4 deletions(-) create mode 100644 primitives/header/Cargo.toml create mode 100644 primitives/header/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index a93e158f..52e610fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8903,6 +8903,24 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "qp-header" +version = "0.1.0" +dependencies = [ + "hex", + "log", + "p3-field", + "p3-goldilocks", + "parity-scale-codec", + "qp-poseidon", + "qp-poseidon-core", + "scale-info", + "serde", + "serde_json", + "sp-core", + "sp-runtime", +] + [[package]] name = "qp-plonky2" version = "1.1.1" @@ -9216,6 +9234,7 @@ dependencies = [ "parity-scale-codec", "primitive-types 0.13.1", "qp-dilithium-crypto", + "qp-header", "qp-poseidon", "qp-scheduler", "qp-wormhole-circuit", diff --git a/Cargo.toml b/Cargo.toml index c1697086..fe5056a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ members = [ "primitives/consensus/pow", "primitives/consensus/qpow", "primitives/dilithium-crypto", + "primitives/header", "primitives/scheduler", "primitives/state-machine", "primitives/trie", @@ -76,6 +77,8 @@ names = { version = "0.14.0", default-features = false } nohash-hasher = { version = "0.2.0" } num-traits = { version = "0.2", default-features = false, features = ["libm"] } once_cell = { version = "1.21.3" } +p3-field = { version = "0.3.0" } +p3-goldilocks = { version = "0.3.0" } parking_lot = { version = "0.12.1", default-features = false } partial_sort = { version = "0.2.0" } paste = { version = "1.0.15", default-features = false } @@ -126,6 +129,7 @@ pallet-reversible-transfers = { path = "./pallets/reversible-transfers", default pallet-scheduler = { path = "./pallets/scheduler", default-features = false } pallet-wormhole = { path = "./pallets/wormhole", default-features = false } qp-dilithium-crypto = { path = "./primitives/dilithium-crypto", version = "0.2.0", default-features = false } +qp-header = { path = "./primitives/header", default-features = false } qp-scheduler = { path = "./primitives/scheduler", default-features = false } qp-wormhole = { path = "./primitives/wormhole", default-features = false } qpow-math = { path = "./qpow-math", default-features = false } diff --git a/primitives/header/Cargo.toml b/primitives/header/Cargo.toml new file mode 100644 index 00000000..a164947d --- /dev/null +++ b/primitives/header/Cargo.toml @@ -0,0 +1,40 @@ +[package] +authors.workspace = true +description = "Fork of sp-runtime's Header type with a custom hash function that's felt aligned for our wormhole circuits" +edition.workspace = true +homepage.workspace = true +license = "Apache-2.0" +name = "qp-header" +publish = false +repository.workspace = true +version = "0.1.0" + +[dependencies] +codec = { features = ["derive"], workspace = true } +log.workspace = true +p3-field = { workspace = true } +p3-goldilocks = { workspace = true } +qp-poseidon = { workspace = true, features = ["serde"] } +qp-poseidon-core = { workspace = true } +scale-info = { features = ["derive", "serde"], workspace = true } +serde = { workspace = true, features = ["derive"], optional = true } +sp-core = { features = ["serde"], workspace = true } +sp-runtime = { features = ["serde"], workspace = true } + +[dev-dependencies] +hex = { workspace = true } +serde_json = { workspace = true, default-features = false, features = [ + "alloc", + "std", +] } + + +[features] +default = ["serde", "std"] +std = [ + "codec/std", + "qp-poseidon/std", + "scale-info/std", + "sp-core/std", + "sp-runtime/std", +] diff --git a/primitives/header/src/lib.rs b/primitives/header/src/lib.rs new file mode 100644 index 00000000..bbe897fe --- /dev/null +++ b/primitives/header/src/lib.rs @@ -0,0 +1,346 @@ +//! Fork of sp-runtime's generic implementation of a block header. +//! We override the hashing function to ensure a felt aligned pre-image for the block hash. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Codec, Decode, DecodeWithMemTracking, Encode}; +use p3_field::integers::QuotientMap; +use p3_goldilocks::Goldilocks; +use qp_poseidon_core::{ + hash_variable_length, + serialization::{injective_bytes_to_felts, unsafe_digest_bytes_to_felts}, +}; +use scale_info::TypeInfo; +use sp_core::U256; +use sp_runtime::{ + generic::Digest, + traits::{AtLeast32BitUnsigned, BlockNumber, Hash as HashT, MaybeDisplay, Member}, + RuntimeDebug, +}; +extern crate alloc; + +use alloc::vec::Vec; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// Custom block header that hashes itself with Poseidon over Goldilocks field elements. +#[derive(Encode, Decode, PartialEq, Eq, Clone, RuntimeDebug, TypeInfo, DecodeWithMemTracking)] +#[scale_info(skip_type_params(Hash))] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "serde", serde(deny_unknown_fields))] +pub struct Header + TryFrom, Hash: HashT> { + pub parent_hash: Hash::Output, + #[cfg_attr( + feature = "serde", + serde(serialize_with = "serialize_number", deserialize_with = "deserialize_number") + )] + pub number: Number, + pub state_root: Hash::Output, + pub extrinsics_root: Hash::Output, + pub digest: Digest, +} + +#[cfg(feature = "serde")] +pub fn serialize_number + TryFrom>( + val: &T, + s: S, +) -> Result +where + S: serde::Serializer, +{ + let u256: U256 = (*val).into(); + serde::Serialize::serialize(&u256, s) +} + +#[cfg(feature = "serde")] +pub fn deserialize_number<'a, D, T: Copy + Into + TryFrom>(d: D) -> Result +where + D: serde::Deserializer<'a>, +{ + let u256: U256 = serde::Deserialize::deserialize(d)?; + TryFrom::try_from(u256).map_err(|_| serde::de::Error::custom("Try from failed")) +} + +impl sp_runtime::traits::Header for Header +where + Number: BlockNumber, + Hash: HashT, + Hash::Output: From<[u8; 32]>, +{ + type Number = Number; + type Hash = ::Output; + type Hashing = Hash; + + fn new( + number: Self::Number, + extrinsics_root: Self::Hash, + state_root: Self::Hash, + parent_hash: Self::Hash, + digest: Digest, + ) -> Self { + Self { number, extrinsics_root, state_root, parent_hash, digest } + } + fn number(&self) -> &Self::Number { + &self.number + } + + fn set_number(&mut self, num: Self::Number) { + self.number = num + } + fn extrinsics_root(&self) -> &Self::Hash { + &self.extrinsics_root + } + + fn set_extrinsics_root(&mut self, root: Self::Hash) { + self.extrinsics_root = root + } + fn state_root(&self) -> &Self::Hash { + &self.state_root + } + + fn set_state_root(&mut self, root: Self::Hash) { + self.state_root = root + } + fn parent_hash(&self) -> &Self::Hash { + &self.parent_hash + } + + fn set_parent_hash(&mut self, hash: Self::Hash) { + self.parent_hash = hash + } + + fn digest(&self) -> &Digest { + &self.digest + } + + fn digest_mut(&mut self) -> &mut Digest { + #[cfg(feature = "std")] + log::debug!(target: "header", "Retrieving mutable reference to digest"); + &mut self.digest + } + // We override the default hashing function to use + // a felt aligned pre-image for poseidon hashing. + fn hash(&self) -> Self::Hash { + Header::hash(&self) + } +} + +impl Header +where + Number: Member + + core::hash::Hash + + Copy + + MaybeDisplay + + AtLeast32BitUnsigned + + Codec + + Into + + TryFrom, + Hash: HashT, + Hash::Output: From<[u8; 32]>, +{ + /// Convenience helper for computing the hash of the header without having + /// to import the trait. + pub fn hash(&self) -> Hash::Output { + let max_encoded_felts = 4 * 3 + 1 + 28; // 3 hashout fields + 1 u32 + 28 felts for injective digest encoding + let mut felts = Vec::with_capacity(max_encoded_felts); + + // parent_hash : 32 bytes → 4 felts + felts.extend(unsafe_digest_bytes_to_felts::( + self.parent_hash.as_ref().try_into().expect("hash is 32 bytes"), + )); + + // block number as u64 (compact encoded, but we only need the value) + // constrain the block number to be with u32 range for simplicity + let number = self.number.into(); + felts.push(Goldilocks::from_int(number.as_u32() as u64)); + + // state_root : 32 bytes → 4 felts + felts.extend(unsafe_digest_bytes_to_felts::( + self.state_root.as_ref().try_into().expect("hash is 32 bytes"), + )); + + // extrinsics_root : 32 bytes → 4 felts + felts.extend(unsafe_digest_bytes_to_felts::( + self.extrinsics_root.as_ref().try_into().expect("hash is 32 bytes"), + )); + + // digest – injective encoding + felts.extend(injective_bytes_to_felts::(&self.digest.encode())); + + let poseidon_hash: [u8; 32] = hash_variable_length(felts); + poseidon_hash.into() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use qp_poseidon::PoseidonHasher; + use sp_core::H256; + use sp_runtime::{traits::BlakeTwo256, DigestItem}; + + #[test] + fn should_serialize_numbers() { + fn serialize(num: u128) -> String { + let mut v = vec![]; + { + let mut ser = serde_json::Serializer::new(std::io::Cursor::new(&mut v)); + serialize_number(&num, &mut ser).unwrap(); + } + String::from_utf8(v).unwrap() + } + + assert_eq!(serialize(0), "\"0x0\"".to_owned()); + assert_eq!(serialize(1), "\"0x1\"".to_owned()); + assert_eq!(serialize(u64::MAX as u128), "\"0xffffffffffffffff\"".to_owned()); + assert_eq!(serialize(u64::MAX as u128 + 1), "\"0x10000000000000000\"".to_owned()); + } + + #[test] + fn should_deserialize_number() { + fn deserialize(num: &str) -> u128 { + let mut der = serde_json::Deserializer::from_str(num); + deserialize_number(&mut der).unwrap() + } + + assert_eq!(deserialize("\"0x0\""), 0); + assert_eq!(deserialize("\"0x1\""), 1); + assert_eq!(deserialize("\"0xffffffffffffffff\""), u64::MAX as u128); + assert_eq!(deserialize("\"0x10000000000000000\""), u64::MAX as u128 + 1); + } + + #[test] + fn ensure_format_is_unchanged() { + let header = Header:: { + parent_hash: BlakeTwo256::hash(b"1"), + number: 2, + state_root: BlakeTwo256::hash(b"3"), + extrinsics_root: BlakeTwo256::hash(b"4"), + digest: Digest { logs: vec![sp_runtime::generic::DigestItem::Other(b"6".to_vec())] }, + }; + + let header_encoded = header.encode(); + assert_eq!( + header_encoded, + vec![ + 146, 205, 245, 120, 196, 112, 133, 165, 153, 34, 86, 240, 220, 249, 125, 11, 25, + 241, 241, 201, 222, 77, 95, 227, 12, 58, 206, 97, 145, 182, 229, 219, 2, 0, 0, 0, + 88, 19, 72, 51, 123, 15, 62, 20, 134, 32, 23, 61, 170, 165, 249, 77, 0, 216, 129, + 112, 93, 203, 240, 170, 131, 239, 218, 186, 97, 210, 237, 225, 235, 134, 73, 33, + 73, 151, 87, 78, 32, 196, 100, 56, 138, 23, 36, 32, 210, 84, 3, 104, 43, 187, 184, + 12, 73, 104, 49, 200, 204, 31, 143, 13, 4, 0, 4, 54 + ], + ); + assert_eq!(Header::::decode(&mut &header_encoded[..]).unwrap(), header); + + let header = Header:: { + parent_hash: BlakeTwo256::hash(b"1000"), + number: 2000, + state_root: BlakeTwo256::hash(b"3000"), + extrinsics_root: BlakeTwo256::hash(b"4000"), + digest: Digest { logs: vec![sp_runtime::generic::DigestItem::Other(b"5000".to_vec())] }, + }; + + let header_encoded = header.encode(); + assert_eq!( + header_encoded, + vec![ + 197, 243, 254, 225, 31, 117, 21, 218, 179, 213, 92, 6, 247, 164, 230, 25, 47, 166, + 140, 117, 142, 159, 195, 202, 67, 196, 238, 26, 44, 18, 33, 92, 208, 7, 0, 0, 219, + 225, 47, 12, 107, 88, 153, 146, 55, 21, 226, 186, 110, 48, 167, 187, 67, 183, 228, + 232, 118, 136, 30, 254, 11, 87, 48, 112, 7, 97, 31, 82, 146, 110, 96, 87, 152, 68, + 98, 162, 227, 222, 78, 14, 244, 194, 120, 154, 112, 97, 222, 144, 174, 101, 220, + 44, 111, 126, 54, 34, 155, 220, 253, 124, 4, 0, 16, 53, 48, 48, 48 + ], + ); + assert_eq!(Header::::decode(&mut &header_encoded[..]).unwrap(), header); + } + + fn hash_header(x: &[u8]) -> [u8; 32] { + let mut y = x; + if let Ok(header) = Header::::decode(&mut y) { + // Only treat this as a header if we consumed the entire input. + if y.is_empty() { + let max_encoded_felts = 4 * 3 + 1 + 28; // 3 hashout fields + 1 u32 + 28 felts + let mut felts = Vec::with_capacity(max_encoded_felts); + + let parent_hash = header.parent_hash.as_bytes(); + let number = header.number; + let state_root = header.state_root.as_bytes(); + let extrinsics_root = header.extrinsics_root.as_bytes(); + let digest = header.digest.encode(); + + felts.extend(unsafe_digest_bytes_to_felts::( + parent_hash.try_into().expect("Parent hash expected to equal 32 bytes"), + )); + felts.push(Goldilocks::from_int(number as u64)); + felts.extend(unsafe_digest_bytes_to_felts::( + state_root.try_into().expect("State root expected to equal 32 bytes"), + )); + felts.extend(unsafe_digest_bytes_to_felts::( + extrinsics_root.try_into().expect("Extrinsics root expected to equal 32 bytes"), + )); + felts.extend(injective_bytes_to_felts::(&digest)); + + return hash_variable_length(felts); + } + } + // Fallback: canonical bytes hashing for non-header data + PoseidonHasher::hash_padded(x) + } + + #[test] + fn poseidon_header_hash_matches_old_path() { + use codec::Encode; + + // Example header from a real block on devnet + let parent_hash = "839b2d2ac0bf4aa71b18ad1ba5e2880b4ef06452cefacd255cfd76f6ad2c7966"; + let number = 4; + let state_root = "1688817041c572d6c971681465f401f06d0fdcfaed61d28c06d42dc2d07816d5"; + let extrinsics_root = "7c6cace2e91b6314e05410b91224c11f5dd4a4a2dbf0e39081fddbe4ac9ad252"; + let digest = Digest { + logs: vec![ + DigestItem::PreRuntime( + [112, 111, 119, 95], + [ + 233, 182, 183, 107, 158, 1, 115, 19, 219, 126, 253, 86, 30, 208, 176, 70, + 21, 45, 180, 229, 9, 62, 91, 4, 6, 53, 245, 52, 48, 38, 123, 225, + ] + .to_vec(), + ), + DigestItem::Seal( + [112, 111, 119, 95], + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 77, 142, + ] + .to_vec(), + ), + ], + }; + let header = Header:: { + parent_hash: H256::from_slice( + hex::decode(parent_hash).expect("valid hex parent hash").as_slice(), + ), + number, + state_root: H256::from_slice( + hex::decode(state_root).expect("valid hex state root").as_slice(), + ), + extrinsics_root: H256::from_slice( + hex::decode(extrinsics_root).expect("valid hex extrinsics root").as_slice(), + ), + digest, + }; + + let encoded = header.encode(); + + let old = hash_header(&encoded); // old path + let new: [u8; 32] = header.hash().into(); + println!("Old hash: 0x{}", hex::encode(old)); + + assert_eq!(old, new); + } +} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index ed4ce404..65ba6ce7 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -46,6 +46,7 @@ pallet-utility.workspace = true pallet-vesting.workspace = true primitive-types.workspace = true qp-dilithium-crypto.workspace = true +qp-header = { workspace = true, features = ["serde"] } qp-poseidon = { workspace = true, features = ["serde"] } qp-scheduler.workspace = true qp-wormhole-circuit = { workspace = true, default-features = false } @@ -114,13 +115,13 @@ std = [ "primitive-types/std", "qp-dilithium-crypto/full_crypto", "qp-dilithium-crypto/std", + "qp-header/std", "qp-poseidon/std", "qp-scheduler/std", "qp-wormhole-circuit/std", "qp-wormhole-verifier/std", "qp-zk-circuits-common/std", "scale-info/std", - "scale-info/std", "serde_json/std", "sp-api/std", "sp-block-builder/std", diff --git a/runtime/src/genesis_config_presets.rs b/runtime/src/genesis_config_presets.rs index 16517f28..0fdba5ca 100644 --- a/runtime/src/genesis_config_presets.rs +++ b/runtime/src/genesis_config_presets.rs @@ -74,6 +74,7 @@ pub fn development_config_genesis() -> Value { let ss58_version = sp_core::crypto::Ss58AddressFormat::custom(189); for account in endowed_accounts.iter() { log::info!("🍆 Endowed account: {:?}", account.to_ss58check_with_version(ss58_version)); + log::info!("🍆 Endowed account raw: {:?}", account); } genesis_template(endowed_accounts, crystal_alice().into_account()) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 5d2de3f4..7c54c2b5 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -38,7 +38,6 @@ pub mod governance; use crate::governance::pallet_custom_origins; use qp_poseidon::PoseidonHasher; - /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades @@ -55,7 +54,7 @@ pub mod opaque { // However, some internal checks in dev build expect extrinsics_root to be computed with same // Hash function, so we change the configs/mod.rs Hashing type as well // Opaque block header type. - pub type Header = generic::Header; + pub type Header = qp_header::Header; // Opaque block type. pub type Block = generic::Block; @@ -143,7 +142,7 @@ pub type BlockNumber = u32; pub type Address = MultiAddress; /// Block header type as expected by this runtime. -pub type Header = generic::Header; +pub type Header = qp_header::Header; /// Block type as expected by this runtime. pub type Block = generic::Block; From 0123aebf13c4ebf742b122003c660b598f7bab5a Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Sat, 29 Nov 2025 20:16:12 +0600 Subject: [PATCH 2/4] Verify header in the wormhole proof (#295) --- Cargo.lock | 1823 ++++++++--------- Cargo.toml | 16 +- node/build.rs | 5 +- pallets/balances/src/lib.rs | 15 +- .../balances/src/tests/reentrancy_tests.rs | 6 +- pallets/mining-rewards/src/mock.rs | 8 +- pallets/mining-rewards/src/tests.rs | 8 +- pallets/wormhole/Cargo.toml | 13 + pallets/wormhole/common.bin | Bin 1037 -> 1905 bytes pallets/wormhole/proof_from_bins.hex | 2 +- pallets/wormhole/src/benchmarking.rs | 47 +- pallets/wormhole/src/lib.rs | 45 +- pallets/wormhole/src/mock.rs | 27 +- pallets/wormhole/src/tests.rs | 405 ++-- pallets/wormhole/src/weights.rs | 18 +- pallets/wormhole/verifier.bin | Bin 552 -> 552 bytes runtime/Cargo.toml | 4 + runtime/src/benchmarks.rs | 1 + runtime/src/configs/mod.rs | 11 + runtime/src/lib.rs | 3 + 20 files changed, 1248 insertions(+), 1209 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52e610fb..6a2353e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,11 +23,11 @@ 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 0.31.1", + "gimli 0.32.3", ] [[package]] @@ -79,7 +79,7 @@ checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "const-random", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -87,9 +87,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 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy-core" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe6c56d58fbfa9f0f6299376e8ce33091fc6494239466814c3f54b55743cb09" +checksum = "5ca96214615ec8cf3fa2a54b32f486eb49100ca7fe7eb0b8c1137cd316e7250a" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -115,9 +115,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f56873f3cac7a2c63d8e98a4314b8311aa96adb1a0f82ae923eb2119809d2c" +checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -131,9 +131,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "125a1c373261b252e53e04d6e92c37d881833afc1315fceab53fd46045695640" +checksum = "5513d5e6bd1cba6bdcf5373470f559f320c05c8c59493b6e98912fbe6733943f" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -143,18 +143,18 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9485c56de23438127a731a6b4c87803d49faf1a7068dcd1d8768aca3a9edb9" +checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28" dependencies = [ "alloy-rlp", - "bytes 1.10.1", + "bytes 1.11.0", "cfg-if", "const-hex", "derive_more 2.0.1", - "foldhash 0.1.5", - "hashbrown 0.15.5", - "indexmap 2.11.4", + "foldhash 0.2.0", + "hashbrown 0.16.0", + "indexmap 2.12.0", "itoa", "k256", "keccak-asm", @@ -175,46 +175,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" dependencies = [ "arrayvec 0.7.6", - "bytes 1.10.1", + "bytes 1.11.0", ] [[package]] name = "alloy-sol-macro" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20d867dcf42019d4779519a1ceb55eba8d7f3d0e4f0a89bcba82b8f9eb01e48" +checksum = "f3ce480400051b5217f19d6e9a82d9010cdde20f1ae9c00d53591e4a1afbb312" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74e91b0b553c115d14bd0ed41898309356dc85d0e3d4b9014c4e7715e48c8ad" +checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" dependencies = [ "alloy-sol-macro-input", "const-hex", "heck 0.5.0", - "indexmap 2.11.4", + "indexmap 2.12.0", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84194d31220803f5f62d0a00f583fd3a062b36382e2bea446f1af96727754565" +checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" dependencies = [ "const-hex", "dunce", @@ -222,15 +222,15 @@ dependencies = [ "macro-string", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe8c27b3cf6b2bb8361904732f955bc7c05e00be5f469cec7e2280b6167f3ff0" +checksum = "954d1b2533b9b2c7959652df3076954ecb1122a28cc740aa84e7b0a49f6ac0a9" dependencies = [ "serde", "winnow", @@ -238,9 +238,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5383d34ea00079e6dd89c652bcbdb764db160cef84e6250926961a0b2295d04" +checksum = "70319350969a3af119da6fb3e9bddb1bce66c9ea933600cb297c8b1850ad2a3c" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -265,9 +265,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[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", @@ -280,9 +280,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" @@ -295,22 +295,22 @@ 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]] @@ -339,7 +339,16 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", +] + +[[package]] +name = "ar_archive_writer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" +dependencies = [ + "object 0.32.2", ] [[package]] @@ -521,7 +530,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -559,7 +568,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -644,7 +653,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -723,7 +732,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27d55334c98d756b32dcceb60248647ab34f027690f87f9a362fd292676ee927" dependencies = [ "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] @@ -778,7 +787,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 2.0.16", + "thiserror 2.0.17", "time", ] @@ -790,7 +799,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", "synstructure 0.13.2", ] @@ -802,7 +811,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", "synstructure 0.13.2", ] @@ -814,7 +823,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -886,7 +895,7 @@ dependencies = [ "polling", "rustix 1.1.2", "slab", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -944,7 +953,7 @@ dependencies = [ "rustix 1.1.2", "signal-hook-registry", "slab", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -966,7 +975,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -983,7 +992,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -992,7 +1001,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures-sink", "futures-util", "memchr", @@ -1005,7 +1014,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a860072022177f903e59730004fb5dc13db9275b79bb2aef7ba8ce831956c233" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures-sink", "futures-util", "memchr", @@ -1043,7 +1052,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -1054,17 +1063,17 @@ 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 0.24.2", + "addr2line 0.25.1", "cfg-if", "libc", "miniz_oxide", - "object 0.36.7", + "object 0.37.3", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -1079,6 +1088,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base256emoji" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c" +dependencies = [ + "const-str", + "match-lookup", +] + [[package]] name = "base58" version = "0.2.0" @@ -1105,9 +1124,9 @@ checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[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", @@ -1141,7 +1160,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -1227,9 +1246,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" @@ -1401,9 +1420,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.23.2" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] name = "byteorder" @@ -1419,9 +1438,9 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[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" dependencies = [ "serde", ] @@ -1448,9 +1467,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1de8bc0aa9e9385ceb3bf0c152e3a9b9544f6c4a912c8ae504e80c1f0368603" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" dependencies = [ "serde_core", ] @@ -1486,9 +1505,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.38" +version = "1.2.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" +checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" dependencies = [ "find-msvc-tools", "jobserver", @@ -1522,9 +1541,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 = "cfg_aliases" @@ -1583,7 +1602,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -1671,9 +1690,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.48" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" dependencies = [ "clap_builder", "clap_derive", @@ -1681,9 +1700,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.48" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" dependencies = [ "anstream", "anstyle", @@ -1694,21 +1713,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 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "clatter" @@ -1744,9 +1763,9 @@ dependencies = [ [[package]] name = "codespan-reporting" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ "serde", "termcolor", @@ -1765,7 +1784,7 @@ version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "memchr", ] @@ -1809,9 +1828,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6407bff74dea37e0fa3dc1c1c974e5d46405f0c987bf9997a0762adce71eda6" +checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" dependencies = [ "cfg-if", "cpufeatures", @@ -1845,11 +1864,17 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "const-str" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3" + [[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", ] @@ -2067,7 +2092,7 @@ dependencies = [ "serde_derive", "serde_json", "tinytemplate", - "tokio 1.47.1", + "tokio 1.48.0", "walkdir", ] @@ -2150,9 +2175,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 0.14.7", "rand_core 0.6.4", @@ -2227,11 +2252,12 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa7c354e70d62b5bb6014cbad499b831e27629b8a2af2f86497cae7f74d309d" +checksum = "ac1d9d194bc0faaef14a95ed6e78d4afccd117e67ff03c0ed712298e1124921a" dependencies = [ - "bytes 1.10.1", + "array-bytes 6.2.3", + "bytes 1.11.0", "cumulus-pallet-parachain-system-proc-macro", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", @@ -2272,7 +2298,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2378,14 +2404,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "cxx" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f81de88da10862f22b5b3a60f18f6f42bbe7cb8faa24845dd7b1e4e22190e77" +checksum = "47ac4eaf7ebe29e92f1b091ceefec7710a53a6f6154b2460afda626c113b65b9" dependencies = [ "cc", "cxx-build", @@ -2398,50 +2424,49 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5edd58bf75c3fdfc80d79806403af626570662f7b6cc782a7fabe156166bd6d6" +checksum = "2abd4c3021eefbac5149f994c117b426852bca3a0aad227698527bca6d4ea657" dependencies = [ "cc", "codespan-reporting", - "indexmap 2.11.4", + "indexmap 2.12.0", "proc-macro2", "quote", "scratch", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "cxxbridge-cmd" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd46bf2b541a4e0c2d5abba76607379ee05d68e714868e3cb406dc8d591ce2d2" +checksum = "6f12fbc5888b2311f23e52a601e11ad7790d8f0dbb903ec26e2513bf5373ed70" dependencies = [ "clap", "codespan-reporting", - "indexmap 2.11.4", + "indexmap 2.12.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "cxxbridge-flags" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c79b68f6a3a8f809d39b38ae8af61305a6113819b19b262643b9c21353b92d9" +checksum = "83d3dd7870af06e283f3f8ce0418019c96171c9ce122cfb9c8879de3d84388fd" [[package]] name = "cxxbridge-macro" -version = "1.0.185" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862b7fdb048ff9ef0779a0d0a03affd09746c4c875543746b640756be9cff2af" +checksum = "a26f0d82da663316786791c3d0e9f9edc7d1ee1f04bdad3d2643086a69d6256c" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.0", "proc-macro2", "quote", - "rustversion", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2475,7 +2500,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2489,7 +2514,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2500,7 +2525,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2511,7 +2536,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2524,7 +2549,7 @@ dependencies = [ "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core 0.9.11", + "parking_lot_core 0.9.12", ] [[package]] @@ -2550,7 +2575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2594,9 +2619,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", ] @@ -2620,7 +2645,7 @@ checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2631,7 +2656,7 @@ checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2642,7 +2667,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2655,7 +2680,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2684,7 +2709,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2695,7 +2720,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", "unicode-xid", ] @@ -2794,7 +2819,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2818,7 +2843,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.106", + "syn 2.0.110", "termcolor", "toml 0.8.23", "walkdir", @@ -2866,7 +2891,7 @@ checksum = "7e8671d54058979a37a26f3511fbf8d198ba1aa35ffb202c42587d918d77213a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2940,7 +2965,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -2993,34 +3018,34 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[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.110", ] [[package]] name = "env_filter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ "log", "regex", @@ -3071,7 +3096,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]] @@ -3162,7 +3187,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -3191,7 +3216,7 @@ checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ "arrayvec 0.7.6", "auto_impl", - "bytes 1.10.1", + "bytes 1.11.0", ] [[package]] @@ -3202,7 +3227,7 @@ checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" dependencies = [ "arrayvec 0.7.6", "auto_impl", - "bytes 1.10.1", + "bytes 1.11.0", ] [[package]] @@ -3222,11 +3247,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb42427514b063d97ce21d5199f36c0c307d981434a6be32582bc79fe5bd2303" dependencies = [ "expander", - "indexmap 2.11.4", + "indexmap 2.12.0", "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -3299,15 +3324,15 @@ dependencies = [ "log", "num-traits", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "scale-info", ] [[package]] name = "find-msvc-tools" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "fixed-hash" @@ -3336,6 +3361,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "fnv" version = "1.0.7" @@ -3485,7 +3516,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7cb8796f93fa038f979a014234d632e9688a120e745f936e2635123c77537f7" dependencies = [ - "frame-metadata 20.0.0", + "frame-metadata 21.0.0", "parity-scale-codec", "scale-decode", "scale-info", @@ -3502,7 +3533,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -3525,9 +3556,9 @@ dependencies = [ [[package]] name = "frame-executive" -version = "41.0.1" +version = "41.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7e5477db02bf54b4413611f55ec59673fa7b071eef08b7097e739f999a215cd" +checksum = "11e495475817addd877fa08bc17fc92d7308f4d5e99be5488433ccf19d222122" dependencies = [ "aquamarine", "frame-support", @@ -3554,6 +3585,17 @@ dependencies = [ "serde", ] +[[package]] +name = "frame-metadata" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20dfd1d7eae1d94e32e869e2fb272d81f52dd8db57820a373adb83ea24d7d862" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "frame-metadata" version = "23.0.0" @@ -3658,7 +3700,7 @@ dependencies = [ "proc-macro2", "quote", "sp-crypto-hashing", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -3671,7 +3713,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -3682,14 +3724,14 @@ checksum = "ed971c6435503a099bdac99fe4c5bea08981709e5b5a0a8535a1856f48561191" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "frame-system" -version = "41.0.0" +version = "41.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce7df989cefbaab681101774748a1bbbcd23d0cc66e392f8f22d3d3159914db" +checksum = "4189198074d7964bd6cb9d1cf69d77d5d224026bce95bb0ca7efc7768bb8e29c" dependencies = [ "cfg-if", "docify", @@ -3854,7 +3896,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -3914,20 +3956,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "generator" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" -dependencies = [ - "cc", - "cfg-if", - "libc", - "log", - "rustversion", - "windows 0.61.3", -] - [[package]] name = "generic-array" version = "0.12.4" @@ -3967,21 +3995,21 @@ 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", "js-sys", "libc", "r-efi", - "wasi 0.14.7+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] @@ -4026,6 +4054,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + [[package]] name = "glob" version = "0.3.3" @@ -4044,7 +4078,7 @@ dependencies = [ "futures-timer", "no-std-compat", "nonzero_ext", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "portable-atomic", "quanta", "rand 0.8.5", @@ -4069,15 +4103,15 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "fnv", "futures-core", "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.11.4", + "indexmap 2.12.0", "slab", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-util", "tracing", ] @@ -4089,26 +4123,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", - "bytes 1.10.1", + "bytes 1.11.0", "fnv", "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.11.4", + "indexmap 2.12.0", "slab", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-util", "tracing", ] [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy", ] [[package]] @@ -4176,6 +4211,15 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "foldhash 0.2.0", "serde", ] @@ -4259,7 +4303,7 @@ dependencies = [ "socket2 0.5.10", "thiserror 1.0.69", "tinyvec", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", "url", ] @@ -4282,9 +4326,9 @@ dependencies = [ "once_cell", "rand 0.9.2", "ring 0.17.14", - "thiserror 2.0.16", + "thiserror 2.0.17", "tinyvec", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", "url", ] @@ -4301,12 +4345,12 @@ dependencies = [ "ipconfig", "lru-cache", "once_cell", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "rand 0.8.5", "resolv-conf", "smallvec", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", ] @@ -4322,12 +4366,12 @@ dependencies = [ "ipconfig", "moka", "once_cell", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "rand 0.9.2", "resolv-conf", "smallvec", - "thiserror 2.0.16", - "tokio 1.47.1", + "thiserror 2.0.17", + "tokio 1.48.0", "tracing", ] @@ -4376,7 +4420,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "fnv", "itoa", ] @@ -4387,7 +4431,7 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "fnv", "itoa", ] @@ -4398,7 +4442,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "http 0.2.12", "pin-project-lite 0.2.16", ] @@ -4409,7 +4453,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "http 1.3.1", ] @@ -4419,7 +4463,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures-core", "http 1.3.1", "http-body 1.0.1", @@ -4469,7 +4513,7 @@ version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures-channel", "futures-core", "futures-util", @@ -4481,7 +4525,7 @@ dependencies = [ "itoa", "pin-project-lite 0.2.16", "socket2 0.5.10", - "tokio 1.47.1", + "tokio 1.48.0", "tower-service", "tracing", "want", @@ -4489,12 +4533,12 @@ dependencies = [ [[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 1.10.1", + "bytes 1.11.0", "futures-channel", "futures-core", "h2 0.4.12", @@ -4506,7 +4550,7 @@ dependencies = [ "pin-project-lite 0.2.16", "pin-utils", "smallvec", - "tokio 1.47.1", + "tokio 1.48.0", "want", ] @@ -4517,34 +4561,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ "http 1.3.1", - "hyper 1.7.0", + "hyper 1.8.1", "hyper-util", "log", "rustls", "rustls-native-certs", "rustls-pki-types", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-rustls", "tower-service", ] [[package]] name = "hyper-util" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures-channel", "futures-core", "futures-util", "http 1.3.1", "http-body 1.0.1", - "hyper 1.7.0", + "hyper 1.8.1", "libc", "pin-project-lite 0.2.16", - "socket2 0.6.0", - "tokio 1.47.1", + "socket2 0.6.1", + "tokio 1.48.0", "tower-service", "tracing", ] @@ -4561,7 +4605,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.0", + "windows-core 0.62.2", ] [[package]] @@ -4575,9 +4619,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", @@ -4588,9 +4632,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", @@ -4601,11 +4645,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", @@ -4616,42 +4659,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.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" 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.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[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", @@ -4715,7 +4754,7 @@ dependencies = [ "netlink-sys", "rtnetlink", "system-configuration 0.6.1", - "tokio 1.47.1", + "tokio 1.48.0", "windows 0.53.0", ] @@ -4727,13 +4766,13 @@ checksum = "064d90fec10d541084e7b39ead8875a5a80d9114a2b18791565253bae25f49e4" dependencies = [ "async-trait", "attohttpc", - "bytes 1.10.1", + "bytes 1.11.0", "futures 0.3.31", "http 0.2.12", "hyper 0.14.32", "log", "rand 0.8.5", - "tokio 1.47.1", + "tokio 1.48.0", "url", "xmltree", ] @@ -4793,7 +4832,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -4828,12 +4867,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.4" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.0", "serde", "serde_core", ] @@ -4882,17 +4921,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[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 = "ip_network" version = "0.4.1" @@ -4919,20 +4947,20 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[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" @@ -4987,26 +5015,26 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", - "serde", + "serde_core", ] [[package]] name = "jiff-static" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -5037,15 +5065,15 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.80" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -5053,9 +5081,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", @@ -5063,15 +5091,15 @@ dependencies = [ "jsonrpsee-server", "jsonrpsee-types", "jsonrpsee-ws-client", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", ] [[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 0.22.1", "futures-util", @@ -5083,7 +5111,7 @@ dependencies = [ "rustls-platform-verifier", "soketto", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-rustls", "tokio-util", "tracing", @@ -5092,54 +5120,54 @@ 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 1.10.1", + "bytes 1.11.0", "futures-timer", "futures-util", "http 1.3.1", "http-body 1.0.1", "http-body-util", "jsonrpsee-types", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project", "rand 0.8.5", "rustc-hash 2.1.1", "serde", "serde_json", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-stream", "tracing", ] [[package]] name = "jsonrpsee-proc-macros" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e65763c942dfc9358146571911b0cd1c361c2d63e2d2305622d40d36376ca80" +checksum = "7398cddf5013cca4702862a2692b66c48a3bd6cf6ec681a47453c93d63cf8de5" dependencies = [ "heck 0.5.0", "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "jsonrpsee-server" -version = "0.24.9" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e363146da18e50ad2b51a0a7925fc423137a0b1371af8235b1c231a0647328" +checksum = "21429bcdda37dcf2d43b68621b994adede0e28061f816b038b0f18c70c143d51" dependencies = [ "futures-util", "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.7.0", + "hyper 1.8.1", "hyper-util", "jsonrpsee-core", "jsonrpsee-types", @@ -5149,7 +5177,7 @@ dependencies = [ "serde_json", "soketto", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-stream", "tokio-util", "tower", @@ -5158,9 +5186,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 1.3.1", "serde", @@ -5170,9 +5198,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 1.3.1", "jsonrpsee-client-transport", @@ -5278,7 +5306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7a85fe66f9ff9cd74e169fdd2c94c6e1e74c412c99a73b4df3200b5d3760b2" dependencies = [ "kvdb", - "parking_lot 0.12.4", + "parking_lot 0.12.5", ] [[package]] @@ -5289,7 +5317,7 @@ checksum = "b644c70b92285f66bfc2032922a79000ea30af7bc2ab31902992a5dcb9b434f6" dependencies = [ "kvdb", "num_cpus", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "regex", "rocksdb", "smallvec", @@ -5312,9 +5340,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.175" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libloading" @@ -5323,7 +5351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -5338,7 +5366,7 @@ version = "0.54.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbe80f9c7e00526cd6b838075b9c171919404a4732cb2fa8ece0a093223bfc4" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "either", "futures 0.3.31", "futures-timer", @@ -5406,7 +5434,7 @@ dependencies = [ "multihash 0.19.3", "multistream-select", "once_cell", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project", "quick-protobuf", "rand 0.8.5", @@ -5430,7 +5458,7 @@ dependencies = [ "hickory-resolver 0.24.4", "libp2p-core", "libp2p-identity", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "smallvec", "tracing", ] @@ -5484,7 +5512,7 @@ checksum = "ced237d0bd84bbebb7c2cad4c073160dacb4fe40534963c32ed6d4c6bb7702a3" dependencies = [ "arrayvec 0.7.6", "asynchronous-codec 0.7.0", - "bytes 1.10.1", + "bytes 1.11.0", "either", "fnv", "futures 0.3.31", @@ -5521,7 +5549,7 @@ dependencies = [ "rand 0.8.5", "smallvec", "socket2 0.5.10", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", "void", ] @@ -5550,7 +5578,7 @@ version = "0.45.10" source = "git+https://github.com/Quantus-Network/qp-libp2p-noise?tag=v0.45.10#901f09f30b32f910395270bba3a566191dc2f61f" dependencies = [ "asynchronous-codec 0.6.2", - "bytes 1.10.1", + "bytes 1.11.0", "clatter", "futures 0.3.31", "libp2p-core", @@ -5591,21 +5619,21 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46352ac5cd040c70e88e7ff8257a2ae2f891a4076abad2c439584a31c15fd24e" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures 0.3.31", "futures-timer", "if-watch", "libp2p-core", "libp2p-identity", "libp2p-tls", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "quinn", "rand 0.8.5", "ring 0.17.14", "rustls", "socket2 0.5.10", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", ] @@ -5647,7 +5675,7 @@ dependencies = [ "once_cell", "rand 0.8.5", "smallvec", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", "void", "web-time", @@ -5662,7 +5690,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -5678,7 +5706,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "socket2 0.5.10", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", ] @@ -5712,7 +5740,7 @@ dependencies = [ "igd-next", "libp2p-core", "libp2p-swarm", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", "void", ] @@ -5728,7 +5756,7 @@ dependencies = [ "futures-rustls", "libp2p-core", "libp2p-identity", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project-lite 0.2.16", "rw-stream-sink", "soketto", @@ -5750,7 +5778,7 @@ dependencies = [ "thiserror 1.0.69", "tracing", "yamux 0.12.1", - "yamux 0.13.6", + "yamux 0.13.8", ] [[package]] @@ -5759,9 +5787,9 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "libc", - "redox_syscall 0.5.17", + "redox_syscall 0.5.18", ] [[package]] @@ -5829,9 +5857,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.22" +version = "1.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" dependencies = [ "cc", "pkg-config", @@ -5855,9 +5883,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linked_hash_set" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae85b5be22d9843c80e5fc80e9b64c8a3b1f98f867c709956eca3efff4e92e2" +checksum = "984fb35d06508d1e69fc91050cceba9c0b748f983e6739fa2c7a9237154c52c8" dependencies = [ "linked-hash-map", ] @@ -5897,9 +5925,9 @@ dependencies = [ [[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 = "litep2p" @@ -5909,19 +5937,19 @@ checksum = "14fb10e63363204b89d91e1292df83322fd9de5d7fa76c3d5c78ddc2f8f3efa9" dependencies = [ "async-trait", "bs58", - "bytes 1.10.1", + "bytes 1.11.0", "cid 0.11.1", "ed25519-dalek", "futures 0.3.31", "futures-timer", "hickory-resolver 0.25.2", - "indexmap 2.11.4", + "indexmap 2.12.0", "libc", "mockall", "multiaddr 0.17.1", "multihash 0.17.0", "network-interface", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project", "prost 0.13.5", "prost-build", @@ -5932,8 +5960,8 @@ dependencies = [ "smallvec", "snow", "socket2 0.5.10", - "thiserror 2.0.16", - "tokio 1.47.1", + "thiserror 2.0.17", + "tokio 1.48.0", "tokio-stream", "tokio-tungstenite", "tokio-util", @@ -5943,18 +5971,17 @@ dependencies = [ "url", "x25519-dalek", "x509-parser 0.17.0", - "yamux 0.13.6", + "yamux 0.13.8", "yasna", "zeroize", ] [[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", ] @@ -5964,19 +5991,6 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - [[package]] name = "lru" version = "0.12.5" @@ -6037,7 +6051,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -6049,7 +6063,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -6063,7 +6077,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -6074,7 +6088,7 @@ checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -6085,16 +6099,27 @@ checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.106", + "syn 2.0.110", +] + +[[package]] +name = "match-lookup" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] @@ -6109,9 +6134,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 = "memfd" @@ -6133,9 +6158,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" dependencies = [ "libc", ] @@ -6209,13 +6234,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -6234,7 +6259,7 @@ dependencies = [ "hashlink", "lioness", "log", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "rand 0.8.5", "rand_chacha 0.3.1", "rand_distr", @@ -6279,25 +6304,24 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "moka" -version = "0.12.10" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" +checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" dependencies = [ "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", - "loom", - "parking_lot 0.12.4", + "equivalent", + "parking_lot 0.12.5", "portable-atomic", "rustc_version 0.4.1", "smallvec", "tagptr", - "thiserror 1.0.69", "uuid", ] @@ -6347,11 +6371,12 @@ dependencies = [ [[package]] name = "multibase" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" +checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77" dependencies = [ "base-x", + "base256emoji", "data-encoding", "data-encoding-macro", ] @@ -6409,7 +6434,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0df8e5eec2298a62b326ee4f0d7fe1a6b90a09dfcf9df37b38f947a8c42f19" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures 0.3.31", "log", "pin-project", @@ -6503,12 +6528,12 @@ version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72452e012c2f8d612410d89eea01e2d9b56205274abb35d53f60200b2ec41d60" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures 0.3.31", "log", "netlink-packet-core", "netlink-sys", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] @@ -6517,11 +6542,11 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures 0.3.31", "libc", "log", - "tokio 1.47.1", + "tokio 1.48.0", ] [[package]] @@ -6532,7 +6557,7 @@ checksum = "07709a6d4eba90ab10ec170a0530b3aafc81cb8a2d380e4423ae41fc55fe5745" dependencies = [ "cc", "libc", - "thiserror 2.0.16", + "thiserror 2.0.17", "winapi", ] @@ -6598,12 +6623,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -6655,7 +6679,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -6731,6 +6755,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "object" version = "0.36.7" @@ -6740,6 +6773,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + [[package]] name = "oid-registry" version = "0.7.1" @@ -6770,9 +6812,9 @@ dependencies = [ [[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 = "oorandom" @@ -6828,21 +6870,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43dfaf083aef571385fccfdc3a2f8ede8d0a1863160455d4f2b014d8f7d04a3f" dependencies = [ "expander", - "indexmap 2.11.4", + "indexmap 2.12.0", "itertools 0.11.0", - "petgraph", + "petgraph 0.6.5", "proc-macro-crate 3.4.0", "proc-macro2", "quote", "syn 1.0.109", ] -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "p3-dft" version = "0.3.0" @@ -7251,9 +7287,9 @@ dependencies = [ [[package]] name = "pallet-ranked-collective" -version = "41.0.0" +version = "41.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf43c766b69c37ab964cf076f605d3993357124fcdd14a8ba3ecc169e2d0fc9c" +checksum = "aae595fd2ce7b0889680e173fe7faf743f127143faf5f2e716bae12cd8c0b354" dependencies = [ "frame-benchmarking", "frame-support", @@ -7325,9 +7361,9 @@ dependencies = [ [[package]] name = "pallet-revive" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474840408264f98eea7f187839ff2157f83a92bec6f3f3503dbf855c38f4de6b" +checksum = "1459d118aeccd7fef1dfb7e3ea002a376c8f07c61053eb2875acc38b1ceee4d9" dependencies = [ "alloy-core", "derive_more 0.99.20", @@ -7393,7 +7429,7 @@ checksum = "63c2dc2fc6961da23fefc54689ce81a8e006f6988bc465dcc9ab9db905d31766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -7618,14 +7654,23 @@ dependencies = [ "log", "pallet-balances 40.0.1", "parity-scale-codec", + "qp-dilithium-crypto", + "qp-header", + "qp-plonky2", + "qp-poseidon", + "qp-poseidon-core", "qp-wormhole", "qp-wormhole-circuit", + "qp-wormhole-circuit-builder", + "qp-wormhole-prover", "qp-wormhole-verifier", "qp-zk-circuits-common", "scale-info", "sp-core", "sp-io", "sp-runtime", + "sp-state-machine", + "sp-trie", ] [[package]] @@ -7655,7 +7700,7 @@ dependencies = [ "log", "lz4", "memmap2 0.5.10", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "rand 0.8.5", "siphasher 0.3.11", "snap", @@ -7671,7 +7716,7 @@ dependencies = [ "arrayvec 0.7.6", "bitvec", "byte-slice-cast", - "bytes 1.10.1", + "bytes 1.11.0", "const_format", "impl-trait-for-tuples", "parity-scale-codec-derive", @@ -7688,7 +7733,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -7716,12 +7761,12 @@ dependencies = [ [[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 0.9.11", + "parking_lot_core 0.9.12", ] [[package]] @@ -7740,15 +7785,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 0.5.17", + "redox_syscall 0.5.18", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -7793,12 +7838,12 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] @@ -7818,20 +7863,19 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ "memchr", - "thiserror 2.0.16", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc58706f770acb1dbd0973e6530a3cff4746fb721207feb3a8a6064cd0b6c663" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ "pest", "pest_generator", @@ -7839,22 +7883,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4f36811dfe07f7b8573462465d5cb8965fffc2e71ae377a33aecf14c2c9a2f" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "pest_meta" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42919b05089acbd0a5dcd5405fb304d17d1053847b81163d09c4ad18ce8e8420" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ "pest", "sha2 0.10.9", @@ -7866,8 +7910,18 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ - "fixedbitset", - "indexmap 2.11.4", + "fixedbitset 0.4.2", + "indexmap 2.12.0", +] + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset 0.5.7", + "indexmap 2.12.0", ] [[package]] @@ -7887,7 +7941,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -8046,9 +8100,9 @@ dependencies = [ [[package]] name = "polkadot-node-primitives" -version = "20.0.0" +version = "20.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "498dd752f08ff2a3f92fa67e5f5cbca65a342c924465ca8cc7e4b3902a6f8613" +checksum = "01b9c91614ec9e0502c547792dd72b00cf3c73d7290f8e611008129207124e4f" dependencies = [ "bitvec", "bounded-vec", @@ -8181,9 +8235,9 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" -version = "20.0.2" +version = "20.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7692d2a6109ef7b4749c51d5c950fa15f8e38fed439d5d520ba49fa322466c45" +checksum = "d5eccffd0a38fc4cdbf9b3b8c0bc9d140fc2cb49e1f073208b88c9c9138ae039" dependencies = [ "bitflags 1.3.2", "bitvec", @@ -8367,7 +8421,7 @@ dependencies = [ "polkavm-common 0.21.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -8379,7 +8433,7 @@ dependencies = [ "polkavm-common 0.24.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -8389,7 +8443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36837f6b7edfd6f4498f8d25d81da16cf03bd6992c3e56f3d477dfc90f4fefca" dependencies = [ "polkavm-derive-impl 0.21.0", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -8399,7 +8453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba0ef0f17ad81413ea1ca5b1b67553aedf5650c88269b673d3ba015c83bc2651" dependencies = [ "polkavm-derive-impl 0.24.0", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -8457,7 +8511,7 @@ dependencies = [ "hermit-abi 0.5.2", "pin-project-lite 0.2.16", "rustix 1.1.2", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -8500,9 +8554,9 @@ dependencies = [ [[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", ] @@ -8530,7 +8584,7 @@ checksum = "b4a326caf27cbf2ac291ca7fd56300497ba9e76a8cc6a7d95b7a18b57f22b61d" dependencies = [ "cc", "dunce", - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] @@ -8596,7 +8650,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -8676,7 +8730,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.23.6", + "toml_edit 0.23.7", ] [[package]] @@ -8722,7 +8776,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -8733,14 +8787,14 @@ checksum = "75eea531cfcd120e0851a3f8aed42c4841f78c889eefafd96339c72677ae42c3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -8755,7 +8809,7 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "thiserror 1.0.69", ] @@ -8767,7 +8821,7 @@ checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "prometheus-client-derive-encode", ] @@ -8779,24 +8833,23 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "proptest" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.9.4", - "lazy_static", + "bitflags 2.10.0", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", "rand_xorshift", - "regex-syntax 0.8.6", + "regex-syntax", "rusty-fork", "tempfile", "unarray", @@ -8808,7 +8861,7 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "prost-derive 0.12.6", ] @@ -8818,7 +8871,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "prost-derive 0.13.5", ] @@ -8833,12 +8886,12 @@ dependencies = [ "log", "multimap", "once_cell", - "petgraph", + "petgraph 0.7.1", "prettyplease", "prost 0.13.5", "prost-types", "regex", - "syn 2.0.106", + "syn 2.0.110", "tempfile", ] @@ -8852,7 +8905,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -8865,7 +8918,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -8879,10 +8932,11 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" +checksum = "d11f2fedc3b7dafdc2851bc52f277377c5473d378859be234bc7ebb593144d01" dependencies = [ + "ar_archive_writer", "cc", ] @@ -8923,9 +8977,9 @@ dependencies = [ [[package]] name = "qp-plonky2" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "068162bd3730e381744eca219f98f0db22874afc8fa24631611e975c93d6cf68" +checksum = "39530b02faa85964bba211e030afa2d54995b403b0022f88e984c4c65679c4bc" dependencies = [ "ahash", "anyhow", @@ -8935,9 +8989,14 @@ dependencies = [ "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", "rand 0.8.5", "rand_chacha 0.3.1", "serde", @@ -8948,9 +9007,9 @@ dependencies = [ [[package]] name = "qp-plonky2-field" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b2f7e0854f9e14aa9b3f6d544ccf71087e751d6adbe6a7e50d2c75fb561d97" +checksum = "7e8d52dadf3bb92708c309922b62d7f3f2587d3047f9fe05a0c9f587e2890526" dependencies = [ "anyhow", "itertools 0.11.0", @@ -8965,9 +9024,9 @@ dependencies = [ [[package]] name = "qp-poseidon" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0353086f7af1df7d45a1ecb995cf84b583c8211d7122f542044b37388b5effcd" +checksum = "8ebc5e9fe1f91f5006aa2b45650d0049887d41d80c669ef5a78a45086895054d" dependencies = [ "log", "p3-field", @@ -8997,14 +9056,15 @@ dependencies = [ [[package]] name = "qp-poseidon-core" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e658a373a7fb22babeda9ffcc8af0a894e6e3c008272ed735509eccb7769ead3" +checksum = "f52c70df221c356b3ce63afabfae623aae632c27d3e078cd20eec4348096c2d7" dependencies = [ "p3-field", "p3-goldilocks", "p3-poseidon2", "p3-symmetric", + "qp-plonky2", "qp-poseidon-constants", "rand_chacha 0.9.0", ] @@ -9037,7 +9097,7 @@ dependencies = [ "rand_core 0.9.3", "serde", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] @@ -9056,21 +9116,34 @@ version = "0.1.0" [[package]] name = "qp-wormhole-circuit" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea70a3a1bf545450cb6320782389cfbfe58fcf0ecf724aa666383807bf5548b" +checksum = "10b7357bec091287185850a6f7b67eb45f899a655b2a86825eae7e39b3bc6c3c" dependencies = [ "anyhow", "hex", "qp-plonky2", + "qp-poseidon-core", "qp-zk-circuits-common", ] [[package]] name = "qp-wormhole-circuit-builder" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d6486fbfd79005d520caff6a32a8fde4eab978110101c9612d140f3e0ebdfd0" +checksum = "7faed51eaa66ba71526955b74aac2fdba9849905a405f74d5f4f26564a9eaa98" +dependencies = [ + "anyhow", + "qp-plonky2", + "qp-wormhole-circuit", + "qp-zk-circuits-common", +] + +[[package]] +name = "qp-wormhole-prover" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a56d84dd9bf64944b88cb0ec971f179a569d3bdf148132ab01bfe2d56c069d" dependencies = [ "anyhow", "qp-plonky2", @@ -9080,9 +9153,9 @@ dependencies = [ [[package]] name = "qp-wormhole-verifier" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f83ee7ce0fdb40f34eed7a31a575e857d24135a383cdfd6f2429a7ce048b665" +checksum = "40387c4c43fe47419cba58eb4f13c2a3c32ac0e381c98c3d77293ebf53298de7" dependencies = [ "anyhow", "qp-plonky2", @@ -9092,12 +9165,14 @@ dependencies = [ [[package]] name = "qp-zk-circuits-common" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a2a62915be0513d045f4d92829c0a26d6f3e8897353e8f8356a7eabef025329" +checksum = "366557f4c727379e2fd9c18b6667ae53c99bb241b973427df09a6b09584a11d4" dependencies = [ "anyhow", + "hex", "qp-plonky2", + "qp-poseidon-core", "serde", ] @@ -9123,7 +9198,7 @@ dependencies = [ "libc", "once_cell", "raw-cpuid", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "web-sys", "winapi", ] @@ -9231,6 +9306,7 @@ dependencies = [ "pallet-treasury", "pallet-utility", "pallet-vesting", + "pallet-wormhole", "parity-scale-codec", "primitive-types 0.13.1", "qp-dilithium-crypto", @@ -9281,7 +9357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15a0580ab32b169745d7a39db2ba969226ca16738931be152a3209b409de2474" dependencies = [ "asynchronous-codec 0.7.0", - "bytes 1.10.1", + "bytes 1.11.0", "quick-protobuf", "thiserror 1.0.69", "unsigned-varint 0.8.0", @@ -9293,7 +9369,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "cfg_aliases 0.2.1", "futures-io", "pin-project-lite 0.2.16", @@ -9301,9 +9377,9 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls", - "socket2 0.6.0", - "thiserror 2.0.16", - "tokio 1.47.1", + "socket2 0.6.1", + "thiserror 2.0.17", + "tokio 1.48.0", "tracing", "web-time", ] @@ -9314,8 +9390,8 @@ version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ - "bytes 1.10.1", - "getrandom 0.3.3", + "bytes 1.11.0", + "getrandom 0.3.4", "lru-slab", "rand 0.9.2", "ring 0.17.14", @@ -9323,7 +9399,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.16", + "thiserror 2.0.17", "tinyvec", "tracing", "web-time", @@ -9338,16 +9414,16 @@ dependencies = [ "cfg_aliases 0.2.1", "libc", "once_cell", - "socket2 0.6.0", + "socket2 0.6.1", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -9421,7 +9497,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "serde", ] @@ -9459,7 +9535,7 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", ] [[package]] @@ -9511,11 +9587,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]] @@ -9531,22 +9607,22 @@ dependencies = [ [[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.110", ] [[package]] @@ -9576,47 +9652,32 @@ dependencies = [ [[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", - "regex-automata 0.4.10", - "regex-syntax 0.8.6", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[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", - "regex-syntax 0.8.6", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" @@ -9625,7 +9686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", - "bytes 1.10.1", + "bytes 1.11.0", "encoding_rs", "futures-core", "futures-util", @@ -9645,7 +9706,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "system-configuration 0.5.1", - "tokio 1.47.1", + "tokio 1.48.0", "tower-service", "url", "wasm-bindgen", @@ -9714,7 +9775,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "rustc-hex", ] @@ -9724,7 +9785,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa24e92bb2a83198bb76d661a71df9f7076b8c420b8696e4d3d97d50d94479e3" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "rustc-hex", ] @@ -9770,7 +9831,7 @@ dependencies = [ "netlink-sys", "nix", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", ] [[package]] @@ -9785,14 +9846,15 @@ dependencies = [ [[package]] name = "ruint" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecb38f82477f20c5c3d62ef52d7c4e536e38ea9b73fb570a20c5cae0e14bcf6" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", "ark-ff 0.4.2", - "bytes 1.10.1", + "ark-ff 0.5.0", + "bytes 1.11.0", "fastrlp 0.3.1", "fastrlp 0.4.0", "num-bigint", @@ -9805,7 +9867,7 @@ dependencies = [ "rand 0.9.2", "rlp 0.5.2", "ruint-macro", - "serde", + "serde_core", "valuable", "zeroize", ] @@ -9887,33 +9949,33 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.32" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "log", "once_cell", "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.103.6", + "rustls-webpki 0.103.8", "subtle 2.6.1", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -9923,9 +9985,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ "web-time", "zeroize", @@ -9945,7 +10007,7 @@ dependencies = [ "rustls", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki 0.103.6", + "rustls-webpki 0.103.8", "security-framework", "security-framework-sys", "webpki-root-certs 0.26.11", @@ -9970,9 +10032,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.6" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring 0.17.14", "rustls-pki-types", @@ -9987,9 +10049,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rusty-fork" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" dependencies = [ "fnv", "quick-error", @@ -10092,7 +10154,7 @@ dependencies = [ "sp-runtime", "substrate-prometheus-endpoint", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", ] [[package]] @@ -10141,7 +10203,7 @@ checksum = "c25df970b58c05e8381a1ead6f5708e3539aefa9212d311866fed64f141214e7" dependencies = [ "array-bytes 6.2.3", "docify", - "memmap2 0.9.8", + "memmap2 0.9.9", "parity-scale-codec", "sc-chain-spec-derive", "sc-client-api", @@ -10169,7 +10231,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -10217,7 +10279,7 @@ dependencies = [ "sp-version", "tempfile", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", ] [[package]] @@ -10230,7 +10292,7 @@ dependencies = [ "futures 0.3.31", "log", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sc-executor", "sc-transaction-pool-api", "sc-utils", @@ -10261,7 +10323,7 @@ dependencies = [ "log", "parity-db", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sc-client-api", "sc-state-db", "schnellru", @@ -10286,7 +10348,7 @@ dependencies = [ "futures 0.3.31", "log", "mockall", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sc-client-api", "sc-network-types", "sc-utils", @@ -10314,7 +10376,7 @@ dependencies = [ "num-rational", "num-traits", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sc-client-api", "sc-consensus", "sc-consensus-epochs", @@ -10361,7 +10423,7 @@ dependencies = [ "hex", "log", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "primitive-types 0.13.1", "sc-client-api", "sc-consensus", @@ -10413,7 +10475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfd7a23eebd1fea90534994440f0ef516cbd8c0ef749e272c6c77fd729bbca71" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sc-executor-common", "sc-executor-polkavm", "sc-executor-wasmtime", @@ -10464,7 +10526,7 @@ checksum = "a5980897e2915ef027560886a2bb52f49a2cea4a9b9f5c75fead841201d03705" dependencies = [ "anyhow", "log", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "rustix 0.36.17", "sc-allocator", "sc-executor-common", @@ -10497,7 +10559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c28fc85c00ddf64f32f68111c61521b1f260f8dfa1eb98f9ed4401aa5d0ce0" dependencies = [ "array-bytes 6.2.3", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "serde_json", "sp-application-crypto", "sp-core", @@ -10514,13 +10576,13 @@ dependencies = [ "array-bytes 6.2.3", "arrayvec 0.7.6", "blake2 0.10.6", - "bytes 1.10.1", + "bytes 1.11.0", "futures 0.3.31", "futures-timer", "log", "mixnet", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sc-client-api", "sc-network", "sc-network-types", @@ -10543,7 +10605,7 @@ dependencies = [ "async-channel 1.9.0", "async-trait", "asynchronous-codec 0.6.2", - "bytes 1.10.1", + "bytes 1.11.0", "cid 0.9.0", "criterion", "either", @@ -10559,7 +10621,7 @@ dependencies = [ "multistream-select", "once_cell", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "partial_sort", "pin-project", "prost 0.12.6", @@ -10585,7 +10647,7 @@ dependencies = [ "substrate-prometheus-endpoint", "tempfile", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-stream", "tokio-test", "tokio-util", @@ -10660,7 +10722,7 @@ dependencies = [ "sp-runtime", "substrate-prometheus-endpoint", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-stream", ] @@ -10691,7 +10753,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "441af5d0adf306ff745ccf23c7426ec2edf24f6fee678fb63994e1f8d2fcc890" dependencies = [ "bs58", - "bytes 1.10.1", + "bytes 1.11.0", "ed25519-dalek", "libp2p-identity", "libp2p-kad", @@ -10712,18 +10774,18 @@ version = "46.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029f2eb16f9510a749201e7a2b405aafcc5afcc515509518d2efb17b164ca47e" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "fnv", "futures 0.3.31", "futures-timer", "http-body-util", - "hyper 1.7.0", + "hyper 1.8.1", "hyper-rustls", "hyper-util", "num_cpus", "once_cell", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "rand 0.8.5", "rustls", "sc-client-api", @@ -10761,7 +10823,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -10781,7 +10843,7 @@ dependencies = [ "sp-session", "sp-statement-store", "sp-version", - "tokio 1.47.1", + "tokio 1.48.0", ] [[package]] @@ -10817,7 +10879,7 @@ dependencies = [ "governor", "http 1.3.1", "http-body-util", - "hyper 1.7.0", + "hyper 1.8.1", "ip_network", "jsonrpsee", "log", @@ -10825,7 +10887,7 @@ dependencies = [ "serde", "serde_json", "substrate-prometheus-endpoint", - "tokio 1.47.1", + "tokio 1.48.0", "tower", "tower-http", ] @@ -10844,7 +10906,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "rand 0.8.5", "sc-chain-spec", "sc-client-api", @@ -10860,7 +10922,7 @@ dependencies = [ "sp-version", "substrate-prometheus-endpoint", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-stream", ] @@ -10894,7 +10956,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project", "rand 0.8.5", "sc-chain-spec", @@ -10940,7 +11002,7 @@ dependencies = [ "substrate-prometheus-endpoint", "tempfile", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tracing", "tracing-futures", ] @@ -10953,7 +11015,7 @@ checksum = "b81d0da325c141081336e8d8724f5342f2586bbb574fde81f716f7fab447325a" dependencies = [ "log", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sp-core", ] @@ -10988,7 +11050,7 @@ dependencies = [ "futures 0.3.31", "libp2p", "log", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project", "rand 0.8.5", "sc-utils", @@ -11000,17 +11062,18 @@ dependencies = [ [[package]] name = "sc-tracing" -version = "40.0.0" +version = "40.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d80e2558a0100794d5b4f4d75cb45cae65c061aaf386fd807d7a7e2c272251d2" +checksum = "b83b0097094cc643a224c093a50eae9b0a9cbfc00288e0544d0e9f0b229dd0bd" dependencies = [ "chrono", "console", + "frame-metadata 23.0.0", "is-terminal", "libc", "log", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "rustc-hash 1.1.0", "sc-client-api", "sc-tracing-proc-macro", @@ -11021,6 +11084,7 @@ dependencies = [ "sp-rpc", "sp-runtime", "sp-tracing", + "sp-trie", "thiserror 1.0.69", "tracing", "tracing-log", @@ -11036,7 +11100,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -11048,11 +11112,11 @@ dependencies = [ "async-trait", "futures 0.3.31", "futures-timer", - "indexmap 2.11.4", + "indexmap 2.12.0", "itertools 0.11.0", "linked-hash-map", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sc-client-api", "sc-transaction-pool-api", "sc-utils", @@ -11066,7 +11130,7 @@ dependencies = [ "sp-transaction-pool", "substrate-prometheus-endpoint", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-stream", "tracing", ] @@ -11079,7 +11143,7 @@ checksum = "c27a9cb54784cf7a1a607d4314f1a4437279ce6d4070eb810f3e4fbfff9b1ba7" dependencies = [ "async-trait", "futures 0.3.31", - "indexmap 2.11.4", + "indexmap 2.12.0", "log", "parity-scale-codec", "serde", @@ -11099,7 +11163,7 @@ dependencies = [ "futures 0.3.31", "futures-timer", "log", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "prometheus", "sp-arithmetic", ] @@ -11128,7 +11192,7 @@ dependencies = [ "scale-decode-derive", "scale-type-resolver", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] @@ -11140,7 +11204,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -11155,7 +11219,7 @@ dependencies = [ "scale-encode-derive", "scale-type-resolver", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] @@ -11168,7 +11232,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -11194,7 +11258,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -11216,15 +11280,15 @@ dependencies = [ "proc-macro2", "quote", "scale-info", - "syn 2.0.106", - "thiserror 2.0.16", + "syn 2.0.110", + "thiserror 2.0.17", ] [[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 0.10.6", @@ -11235,7 +11299,7 @@ dependencies = [ "scale-encode", "scale-type-resolver", "serde", - "thiserror 2.0.16", + "thiserror 2.0.17", "yap", ] @@ -11245,7 +11309,7 @@ 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]] @@ -11278,12 +11342,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -11399,11 +11457,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc198e42d9b7510827939c9a15f5062a0c913f3371d765977e586d2fe6c16f4a" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -11465,9 +11523,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -11485,22 +11543,22 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.226" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -11539,15 +11597,14 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.14.1" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e" +checksum = "10574371d41b0d9b2cff89418eda27da52bcaff2cc8741db26382a77c29131f1" dependencies = [ "base64 0.22.1", "chrono", "hex", - "serde", - "serde_derive", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -11555,14 +11612,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.14.1" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327ada00f7d64abaac1e55a6911e90cf665aa051b9a561c7006c157f4633135e" +checksum = "08a72d8216842fdd57820dc78d840bef99248e35fb2554ff923319e60f2d686b" dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -11683,7 +11740,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", ] [[package]] @@ -11816,7 +11873,7 @@ dependencies = [ "itertools 0.13.0", "log", "lru", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project", "rand 0.8.5", "rand_chacha 0.3.1", @@ -11859,12 +11916,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]] @@ -11874,7 +11931,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e859df029d160cb88608f5d7df7fb4753fd20fdfb4de5644f3d8b8440841721" dependencies = [ "base64 0.22.1", - "bytes 1.10.1", + "bytes 1.11.0", "futures 0.3.31", "http 1.3.1", "httparse", @@ -11918,7 +11975,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -11981,7 +12038,7 @@ checksum = "849f1cfcf170048d59c8d3d1175feea2a5cd41fe39742660b9ed542f0d1be7b0" dependencies = [ "futures 0.3.31", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "schnellru", "sp-api", "sp-consensus", @@ -12120,7 +12177,7 @@ dependencies = [ "merlin", "parity-bip39", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "paste", "primitive-types 0.13.1", "rand 0.8.5", @@ -12166,7 +12223,7 @@ checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" dependencies = [ "quote", "sp-crypto-hashing", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -12176,7 +12233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "722cbecdbf5b94578137dbd07feb51e95f7de221be0c1ff4dcfe0bb4cd986929" dependencies = [ "kvdb", - "parking_lot 0.12.4", + "parking_lot 0.12.5", ] [[package]] @@ -12187,7 +12244,7 @@ checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -12234,7 +12291,7 @@ version = "41.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3f244e9a2818d21220ceb0915ac73a462814a92d0c354a124a818abdb7f4f66" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "docify", "ed25519-dalek", "libsecp256k1", @@ -12273,16 +12330,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "269d0ee360f6d072f9203485afea35583ac151521a525cc48b2a107fc576c2d9" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "sp-core", "sp-externalities", ] [[package]] name = "sp-maybe-compressed-blob" -version = "11.0.0" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c768c11afbe698a090386876911da4236af199cd38a5866748df4d8628aeff" +checksum = "c9d204064a17660455603ae152b02fc7ea4cfff2d14796f6483d7a35c4cca336" dependencies = [ "thiserror 1.0.69", "zstd 0.12.4", @@ -12411,7 +12468,7 @@ version = "30.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fcd9c219da8c85d45d5ae1ce80e73863a872ac27424880322903c6ac893c06e" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "impl-trait-for-tuples", "parity-scale-codec", "polkavm-derive 0.24.0", @@ -12436,7 +12493,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -12478,7 +12535,7 @@ dependencies = [ "hash-db", "log", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pretty_assertions", "rand 0.8.5", "smallvec", @@ -12494,9 +12551,9 @@ dependencies = [ [[package]] name = "sp-statement-store" -version = "21.0.0" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d11b0753df3d68f5bb0f4d0d3975788c3a4dd2d0e479e28b7af17b52f15160" +checksum = "031e2366f3633aac66c223747f47db82d774e726e117776eab66937c0bf9f4a8" dependencies = [ "aes-gcm", "curve25519-dalek", @@ -12600,7 +12657,7 @@ dependencies = [ "memory-db", "nohash-hasher", "parity-scale-codec", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "rand 0.8.5", "scale-info", "schnellru", @@ -12644,7 +12701,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -12723,9 +12780,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 = "staging-xcm" @@ -12810,8 +12867,8 @@ dependencies = [ "bitflags 1.3.2", "cfg_aliases 0.2.1", "libc", - "parking_lot 0.12.4", - "parking_lot_core 0.9.11", + "parking_lot 0.12.5", + "parking_lot_core 0.9.12", "static_init_macro", "winapi", ] @@ -12889,7 +12946,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -12952,12 +13009,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d23e4bc8e910a312820d589047ab683928b761242dbe31dee081fbdb37cbe0be" dependencies = [ "http-body-util", - "hyper 1.7.0", + "hyper 1.8.1", "hyper-util", "log", "prometheus", "thiserror 1.0.69", - "tokio 1.47.1", + "tokio 1.48.0", ] [[package]] @@ -13052,8 +13109,8 @@ dependencies = [ "subxt-macro", "subxt-metadata", "subxt-rpcs", - "thiserror 2.0.16", - "tokio 1.47.1", + "thiserror 2.0.17", + "tokio 1.48.0", "tokio-util", "tracing", "url", @@ -13073,8 +13130,8 @@ dependencies = [ "scale-info", "scale-typegen", "subxt-metadata", - "syn 2.0.106", - "thiserror 2.0.16", + "syn 2.0.110", + "thiserror 2.0.17", ] [[package]] @@ -13103,7 +13160,7 @@ dependencies = [ "serde_json", "sp-crypto-hashing", "subxt-metadata", - "thiserror 2.0.16", + "thiserror 2.0.17", "tracing", ] @@ -13118,8 +13175,8 @@ dependencies = [ "serde", "serde_json", "smoldot-light", - "thiserror 2.0.16", - "tokio 1.47.1", + "thiserror 2.0.17", + "tokio 1.48.0", "tokio-stream", "tracing", ] @@ -13137,7 +13194,7 @@ dependencies = [ "scale-typegen", "subxt-codegen", "subxt-utils-fetchmetadata", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -13152,7 +13209,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-crypto-hashing", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] @@ -13173,7 +13230,7 @@ dependencies = [ "serde_json", "subxt-core", "subxt-lightclient", - "thiserror 2.0.16", + "thiserror 2.0.17", "tracing", "url", ] @@ -13204,7 +13261,7 @@ dependencies = [ "sha2 0.10.9", "sp-crypto-hashing", "subxt-core", - "thiserror 2.0.16", + "thiserror 2.0.17", "zeroize", ] @@ -13216,7 +13273,7 @@ checksum = "fc868b55fe2303788dc7703457af390111940c3da4714b510983284501780ed5" dependencies = [ "hex", "parity-scale-codec", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] @@ -13232,9 +13289,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" dependencies = [ "proc-macro2", "quote", @@ -13243,14 +13300,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0b198d366dbec045acfcd97295eb653a7a2b40e4dc764ef1e79aafcad439d3c" +checksum = "ff790eb176cc81bb8936aed0f7b9f14fc4670069a2d371b3e3b0ecce908b2cb3" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -13279,7 +13336,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -13314,7 +13371,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "core-foundation 0.9.4", "system-configuration-sys 0.6.0", ] @@ -13359,15 +13416,15 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.22.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "rustix 1.1.2", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -13406,11 +13463,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.16", + "thiserror-impl 2.0.17", ] [[package]] @@ -13421,18 +13478,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -13542,9 +13599,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", @@ -13588,22 +13645,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", - "bytes 1.10.1", - "io-uring", + "bytes 1.11.0", "libc", "mio", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project-lite 0.2.16", "signal-hook-registry", - "slab", - "socket2 0.6.0", - "tokio-macros 2.5.0", - "windows-sys 0.59.0", + "socket2 0.6.1", + "tokio-macros 2.6.0", + "windows-sys 0.61.2", ] [[package]] @@ -13619,23 +13673,23 @@ dependencies = [ [[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.110", ] [[package]] name = "tokio-rustls" -version = "0.26.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", - "tokio 1.47.1", + "tokio 1.48.0", ] [[package]] @@ -13646,7 +13700,7 @@ checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite 0.2.16", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-util", ] @@ -13657,9 +13711,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" dependencies = [ "async-stream", - "bytes 1.10.1", + "bytes 1.11.0", "futures-core", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-stream", ] @@ -13674,23 +13728,23 @@ dependencies = [ "rustls", "rustls-native-certs", "rustls-pki-types", - "tokio 1.47.1", + "tokio 1.48.0", "tokio-rustls", "tungstenite", ] [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "futures-core", "futures-io", "futures-sink", "pin-project-lite 0.2.16", - "tokio 1.47.1", + "tokio 1.48.0", ] [[package]] @@ -13725,9 +13779,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" dependencies = [ "serde_core", ] @@ -13738,7 +13792,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.0", "serde", "serde_spanned", "toml_datetime 0.6.11", @@ -13748,21 +13802,21 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.23.6" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" dependencies = [ - "indexmap 2.11.4", - "toml_datetime 0.7.2", + "indexmap 2.12.0", + "toml_datetime 0.7.3", "toml_parser", "winnow", ] [[package]] name = "toml_parser" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" dependencies = [ "winnow", ] @@ -13794,8 +13848,8 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.9.4", - "bytes 1.10.1", + "bitflags 2.10.0", + "bytes 1.11.0", "http 1.3.1", "http-body 1.0.1", "http-body-util", @@ -13836,7 +13890,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -13881,7 +13935,7 @@ dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -13897,15 +13951,15 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "parking_lot 0.12.4", - "regex", + "parking_lot 0.12.5", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -13990,7 +14044,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "data-encoding", "http 1.3.1", "httparse", @@ -13999,7 +14053,7 @@ dependencies = [ "rustls", "rustls-pki-types", "sha1", - "thiserror 2.0.16", + "thiserror 2.0.17", "url", "utf-8", ] @@ -14024,9 +14078,9 @@ dependencies = [ [[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 = "ucd-trie" @@ -14066,9 +14120,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" @@ -14087,9 +14141,9 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" @@ -14124,7 +14178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" dependencies = [ "asynchronous-codec 0.6.2", - "bytes 1.10.1", + "bytes 1.11.0", "futures-io", "futures-util", ] @@ -14135,7 +14189,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" dependencies = [ - "bytes 1.10.1", + "bytes 1.11.0", "tokio-util", ] @@ -14187,7 +14241,7 @@ version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", "serde", "wasm-bindgen", @@ -14319,15 +14373,6 @@ 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.7+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" -dependencies = [ - "wasip2", -] - [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" @@ -14343,14 +14388,14 @@ version = "0.12.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" dependencies = [ - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "wasm-bindgen" -version = "0.2.103" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", @@ -14359,25 +14404,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.106", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.53" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0b221ff421256839509adbb55998214a70d829d3a28c69b4a6672e9d2a42f67" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -14388,9 +14419,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.103" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -14398,22 +14429,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.103" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.106", - "wasm-bindgen-backend", + "syn 2.0.110", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.103" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] @@ -14738,9 +14769,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.80" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbe734895e869dc429d78c4b433f8d17d95f8d05317440b4fad5ab2d33e596dc" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -14762,14 +14793,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.4", ] [[package]] name = "webpki-root-certs" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a" +checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b" dependencies = [ "rustls-pki-types", ] @@ -14792,9 +14823,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" [[package]] name = "winapi" @@ -14818,7 +14849,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]] @@ -14847,28 +14878,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections", - "windows-core 0.61.2", - "windows-future", - "windows-link 0.1.3", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", -] - [[package]] name = "windows-core" version = "0.52.0" @@ -14890,84 +14899,44 @@ dependencies = [ [[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-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-core" -version = "0.62.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.2.0", - "windows-result 0.4.0", - "windows-strings 0.5.0", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading", + "windows-link", + "windows-result 0.4.1", + "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.110", ] [[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.110", ] [[package]] name = "windows-link" -version = "0.1.3" -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" - -[[package]] -name = "windows-numerics" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" @@ -14980,38 +14949,20 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows-result" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" -dependencies = [ - "windows-link 0.2.0", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.0", + "windows-link", ] [[package]] @@ -15056,16 +15007,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]] @@ -15116,28 +15067,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" -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", -] - -[[package]] -name = "windows-threading" -version = "0.1.0" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.1.3", + "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]] @@ -15160,9 +15102,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" @@ -15184,9 +15126,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" @@ -15208,9 +15150,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" @@ -15220,9 +15162,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" @@ -15244,9 +15186,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" @@ -15268,9 +15210,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" @@ -15292,9 +15234,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" @@ -15316,9 +15258,9 @@ 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" @@ -15347,9 +15289,9 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[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" @@ -15402,7 +15344,7 @@ dependencies = [ "nom", "oid-registry 0.8.1", "rusticata-macros", - "thiserror 2.0.16", + "thiserror 2.0.17", "time", ] @@ -15415,14 +15357,14 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] name = "xml-rs" -version = "0.8.27" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "xmltree" @@ -15442,7 +15384,7 @@ dependencies = [ "futures 0.3.31", "log", "nohash-hasher", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project", "rand 0.8.5", "static_assertions", @@ -15450,14 +15392,14 @@ dependencies = [ [[package]] name = "yamux" -version = "0.13.6" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2dd50a6d6115feb3e5d7d0efd45e8ca364b6c83722c1e9c602f5764e0e9597" +checksum = "deab71f2e20691b4728b349c6cee8fc7223880fa67b6b4f92225ec32225447e5" dependencies = [ "futures 0.3.31", "log", "nohash-hasher", - "parking_lot 0.12.4", + "parking_lot 0.12.5", "pin-project", "rand 0.9.2", "static_assertions", @@ -15487,11 +15429,10 @@ dependencies = [ [[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", @@ -15499,13 +15440,13 @@ 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.110", "synstructure 0.13.2", ] @@ -15526,7 +15467,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[package]] @@ -15546,15 +15487,15 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", "synstructure 0.13.2", ] [[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", ] @@ -15567,14 +15508,14 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.110", ] [[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", @@ -15583,9 +15524,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", @@ -15594,13 +15535,13 @@ 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.110", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index fe5056a4..45a9c307 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -140,16 +140,20 @@ sp-consensus-pow = { path = "./primitives/consensus/pow", default-features = fal sp-consensus-qpow = { path = "./primitives/consensus/qpow", default-features = false } # Quantus network dependencies -qp-poseidon = { version = "1.0.1", default-features = false } -qp-poseidon-core = { version = "1.0.1", default-features = false, features = ["p3"] } +qp-plonky2 = { version = "1.1.3", default-features = false } +qp-poseidon = { version = "1.0.3", default-features = false } +qp-poseidon-core = { version = "1.0.3", 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.2", default-features = false } -qp-wormhole-circuit-builder = { version = "0.1.2", default-features = false } -qp-wormhole-verifier = { version = "0.1.2", default-features = false, features = [ +qp-wormhole-circuit = { version = "0.1.3", default-features = false } +qp-wormhole-circuit-builder = { version = "0.1.4", default-features = false } +qp-wormhole-prover = { version = "0.1.4", default-features = false, features = [ "no_random", ] } -qp-zk-circuits-common = { version = "0.1.2", default-features = false, features = [ +qp-wormhole-verifier = { version = "0.1.4", default-features = false, features = [ + "no_random", +] } +qp-zk-circuits-common = { version = "0.1.4", default-features = false, features = [ "no_random", ] } diff --git a/node/build.rs b/node/build.rs index 2de7de2a..6b47474f 100644 --- a/node/build.rs +++ b/node/build.rs @@ -33,8 +33,9 @@ fn generate_circuit_binaries() { // Call the circuit-builder to generate binaries directly in the pallet directory // We don't need the prover binary for the chain, only verifier and common - qp_wormhole_circuit_builder::generate_circuit_binaries("../pallets/wormhole", false) - .expect("Failed to generate circuit binaries"); + // TODO: uncomment this once `no_random` issue is fixed in zk-circuits + // qp_wormhole_circuit_builder::generate_circuit_binaries("../pallets/wormhole", false) + // .expect("Failed to generate circuit binaries"); println!("cargo:trace=✅ Circuit binaries generated successfully"); } diff --git a/pallets/balances/src/lib.rs b/pallets/balances/src/lib.rs index 1ead5bcf..20165bea 100644 --- a/pallets/balances/src/lib.rs +++ b/pallets/balances/src/lib.rs @@ -401,6 +401,13 @@ pub mod pallet { Thawed { who: T::AccountId, amount: T::Balance }, /// The `TotalIssuance` was forcefully changed. TotalIssuanceForced { old: T::Balance, new: T::Balance }, + /// Transfer proof was stored. + TransferProofStored { + transfer_count: u64, + source: T::AccountId, + dest: T::AccountId, + funding_amount: T::Balance, + }, } #[pallet::error] @@ -874,9 +881,15 @@ pub mod pallet { ) { if from != to { let current_count = Self::transfer_count(); + TransferProof::::insert((current_count, from.clone(), to.clone(), value), ()); TransferCount::::put(current_count.saturating_add(One::one())); - TransferProof::::insert((current_count, from.clone(), to.clone(), value), ()); + Self::deposit_event(Event::TransferProofStored { + transfer_count: current_count, + source: from.clone(), + dest: to.clone(), + funding_amount: value, + }); } } diff --git a/pallets/balances/src/tests/reentrancy_tests.rs b/pallets/balances/src/tests/reentrancy_tests.rs index 89b27528..767f3ddf 100644 --- a/pallets/balances/src/tests/reentrancy_tests.rs +++ b/pallets/balances/src/tests/reentrancy_tests.rs @@ -56,7 +56,7 @@ fn transfer_dust_removal_tst1_should_work() { assert_eq!(Balances::free_balance(account_id(1)), 1050); // Verify the events - assert_eq!(System::events().len(), 14); + assert_eq!(System::events().len(), 15); System::assert_has_event(RuntimeEvent::Balances(crate::Event::Transfer { from: account_id(2), @@ -99,7 +99,7 @@ fn transfer_dust_removal_tst2_should_work() { // Dust balance is deposited to account 1 assert_eq!(Balances::free_balance(account_id(1)), 1000 + 450 + 50); // Verify the events - assert_eq!(System::events().len(), 12); + assert_eq!(System::events().len(), 13); System::assert_has_event(RuntimeEvent::Balances(crate::Event::Transfer { from: account_id(2), @@ -149,7 +149,7 @@ fn repatriating_reserved_balance_dust_removal_should_work() { assert_eq!(Balances::free_balance(account_id(1)), 1500); // Verify the events - assert_eq!(System::events().len(), 12); + assert_eq!(System::events().len(), 13); System::assert_has_event(RuntimeEvent::Balances(crate::Event::Transfer { from: account_id(2), diff --git a/pallets/mining-rewards/src/mock.rs b/pallets/mining-rewards/src/mock.rs index a4bbd286..1b4529a3 100644 --- a/pallets/mining-rewards/src/mock.rs +++ b/pallets/mining-rewards/src/mock.rs @@ -11,7 +11,7 @@ use sp_runtime::{ app_crypto::sp_core, testing::H256, traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, Digest, DigestItem, + BuildStorage, DigestItem, }; // Configure a mock runtime to test the pallet @@ -127,13 +127,11 @@ pub fn new_test_ext() -> sp_io::TestExternalities { // Helper function to create a block digest with a miner pre-runtime digest pub fn set_miner_digest(miner: sp_core::crypto::AccountId32) { + // reset logs let miner_bytes = miner.encode(); let pre_digest = DigestItem::PreRuntime(POW_ENGINE_ID, miner_bytes); - let digest = Digest { logs: vec![pre_digest] }; - // Set the digest in the system - System::reset_events(); - System::initialize(&1, &sp_core::H256::default(), &digest); + System::deposit_log(pre_digest); } // Helper function to run a block diff --git a/pallets/mining-rewards/src/tests.rs b/pallets/mining-rewards/src/tests.rs index 04d9ef13..bd4604d4 100644 --- a/pallets/mining-rewards/src/tests.rs +++ b/pallets/mining-rewards/src/tests.rs @@ -1,6 +1,6 @@ use crate::{mock::*, weights::WeightInfo, Event}; use frame_support::traits::{Currency, Hooks}; -use sp_runtime::traits::AccountIdConversion; +use sp_runtime::{testing::Digest, traits::AccountIdConversion}; const UNIT: u128 = 1_000_000_000_000; @@ -153,11 +153,15 @@ fn different_miners_get_different_rewards() { assert_eq!(Balances::free_balance(miner()), balance_after_block_1); // Block 2 - Second miner - System::set_block_number(2); + let block_1 = System::finalize(); + // reset logs and go to block 2 + System::initialize(&2, &block_1.hash(), &Digest { logs: vec![] }); set_miner_digest(miner2()); MiningRewards::collect_transaction_fees(20); MiningRewards::on_finalize(2); + println!("Balnce {}", Balances::free_balance(miner())); + // Check second miner balance // Current implementation: miner gets base reward (50) + all fees (20) assert_eq!( diff --git a/pallets/wormhole/Cargo.toml b/pallets/wormhole/Cargo.toml index 54dba6aa..78e624e7 100644 --- a/pallets/wormhole/Cargo.toml +++ b/pallets/wormhole/Cargo.toml @@ -16,6 +16,8 @@ hex = { workspace = true, features = ["alloc"], optional = true } lazy_static.workspace = true log.workspace = true pallet-balances.workspace = true +qp-header = { workspace = true, features = ["serde"] } +qp-poseidon.workspace = true qp-wormhole.workspace = true qp-wormhole-circuit = { workspace = true, default-features = false } qp-wormhole-verifier = { workspace = true, default-features = false } @@ -29,6 +31,15 @@ sp-runtime.workspace = true [dev-dependencies] hex = { workspace = true, features = ["alloc"] } +qp-dilithium-crypto = { workspace = true, features = ["std"] } +qp-plonky2 = { workspace = true, default-features = false } +qp-poseidon-core.workspace = true +qp-wormhole-circuit.workspace = true +qp-wormhole-circuit-builder = { workspace = true, default-features = false } +qp-wormhole-prover.workspace = true +qp-zk-circuits-common.workspace = true +sp-state-machine = { path = "../../primitives/state-machine" } +sp-trie.workspace = true [features] default = ["std"] @@ -48,6 +59,8 @@ std = [ "lazy_static/spin_no_std", "log/std", "pallet-balances/std", + "qp-header/std", + "qp-poseidon/std", "qp-wormhole-circuit/std", "qp-wormhole-verifier/std", "qp-wormhole/std", diff --git a/pallets/wormhole/common.bin b/pallets/wormhole/common.bin index 81c43fbdb560a05e0ae97102c2d9c88e9ce85afd..9232df9c3bdbf92f77f73c7a28db999bdfafe660 100644 GIT binary patch delta 939 zcmZ9LO-{ow7zLdMN@$@i(9()OQAAm>;zHbl4GUj@N?2^U143MYi*N-b7HkoD&Kt>U zRCV6ijuZQH*3Hl8`6=B`(reTH29w}xmELdD=P-RW%gRl?4c7KLt>@`?5&QO?4K{YT zYlj0n9NOWY9q!xVsPntv5XK$=S=52sK|lS?BX7miAy0!$4w)1ldR92K!(%&KbRL64 zIPm~@W``Gccxi`Mc6e=vD?1B*%-(MDkvnD|H`QD3oN+3TN=(_c5#yKd`ZTif`My#r z3CAUrl6#mb_aM24qm+A)imldjlwF#bh0~#qvPQg*+L=J)Fep Vec { hex::decode(hex_proof.trim()).expect("Failed to decode hex proof") } -#[benchmarks( - where - T: Send + Sync, - T: Config, - BalanceOf: Into<<::Currency as Inspect>::Balance>, -)] +#[benchmarks] mod benchmarks { use super::*; @@ -27,6 +26,7 @@ mod benchmarks { fn verify_wormhole_proof() -> Result<(), BenchmarkError> { let proof_bytes = get_benchmark_proof(); + // Parse the proof to get public inputs let verifier = crate::get_wormhole_verifier() .map_err(|_| BenchmarkError::Stop("Verifier not available"))?; @@ -39,28 +39,43 @@ mod benchmarks { let public_inputs = PublicCircuitInputs::try_from(&proof) .map_err(|_| BenchmarkError::Stop("Invalid public inputs"))?; + // Extract values from public inputs let nullifier_bytes = *public_inputs.nullifier; + let block_number_u32 = public_inputs.block_number; + let block_hash_bytes: [u8; 32] = (*public_inputs.block_hash) + .try_into() + .map_err(|_| BenchmarkError::Stop("Invalid block hash length"))?; + // Ensure nullifier hasn't been used ensure!( !UsedNullifiers::::contains_key(nullifier_bytes), BenchmarkError::Stop("Nullifier already used") ); + // Verify the proof is valid (sanity check) verifier .verify(proof) .map_err(|_| BenchmarkError::Stop("Proof verification failed"))?; - let block_number = frame_system::Pallet::::block_number(); + // Set up storage to match the proof's public inputs: + // Set current block number to be >= proof's block_number + let block_number: BlockNumberFor = block_number_u32.into(); + frame_system::Pallet::::set_block_number(block_number + 1u32.into()); + + // Override block hash to match proof's block_hash + let block_hash = T::Hash::decode(&mut &block_hash_bytes[..]) + .map_err(|_| BenchmarkError::Stop("Failed to decode block hash"))?; + frame_system::BlockHash::::insert(block_number, block_hash); #[extrinsic_call] - verify_wormhole_proof(RawOrigin::None, proof_bytes, block_number); + verify_wormhole_proof(RawOrigin::None, proof_bytes); - Ok(()) - } + // Verify nullifier was marked as used + ensure!( + UsedNullifiers::::contains_key(nullifier_bytes), + BenchmarkError::Stop("Nullifier should be marked as used after verification") + ); - impl_benchmark_test_suite! { - Pallet, - crate::mock::new_test_ext(), - crate::mock::Test, + Ok(()) } } diff --git a/pallets/wormhole/src/lib.rs b/pallets/wormhole/src/lib.rs index 36457741..86d8281a 100644 --- a/pallets/wormhole/src/lib.rs +++ b/pallets/wormhole/src/lib.rs @@ -105,11 +105,7 @@ pub mod pallet { impl Pallet { #[pallet::call_index(0)] #[pallet::weight(::WeightInfo::verify_wormhole_proof())] - pub fn verify_wormhole_proof( - origin: OriginFor, - proof_bytes: Vec, - block_number: BlockNumberFor, - ) -> DispatchResult { + pub fn verify_wormhole_proof(origin: OriginFor, proof_bytes: Vec) -> DispatchResult { ensure_none(origin)?; let verifier = @@ -133,6 +129,10 @@ pub mod pallet { Error::::NullifierAlreadyUsed ); + // Extract the block number from public inputs + let block_number = BlockNumberFor::::try_from(public_inputs.block_number) + .map_err(|_| Error::::InvalidPublicInputs)?; + // Get the block hash for the specified block number let block_hash = frame_system::Pallet::::block_hash(block_number); @@ -145,36 +145,11 @@ pub mod pallet { let default_hash = T::Hash::default(); ensure!(block_hash != default_hash, Error::::BlockNotFound); - // Get the storage root for the specified block - let storage_root = sp_io::storage::root(sp_runtime::StateVersion::V1); - - let root_hash = public_inputs.root_hash; - let storage_root_bytes = storage_root.as_slice(); - - // Compare the root_hash from the proof with the actual storage root - // Skip storage root validation in test and benchmark environments since proofs - // may have been generated with different state - #[cfg(not(any(test, feature = "runtime-benchmarks")))] - if root_hash.as_ref() != storage_root_bytes { - log::warn!( - target: "wormhole", - "Storage root mismatch for block {:?}: expected {:?}, got {:?}", - block_number, - root_hash.as_ref(), - storage_root_bytes - ); - return Err(Error::::StorageRootMismatch.into()); - } - - #[cfg(any(test, feature = "runtime-benchmarks"))] - { - let _root_hash = root_hash; - let _storage_root_bytes = storage_root_bytes; - log::debug!( - target: "wormhole", - "Skipping storage root validation in test/benchmark environment" - ); - } + // Ensure that the block hash from storage matches the one in public inputs + ensure!( + block_hash.as_ref() == public_inputs.block_hash.as_ref(), + Error::::InvalidPublicInputs + ); verifier.verify(proof.clone()).map_err(|_| Error::::VerificationFailed)?; diff --git a/pallets/wormhole/src/mock.rs b/pallets/wormhole/src/mock.rs index 4c764f26..c902099c 100644 --- a/pallets/wormhole/src/mock.rs +++ b/pallets/wormhole/src/mock.rs @@ -4,11 +4,10 @@ use frame_support::{ traits::{ConstU32, Everything}, weights::IdentityFee, }; +use frame_system::mocking::MockUncheckedExtrinsic; +use qp_poseidon::PoseidonHasher; use sp_core::H256; -use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, -}; +use sp_runtime::{traits::IdentityLookup, BuildStorage}; // --- MOCK RUNTIME --- construct_runtime!( @@ -21,7 +20,10 @@ construct_runtime!( pub type Balance = u128; pub type AccountId = sp_core::crypto::AccountId32; -pub type Block = frame_system::mocking::MockBlock; +pub type Block = sp_runtime::generic::Block< + qp_header::Header, + MockUncheckedExtrinsic, +>; /// Helper function to convert a u64 to an AccountId32 pub fn account_id(id: u64) -> AccountId { @@ -46,10 +48,10 @@ impl frame_system::Config for Test { type RuntimeTask = (); type Nonce = u64; type Hash = H256; - type Hashing = BlakeTwo256; + type Hashing = PoseidonHasher; type AccountId = AccountId; type Lookup = IdentityLookup; - type Block = Block; + type Block = Block; type BlockHashCount = BlockHashCount; type DbWeight = (); type Version = (); @@ -108,12 +110,15 @@ impl pallet_wormhole::Config for Test { } // Helper function to build a genesis configuration -pub fn new_test_ext() -> sp_io::TestExternalities { +pub fn new_test_ext() -> sp_state_machine::TestExternalities { let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![] } - .assimilate_storage(&mut t) - .unwrap(); + let endowment = 1e18 as Balance; + pallet_balances::GenesisConfig:: { + balances: vec![(account_id(1), endowment), (account_id(2), endowment)], + } + .assimilate_storage(&mut t) + .unwrap(); t.into() } diff --git a/pallets/wormhole/src/tests.rs b/pallets/wormhole/src/tests.rs index a96fca74..ae2a7de1 100644 --- a/pallets/wormhole/src/tests.rs +++ b/pallets/wormhole/src/tests.rs @@ -1,211 +1,262 @@ #[cfg(test)] mod wormhole_tests { - use crate::{get_wormhole_verifier, mock::*, weights, Config, Error, WeightInfo}; - use frame_support::{assert_noop, assert_ok, weights::WeightToFee}; - use qp_wormhole_circuit::inputs::PublicCircuitInputs; + use crate::{get_wormhole_verifier, mock::*}; + use codec::Encode; + use frame_support::{ + assert_ok, + traits::fungible::{Inspect, Mutate}, + }; + use plonky2::plonk::circuit_data::CircuitConfig; + use qp_poseidon::PoseidonHasher; + use qp_wormhole_circuit::{ + inputs::{CircuitInputs, PrivateCircuitInputs, PublicCircuitInputs}, + nullifier::Nullifier, + }; + use qp_wormhole_prover::WormholeProver; use qp_wormhole_verifier::ProofWithPublicInputs; - use sp_runtime::Perbill; + use qp_zk_circuits_common::{ + circuit::{C, F}, + storage_proof::prepare_proof_for_circuit, + utils::{digest_felts_to_bytes, BytesDigest, Digest}, + }; + use sp_runtime::{traits::Header, DigestItem}; // Helper function to generate proof and inputs for - fn get_test_proof() -> Vec { - let hex_proof = include_str!("../proof_from_bins.hex"); - hex::decode(hex_proof.trim()).expect("Failed to decode hex proof") + fn generate_proof(inputs: CircuitInputs) -> ProofWithPublicInputs { + let config = CircuitConfig::standard_recursion_config(); + let prover = WormholeProver::new(config); + let prover_next = prover.commit(&inputs).expect("proof failed"); + let proof = prover_next.prove().expect("valid proof"); + proof } #[test] - fn test_verifier_availability() { - new_test_ext().execute_with(|| { - let verifier = get_wormhole_verifier(); - assert!(verifier.is_ok(), "Verifier should be available in tests"); + fn test_wormhole_transfer_proof_generation() { + // Setup accounts + let alice = account_id(1); + let secret: BytesDigest = [1u8; 32].try_into().expect("valid secret"); + let unspendable_account = + qp_wormhole_circuit::unspendable_account::UnspendableAccount::from_secret(secret) + .account_id; + let unspendable_account_bytes_digest = 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 = AccountId::new(unspendable_account_bytes); + let exit_account_id = AccountId::new([42u8; 32]); + let funding_amount = 1_000_000_000_001u128; - // Verify the verifier can be used - let verifier = verifier.unwrap(); - // Check that the circuit data is valid by checking gates - assert!(!verifier.circuit_data.common.gates.is_empty(), "Circuit should have gates"); - }); - } + let mut ext = new_test_ext(); - #[test] - fn test_verify_empty_proof_fails() { - new_test_ext().execute_with(|| { - let empty_proof = vec![]; - let block_number = frame_system::Pallet::::block_number(); - assert_noop!( - Wormhole::verify_wormhole_proof(RuntimeOrigin::none(), empty_proof, block_number), - Error::::ProofDeserializationFailed - ); - }); - } + // Execute the transfer and get the header + let (storage_key, state_root, leaf_hash, event_transfer_count, header) = + ext.execute_with(|| { + System::set_block_number(1); - #[test] - fn test_verify_invalid_proof_data_fails() { - new_test_ext().execute_with(|| { - // Create some random bytes that will fail deserialization - let invalid_proof = vec![1u8; 100]; - let block_number = frame_system::Pallet::::block_number(); - assert_noop!( - Wormhole::verify_wormhole_proof(RuntimeOrigin::none(), invalid_proof, block_number), - Error::::ProofDeserializationFailed - ); - }); - } + // Add dummy digest items to match expected format + let pre_runtime_data = vec![ + 233, 182, 183, 107, 158, 1, 115, 19, 219, 126, 253, 86, 30, 208, 176, 70, 21, + 45, 180, 229, 9, 62, 91, 4, 6, 53, 245, 52, 48, 38, 123, 225, + ]; + let seal_data = vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 77, 142, + ]; - #[test] - fn test_verify_valid_proof() { - new_test_ext().execute_with(|| { - let proof = get_test_proof(); - let block_number = frame_system::Pallet::::block_number(); - assert_ok!(Wormhole::verify_wormhole_proof(RuntimeOrigin::none(), proof, block_number)); - }); - } + System::deposit_log(DigestItem::PreRuntime(*b"pow_", pre_runtime_data)); + System::deposit_log(DigestItem::Seal(*b"pow_", seal_data)); - #[test] - fn test_verify_invalid_inputs() { - new_test_ext().execute_with(|| { - let mut proof = get_test_proof(); - let block_number = frame_system::Pallet::::block_number(); + assert_ok!(Balances::mint_into(&unspendable_account_id, funding_amount)); + assert_ok!(Balances::transfer_keep_alive( + frame_system::RawOrigin::Signed(alice.clone()).into(), + unspendable_account_id.clone(), + funding_amount, + )); - if let Some(byte) = proof.get_mut(0) { - *byte = !*byte; // Flip bits to make proof invalid - } + let transfer_count = pallet_balances::TransferCount::::get(); + let event_transfer_count = transfer_count - 1; - assert_noop!( - Wormhole::verify_wormhole_proof(RuntimeOrigin::none(), proof, block_number), - Error::::VerificationFailed - ); - }); - } + let leaf_hash = PoseidonHasher::hash_storage::( + &( + event_transfer_count, + alice.clone(), + unspendable_account_id.clone(), + funding_amount, + ) + .encode(), + ); - #[test] - fn test_wormhole_exit_balance_and_fees() { - new_test_ext().execute_with(|| { - let proof = get_test_proof(); - let expected_exit_account = account_id(8226349481601990196u64); - - // Parse the proof to get expected funding amount - let verifier = get_wormhole_verifier().expect("Verifier should be available"); - let proof_with_inputs = ProofWithPublicInputs::from_bytes(proof.clone(), &verifier.circuit_data.common) - .expect("Should be able to parse test proof"); - - let public_inputs = PublicCircuitInputs::try_from(&proof_with_inputs) - .expect("Should be able to parse public inputs"); - - let expected_funding_amount = public_inputs.funding_amount; - - // Calculate expected fees (matching lib.rs logic exactly) - let weight = as WeightInfo>::verify_wormhole_proof(); - let weight_fee: u128 = ::WeightToFee::weight_to_fee(&weight); - let volume_fee = Perbill::from_rational(1u32, 1000u32) * expected_funding_amount; - let expected_total_fee = weight_fee.saturating_add(volume_fee); - let expected_net_balance_increase = expected_funding_amount.saturating_sub(expected_total_fee); - - let initial_exit_balance = - pallet_balances::Pallet::::free_balance(&expected_exit_account); - - let block_number = frame_system::Pallet::::block_number(); - let result = - Wormhole::verify_wormhole_proof(RuntimeOrigin::none(), proof, block_number); - assert_ok!(result); - - let final_exit_balance = - pallet_balances::Pallet::::free_balance(&expected_exit_account); - - let balance_increase = final_exit_balance - initial_exit_balance; - - // Assert the exact expected balance increase - assert_eq!( - balance_increase - , expected_net_balance_increase, - "Balance increase should equal funding amount minus fees. Funding: {}, Fees: {}, Expected net: {}, Actual: {}" - , expected_funding_amount - , expected_total_fee - , expected_net_balance_increase - , balance_increase - ); - - // NOTE: In this mock/test context, the OnUnbalanced handler is not triggered for this withdrawal. - // In production, the fee will be routed to the handler as expected. - }); - } + let proof_address = pallet_balances::TransferProof::::hashed_key_for(&( + event_transfer_count, + alice.clone(), + unspendable_account_id.clone(), + funding_amount, + )); + let mut storage_key = proof_address; + storage_key.extend_from_slice(&leaf_hash); - #[test] - fn test_nullifier_already_used() { + let header = System::finalize(); + let state_root = *header.state_root(); + + (storage_key, state_root, leaf_hash, event_transfer_count, header) + }); + + // Generate a storage proof for the specific storage key + use sp_state_machine::prove_read; + let proof = prove_read(ext.as_backend(), &[&storage_key]) + .expect("failed to generate storage proof"); + + let proof_nodes_vec: Vec> = proof.iter_nodes().map(|n| n.to_vec()).collect(); + + // Prepare the storage proof for the circuit + let processed_storage_proof = + prepare_proof_for_circuit(proof_nodes_vec, hex::encode(&state_root), leaf_hash) + .expect("failed to prepare proof for circuit"); + + // Build the header components + let parent_hash = *header.parent_hash(); + let extrinsics_root = *header.extrinsics_root(); + let digest = header.digest().encode(); + let digest_array: [u8; 110] = digest.try_into().expect("digest should be 110 bytes"); + let block_number: u32 = (*header.number()).try_into().expect("block number fits in u32"); + + // Compute block hash + let block_hash = header.hash(); + + // Assemble circuit inputs + let circuit_inputs = CircuitInputs { + private: PrivateCircuitInputs { + secret, + transfer_count: event_transfer_count, + funding_account: BytesDigest::try_from(alice.as_ref() as &[u8]) + .expect("account is 32 bytes"), + storage_proof: processed_storage_proof, + unspendable_account: Digest::from(unspendable_account).into(), + state_root: BytesDigest::try_from(state_root.as_ref()) + .expect("state root is 32 bytes"), + extrinsics_root: BytesDigest::try_from(extrinsics_root.as_ref()) + .expect("extrinsics root is 32 bytes"), + digest: digest_array, + }, + 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]) + .expect("account is 32 bytes"), + block_hash: BytesDigest::try_from(block_hash.as_ref()) + .expect("block hash is 32 bytes"), + parent_hash: BytesDigest::try_from(parent_hash.as_ref()) + .expect("parent hash is 32 bytes"), + block_number, + }, + }; + + // Generate the ZK proof + let proof = generate_proof(circuit_inputs); + + // Verify the proof can be parsed + let public_inputs = + PublicCircuitInputs::try_from(&proof).expect("failed to parse public inputs"); + + // Verify that the public inputs match what we expect + assert_eq!(public_inputs.funding_amount, funding_amount); + assert_eq!( + public_inputs.exit_account, + BytesDigest::try_from(exit_account_id.as_ref() as &[u8]).unwrap() + ); + + // Verify the proof using the verifier + let verifier = get_wormhole_verifier().expect("verifier should be available"); + verifier.verify(proof.clone()).expect("proof should verify"); + + // Serialize the proof to bytes for extrinsic testing + let proof_bytes = proof.to_bytes(); + + // Now test the extrinsic in a new environment new_test_ext().execute_with(|| { - let proof = get_test_proof(); - let block_number = frame_system::Pallet::::block_number(); + // Set up the blockchain state to have block 1 + System::set_block_number(1); - // First verification should succeed + // Add the same digest items + let pre_runtime_data = vec![ + 233, 182, 183, 107, 158, 1, 115, 19, 219, 126, 253, 86, 30, 208, 176, 70, 21, 45, + 180, 229, 9, 62, 91, 4, 6, 53, 245, 52, 48, 38, 123, 225, + ]; + let seal_data = vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30, 77, 142, + ]; + + System::deposit_log(DigestItem::PreRuntime(*b"pow_", pre_runtime_data)); + System::deposit_log(DigestItem::Seal(*b"pow_", seal_data)); + + // Execute the same transfer to recreate the exact state + assert_ok!(Balances::mint_into(&unspendable_account_id, funding_amount)); + assert_ok!(Balances::transfer_keep_alive( + frame_system::RawOrigin::Signed(alice.clone()).into(), + unspendable_account_id.clone(), + funding_amount, + )); + + // Finalize the block to get the same header and store the block hash + let block_1_header = System::finalize(); + + // Initialize block 2 to store block 1's hash + System::reset_events(); + System::initialize(&2, &block_1_header.hash(), block_1_header.digest()); + + // Check exit account balance before verification + let balance_before = Balances::balance(&exit_account_id); + assert_eq!(balance_before, 0); + + // Call the verify_wormhole_proof extrinsic assert_ok!(Wormhole::verify_wormhole_proof( - RuntimeOrigin::none(), - proof.clone(), - block_number + frame_system::RawOrigin::None.into(), + proof_bytes.clone() )); - // Second verification with same proof should fail due to nullifier reuse - assert_noop!( - Wormhole::verify_wormhole_proof(RuntimeOrigin::none(), proof, block_number), - Error::::NullifierAlreadyUsed + // Check that the exit account received the funds (minus fees) + let balance_after = Balances::balance(&exit_account_id); + + // The balance should be funding_amount minus fees + // Weight fee + 0.1% volume fee + assert!(balance_after > 0, "Exit account should have received funds"); + assert!( + balance_after < funding_amount, + "Exit account balance should be less than funding amount due to fees" ); }); - } - #[test] - fn test_verify_future_block_number_fails() { + // Test that proof fails when state doesn't match new_test_ext().execute_with(|| { - let proof = get_test_proof(); - let current_block = frame_system::Pallet::::block_number(); - let future_block = current_block + 1; + // Set up block 1 but DON'T recreate the exact same state + System::set_block_number(1); - assert_noop!( - Wormhole::verify_wormhole_proof(RuntimeOrigin::none(), proof, future_block), - Error::::InvalidBlockNumber - ); - }); - } + // Add different digest items with same 110-byte format but different content + let pre_runtime_data = vec![1u8; 32]; // Different data + let seal_data = vec![2u8; 64]; // Different data - #[test] - fn test_verify_storage_root_mismatch_fails() { - new_test_ext().execute_with(|| { - // This test would require a proof with a different root_hash than the current storage - // root - let proof = get_test_proof(); - let block_number = frame_system::Pallet::::block_number(); - - let result = - Wormhole::verify_wormhole_proof(RuntimeOrigin::none(), proof, block_number); - - // This should either succeed (if root_hash matches) or fail with StorageRootMismatch - // We can't easily create a proof with wrong root_hash in tests, so we just verify - // that the validation logic is executed - assert!(result.is_ok() || result.is_err()); - }); - } + System::deposit_log(DigestItem::PreRuntime(*b"pow_", pre_runtime_data)); + System::deposit_log(DigestItem::Seal(*b"pow_", seal_data)); - #[test] - fn test_verify_with_different_block_numbers() { - new_test_ext().execute_with(|| { - let proof = get_test_proof(); - let current_block = frame_system::Pallet::::block_number(); + // Finalize block 1 with different state + let different_header = System::finalize(); - // Test with current block (should succeed) - assert_ok!(Wormhole::verify_wormhole_proof( - RuntimeOrigin::none(), - proof.clone(), - current_block - )); + // Initialize block 2 + System::reset_events(); + System::initialize(&2, &different_header.hash(), different_header.digest()); - // Test with a recent block (should succeed if it exists) - if current_block > 1 { - let recent_block = current_block - 1; - let result = Wormhole::verify_wormhole_proof( - RuntimeOrigin::none(), - proof.clone(), - recent_block, - ); - // This might succeed or fail depending on whether the block exists - // and whether the storage root matches - assert!(result.is_ok() || result.is_err()); - } + // Try to use the proof with the original header (which has different block hash) + let result = Wormhole::verify_wormhole_proof( + frame_system::RawOrigin::None.into(), + proof_bytes.clone(), + ); + + // This should fail because the block hash in the proof doesn't match + assert!(result.is_err(), "Proof verification should fail with mismatched state"); }); } } diff --git a/pallets/wormhole/src/weights.rs b/pallets/wormhole/src/weights.rs index b1516fa8..8d06df5b 100644 --- a/pallets/wormhole/src/weights.rs +++ b/pallets/wormhole/src/weights.rs @@ -18,10 +18,10 @@ //! Autogenerated weights for `pallet_wormhole` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 46.2.0 -//! DATE: 2025-07-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 49.1.0 +//! DATE: 2025-11-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `Veronikas-MacBook-Air.local`, CPU: `` +//! HOSTNAME: `Dastans-MacBook-Pro.local`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` // Executed Command: @@ -70,10 +70,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Balances::TransferProof` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `MaxEncodedLen`) fn verify_wormhole_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `424` + // Measured: `256` // Estimated: `3593` - // Minimum execution time: 17_162_000_000 picoseconds. - Weight::from_parts(17_576_000_000, 3593) + // Minimum execution time: 14_318_000_000 picoseconds. + Weight::from_parts(14_468_000_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -93,10 +93,10 @@ impl WeightInfo for () { /// Proof: `Balances::TransferProof` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `MaxEncodedLen`) fn verify_wormhole_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `424` + // Measured: `256` // Estimated: `3593` - // Minimum execution time: 17_162_000_000 picoseconds. - Weight::from_parts(17_576_000_000, 3593) + // Minimum execution time: 14_318_000_000 picoseconds. + Weight::from_parts(14_468_000_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } diff --git a/pallets/wormhole/verifier.bin b/pallets/wormhole/verifier.bin index 6f7404b667329a8017f4474738e1864f35740b79..121eb2b02d5badfed2fbdcc2c29e9d7a7ffec909 100644 GIT binary patch literal 552 zcmV+@0@wWn000000001{fgdmlpg^a6wNw|p^n-O4(K!Freq^lh(_{C)mkWt!KDUW$ zE?PNjBmiDLoZ{RA6jg7PSxr{BizIHJW~f*HO{9pc&uXqZjrcId3x@z<4KDbJIfrOx z3FS>VcY)vNi24;Io?*Yn7P+jd*v`UX^%^YUdrQkHvuml_sF!}-T;4qK!GOD-UtYyb zZfVj=Uoi;ph0JLtv6@F>U9H=K?8W=9Um3#E&28RBK*imrCh|tLm``n>T0iw%B&g~U zLHCzUTEj;0(O=t!{eN>!%#+cA6Jn(-a7yeFbw!h6R3ADGoPx(lp`OJ9E9cB0yYUCvl07q z2E9l&(l;2u;gF8HIhzbxcX&Omio1+M9&4fZM%uPN(d_}gXv3BeaZh4RY>l>s?G9bk z&ekwT5?b=MPr;MuP0MkQ%(e&ddMhGQVUJ5L>W-xNqo|R;gFc|_#5f`v2^nITGT}?g z)0Gs3-u}JJUGbhZm!M0U++70}*uA7{Dveh_&fT$~77p?a*$|iW9q^4&?iN?J93InB z_r-UE{N^JNuC9aIJk+lv!L++*S;2N+gcngm8J6`v+%Xqm<$jET;|f!$tR5)JxbPf~ qKk68O>uJ)jvp@aiEmphF1 zt=EwEV3`!C%DOHzBcO`Nn}z?iC(n1J%E~RK{>@7be>23SGfkcp+}r6(aMku|TbmAU zXrvkRZ{VGl_&}lwx_azzDm4Q*Gdc-%leoNxAW=R=MBgK|-WN=A{TuL#eQa`NHwWXG zl?|0r;!mqt+Z>~oULuS3xo$NuM1my_ktngy@30kh)^C;PHLCwM6LD`H#8}24RErRi zenXR9((a41u@*5HO9_1Oa?B~~$@I(eA820>@lPW(Kqgl$_O z8ZgGiQ^L7iT)4ai5L7ua~{&D*+DfTc5EAyADHBW`zC`Z&G<3L;3+W+ ztfy#C=~AZ_jGRSU#(7p{k{q-A;z0H12G=@*vtvHf49ARUh_WGBEmm2P8 qXKRDCF!y7cTf!)t9w)1yPwkj)P{8vPStKjYr_ZO+O{pLv{XmN~s0O6~ diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 65ba6ce7..078a04d8 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -44,6 +44,7 @@ pallet-transaction-payment-rpc-runtime-api.workspace = true pallet-treasury.workspace = true pallet-utility.workspace = true pallet-vesting.workspace = true +pallet-wormhole.workspace = true primitive-types.workspace = true qp-dilithium-crypto.workspace = true qp-header = { workspace = true, features = ["serde"] } @@ -112,6 +113,7 @@ std = [ "pallet-treasury/std", "pallet-utility/std", "pallet-vesting/std", + "pallet-wormhole/std", "primitive-types/std", "qp-dilithium-crypto/full_crypto", "qp-dilithium-crypto/std", @@ -162,6 +164,7 @@ runtime-benchmarks = [ "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", + "pallet-wormhole/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] @@ -181,6 +184,7 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "pallet-treasury/try-runtime", "pallet-vesting/try-runtime", + "pallet-wormhole/try-runtime", "sp-runtime/try-runtime", ] diff --git a/runtime/src/benchmarks.rs b/runtime/src/benchmarks.rs index c670981c..fe021308 100644 --- a/runtime/src/benchmarks.rs +++ b/runtime/src/benchmarks.rs @@ -34,4 +34,5 @@ frame_benchmarking::define_benchmarks!( [pallet_mining_rewards, MiningRewards] [pallet_scheduler, Scheduler] [pallet_qpow, QPoW] + [pallet_wormhole, Wormhole] ); diff --git a/runtime/src/configs/mod.rs b/runtime/src/configs/mod.rs index e76063a3..693319cf 100644 --- a/runtime/src/configs/mod.rs +++ b/runtime/src/configs/mod.rs @@ -621,3 +621,14 @@ impl TryFrom for pallet_assets::Call { } } } + +parameter_types! { + pub WormholeMintingAccount: AccountId = PalletId(*b"wormhole").into_account_truncating(); +} + +impl pallet_wormhole::Config for Runtime { + type MintingAccount = WormholeMintingAccount; + type WeightInfo = (); + type Currency = Balances; + type WeightToFee = IdentityFee; +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 7c54c2b5..2dbbb1bf 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -275,4 +275,7 @@ mod runtime { #[runtime::pallet_index(22)] pub type AssetsHolder = pallet_assets_holder; + + #[runtime::pallet_index(23)] + pub type Wormhole = pallet_wormhole; } From cd916c2e8857608aadf0afe38d5af02db0a68d91 Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Mon, 22 Dec 2025 13:47:33 +0600 Subject: [PATCH 3/4] Use canonical balances pallet and add support for assets in wormhole (#333) * Use canonical balances pallet, add assets support to wormhole * Ignore old tests * Remove tests * Override native asset id * Use poseidon hasher * Use poseidon storage hasher * Passing wormhole proof tests * Update binaries * Update binaries * Update zk-circuits crates * Use crates.io dep versions --- Cargo.lock | 69 +- Cargo.toml | 18 +- node/src/benchmarking.rs | 4 + pallets/balances/Cargo.toml | 65 - pallets/balances/README.md | 127 -- pallets/balances/src/benchmarking.rs | 350 ---- pallets/balances/src/impl_currency.rs | 952 ---------- pallets/balances/src/impl_fungible.rs | 385 ---- pallets/balances/src/impl_proofs.rs | 28 - pallets/balances/src/lib.rs | 1338 -------------- pallets/balances/src/migration.rs | 103 -- pallets/balances/src/tests/currency_tests.rs | 1643 ----------------- .../balances/src/tests/dispatchable_tests.rs | 410 ---- .../src/tests/fungible_conformance_tests.rs | 141 -- pallets/balances/src/tests/fungible_tests.rs | 883 --------- pallets/balances/src/tests/general_tests.rs | 143 -- pallets/balances/src/tests/mod.rs | 330 ---- .../balances/src/tests/reentrancy_tests.rs | 212 --- .../src/tests/transfer_counter_tests.rs | 336 ---- pallets/balances/src/types.rs | 164 -- pallets/balances/src/weights.rs | 300 --- pallets/merkle-airdrop/src/mock.rs | 2 + pallets/mining-rewards/src/lib.rs | 31 +- pallets/mining-rewards/src/mock.rs | 21 + .../reversible-transfers/src/tests/mock.rs | 1 + pallets/wormhole/Cargo.toml | 2 + pallets/wormhole/common.bin | Bin 1905 -> 1905 bytes pallets/wormhole/src/lib.rs | 252 ++- pallets/wormhole/src/mock.rs | 44 +- pallets/wormhole/src/tests.rs | 188 +- pallets/wormhole/verifier.bin | Bin 552 -> 552 bytes primitives/wormhole/src/lib.rs | 31 +- runtime/Cargo.toml | 4 + runtime/src/configs/mod.rs | 13 +- runtime/src/genesis_config_presets.rs | 15 +- runtime/src/lib.rs | 1 + runtime/src/transaction_extensions.rs | 251 ++- runtime/tests/governance/treasury.rs | 9 +- 38 files changed, 775 insertions(+), 8091 deletions(-) delete mode 100644 pallets/balances/Cargo.toml delete mode 100644 pallets/balances/README.md delete mode 100644 pallets/balances/src/benchmarking.rs delete mode 100644 pallets/balances/src/impl_currency.rs delete mode 100644 pallets/balances/src/impl_fungible.rs delete mode 100644 pallets/balances/src/impl_proofs.rs delete mode 100644 pallets/balances/src/lib.rs delete mode 100644 pallets/balances/src/migration.rs delete mode 100644 pallets/balances/src/tests/currency_tests.rs delete mode 100644 pallets/balances/src/tests/dispatchable_tests.rs delete mode 100644 pallets/balances/src/tests/fungible_conformance_tests.rs delete mode 100644 pallets/balances/src/tests/fungible_tests.rs delete mode 100644 pallets/balances/src/tests/general_tests.rs delete mode 100644 pallets/balances/src/tests/mod.rs delete mode 100644 pallets/balances/src/tests/reentrancy_tests.rs delete mode 100644 pallets/balances/src/tests/transfer_counter_tests.rs delete mode 100644 pallets/balances/src/types.rs delete mode 100644 pallets/balances/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index b98c66c9..9bfabe60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7081,27 +7081,6 @@ dependencies = [ "sp-staking", ] -[[package]] -name = "pallet-balances" -version = "40.0.1" -dependencies = [ - "docify", - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "pallet-transaction-payment", - "parity-scale-codec", - "paste", - "qp-poseidon", - "qp-wormhole", - "scale-info", - "sp-core", - "sp-io", - "sp-metadata-ir", - "sp-runtime", -] - [[package]] name = "pallet-balances" version = "42.0.0" @@ -7164,7 +7143,7 @@ dependencies = [ "frame-support", "frame-system", "log", - "pallet-balances 40.0.1", + "pallet-balances", "pallet-vesting", "parity-scale-codec", "scale-info", @@ -7202,7 +7181,7 @@ dependencies = [ "frame-support", "frame-system", "log", - "pallet-balances 40.0.1", + "pallet-balances", "parity-scale-codec", "qp-wormhole", "scale-info", @@ -7323,7 +7302,7 @@ dependencies = [ "log", "pallet-assets", "pallet-assets-holder", - "pallet-balances 40.0.1", + "pallet-balances", "pallet-preimage", "pallet-recovery", "pallet-scheduler", @@ -7582,7 +7561,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "log", - "pallet-balances 42.0.0", + "pallet-balances", "parity-scale-codec", "scale-info", "serde", @@ -7631,7 +7610,8 @@ dependencies = [ "hex", "lazy_static", "log", - "pallet-balances 40.0.1", + "pallet-assets", + "pallet-balances", "parity-scale-codec", "qp-dilithium-crypto", "qp-header", @@ -7647,6 +7627,7 @@ dependencies = [ "scale-info", "sp-core", "sp-io", + "sp-metadata-ir", "sp-runtime", "sp-state-machine", "sp-trie", @@ -8229,7 +8210,7 @@ dependencies = [ "pallet-authority-discovery", "pallet-authorship", "pallet-babe", - "pallet-balances 42.0.0", + "pallet-balances", "pallet-broker", "pallet-message-queue", "pallet-mmr", @@ -9003,9 +8984,9 @@ dependencies = [ [[package]] name = "qp-poseidon" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ebc5e9fe1f91f5006aa2b45650d0049887d41d80c669ef5a78a45086895054d" +checksum = "5029d1c8223c0312a0247ebc745c5b09622dcbebe104f0fdb9de358b87ef032a" dependencies = [ "log", "p3-field", @@ -9035,9 +9016,9 @@ dependencies = [ [[package]] name = "qp-poseidon-core" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52c70df221c356b3ce63afabfae623aae632c27d3e078cd20eec4348096c2d7" +checksum = "71dd1bf5d2997abf70247fcd23c8f04d7093b1faf33b775a42fb00c07e0a0e05" dependencies = [ "p3-field", "p3-goldilocks", @@ -9095,9 +9076,9 @@ version = "0.1.0" [[package]] name = "qp-wormhole-circuit" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b7357bec091287185850a6f7b67eb45f899a655b2a86825eae7e39b3bc6c3c" +checksum = "bcbccee20e314a1c52f36d8e78b1fa8205da46050c18da60d4964f41875bd4f6" dependencies = [ "anyhow", "hex", @@ -9108,9 +9089,9 @@ dependencies = [ [[package]] name = "qp-wormhole-circuit-builder" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7faed51eaa66ba71526955b74aac2fdba9849905a405f74d5f4f26564a9eaa98" +checksum = "aec473c32d69e2e0941d192ab8cf8712761ee2e84d3829fc211087f53be15bf3" dependencies = [ "anyhow", "qp-plonky2", @@ -9120,9 +9101,9 @@ dependencies = [ [[package]] name = "qp-wormhole-prover" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a56d84dd9bf64944b88cb0ec971f179a569d3bdf148132ab01bfe2d56c069d" +checksum = "9fd377a2fa936e6edb069ffecbf41afe10803b342e5cda8ff3aab199f77fde5d" dependencies = [ "anyhow", "qp-plonky2", @@ -9132,9 +9113,9 @@ dependencies = [ [[package]] name = "qp-wormhole-verifier" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40387c4c43fe47419cba58eb4f13c2a3c32ac0e381c98c3d77293ebf53298de7" +checksum = "08e114bc7ad7a7589c502960abc570685b726993ccce05443577a9ddd8dc4ee1" dependencies = [ "anyhow", "qp-plonky2", @@ -9144,9 +9125,9 @@ dependencies = [ [[package]] name = "qp-zk-circuits-common" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "366557f4c727379e2fd9c18b6667ae53c99bb241b973427df09a6b09584a11d4" +checksum = "445cc21c39959d1b553c4d8ea94d058ceab84cd70e5d47ec82b11535494cec46" dependencies = [ "anyhow", "hex", @@ -9264,7 +9245,7 @@ dependencies = [ "log", "pallet-assets", "pallet-assets-holder", - "pallet-balances 40.0.1", + "pallet-balances", "pallet-conviction-voting", "pallet-merkle-airdrop", "pallet-mining-rewards", @@ -9289,6 +9270,10 @@ dependencies = [ "qp-header", "qp-poseidon", "qp-scheduler", + "qp-wormhole", + "qp-wormhole-circuit", + "qp-wormhole-verifier", + "qp-zk-circuits-common", "scale-info", "serde_json", "sp-api", diff --git a/Cargo.toml b/Cargo.toml index b4d891f1..4878ed36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ members = [ "client/network", "miner-api", "node", - "pallets/balances", "pallets/merkle-airdrop", "pallets/mining-rewards", "pallets/qpow", @@ -130,7 +129,7 @@ wasm-timer = { version = "0.2.5" } zeroize = { version = "1.7.0", default-features = false } # Own dependencies -pallet-balances = { path = "./pallets/balances", default-features = false } +pallet-balances = { version = "42.0.0", default-features = false } pallet-merkle-airdrop = { path = "./pallets/merkle-airdrop", default-features = false } pallet-mining-rewards = { path = "./pallets/mining-rewards", default-features = false } pallet-qpow = { path = "./pallets/qpow", default-features = false } @@ -150,19 +149,19 @@ 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.3", default-features = false } -qp-poseidon-core = { version = "1.0.3", default-features = false, features = ["p2", "p3"] } +qp-poseidon = { version = "1.0.5", default-features = false } +qp-poseidon-core = { version = "1.0.5", 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.3", default-features = false } -qp-wormhole-circuit-builder = { version = "0.1.4", default-features = false } -qp-wormhole-prover = { version = "0.1.4", default-features = false, features = [ +qp-wormhole-circuit = { version = "0.1.7", default-features = false } +qp-wormhole-circuit-builder = { version = "0.1.7", default-features = false } +qp-wormhole-prover = { version = "0.1.7", default-features = false, features = [ "no_random", ] } -qp-wormhole-verifier = { version = "0.1.4", default-features = false, features = [ +qp-wormhole-verifier = { version = "0.1.7", default-features = false, features = [ "no_random", ] } -qp-zk-circuits-common = { version = "0.1.4", default-features = false, features = [ +qp-zk-circuits-common = { version = "0.1.7", default-features = false, features = [ "no_random", ] } @@ -244,7 +243,6 @@ sc-network = { path = "client/network" } sp-state-machine = { path = "./primitives/state-machine" } sp-trie = { path = "./primitives/trie" } - [profile.release] opt-level = 3 panic = "unwind" diff --git a/node/src/benchmarking.rs b/node/src/benchmarking.rs index 2d3d33eb..2dd9a8ef 100644 --- a/node/src/benchmarking.rs +++ b/node/src/benchmarking.rs @@ -127,6 +127,9 @@ pub fn create_benchmark_extrinsic( quantus_runtime::transaction_extensions::ReversibleTransactionExtension::< runtime::Runtime, >::new(), + quantus_runtime::transaction_extensions::WormholeProofRecorderExtension::< + runtime::Runtime, + >::new(), ); let raw_payload = runtime::SignedPayload::from_raw( @@ -143,6 +146,7 @@ pub fn create_benchmark_extrinsic( (), None, (), + (), ), ); let signature = raw_payload.using_encoded(|e| sender.sign(e)); diff --git a/pallets/balances/Cargo.toml b/pallets/balances/Cargo.toml deleted file mode 100644 index 686b4e18..00000000 --- a/pallets/balances/Cargo.toml +++ /dev/null @@ -1,65 +0,0 @@ -[package] -authors.workspace = true -description = "FRAME pallet to manage balances" -edition.workspace = true -homepage.workspace = true -license = "Apache-2.0" -name = "pallet-balances" -readme = "README.md" -repository.workspace = true -version = "40.0.1" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { features = ["derive", "max-encoded-len"], workspace = true } -docify = { workspace = true } -frame-benchmarking = { optional = true, workspace = true } -frame-support.workspace = true -frame-system.workspace = true -log.workspace = true -qp-poseidon = { workspace = true, features = ["serde"] } -qp-wormhole = { workspace = true } -scale-info = { features = ["derive"], workspace = true } -sp-metadata-ir = { workspace = true } -sp-runtime.workspace = true - -[dev-dependencies] -frame-support = { workspace = true, features = ["experimental"], default-features = true } -pallet-transaction-payment.features = ["std"] -pallet-transaction-payment.workspace = true -paste.workspace = true -sp-core.workspace = true -sp-io.workspace = true - -[features] -default = ["std"] -std = [ - "codec/std", - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "log/std", - "pallet-transaction-payment/std", - "qp-poseidon/std", - "qp-wormhole/std", - "scale-info/std", - "sp-core/std", - "sp-io/std", - "sp-metadata-ir/std", - "sp-runtime/std", -] -# Enable support for setting the existential deposit to zero. -insecure_zero_ed = [] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "sp-runtime/try-runtime", -] diff --git a/pallets/balances/README.md b/pallets/balances/README.md deleted file mode 100644 index b1e9c82f..00000000 --- a/pallets/balances/README.md +++ /dev/null @@ -1,127 +0,0 @@ -# Balances Module - -The Balances module provides functionality for handling accounts and balances. - -- [`Config`](https://docs.rs/pallet-balances/latest/pallet_balances/pallet/trait.Config.html) -- [`Call`](https://docs.rs/pallet-balances/latest/pallet_balances/pallet/enum.Call.html) -- [`Pallet`](https://docs.rs/pallet-balances/latest/pallet_balances/pallet/struct.Pallet.html) - -## Overview - -The Balances module provides functions for: - -- Getting and setting free balances. -- Retrieving total, reserved and unreserved balances. -- Repatriating a reserved balance to a beneficiary account that exists. -- Transferring a balance between accounts (when not reserved). -- Slashing an account balance. -- Account creation and removal. -- Managing total issuance. -- Setting and managing locks. - -### Terminology - -- **Existential Deposit:** The minimum balance required to create or keep an account open. This prevents "dust accounts" -from filling storage. When the free plus the reserved balance (i.e. the total balance) fall below this, then the account - is said to be dead; and it loses its functionality as well as any prior history and all information on it is removed - from the chain's state. No account should ever have a total balance that is strictly between 0 and the existential - deposit (exclusive). If this ever happens, it indicates either a bug in this module or an erroneous raw mutation of - storage. - -- **Total Issuance:** The total number of units in existence in a system. - -- **Reaping an account:** The act of removing an account by resetting its nonce. Happens after its total balance has -become zero (or, strictly speaking, less than the Existential Deposit). - -- **Free Balance:** The portion of a balance that is not reserved. The free balance is the only balance that matters for - most operations. - -- **Reserved Balance:** Reserved balance still belongs to the account holder, but is suspended. Reserved balance can - still be slashed, but only after all the free balance has been slashed. - -- **Imbalance:** A condition when some funds were credited or debited without equal and opposite accounting (i.e. a -difference between total issuance and account balances). Functions that result in an imbalance will return an object of -the `Imbalance` trait that can be managed within your runtime logic. (If an imbalance is simply dropped, it should -automatically maintain any book-keeping such as total issuance.) - -- **Lock:** A freeze on a specified amount of an account's free balance until a specified block number. Multiple locks -always operate over the same funds, so they "overlay" rather than "stack". - -### Implementations - -The Balances module provides implementations for the following traits. If these traits provide the functionality that -you need, then you can avoid coupling with the Balances module. - -- [`Currency`](https://docs.rs/frame-support/latest/frame_support/traits/trait.Currency.html): Functions for dealing -with a fungible assets system. -- [`ReservableCurrency`](https://docs.rs/frame-support/latest/frame_support/traits/trait.ReservableCurrency.html): -Functions for dealing with assets that can be reserved from an account. -- [`LockableCurrency`](https://docs.rs/frame-support/latest/frame_support/traits/trait.LockableCurrency.html): Functions -for dealing with accounts that allow liquidity restrictions. -- [`Imbalance`](https://docs.rs/frame-support/latest/frame_support/traits/trait.Imbalance.html): Functions for handling -imbalances between total issuance in the system and account balances. Must be used when a function creates new funds -(e.g. a reward) or destroys some funds (e.g. a system fee). -- [`IsDeadAccount`](https://docs.rs/frame-support/latest/frame_support/traits/trait.IsDeadAccount.html): Determiner to -say whether a given account is unused. - -## Interface - -### Dispatchable Functions - -- `transfer` - Transfer some liquid free balance to another account. -- `force_set_balance` - Set the balances of a given account. The origin of this call must be root. - -## Usage - -The following examples show how to use the Balances module in your custom module. - -### Examples from the FRAME - -The Contract module uses the `Currency` trait to handle gas payment, and its types inherit from `Currency`: - -```rust -use frame_support::traits::Currency; - -pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -pub type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; - -``` - -The Staking module uses the `LockableCurrency` trait to lock a stash account's funds: - -```rust -use frame_support::traits::{WithdrawReasons, LockableCurrency}; -use sp_runtime::traits::Bounded; -pub trait Config: frame_system::Config { - type Currency: LockableCurrency>; -} - -fn update_ledger( - controller: &T::AccountId, - ledger: &StakingLedger -) { - T::Currency::set_lock( - STAKING_ID, - &ledger.stash, - ledger.total, - WithdrawReasons::all() - ); - // >::insert(controller, ledger); // Commented out as we don't have access to Staking's storage here. -} -``` - -## Genesis config - -The Balances module depends on the -[`GenesisConfig`](https://docs.rs/pallet-balances/latest/pallet_balances/pallet/struct.GenesisConfig.html). - -## Assumptions - -- Total issued balanced of all accounts should be less than `Config::Balance::max_value()`. - -License: Apache-2.0 - - -## Release - -Polkadot SDK Stable 2412 diff --git a/pallets/balances/src/benchmarking.rs b/pallets/balances/src/benchmarking.rs deleted file mode 100644 index 06f3d24d..00000000 --- a/pallets/balances/src/benchmarking.rs +++ /dev/null @@ -1,350 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Balances pallet benchmarking. - -#![cfg(feature = "runtime-benchmarks")] - -use super::*; -use crate::Pallet as Balances; - -use frame_benchmarking::v2::*; -use frame_system::RawOrigin; -use sp_runtime::traits::Bounded; -use types::ExtraFlags; - -const SEED: u32 = 0; -// existential deposit multiplier -const ED_MULTIPLIER: u32 = 10; - -fn minimum_balance, I: 'static>() -> T::Balance { - if cfg!(feature = "insecure_zero_ed") { - 100u32.into() - } else { - T::ExistentialDeposit::get() - } -} - -#[instance_benchmarks] -mod benchmarks { - use super::*; - - // Benchmark `transfer` extrinsic with the worst possible conditions: - // * Transfer will kill the sender account. - // * Transfer will create the recipient account. - #[benchmark] - fn transfer_allow_death() { - let existential_deposit: T::Balance = minimum_balance::(); - let caller = whitelisted_caller(); - - // Give some multiple of the existential deposit - let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()).max(1u32.into()); - let _ = as Currency<_>>::make_free_balance_be(&caller, balance); - - // Transfer `e - 1` existential deposits + 1 unit, which guarantees to create one account, - // and reap this user. - let recipient: T::AccountId = account("recipient", 0, SEED); - let recipient_lookup = T::Lookup::unlookup(recipient.clone()); - let transfer_amount = - existential_deposit.saturating_mul((ED_MULTIPLIER - 1).into()) + 1u32.into(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller.clone()), recipient_lookup, transfer_amount); - - assert_eq!(Balances::::free_balance(&caller), Zero::zero()); - assert_eq!(Balances::::free_balance(&recipient), transfer_amount); - } - - // Benchmark `transfer` with the best possible condition: - // * Both accounts exist and will continue to exist. - #[benchmark(extra)] - fn transfer_best_case() { - let caller = whitelisted_caller(); - let recipient: T::AccountId = account("recipient", 0, SEED); - let recipient_lookup = T::Lookup::unlookup(recipient.clone()); - - // Give the sender account max funds for transfer (their account will never reasonably be - // killed). - let _ = - as Currency<_>>::make_free_balance_be(&caller, T::Balance::max_value()); - - // Give the recipient account existential deposit (thus their account already exists). - let existential_deposit: T::Balance = minimum_balance::(); - let _ = - as Currency<_>>::make_free_balance_be(&recipient, existential_deposit); - let transfer_amount = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - - #[extrinsic_call] - transfer_allow_death(RawOrigin::Signed(caller.clone()), recipient_lookup, transfer_amount); - - assert!(!Balances::::free_balance(&caller).is_zero()); - assert!(!Balances::::free_balance(&recipient).is_zero()); - } - - // Benchmark `transfer_keep_alive` with the worst possible condition: - // * The recipient account is created. - #[benchmark] - fn transfer_keep_alive() { - let caller = whitelisted_caller(); - let recipient: T::AccountId = account("recipient", 0, SEED); - let recipient_lookup = T::Lookup::unlookup(recipient.clone()); - - // Give the sender account max funds, thus a transfer will not kill account. - let _ = - as Currency<_>>::make_free_balance_be(&caller, T::Balance::max_value()); - let existential_deposit: T::Balance = minimum_balance::(); - let transfer_amount = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - - #[extrinsic_call] - _(RawOrigin::Signed(caller.clone()), recipient_lookup, transfer_amount); - - assert!(!Balances::::free_balance(&caller).is_zero()); - assert_eq!(Balances::::free_balance(&recipient), transfer_amount); - } - - // Benchmark `force_set_balance` coming from ROOT account. This always creates an account. - #[benchmark] - fn force_set_balance_creating() { - let user: T::AccountId = account("user", 0, SEED); - let user_lookup = T::Lookup::unlookup(user.clone()); - - // Give the user some initial balance. - let existential_deposit: T::Balance = minimum_balance::(); - let balance_amount = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - let _ = as Currency<_>>::make_free_balance_be(&user, balance_amount); - - #[extrinsic_call] - force_set_balance(RawOrigin::Root, user_lookup, balance_amount); - - assert_eq!(Balances::::free_balance(&user), balance_amount); - } - - // Benchmark `force_set_balance` coming from ROOT account. This always kills an account. - #[benchmark] - fn force_set_balance_killing() { - let user: T::AccountId = account("user", 0, SEED); - let user_lookup = T::Lookup::unlookup(user.clone()); - - // Give the user some initial balance. - let existential_deposit: T::Balance = minimum_balance::(); - let balance_amount = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - let _ = as Currency<_>>::make_free_balance_be(&user, balance_amount); - - #[extrinsic_call] - force_set_balance(RawOrigin::Root, user_lookup, Zero::zero()); - - assert!(Balances::::free_balance(&user).is_zero()); - } - - // Benchmark `force_transfer` extrinsic with the worst possible conditions: - // * Transfer will kill the sender account. - // * Transfer will create the recipient account. - #[benchmark] - fn force_transfer() { - let existential_deposit: T::Balance = minimum_balance::(); - let source: T::AccountId = account("source", 0, SEED); - let source_lookup = T::Lookup::unlookup(source.clone()); - - // Give some multiple of the existential deposit - let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - let _ = as Currency<_>>::make_free_balance_be(&source, balance); - - // Transfer `e - 1` existential deposits + 1 unit, which guarantees to create one account, - // and reap this user. - let recipient: T::AccountId = account("recipient", 0, SEED); - let recipient_lookup = T::Lookup::unlookup(recipient.clone()); - let transfer_amount = - existential_deposit.saturating_mul((ED_MULTIPLIER - 1).into()) + 1u32.into(); - - #[extrinsic_call] - _(RawOrigin::Root, source_lookup, recipient_lookup, transfer_amount); - - assert_eq!(Balances::::free_balance(&source), Zero::zero()); - assert_eq!(Balances::::free_balance(&recipient), transfer_amount); - } - - // This benchmark performs the same operation as `transfer` in the worst case scenario, - // but additionally introduces many new users into the storage, increasing the the merkle - // trie and PoV size. - #[benchmark(extra)] - fn transfer_increasing_users(u: Linear<0, 1_000>) { - // 1_000 is not very much, but this upper bound can be controlled by the CLI. - let existential_deposit: T::Balance = minimum_balance::(); - let caller = whitelisted_caller(); - - // Give some multiple of the existential deposit - let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - let _ = as Currency<_>>::make_free_balance_be(&caller, balance); - - // Transfer `e - 1` existential deposits + 1 unit, which guarantees to create one account, - // and reap this user. - let recipient: T::AccountId = account("recipient", 0, SEED); - let recipient_lookup = T::Lookup::unlookup(recipient.clone()); - let transfer_amount = - existential_deposit.saturating_mul((ED_MULTIPLIER - 1).into()) + 1u32.into(); - - // Create a bunch of users in storage. - for i in 0..u { - // The `account` function uses `blake2_256` to generate unique accounts, so these - // should be quite random and evenly distributed in the trie. - let new_user: T::AccountId = account("new_user", i, SEED); - let _ = as Currency<_>>::make_free_balance_be(&new_user, balance); - } - - #[extrinsic_call] - transfer_allow_death(RawOrigin::Signed(caller.clone()), recipient_lookup, transfer_amount); - - assert_eq!(Balances::::free_balance(&caller), Zero::zero()); - assert_eq!(Balances::::free_balance(&recipient), transfer_amount); - } - - // Benchmark `transfer_all` with the worst possible condition: - // * The recipient account is created - // * The sender is killed - #[benchmark] - fn transfer_all() { - let caller = whitelisted_caller(); - let recipient: T::AccountId = account("recipient", 0, SEED); - let recipient_lookup = T::Lookup::unlookup(recipient.clone()); - - // Give some multiple of the existential deposit - let existential_deposit: T::Balance = minimum_balance::(); - let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - let _ = as Currency<_>>::make_free_balance_be(&caller, balance); - - #[extrinsic_call] - _(RawOrigin::Signed(caller.clone()), recipient_lookup, false); - - assert!(Balances::::free_balance(&caller).is_zero()); - assert_eq!(Balances::::free_balance(&recipient), balance); - } - - #[benchmark] - fn force_unreserve() -> Result<(), BenchmarkError> { - let user: T::AccountId = account("user", 0, SEED); - let user_lookup = T::Lookup::unlookup(user.clone()); - - // Give some multiple of the existential deposit - let ed = minimum_balance::(); - let balance = ed + ed; - let _ = as Currency<_>>::make_free_balance_be(&user, balance); - - // Reserve the balance - as ReservableCurrency<_>>::reserve(&user, ed)?; - assert_eq!(Balances::::reserved_balance(&user), ed); - assert_eq!(Balances::::free_balance(&user), ed); - - #[extrinsic_call] - _(RawOrigin::Root, user_lookup, balance); - - assert!(Balances::::reserved_balance(&user).is_zero()); - assert_eq!(Balances::::free_balance(&user), ed + ed); - - Ok(()) - } - - #[benchmark] - fn upgrade_accounts(u: Linear<1, 1_000>) { - let caller: T::AccountId = whitelisted_caller(); - let who = (0..u) - .map(|i| -> T::AccountId { - let user = account("old_user", i, SEED); - let account = AccountData { - free: minimum_balance::(), - reserved: minimum_balance::(), - frozen: Zero::zero(), - flags: ExtraFlags::old_logic(), - }; - frame_system::Pallet::::inc_providers(&user); - assert!(T::AccountStore::try_mutate_exists(&user, |a| -> DispatchResult { - *a = Some(account); - Ok(()) - }) - .is_ok()); - assert!(!Balances::::account(&user).flags.is_new_logic()); - assert_eq!(frame_system::Pallet::::providers(&user), 1); - assert_eq!(frame_system::Pallet::::consumers(&user), 0); - user - }) - .collect(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller.clone()), who); - - for i in 0..u { - let user: T::AccountId = account("old_user", i, SEED); - assert!(Balances::::account(&user).flags.is_new_logic()); - assert_eq!(frame_system::Pallet::::providers(&user), 1); - assert_eq!(frame_system::Pallet::::consumers(&user), 1); - } - } - - #[benchmark] - fn force_adjust_total_issuance() { - let ti = TotalIssuance::::get(); - let delta = 123u32.into(); - - #[extrinsic_call] - _(RawOrigin::Root, AdjustmentDirection::Increase, delta); - - assert_eq!(TotalIssuance::::get(), ti + delta); - } - - /// Benchmark `burn` extrinsic with the worst possible condition - burn kills the account. - #[benchmark] - fn burn_allow_death() { - let existential_deposit = T::ExistentialDeposit::get(); - let caller = whitelisted_caller(); - - // Give some multiple of the existential deposit - let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - let _ = as Currency<_>>::make_free_balance_be(&caller, balance); - - // Burn enough to kill the account. - let burn_amount = balance - existential_deposit + 1u32.into(); - - #[extrinsic_call] - burn(RawOrigin::Signed(caller.clone()), burn_amount, false); - - assert_eq!(Balances::::free_balance(&caller), Zero::zero()); - } - - // Benchmark `burn` extrinsic with the case where account is kept alive. - #[benchmark] - fn burn_keep_alive() { - let existential_deposit = T::ExistentialDeposit::get(); - let caller = whitelisted_caller(); - - // Give some multiple of the existential deposit - let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); - let _ = as Currency<_>>::make_free_balance_be(&caller, balance); - - // Burn minimum possible amount which should not kill the account. - let burn_amount = 1u32.into(); - - #[extrinsic_call] - burn(RawOrigin::Signed(caller.clone()), burn_amount, true); - - assert_eq!(Balances::::free_balance(&caller), balance - burn_amount); - } - - impl_benchmark_test_suite! { - Balances, - crate::tests::ExtBuilder::default().build(), - crate::tests::Test, - } -} diff --git a/pallets/balances/src/impl_currency.rs b/pallets/balances/src/impl_currency.rs deleted file mode 100644 index 547cca75..00000000 --- a/pallets/balances/src/impl_currency.rs +++ /dev/null @@ -1,952 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Implementations for the `Currency` family of traits. -//! -//! Note that `WithdrawReasons` are intentionally not used for anything in this implementation and -//! are expected to be removed in the near future, once migration to `fungible::*` traits is done. - -use super::*; -use core::cmp::Ordering; -use frame_support::{ - ensure, - pallet_prelude::DispatchResult, - traits::{ - tokens::{ - fungible, Balance, BalanceStatus as Status, Fortitude::Polite, Precision::BestEffort, - }, - Currency, DefensiveSaturating, - ExistenceRequirement::{self, AllowDeath}, - Get, Imbalance, InspectLockableCurrency, LockIdentifier, LockableCurrency, - NamedReservableCurrency, ReservableCurrency, SignedImbalance, TryDrop, WithdrawReasons, - }, -}; -use frame_system::pallet_prelude::BlockNumberFor; -pub use imbalances::{NegativeImbalance, PositiveImbalance}; -use sp_runtime::traits::Bounded; - -// wrapping these imbalances in a private module is necessary to ensure absolute privacy -// of the inner member. -mod imbalances { - use super::*; - use core::mem; - use frame_support::traits::{tokens::imbalance::TryMerge, SameOrOther}; - - /// Opaque, move-only struct with private fields that serves as a token denoting that - /// funds have been created without any equal and opposite accounting. - #[must_use] - #[derive(RuntimeDebug, PartialEq, Eq)] - pub struct PositiveImbalance, I: 'static = ()>(T::Balance); - - impl, I: 'static> PositiveImbalance { - /// Create a new positive imbalance from a balance. - pub fn new(amount: T::Balance) -> Self { - PositiveImbalance(amount) - } - } - - /// Opaque, move-only struct with private fields that serves as a token denoting that - /// funds have been destroyed without any equal and opposite accounting. - #[must_use] - #[derive(RuntimeDebug, PartialEq, Eq)] - pub struct NegativeImbalance, I: 'static = ()>(T::Balance); - - impl, I: 'static> NegativeImbalance { - /// Create a new negative imbalance from a balance. - pub fn new(amount: T::Balance) -> Self { - NegativeImbalance(amount) - } - } - - impl, I: 'static> TryDrop for PositiveImbalance { - fn try_drop(self) -> result::Result<(), Self> { - self.drop_zero() - } - } - - impl, I: 'static> Default for PositiveImbalance { - fn default() -> Self { - Self::zero() - } - } - - impl, I: 'static> Imbalance for PositiveImbalance { - type Opposite = NegativeImbalance; - - fn zero() -> Self { - Self(Zero::zero()) - } - fn drop_zero(self) -> result::Result<(), Self> { - if self.0.is_zero() { - Ok(()) - } else { - Err(self) - } - } - fn split(self, amount: T::Balance) -> (Self, Self) { - let first = self.0.min(amount); - let second = self.0 - first; - - mem::forget(self); - (Self(first), Self(second)) - } - fn extract(&mut self, amount: T::Balance) -> Self { - let new = self.0.min(amount); - self.0 -= new; - Self(new) - } - fn merge(mut self, other: Self) -> Self { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - - self - } - fn subsume(&mut self, other: Self) { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - } - fn offset(self, other: Self::Opposite) -> SameOrOther { - let (a, b) = (self.0, other.0); - mem::forget((self, other)); - - match a.cmp(&b) { - Ordering::Greater => SameOrOther::Same(Self(a - b)), - Ordering::Less => SameOrOther::Other(NegativeImbalance::new(b - a)), - Ordering::Equal => SameOrOther::None, - } - } - fn peek(&self) -> T::Balance { - self.0 - } - } - - impl, I: 'static> TryMerge for PositiveImbalance { - fn try_merge(self, other: Self) -> Result { - Ok(self.merge(other)) - } - } - - impl, I: 'static> TryDrop for NegativeImbalance { - fn try_drop(self) -> result::Result<(), Self> { - self.drop_zero() - } - } - - impl, I: 'static> Default for NegativeImbalance { - fn default() -> Self { - Self::zero() - } - } - - impl, I: 'static> Imbalance for NegativeImbalance { - type Opposite = PositiveImbalance; - - fn zero() -> Self { - Self(Zero::zero()) - } - fn drop_zero(self) -> result::Result<(), Self> { - if self.0.is_zero() { - Ok(()) - } else { - Err(self) - } - } - fn split(self, amount: T::Balance) -> (Self, Self) { - let first = self.0.min(amount); - let second = self.0 - first; - - mem::forget(self); - (Self(first), Self(second)) - } - fn extract(&mut self, amount: T::Balance) -> Self { - let new = self.0.min(amount); - self.0 -= new; - Self(new) - } - fn merge(mut self, other: Self) -> Self { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - - self - } - fn subsume(&mut self, other: Self) { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - } - fn offset(self, other: Self::Opposite) -> SameOrOther { - let (a, b) = (self.0, other.0); - mem::forget((self, other)); - - match a.cmp(&b) { - Ordering::Greater => SameOrOther::Same(Self(a - b)), - Ordering::Less => SameOrOther::Other(PositiveImbalance::new(b - a)), - Ordering::Equal => SameOrOther::None, - } - } - fn peek(&self) -> T::Balance { - self.0 - } - } - - impl, I: 'static> TryMerge for NegativeImbalance { - fn try_merge(self, other: Self) -> Result { - Ok(self.merge(other)) - } - } - - impl, I: 'static> Drop for PositiveImbalance { - /// Basic drop handler will just square up the total issuance. - fn drop(&mut self) { - if !self.0.is_zero() { - >::mutate(|v| *v = v.saturating_add(self.0)); - Pallet::::deposit_event(Event::::Issued { amount: self.0 }); - } - } - } - - impl, I: 'static> Drop for NegativeImbalance { - /// Basic drop handler will just square up the total issuance. - fn drop(&mut self) { - if !self.0.is_zero() { - >::mutate(|v| *v = v.saturating_sub(self.0)); - Pallet::::deposit_event(Event::::Rescinded { amount: self.0 }); - } - } - } -} - -impl, I: 'static> Currency for Pallet -where - T::Balance: Balance, -{ - type Balance = T::Balance; - type PositiveImbalance = PositiveImbalance; - type NegativeImbalance = NegativeImbalance; - - fn total_balance(who: &T::AccountId) -> Self::Balance { - Self::account(who).total() - } - - // Check if `value` amount of free balance can be slashed from `who`. - fn can_slash(who: &T::AccountId, value: Self::Balance) -> bool { - if value.is_zero() { - return true; - } - Self::free_balance(who) >= value - } - - fn total_issuance() -> Self::Balance { - TotalIssuance::::get() - } - - fn active_issuance() -> Self::Balance { - >::active_issuance() - } - - fn deactivate(amount: Self::Balance) { - >::deactivate(amount); - } - - fn reactivate(amount: Self::Balance) { - >::reactivate(amount); - } - - fn minimum_balance() -> Self::Balance { - T::ExistentialDeposit::get() - } - - // Burn funds from the total issuance, returning a positive imbalance for the amount burned. - // Is a no-op if amount to be burned is zero. - fn burn(mut amount: Self::Balance) -> Self::PositiveImbalance { - if amount.is_zero() { - return PositiveImbalance::zero(); - } - >::mutate(|issued| { - *issued = issued.checked_sub(&amount).unwrap_or_else(|| { - amount = *issued; - Zero::zero() - }); - }); - - Pallet::::deposit_event(Event::::Rescinded { amount }); - PositiveImbalance::new(amount) - } - - // Create new funds into the total issuance, returning a negative imbalance - // for the amount issued. - // Is a no-op if amount to be issued it zero. - fn issue(mut amount: Self::Balance) -> Self::NegativeImbalance { - if amount.is_zero() { - return NegativeImbalance::zero(); - } - >::mutate(|issued| { - *issued = issued.checked_add(&amount).unwrap_or_else(|| { - amount = Self::Balance::max_value() - *issued; - Self::Balance::max_value() - }) - }); - - Pallet::::deposit_event(Event::::Issued { amount }); - NegativeImbalance::new(amount) - } - - fn free_balance(who: &T::AccountId) -> Self::Balance { - Self::account(who).free - } - - // Ensure that an account can withdraw from their free balance given any existing withdrawal - // restrictions like locks and vesting balance. - // Is a no-op if amount to be withdrawn is zero. - fn ensure_can_withdraw( - who: &T::AccountId, - amount: T::Balance, - _reasons: WithdrawReasons, - new_balance: T::Balance, - ) -> DispatchResult { - if amount.is_zero() { - return Ok(()); - } - ensure!(new_balance >= Self::account(who).frozen, Error::::LiquidityRestrictions); - Ok(()) - } - - // Transfer some free balance from `transactor` to `dest`, respecting existence requirements. - // Is a no-op if value to be transferred is zero or the `transactor` is the same as `dest`. - fn transfer( - transactor: &T::AccountId, - dest: &T::AccountId, - value: Self::Balance, - existence_requirement: ExistenceRequirement, - ) -> DispatchResult { - if value.is_zero() || transactor == dest { - return Ok(()); - } - let keep_alive = match existence_requirement { - ExistenceRequirement::KeepAlive => Preserve, - ExistenceRequirement::AllowDeath => Expendable, - }; - >::transfer(transactor, dest, value, keep_alive)?; - Ok(()) - } - - /// Slash a target account `who`, returning the negative imbalance created and any left over - /// amount that could not be slashed. - /// - /// Is a no-op if `value` to be slashed is zero or the account does not exist. - /// - /// NOTE: `slash()` prefers free balance, but assumes that reserve balance can be drawn - /// from in extreme circumstances. `can_slash()` should be used prior to `slash()` to avoid - /// having to draw from reserved funds, however we err on the side of punishment if things are - /// inconsistent or `can_slash` wasn't used appropriately. - fn slash(who: &T::AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) { - if value.is_zero() { - return (NegativeImbalance::zero(), Zero::zero()); - } - if Self::total_balance(who).is_zero() { - return (NegativeImbalance::zero(), value); - } - - match Self::try_mutate_account_handling_dust( - who, - |account, _is_new| -> Result<(Self::NegativeImbalance, Self::Balance), DispatchError> { - // Best value is the most amount we can slash following liveness rules. - let ed = T::ExistentialDeposit::get(); - let actual = match system::Pallet::::can_dec_provider(who) { - true => value.min(account.free), - false => value.min(account.free.saturating_sub(ed)), - }; - account.free.saturating_reduce(actual); - let remaining = value.saturating_sub(actual); - Ok((NegativeImbalance::new(actual), remaining)) - }, - ) { - Ok((imbalance, remaining)) => { - Self::deposit_event(Event::Slashed { - who: who.clone(), - amount: value.saturating_sub(remaining), - }); - (imbalance, remaining) - }, - Err(_) => (Self::NegativeImbalance::zero(), value), - } - } - - /// Deposit some `value` into the free balance of an existing target account `who`. - /// - /// Is a no-op if the `value` to be deposited is zero. - fn deposit_into_existing( - who: &T::AccountId, - value: Self::Balance, - ) -> Result { - if value.is_zero() { - return Ok(PositiveImbalance::zero()); - } - - Self::try_mutate_account_handling_dust( - who, - |account, is_new| -> Result { - ensure!(!is_new, Error::::DeadAccount); - account.free = account.free.checked_add(&value).ok_or(ArithmeticError::Overflow)?; - Self::deposit_event(Event::Deposit { who: who.clone(), amount: value }); - Ok(PositiveImbalance::new(value)) - }, - ) - } - - /// Deposit some `value` into the free balance of `who`, possibly creating a new account. - /// - /// This function is a no-op if: - /// - the `value` to be deposited is zero; or - /// - the `value` to be deposited is less than the required ED and the account does not yet - /// exist; or - /// - the deposit would necessitate the account to exist and there are no provider references; - /// or - /// - `value` is so large it would cause the balance of `who` to overflow. - fn deposit_creating(who: &T::AccountId, value: Self::Balance) -> Self::PositiveImbalance { - if value.is_zero() { - return Self::PositiveImbalance::zero(); - } - - Self::try_mutate_account_handling_dust( - who, - |account, is_new| -> Result { - let ed = T::ExistentialDeposit::get(); - ensure!(value >= ed || !is_new, Error::::ExistentialDeposit); - - // defensive only: overflow should never happen, however in case it does, then this - // operation is a no-op. - account.free = match account.free.checked_add(&value) { - Some(x) => x, - None => return Ok(Self::PositiveImbalance::zero()), - }; - - Self::deposit_event(Event::Deposit { who: who.clone(), amount: value }); - Ok(PositiveImbalance::new(value)) - }, - ) - .unwrap_or_else(|_| Self::PositiveImbalance::zero()) - } - - /// Withdraw some free balance from an account, respecting existence requirements. - /// - /// Is a no-op if value to be withdrawn is zero. - fn withdraw( - who: &T::AccountId, - value: Self::Balance, - reasons: WithdrawReasons, - liveness: ExistenceRequirement, - ) -> result::Result { - if value.is_zero() { - return Ok(NegativeImbalance::zero()); - } - - Self::try_mutate_account_handling_dust( - who, - |account, _| -> Result { - let new_free_account = - account.free.checked_sub(&value).ok_or(Error::::InsufficientBalance)?; - - // bail if we need to keep the account alive and this would kill it. - let ed = T::ExistentialDeposit::get(); - let would_be_dead = new_free_account < ed; - let would_kill = would_be_dead && account.free >= ed; - ensure!(liveness == AllowDeath || !would_kill, Error::::Expendability); - - Self::ensure_can_withdraw(who, value, reasons, new_free_account)?; - - account.free = new_free_account; - - Self::deposit_event(Event::Withdraw { who: who.clone(), amount: value }); - Ok(NegativeImbalance::new(value)) - }, - ) - } - - /// Force the new free balance of a target account `who` to some new value `balance`. - fn make_free_balance_be( - who: &T::AccountId, - value: Self::Balance, - ) -> SignedImbalance { - Self::try_mutate_account_handling_dust( - who, - |account, - is_new| - -> Result, DispatchError> { - let ed = T::ExistentialDeposit::get(); - // If we're attempting to set an existing account to less than ED, then - // bypass the entire operation. It's a no-op if you follow it through, but - // since this is an instance where we might account for a negative imbalance - // (in the dust cleaner of set_account) before we account for its actual - // equal and opposite cause (returned as an Imbalance), then in the - // instance that there's no other accounts on the system at all, we might - // underflow the issuance and our arithmetic will be off. - ensure!(value >= ed || !is_new, Error::::ExistentialDeposit); - - let imbalance = if account.free <= value { - SignedImbalance::Positive(PositiveImbalance::new(value - account.free)) - } else { - SignedImbalance::Negative(NegativeImbalance::new(account.free - value)) - }; - account.free = value; - Self::deposit_event(Event::BalanceSet { who: who.clone(), free: account.free }); - Ok(imbalance) - }, - ) - .unwrap_or_else(|_| SignedImbalance::Positive(Self::PositiveImbalance::zero())) - } -} - -impl, I: 'static> ReservableCurrency for Pallet -where - T::Balance: Balance, -{ - /// Check if `who` can reserve `value` from their free balance. - /// - /// Always `true` if value to be reserved is zero. - fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool { - if value.is_zero() { - return true; - } - Self::account(who).free.checked_sub(&value).is_some_and(|new_balance| { - new_balance >= T::ExistentialDeposit::get() && - Self::ensure_can_withdraw(who, value, WithdrawReasons::RESERVE, new_balance) - .is_ok() - }) - } - - fn reserved_balance(who: &T::AccountId) -> Self::Balance { - Self::account(who).reserved - } - - /// Move `value` from the free balance from `who` to their reserved balance. - /// - /// Is a no-op if value to be reserved is zero. - fn reserve(who: &T::AccountId, value: Self::Balance) -> DispatchResult { - if value.is_zero() { - return Ok(()); - } - - Self::try_mutate_account_handling_dust(who, |account, _| -> DispatchResult { - account.free = - account.free.checked_sub(&value).ok_or(Error::::InsufficientBalance)?; - account.reserved = - account.reserved.checked_add(&value).ok_or(ArithmeticError::Overflow)?; - Self::ensure_can_withdraw(who, value, WithdrawReasons::RESERVE, account.free) - })?; - - Self::deposit_event(Event::Reserved { who: who.clone(), amount: value }); - Ok(()) - } - - /// Unreserve some funds, returning any amount that was unable to be unreserved. - /// - /// Is a no-op if the value to be unreserved is zero or the account does not exist. - /// - /// NOTE: returns amount value which wasn't successfully unreserved. - fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance { - if value.is_zero() { - return Zero::zero(); - } - if Self::total_balance(who).is_zero() { - return value; - } - - let actual = match Self::mutate_account_handling_dust(who, |account| { - let actual = cmp::min(account.reserved, value); - account.reserved -= actual; - // defensive only: this can never fail since total issuance which is at least - // free+reserved fits into the same data type. - account.free = account.free.defensive_saturating_add(actual); - actual - }) { - Ok(x) => x, - Err(_) => { - // This should never happen since we don't alter the total amount in the account. - // If it ever does, then we should fail gracefully though, indicating that nothing - // could be done. - return value; - }, - }; - - Self::deposit_event(Event::Unreserved { who: who.clone(), amount: actual }); - value - actual - } - - /// Slash from reserved balance, returning the negative imbalance created, - /// and any amount that was unable to be slashed. - /// - /// Is a no-op if the value to be slashed is zero or the account does not exist. - fn slash_reserved( - who: &T::AccountId, - value: Self::Balance, - ) -> (Self::NegativeImbalance, Self::Balance) { - if value.is_zero() { - return (NegativeImbalance::zero(), Zero::zero()); - } - if Self::total_balance(who).is_zero() { - return (NegativeImbalance::zero(), value); - } - - // NOTE: `mutate_account` may fail if it attempts to reduce the balance to the point that an - // account is attempted to be illegally destroyed. - - match Self::mutate_account_handling_dust(who, |account| { - let actual = value.min(account.reserved); - account.reserved.saturating_reduce(actual); - - // underflow should never happen, but it if does, there's nothing to be done here. - (NegativeImbalance::new(actual), value.saturating_sub(actual)) - }) { - Ok((imbalance, not_slashed)) => { - Self::deposit_event(Event::Slashed { - who: who.clone(), - amount: value.saturating_sub(not_slashed), - }); - (imbalance, not_slashed) - }, - Err(_) => (Self::NegativeImbalance::zero(), value), - } - } - - /// Move the reserved balance of one account into the balance of another, according to `status`. - /// - /// Is a no-op if: - /// - the value to be moved is zero; or - /// - the `slashed` id equal to `beneficiary` and the `status` is `Reserved`. - /// - /// This is `Polite` and thus will not repatriate any funds which would lead the total balance - /// to be less than the frozen amount. Returns `Ok` with the actual amount of funds moved, - /// which may be less than `value` since the operation is done an a `BestEffort` basis. - fn repatriate_reserved( - slashed: &T::AccountId, - beneficiary: &T::AccountId, - value: Self::Balance, - status: Status, - ) -> Result { - let actual = - Self::do_transfer_reserved(slashed, beneficiary, value, BestEffort, Polite, status)?; - Ok(value.saturating_sub(actual)) - } -} - -impl, I: 'static> NamedReservableCurrency for Pallet -where - T::Balance: Balance, -{ - type ReserveIdentifier = T::ReserveIdentifier; - - fn reserved_balance_named(id: &Self::ReserveIdentifier, who: &T::AccountId) -> Self::Balance { - let reserves = Self::reserves(who); - reserves - .binary_search_by_key(id, |data| data.id) - .map(|index| reserves[index].amount) - .unwrap_or_default() - } - - /// Move `value` from the free balance from `who` to a named reserve balance. - /// - /// Is a no-op if value to be reserved is zero. - fn reserve_named( - id: &Self::ReserveIdentifier, - who: &T::AccountId, - value: Self::Balance, - ) -> DispatchResult { - if value.is_zero() { - return Ok(()); - } - - Reserves::::try_mutate(who, |reserves| -> DispatchResult { - match reserves.binary_search_by_key(id, |data| data.id) { - Ok(index) => { - reserves[index].amount = reserves[index] - .amount - .checked_add(&value) - .ok_or(ArithmeticError::Overflow)?; - }, - Err(index) => { - reserves - .try_insert(index, ReserveData { id: *id, amount: value }) - .map_err(|_| Error::::TooManyReserves)?; - }, - }; - >::reserve(who, value)?; - Ok(()) - }) - } - - /// Unreserve some funds, returning any amount that was unable to be unreserved. - /// - /// Is a no-op if the value to be unreserved is zero. - fn unreserve_named( - id: &Self::ReserveIdentifier, - who: &T::AccountId, - value: Self::Balance, - ) -> Self::Balance { - if value.is_zero() { - return Zero::zero(); - } - - Reserves::::mutate_exists(who, |maybe_reserves| -> Self::Balance { - if let Some(reserves) = maybe_reserves.as_mut() { - match reserves.binary_search_by_key(id, |data| data.id) { - Ok(index) => { - let to_change = cmp::min(reserves[index].amount, value); - - let remain = >::unreserve(who, to_change); - - // remain should always be zero but just to be defensive here. - let actual = to_change.defensive_saturating_sub(remain); - - // `actual <= to_change` and `to_change <= amount`; qed; - reserves[index].amount -= actual; - - if reserves[index].amount.is_zero() { - if reserves.len() == 1 { - // no more named reserves - *maybe_reserves = None; - } else { - // remove this named reserve - reserves.remove(index); - } - } - - value - actual - }, - Err(_) => value, - } - } else { - value - } - }) - } - - /// Slash from reserved balance, returning the negative imbalance created, - /// and any amount that was unable to be slashed. - /// - /// Is a no-op if the value to be slashed is zero. - fn slash_reserved_named( - id: &Self::ReserveIdentifier, - who: &T::AccountId, - value: Self::Balance, - ) -> (Self::NegativeImbalance, Self::Balance) { - if value.is_zero() { - return (NegativeImbalance::zero(), Zero::zero()); - } - - Reserves::::mutate(who, |reserves| -> (Self::NegativeImbalance, Self::Balance) { - match reserves.binary_search_by_key(id, |data| data.id) { - Ok(index) => { - let to_change = cmp::min(reserves[index].amount, value); - - let (imb, remain) = - >::slash_reserved(who, to_change); - - // remain should always be zero but just to be defensive here. - let actual = to_change.defensive_saturating_sub(remain); - - // `actual <= to_change` and `to_change <= amount`; qed; - reserves[index].amount -= actual; - - Self::deposit_event(Event::Slashed { who: who.clone(), amount: actual }); - (imb, value - actual) - }, - Err(_) => (NegativeImbalance::zero(), value), - } - }) - } - - /// Move the reserved balance of one account into the balance of another, according to `status`. - /// If `status` is `Reserved`, the balance will be reserved with given `id`. - /// - /// Is a no-op if: - /// - the value to be moved is zero; or - /// - the `slashed` id equal to `beneficiary` and the `status` is `Reserved`. - fn repatriate_reserved_named( - id: &Self::ReserveIdentifier, - slashed: &T::AccountId, - beneficiary: &T::AccountId, - value: Self::Balance, - status: Status, - ) -> Result { - if value.is_zero() { - return Ok(Zero::zero()); - } - - if slashed == beneficiary { - return match status { - Status::Free => Ok(Self::unreserve_named(id, slashed, value)), - Status::Reserved => - Ok(value.saturating_sub(Self::reserved_balance_named(id, slashed))), - }; - } - - Reserves::::try_mutate(slashed, |reserves| -> Result { - match reserves.binary_search_by_key(id, |data| data.id) { - Ok(index) => { - let to_change = cmp::min(reserves[index].amount, value); - - let actual = if status == Status::Reserved { - // make it the reserved under same identifier - Reserves::::try_mutate( - beneficiary, - |reserves| -> Result { - match reserves.binary_search_by_key(id, |data| data.id) { - Ok(index) => { - let remain = - >::repatriate_reserved( - slashed, - beneficiary, - to_change, - status, - )?; - - // remain should always be zero but just to be defensive - // here. - let actual = to_change.defensive_saturating_sub(remain); - - // this add can't overflow but just to be defensive. - reserves[index].amount = - reserves[index].amount.defensive_saturating_add(actual); - - Ok(actual) - }, - Err(index) => { - let remain = - >::repatriate_reserved( - slashed, - beneficiary, - to_change, - status, - )?; - - // remain should always be zero but just to be defensive - // here - let actual = to_change.defensive_saturating_sub(remain); - - reserves - .try_insert( - index, - ReserveData { id: *id, amount: actual }, - ) - .map_err(|_| Error::::TooManyReserves)?; - - Ok(actual) - }, - } - }, - )? - } else { - let remain = >::repatriate_reserved( - slashed, - beneficiary, - to_change, - status, - )?; - - // remain should always be zero but just to be defensive here - to_change.defensive_saturating_sub(remain) - }; - - // `actual <= to_change` and `to_change <= amount`; qed; - reserves[index].amount -= actual; - - Ok(value - actual) - }, - Err(_) => Ok(value), - } - }) - } -} - -impl, I: 'static> LockableCurrency for Pallet -where - T::Balance: Balance, -{ - type Moment = BlockNumberFor; - - type MaxLocks = T::MaxLocks; - - // Set or alter a lock on the balance of `who`. - fn set_lock( - id: LockIdentifier, - who: &T::AccountId, - amount: T::Balance, - reasons: WithdrawReasons, - ) { - if reasons.is_empty() || amount.is_zero() { - Self::remove_lock(id, who); - return; - } - - let mut new_lock = Some(BalanceLock { id, amount, reasons: reasons.into() }); - let mut locks = Self::locks(who) - .into_iter() - .filter_map(|l| if l.id == id { new_lock.take() } else { Some(l) }) - .collect::>(); - if let Some(lock) = new_lock { - locks.push(lock) - } - Self::update_locks(who, &locks[..]); - } - - // Extend a lock on the balance of `who`. - // Is a no-op if lock amount is zero or `reasons` `is_none()`. - fn extend_lock( - id: LockIdentifier, - who: &T::AccountId, - amount: T::Balance, - reasons: WithdrawReasons, - ) { - if amount.is_zero() || reasons.is_empty() { - return; - } - let mut new_lock = Some(BalanceLock { id, amount, reasons: reasons.into() }); - let mut locks = Self::locks(who) - .into_iter() - .filter_map(|l| { - if l.id == id { - new_lock.take().map(|nl| BalanceLock { - id: l.id, - amount: l.amount.max(nl.amount), - reasons: l.reasons | nl.reasons, - }) - } else { - Some(l) - } - }) - .collect::>(); - if let Some(lock) = new_lock { - locks.push(lock) - } - Self::update_locks(who, &locks[..]); - } - - fn remove_lock(id: LockIdentifier, who: &T::AccountId) { - let mut locks = Self::locks(who); - locks.retain(|l| l.id != id); - Self::update_locks(who, &locks[..]); - } -} - -impl, I: 'static> InspectLockableCurrency for Pallet { - fn balance_locked(id: LockIdentifier, who: &T::AccountId) -> Self::Balance { - Self::locks(who) - .into_iter() - .filter(|l| l.id == id) - .fold(Zero::zero(), |acc, l| acc + l.amount) - } -} diff --git a/pallets/balances/src/impl_fungible.rs b/pallets/balances/src/impl_fungible.rs deleted file mode 100644 index e5e43e04..00000000 --- a/pallets/balances/src/impl_fungible.rs +++ /dev/null @@ -1,385 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Implementation of `fungible` traits for Balances pallet. -use super::*; -use frame_support::traits::{ - tokens::{ - Fortitude, - Preservation::{self, Preserve, Protect}, - Provenance::{self, Minted}, - }, - AccountTouch, -}; - -impl, I: 'static> fungible::Inspect for Pallet { - type Balance = T::Balance; - - fn total_issuance() -> Self::Balance { - TotalIssuance::::get() - } - fn active_issuance() -> Self::Balance { - TotalIssuance::::get().saturating_sub(InactiveIssuance::::get()) - } - fn minimum_balance() -> Self::Balance { - T::ExistentialDeposit::get() - } - fn total_balance(who: &T::AccountId) -> Self::Balance { - Self::account(who).total() - } - fn balance(who: &T::AccountId) -> Self::Balance { - Self::account(who).free - } - fn reducible_balance( - who: &T::AccountId, - preservation: Preservation, - force: Fortitude, - ) -> Self::Balance { - let a = Self::account(who); - let mut untouchable = Zero::zero(); - if force == Polite { - // Frozen balance applies to total. Anything on hold therefore gets discounted from the - // limit given by the freezes. - untouchable = a.frozen.saturating_sub(a.reserved); - } - // If we want to keep our provider ref.. - if preservation == Preserve - // ..or we don't want the account to die and our provider ref is needed for it to live.. - || preservation == Protect && !a.free.is_zero() && - frame_system::Pallet::::providers(who) == 1 - // ..or we don't care about the account dying but our provider ref is required.. - || preservation == Expendable && !a.free.is_zero() && - !frame_system::Pallet::::can_dec_provider(who) - { - // ..then the ED needed.. - untouchable = untouchable.max(T::ExistentialDeposit::get()); - } - // Liquid balance is what is neither on hold nor frozen/required for provider. - a.free.saturating_sub(untouchable) - } - fn can_deposit( - who: &T::AccountId, - amount: Self::Balance, - provenance: Provenance, - ) -> DepositConsequence { - if amount.is_zero() { - return DepositConsequence::Success; - } - - if provenance == Minted && TotalIssuance::::get().checked_add(&amount).is_none() { - return DepositConsequence::Overflow; - } - - let account = Self::account(who); - let new_free = match account.free.checked_add(&amount) { - None => return DepositConsequence::Overflow, - Some(x) if x < T::ExistentialDeposit::get() => return DepositConsequence::BelowMinimum, - Some(x) => x, - }; - - match account.reserved.checked_add(&new_free) { - Some(_) => {}, - None => return DepositConsequence::Overflow, - }; - - // NOTE: We assume that we are a provider, so don't need to do any checks in the - // case of account creation. - - DepositConsequence::Success - } - fn can_withdraw( - who: &T::AccountId, - amount: Self::Balance, - ) -> WithdrawConsequence { - if amount.is_zero() { - return WithdrawConsequence::Success; - } - - if TotalIssuance::::get().checked_sub(&amount).is_none() { - return WithdrawConsequence::Underflow; - } - - let account = Self::account(who); - let new_free_balance = match account.free.checked_sub(&amount) { - Some(x) => x, - None => return WithdrawConsequence::BalanceLow, - }; - - let liquid = Self::reducible_balance(who, Expendable, Polite); - if amount > liquid { - return WithdrawConsequence::Frozen; - } - - // Provider restriction - total account balance cannot be reduced to zero if it cannot - // sustain the loss of a provider reference. - // NOTE: This assumes that the pallet is a provider (which is true). Is this ever changes, - // then this will need to adapt accordingly. - let ed = T::ExistentialDeposit::get(); - let success = if new_free_balance < ed { - if frame_system::Pallet::::can_dec_provider(who) { - WithdrawConsequence::ReducedToZero(new_free_balance) - } else { - return WithdrawConsequence::WouldDie; - } - } else { - WithdrawConsequence::Success - }; - - let new_total_balance = new_free_balance.saturating_add(account.reserved); - - // Eventual free funds must be no less than the frozen balance. - if new_total_balance < account.frozen { - return WithdrawConsequence::Frozen; - } - - success - } -} - -impl, I: 'static> fungible::Unbalanced for Pallet { - fn handle_dust(dust: fungible::Dust) { - T::DustRemoval::on_unbalanced(dust.into_credit()); - } - fn write_balance( - who: &T::AccountId, - amount: Self::Balance, - ) -> Result, DispatchError> { - let max_reduction = - >::reducible_balance(who, Expendable, Force); - let (result, maybe_dust) = Self::mutate_account(who, |account| -> DispatchResult { - // Make sure the reduction (if there is one) is no more than the maximum allowed. - let reduction = account.free.saturating_sub(amount); - ensure!(reduction <= max_reduction, Error::::InsufficientBalance); - - account.free = amount; - Ok(()) - })?; - result?; - Ok(maybe_dust) - } - - fn set_total_issuance(amount: Self::Balance) { - TotalIssuance::::mutate(|t| *t = amount); - } - - fn deactivate(amount: Self::Balance) { - InactiveIssuance::::mutate(|b| { - // InactiveIssuance cannot be greater than TotalIssuance. - *b = b.saturating_add(amount).min(TotalIssuance::::get()); - }); - } - - fn reactivate(amount: Self::Balance) { - InactiveIssuance::::mutate(|b| b.saturating_reduce(amount)); - } -} - -impl, I: 'static> fungible::Mutate for Pallet { - fn done_mint_into(who: &T::AccountId, amount: Self::Balance) { - Self::deposit_event(Event::::Minted { who: who.clone(), amount }); - } - fn done_burn_from(who: &T::AccountId, amount: Self::Balance) { - Self::deposit_event(Event::::Burned { who: who.clone(), amount }); - } - fn done_shelve(who: &T::AccountId, amount: Self::Balance) { - Self::deposit_event(Event::::Suspended { who: who.clone(), amount }); - } - fn done_restore(who: &T::AccountId, amount: Self::Balance) { - Self::deposit_event(Event::::Restored { who: who.clone(), amount }); - } - fn done_transfer(source: &T::AccountId, dest: &T::AccountId, amount: Self::Balance) { - Self::deposit_event(Event::::Transfer { - from: source.clone(), - to: dest.clone(), - amount, - }); - } -} - -impl, I: 'static> fungible::MutateHold for Pallet {} - -impl, I: 'static> fungible::InspectHold for Pallet { - type Reason = T::RuntimeHoldReason; - - fn total_balance_on_hold(who: &T::AccountId) -> T::Balance { - Self::account(who).reserved - } - fn reducible_total_balance_on_hold(who: &T::AccountId, force: Fortitude) -> Self::Balance { - // The total balance must never drop below the freeze requirements if we're not forcing: - let a = Self::account(who); - let unavailable = if force == Force { - Self::Balance::zero() - } else { - // The freeze lock applies to the total balance, so we can discount the free balance - // from the amount which the total reserved balance must provide to satisfy it. - a.frozen.saturating_sub(a.free) - }; - a.reserved.saturating_sub(unavailable) - } - fn balance_on_hold(reason: &Self::Reason, who: &T::AccountId) -> T::Balance { - Holds::::get(who) - .iter() - .find(|x| &x.id == reason) - .map_or_else(Zero::zero, |x| x.amount) - } - fn hold_available(reason: &Self::Reason, who: &T::AccountId) -> bool { - if frame_system::Pallet::::providers(who) == 0 { - return false; - } - let holds = Holds::::get(who); - if holds.is_full() && !holds.iter().any(|x| &x.id == reason) { - return false; - } - true - } -} - -impl, I: 'static> fungible::UnbalancedHold for Pallet { - fn set_balance_on_hold( - reason: &Self::Reason, - who: &T::AccountId, - amount: Self::Balance, - ) -> DispatchResult { - let mut new_account = Self::account(who); - let mut holds = Holds::::get(who); - let mut increase = true; - let mut delta = amount; - - if let Some(item) = holds.iter_mut().find(|x| &x.id == reason) { - delta = item.amount.max(amount) - item.amount.min(amount); - increase = amount > item.amount; - item.amount = amount; - holds.retain(|x| !x.amount.is_zero()); - } else if !amount.is_zero() { - holds - .try_push(IdAmount { id: *reason, amount }) - .map_err(|_| Error::::TooManyHolds)?; - } - - new_account.reserved = if increase { - new_account.reserved.checked_add(&delta).ok_or(ArithmeticError::Overflow)? - } else { - new_account.reserved.checked_sub(&delta).ok_or(ArithmeticError::Underflow)? - }; - - let (result, maybe_dust) = Self::try_mutate_account(who, |a, _| -> DispatchResult { - *a = new_account; - Ok(()) - })?; - debug_assert!( - maybe_dust.is_none(), - "Does not alter main balance; dust only happens when it is altered; qed" - ); - Holds::::insert(who, holds); - Ok(result) - } -} - -impl, I: 'static> fungible::InspectFreeze for Pallet { - type Id = T::FreezeIdentifier; - - fn balance_frozen(id: &Self::Id, who: &T::AccountId) -> Self::Balance { - let locks = Freezes::::get(who); - locks.into_iter().find(|l| &l.id == id).map_or(Zero::zero(), |l| l.amount) - } - - fn can_freeze(id: &Self::Id, who: &T::AccountId) -> bool { - let l = Freezes::::get(who); - !l.is_full() || l.iter().any(|x| &x.id == id) - } -} - -impl, I: 'static> fungible::MutateFreeze for Pallet { - fn set_freeze(id: &Self::Id, who: &T::AccountId, amount: Self::Balance) -> DispatchResult { - if amount.is_zero() { - return Self::thaw(id, who); - } - let mut locks = Freezes::::get(who); - if let Some(i) = locks.iter_mut().find(|x| &x.id == id) { - i.amount = amount; - } else { - locks - .try_push(IdAmount { id: *id, amount }) - .map_err(|_| Error::::TooManyFreezes)?; - } - Self::update_freezes(who, locks.as_bounded_slice()) - } - - fn extend_freeze(id: &Self::Id, who: &T::AccountId, amount: Self::Balance) -> DispatchResult { - if amount.is_zero() { - return Ok(()); - } - let mut locks = Freezes::::get(who); - if let Some(i) = locks.iter_mut().find(|x| &x.id == id) { - i.amount = i.amount.max(amount); - } else { - locks - .try_push(IdAmount { id: *id, amount }) - .map_err(|_| Error::::TooManyFreezes)?; - } - Self::update_freezes(who, locks.as_bounded_slice()) - } - - fn thaw(id: &Self::Id, who: &T::AccountId) -> DispatchResult { - let mut locks = Freezes::::get(who); - locks.retain(|l| &l.id != id); - Self::update_freezes(who, locks.as_bounded_slice()) - } -} - -impl, I: 'static> fungible::Balanced for Pallet { - type OnDropCredit = fungible::DecreaseIssuance; - type OnDropDebt = fungible::IncreaseIssuance; - - fn done_deposit(who: &T::AccountId, amount: Self::Balance) { - Self::deposit_event(Event::::Deposit { who: who.clone(), amount }); - } - fn done_withdraw(who: &T::AccountId, amount: Self::Balance) { - Self::deposit_event(Event::::Withdraw { who: who.clone(), amount }); - } - fn done_issue(amount: Self::Balance) { - if !amount.is_zero() { - Self::deposit_event(Event::::Issued { amount }); - } - } - fn done_rescind(amount: Self::Balance) { - Self::deposit_event(Event::::Rescinded { amount }); - } -} - -impl, I: 'static> fungible::BalancedHold for Pallet {} - -impl, I: 'static> - fungible::hold::DoneSlash for Pallet -{ - fn done_slash(reason: &T::RuntimeHoldReason, who: &T::AccountId, amount: T::Balance) { - T::DoneSlashHandler::done_slash(reason, who, amount); - } -} - -impl, I: 'static> AccountTouch<(), T::AccountId> for Pallet { - type Balance = T::Balance; - fn deposit_required(_: ()) -> Self::Balance { - Self::Balance::zero() - } - fn should_touch(_: (), _: &T::AccountId) -> bool { - false - } - fn touch(_: (), _: &T::AccountId, _: &T::AccountId) -> DispatchResult { - Ok(()) - } -} diff --git a/pallets/balances/src/impl_proofs.rs b/pallets/balances/src/impl_proofs.rs deleted file mode 100644 index 517225f5..00000000 --- a/pallets/balances/src/impl_proofs.rs +++ /dev/null @@ -1,28 +0,0 @@ -use super::*; -use qp_wormhole::TransferProofs; - -impl, I: 'static> TransferProofs - for Pallet -{ - fn transfer_proof_exists( - count: TransferCountType, - from: &T::AccountId, - to: &T::AccountId, - value: T::Balance, - ) -> bool { - TransferProof::::get((count, from, to, value)).is_some() - } - - fn store_transfer_proof(from: &T::AccountId, to: &T::AccountId, value: T::Balance) { - Pallet::::do_store_transfer_proof(from, to, value); - } - - fn transfer_proof_key( - transfer_count: u64, - from: T::AccountId, - to: T::AccountId, - value: T::Balance, - ) -> Vec { - Pallet::::transfer_proof_storage_key(transfer_count, from, to, value) - } -} diff --git a/pallets/balances/src/lib.rs b/pallets/balances/src/lib.rs deleted file mode 100644 index 583ea420..00000000 --- a/pallets/balances/src/lib.rs +++ /dev/null @@ -1,1338 +0,0 @@ -// This file is part of Substrate. - -#![allow(clippy::all)] -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! # Balances Pallet -//! -//! The Balances pallet provides functionality for handling accounts and balances for a single -//! token. -//! -//! It makes heavy use of concepts such as Holds and Freezes from the -//! [`frame_support::traits::fungible`] traits, therefore you should read and understand those docs -//! as a prerequisite to understanding this pallet. -//! -//! Also see the [`frame_tokens`] reference docs for higher level information regarding the -//! place of this palet in FRAME. -//! -//! ## Overview -//! -//! The Balances pallet provides functions for: -//! -//! - Getting and setting free balances. -//! - Retrieving total, reserved and unreserved balances. -//! - Repatriating a reserved balance to a beneficiary account that exists. -//! - Transferring a balance between accounts (when not reserved). -//! - Slashing an account balance. -//! - Account creation and removal. -//! - Managing total issuance. -//! - Setting and managing locks. -//! -//! ### Terminology -//! -//! - **Reaping an account:** The act of removing an account by resetting its nonce. Happens after -//! its total balance has become less than the Existential Deposit. -//! -//! ### Implementations -//! -//! The Balances pallet provides implementations for the following [`fungible`] traits. If these -//! traits provide the functionality that you need, then you should avoid tight coupling with the -//! Balances pallet. -//! -//! - [`fungible::Inspect`] -//! - [`fungible::Mutate`] -//! - [`fungible::Unbalanced`] -//! - [`fungible::Balanced`] -//! - [`fungible::BalancedHold`] -//! - [`fungible::InspectHold`] -//! - [`fungible::MutateHold`] -//! - [`fungible::InspectFreeze`] -//! - [`fungible::MutateFreeze`] -//! - [`fungible::Imbalance`] -//! -//! It also implements the following [`Currency`] related traits, however they are deprecated and -//! will eventually be removed. -//! -//! - [`Currency`]: Functions for dealing with a fungible assets system. -//! - [`ReservableCurrency`] -//! - [`NamedReservableCurrency`](frame_support::traits::NamedReservableCurrency): Functions for -//! dealing with assets that can be reserved from an account. -//! - [`LockableCurrency`](frame_support::traits::LockableCurrency): Functions for dealing with -//! accounts that allow liquidity restrictions. -//! - [`Imbalance`](frame_support::traits::Imbalance): Functions for handling imbalances between -//! total issuance in the system and account balances. Must be used when a function creates new -//! funds (e.g. a reward) or destroys some funds (e.g. a system fee). -//! -//! ## Usage -//! -//! The following examples show how to use the Balances pallet in your custom pallet. -//! -//! ### Examples from the FRAME -//! -//! The Contract pallet uses the `Currency` trait to handle gas payment, and its types inherit from -//! `Currency`: -//! -//! ``` -//! use frame_support::traits::Currency; -//! # pub trait Config: frame_system::Config { -//! # type Currency: Currency; -//! # } -//! -//! pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -//! pub type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; -//! -//! # fn main() {} -//! ``` -//! -//! The Staking pallet uses the `LockableCurrency` trait to lock a stash account's funds: -//! -//! ``` -//! use frame_support::traits::{WithdrawReasons, LockableCurrency}; -//! use sp_runtime::traits::Bounded; -//! pub trait Config: frame_system::Config { -//! type Currency: LockableCurrency>; -//! } -//! # struct StakingLedger { -//! # stash: ::AccountId, -//! # total: <::Currency as frame_support::traits::Currency<::AccountId>>::Balance, -//! # phantom: std::marker::PhantomData, -//! # } -//! # const STAKING_ID: [u8; 8] = *b"staking "; -//! -//! fn update_ledger( -//! controller: &T::AccountId, -//! ledger: &StakingLedger -//! ) { -//! T::Currency::set_lock( -//! STAKING_ID, -//! &ledger.stash, -//! ledger.total, -//! WithdrawReasons::all() -//! ); -//! // >::insert(controller, ledger); // Commented out as we don't have access to Staking's storage here. -//! } -//! # fn main() {} -//! ``` -//! -//! ## Genesis config -//! -//! The Balances pallet depends on the [`GenesisConfig`]. -//! -//! ## Assumptions -//! -//! * Total issued balanced of all accounts should be less than `Config::Balance::max_value()`. -//! * Existential Deposit is set to a value greater than zero. -//! -//! Note, you may find the Balances pallet still functions with an ED of zero when the -//! `insecure_zero_ed` cargo feature is enabled. However this is not a configuration which is -//! generally supported, nor will it be. -//! -//! [`frame_tokens`]: ../polkadot_sdk_docs/reference_docs/frame_tokens/index.html - -#![cfg_attr(not(feature = "std"), no_std)] -mod benchmarking; -mod impl_currency; -mod impl_fungible; -mod impl_proofs; -pub mod migration; -mod tests; -mod types; -pub mod weights; - -extern crate alloc; - -use alloc::vec::Vec; -use codec::{Codec, Decode, Encode, MaxEncodedLen}; -use core::{cmp, fmt::Debug, marker::PhantomData, mem, result}; -use frame_support::{ - ensure, - pallet_prelude::DispatchResult, - traits::{ - tokens::{ - fungible, Balance as BalanceT, BalanceStatus as Status, DepositConsequence, - Fortitude::{self, Force, Polite}, - IdAmount, - Preservation::{Expendable, Preserve, Protect}, - WithdrawConsequence, - }, - Currency, Defensive, Get, OnUnbalanced, ReservableCurrency, StoredMap, - }, - BoundedSlice, StorageHasher, WeakBoundedVec, -}; -use frame_system as system; -pub use impl_currency::{NegativeImbalance, PositiveImbalance}; -pub use pallet::*; -use qp_poseidon::PoseidonHasher as PoseidonCore; -use scale_info::TypeInfo; -use sp_metadata_ir::StorageHasherIR; -use sp_runtime::{ - traits::{ - AtLeast32BitUnsigned, CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Saturating, - StaticLookup, Zero, - }, - ArithmeticError, DispatchError, FixedPointOperand, Perbill, RuntimeDebug, TokenError, -}; -pub use types::{ - AccountData, AdjustmentDirection, BalanceLock, DustCleaner, ExtraFlags, Reasons, ReserveData, -}; -pub use weights::WeightInfo; - -const LOG_TARGET: &str = "runtime::balances"; - -type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; - -pub struct PoseidonStorageHasher(PhantomData); - -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) - } - - fn max_len() -> usize { - 32 - } -} - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::{ - pallet_prelude::*, - traits::{fungible::Credit, tokens::Precision, VariantCount, VariantCountOf}, - }; - use frame_system::pallet_prelude::*; - - pub type CreditOf = Credit<::AccountId, Pallet>; - pub type TransferCountType = u64; - - /// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`]. - pub mod config_preludes { - use super::*; - use frame_support::{derive_impl, traits::ConstU64}; - - pub struct TestDefaultConfig; - - #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)] - impl frame_system::DefaultConfig for TestDefaultConfig {} - - #[frame_support::register_default_impl(TestDefaultConfig)] - impl DefaultConfig for TestDefaultConfig { - #[inject_runtime_type] - type RuntimeHoldReason = (); - #[inject_runtime_type] - type RuntimeFreezeReason = (); - - type Balance = u64; - type ExistentialDeposit = ConstU64<1>; - - type ReserveIdentifier = (); - type FreezeIdentifier = Self::RuntimeFreezeReason; - - type DustRemoval = (); - - type MaxLocks = ConstU32<100>; - type MaxReserves = ConstU32<100>; - type MaxFreezes = VariantCountOf; - - type WeightInfo = (); - type DoneSlashHandler = (); - } - } - - #[pallet::config(with_default)] - pub trait Config: frame_system::Config { - /// The overarching hold reason. - #[pallet::no_default_bounds] - type RuntimeHoldReason: Parameter + Member + MaxEncodedLen + Copy + VariantCount; - - /// The overarching freeze reason. - #[pallet::no_default_bounds] - type RuntimeFreezeReason: VariantCount; - - /// Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - - /// The balance of an account. - type Balance: Parameter - + Member - + AtLeast32BitUnsigned - + Codec - + Default - + Copy - + MaybeSerializeDeserialize - + Debug - + MaxEncodedLen - + TypeInfo - + FixedPointOperand - + BalanceT; - - /// Handler for the unbalanced reduction when removing a dust account. - #[pallet::no_default_bounds] - type DustRemoval: OnUnbalanced>; - - /// The minimum amount required to keep an account open. MUST BE GREATER THAN ZERO! - /// - /// If you *really* need it to be zero, you can enable the feature `insecure_zero_ed` for - /// this pallet. However, you do so at your own risk: this will open up a major DoS vector. - /// In case you have multiple sources of provider references, you may also get unexpected - /// behaviour if you set this to zero. - /// - /// Bottom line: Do yourself a favour and make it at least one! - #[pallet::constant] - #[pallet::no_default_bounds] - type ExistentialDeposit: Get; - - /// The means of storing the balances of an account. - #[pallet::no_default] - type AccountStore: StoredMap>; - - /// The ID type for reserves. - /// - /// Use of reserves is deprecated in favour of holds. See `https://github.com/paritytech/substrate/pull/12951/` - type ReserveIdentifier: Parameter + Member + MaxEncodedLen + Ord + Copy; - - /// The ID type for freezes. - type FreezeIdentifier: Parameter + Member + MaxEncodedLen + Copy; - - /// The maximum number of locks that should exist on an account. - /// Not strictly enforced, but used for weight estimation. - /// - /// Use of locks is deprecated in favour of freezes. See `https://github.com/paritytech/substrate/pull/12951/` - #[pallet::constant] - type MaxLocks: Get; - - /// The maximum number of named reserves that can exist on an account. - /// - /// Use of reserves is deprecated in favour of holds. See `https://github.com/paritytech/substrate/pull/12951/` - #[pallet::constant] - type MaxReserves: Get; - - /// The maximum number of individual freeze locks that can exist on an account at any time. - #[pallet::constant] - type MaxFreezes: Get; - - /// Allows callbacks to other pallets so they can update their bookkeeping when a slash - /// occurs. - type DoneSlashHandler: fungible::hold::DoneSlash< - Self::RuntimeHoldReason, - Self::AccountId, - Self::Balance, - >; - } - - /// The in-code storage version. - const STORAGE_VERSION: frame_support::traits::StorageVersion = - frame_support::traits::StorageVersion::new(1); - - #[pallet::pallet] - #[pallet::storage_version(STORAGE_VERSION)] - pub struct Pallet(PhantomData<(T, I)>); - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event, I: 'static = ()> { - /// An account was created with some free balance. - Endowed { account: T::AccountId, free_balance: T::Balance }, - /// An account was removed whose balance was non-zero but below ExistentialDeposit, - /// resulting in an outright loss. - DustLost { account: T::AccountId, amount: T::Balance }, - /// Transfer succeeded. - Transfer { from: T::AccountId, to: T::AccountId, amount: T::Balance }, - /// A balance was set by root. - BalanceSet { who: T::AccountId, free: T::Balance }, - /// Some balance was reserved (moved from free to reserved). - Reserved { who: T::AccountId, amount: T::Balance }, - /// Some balance was unreserved (moved from reserved to free). - Unreserved { who: T::AccountId, amount: T::Balance }, - /// Some balance was moved from the reserve of the first account to the second account. - /// Final argument indicates the destination balance type. - ReserveRepatriated { - from: T::AccountId, - to: T::AccountId, - amount: T::Balance, - destination_status: Status, - }, - /// Some amount was deposited (e.g. for transaction fees). - Deposit { who: T::AccountId, amount: T::Balance }, - /// Some amount was withdrawn from the account (e.g. for transaction fees). - Withdraw { who: T::AccountId, amount: T::Balance }, - /// Some amount was removed from the account (e.g. for misbehavior). - Slashed { who: T::AccountId, amount: T::Balance }, - /// Some amount was minted into an account. - Minted { who: T::AccountId, amount: T::Balance }, - /// Some amount was burned from an account. - Burned { who: T::AccountId, amount: T::Balance }, - /// Some amount was suspended from an account (it can be restored later). - Suspended { who: T::AccountId, amount: T::Balance }, - /// Some amount was restored into an account. - Restored { who: T::AccountId, amount: T::Balance }, - /// An account was upgraded. - Upgraded { who: T::AccountId }, - /// Total issuance was increased by `amount`, creating a credit to be balanced. - Issued { amount: T::Balance }, - /// Total issuance was decreased by `amount`, creating a debt to be balanced. - Rescinded { amount: T::Balance }, - /// Some balance was locked. - Locked { who: T::AccountId, amount: T::Balance }, - /// Some balance was unlocked. - Unlocked { who: T::AccountId, amount: T::Balance }, - /// Some balance was frozen. - Frozen { who: T::AccountId, amount: T::Balance }, - /// Some balance was thawed. - Thawed { who: T::AccountId, amount: T::Balance }, - /// The `TotalIssuance` was forcefully changed. - TotalIssuanceForced { old: T::Balance, new: T::Balance }, - /// Transfer proof was stored. - TransferProofStored { - transfer_count: u64, - source: T::AccountId, - dest: T::AccountId, - funding_amount: T::Balance, - }, - } - - #[pallet::error] - pub enum Error { - /// Vesting balance too high to send value. - VestingBalance, - /// Account liquidity restrictions prevent withdrawal. - LiquidityRestrictions, - /// Balance too low to send value. - InsufficientBalance, - /// Value too low to create account due to existential deposit. - ExistentialDeposit, - /// Transfer/payment would kill account. - Expendability, - /// A vesting schedule already exists for this account. - ExistingVestingSchedule, - /// Beneficiary account must pre-exist. - DeadAccount, - /// Number of named reserves exceed `MaxReserves`. - TooManyReserves, - /// Number of holds exceed `VariantCountOf`. - TooManyHolds, - /// Number of freezes exceed `MaxFreezes`. - TooManyFreezes, - /// The issuance cannot be modified since it is already deactivated. - IssuanceDeactivated, - /// The delta cannot be zero. - DeltaZero, - } - - /// The total units issued in the system. - #[pallet::storage] - #[pallet::whitelist_storage] - pub type TotalIssuance, I: 'static = ()> = StorageValue<_, T::Balance, ValueQuery>; - - /// The total units of outstanding deactivated balance in the system. - #[pallet::storage] - #[pallet::whitelist_storage] - pub type InactiveIssuance, I: 'static = ()> = - StorageValue<_, T::Balance, ValueQuery>; - - /// The Balances pallet example of storing the balance of an account. - /// - /// # Example - /// - /// ```nocompile - /// impl pallet_balances::Config for Runtime { - /// type AccountStore = StorageMapShim, frame_system::Provider, AccountId, Self::AccountData> - /// } - /// ``` - /// - /// You can also store the balance of an account in the `System` pallet. - /// - /// # Example - /// - /// ```nocompile - /// impl pallet_balances::Config for Runtime { - /// type AccountStore = System - /// } - /// ``` - /// - /// But this comes with tradeoffs, storing account balances in the system pallet stores - /// `frame_system` data alongside the account data contrary to storing account balances in the - /// `Balances` pallet, which uses a `StorageMap` to store balances data only. - /// NOTE: This is only used in the case that this pallet is used to store balances. - #[pallet::storage] - pub type Account, I: 'static = ()> = - StorageMap<_, Blake2_128Concat, T::AccountId, AccountData, ValueQuery>; - - /// Any liquidity locks on some account balances. - /// NOTE: Should only be accessed when setting, changing and freeing a lock. - /// - /// Use of locks is deprecated in favour of freezes. See `https://github.com/paritytech/substrate/pull/12951/` - #[pallet::storage] - pub type Locks, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - WeakBoundedVec, T::MaxLocks>, - ValueQuery, - >; - - /// Named reserves on some account balances. - /// - /// Use of reserves is deprecated in favour of holds. See `https://github.com/paritytech/substrate/pull/12951/` - #[pallet::storage] - pub type Reserves, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - BoundedVec, T::MaxReserves>, - ValueQuery, - >; - - /// Holds on account balances. - #[pallet::storage] - pub type Holds, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - BoundedVec< - IdAmount, - VariantCountOf, - >, - ValueQuery, - >; - - /// Freeze locks on account balances. - #[pallet::storage] - pub type Freezes, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - BoundedVec, T::MaxFreezes>, - ValueQuery, - >; - - /// Transfer proofs for a wormhole transfers - #[pallet::storage] - #[pallet::getter(fn transfer_proof)] - pub type TransferProof, I: 'static = ()> = StorageMap< - _, - PoseidonStorageHasher, - (u64, T::AccountId, T::AccountId, T::Balance), // (tx_count, from, to, amount) - (), - OptionQuery, // Returns None if not present - >; - - #[pallet::storage] - #[pallet::getter(fn transfer_count)] - pub type TransferCount, I: 'static = ()> = - StorageValue<_, TransferCountType, ValueQuery>; - - #[pallet::genesis_config] - pub struct GenesisConfig, I: 'static = ()> { - pub balances: Vec<(T::AccountId, T::Balance)>, - } - - impl, I: 'static> Default for GenesisConfig { - fn default() -> Self { - Self { balances: Default::default() } - } - } - - #[pallet::genesis_build] - impl, I: 'static> BuildGenesisConfig for GenesisConfig { - fn build(&self) { - let total = self.balances.iter().fold(Zero::zero(), |acc: T::Balance, &(_, n)| acc + n); - - >::put(total); - - for (_, balance) in &self.balances { - assert!( - *balance >= >::ExistentialDeposit::get(), - "the balance of any account should always be at least the existential deposit.", - ) - } - - // ensure no duplicates exist. - let endowed_accounts = self - .balances - .iter() - .map(|(x, _)| x) - .cloned() - .collect::>(); - - assert!( - endowed_accounts.len() == self.balances.len(), - "duplicate balances in genesis." - ); - - for &(ref who, free) in self.balances.iter() { - frame_system::Pallet::::inc_providers(who); - assert!(T::AccountStore::insert(who, AccountData { free, ..Default::default() }) - .is_ok()); - } - } - } - - #[pallet::hooks] - impl, I: 'static> Hooks> for Pallet { - fn integrity_test() { - #[cfg(not(feature = "insecure_zero_ed"))] - assert!( - !>::ExistentialDeposit::get().is_zero(), - "The existential deposit must be greater than zero!" - ); - - assert!( - T::MaxFreezes::get() >= ::VARIANT_COUNT, - "MaxFreezes should be greater than or equal to the number of freeze reasons: {} < {}", - T::MaxFreezes::get(), ::VARIANT_COUNT, - ); - } - - #[cfg(feature = "try-runtime")] - fn try_state(_n: BlockNumberFor) -> Result<(), sp_runtime::TryRuntimeError> { - Holds::::iter_keys().try_for_each(|k| { - if Holds::::decode_len(k).unwrap_or(0) > - T::RuntimeHoldReason::VARIANT_COUNT as usize - { - Err("Found `Hold` with too many elements") - } else { - Ok(()) - } - })?; - - Freezes::::iter_keys().try_for_each(|k| { - if Freezes::::decode_len(k).unwrap_or(0) > T::MaxFreezes::get() as usize { - Err("Found `Freeze` with too many elements") - } else { - Ok(()) - } - })?; - - Ok(()) - } - } - - #[pallet::call(weight(>::WeightInfo))] - impl, I: 'static> Pallet { - /// Transfer some liquid free balance to another account. - /// - /// `transfer_allow_death` will set the `FreeBalance` of the sender and receiver. - /// If the sender's account is below the existential deposit as a result - /// of the transfer, the account will be reaped. - /// - /// The dispatch origin for this call must be `Signed` by the transactor. - #[pallet::call_index(0)] - pub fn transfer_allow_death( - origin: OriginFor, - dest: AccountIdLookupOf, - #[pallet::compact] value: T::Balance, - ) -> DispatchResult { - let source = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; - >::transfer(&source, &dest, value, Expendable)?; - Self::do_store_transfer_proof(&source, &dest, value); - Ok(()) - } - - /// Exactly as `transfer_allow_death`, except the origin must be root and the source account - /// may be specified. - #[pallet::call_index(2)] - pub fn force_transfer( - origin: OriginFor, - source: AccountIdLookupOf, - dest: AccountIdLookupOf, - #[pallet::compact] value: T::Balance, - ) -> DispatchResult { - ensure_root(origin)?; - let source = T::Lookup::lookup(source)?; - let dest = T::Lookup::lookup(dest)?; - >::transfer(&source, &dest, value, Expendable)?; - Self::do_store_transfer_proof(&source, &dest, value); - Ok(()) - } - - /// Same as the [`transfer_allow_death`] call, but with a check that the transfer will not - /// kill the origin account. - /// - /// 99% of the time you want [`transfer_allow_death`] instead. - /// - /// [`transfer_allow_death`]: struct.Pallet.html#method.transfer - #[pallet::call_index(3)] - pub fn transfer_keep_alive( - origin: OriginFor, - dest: AccountIdLookupOf, - #[pallet::compact] value: T::Balance, - ) -> DispatchResult { - let source = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; - >::transfer(&source, &dest, value, Preserve)?; - Self::do_store_transfer_proof(&source, &dest, value); - Ok(()) - } - - /// Transfer the entire transferable balance from the caller account. - /// - /// NOTE: This function only attempts to transfer _transferable_ balances. This means that - /// any locked, reserved, or existential deposits (when `keep_alive` is `true`), will not be - /// transferred by this function. To ensure that this function results in a killed account, - /// you might need to prepare the account by removing any reference counters, storage - /// deposits, etc... - /// - /// The dispatch origin of this call must be Signed. - /// - /// - `dest`: The recipient of the transfer. - /// - `keep_alive`: A boolean to determine if the `transfer_all` operation should send all - /// of the funds the account has, causing the sender account to be killed (false), or - /// transfer everything except at least the existential deposit, which will guarantee to - /// keep the sender account alive (true). - #[pallet::call_index(4)] - pub fn transfer_all( - origin: OriginFor, - dest: AccountIdLookupOf, - keep_alive: bool, - ) -> DispatchResult { - let transactor = ensure_signed(origin)?; - let keep_alive = if keep_alive { Preserve } else { Expendable }; - let reducible_balance = >::reducible_balance( - &transactor, - keep_alive, - Fortitude::Polite, - ); - let dest = T::Lookup::lookup(dest)?; - >::transfer( - &transactor, - &dest, - reducible_balance, - keep_alive, - )?; - Self::do_store_transfer_proof(&transactor, &dest, reducible_balance); - Ok(()) - } - - /// Unreserve some balance from a user by force. - /// - /// Can only be called by ROOT. - #[pallet::call_index(5)] - pub fn force_unreserve( - origin: OriginFor, - who: AccountIdLookupOf, - amount: T::Balance, - ) -> DispatchResult { - ensure_root(origin)?; - let who = T::Lookup::lookup(who)?; - let _leftover = >::unreserve(&who, amount); - Ok(()) - } - - /// Upgrade a specified account. - /// - /// - `origin`: Must be `Signed`. - /// - `who`: The account to be upgraded. - /// - /// This will waive the transaction fee if at least all but 10% of the accounts needed to - /// be upgraded. (We let some not have to be upgraded just in order to allow for the - /// possibility of churn). - #[pallet::call_index(6)] - #[pallet::weight(T::WeightInfo::upgrade_accounts(who.len() as u32))] - pub fn upgrade_accounts( - origin: OriginFor, - who: Vec, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - if who.is_empty() { - return Ok(Pays::Yes.into()); - } - let mut upgrade_count = 0; - for i in &who { - let upgraded = Self::ensure_upgraded(i); - if upgraded { - upgrade_count.saturating_inc(); - } - } - let proportion_upgraded = Perbill::from_rational(upgrade_count, who.len() as u32); - if proportion_upgraded >= Perbill::from_percent(90) { - Ok(Pays::No.into()) - } else { - Ok(Pays::Yes.into()) - } - } - - /// Set the regular balance of a given account. - /// - /// The dispatch origin for this call is `root`. - #[pallet::call_index(8)] - #[pallet::weight( - T::WeightInfo::force_set_balance_creating() // Creates a new account. - .max(T::WeightInfo::force_set_balance_killing()) // Kills an existing account. - )] - pub fn force_set_balance( - origin: OriginFor, - who: AccountIdLookupOf, - #[pallet::compact] new_free: T::Balance, - ) -> DispatchResult { - ensure_root(origin)?; - let who = T::Lookup::lookup(who)?; - let existential_deposit = Self::ed(); - - let wipeout = new_free < existential_deposit; - let new_free = if wipeout { Zero::zero() } else { new_free }; - - // First we try to modify the account's balance to the forced balance. - let old_free = Self::mutate_account_handling_dust(&who, |account| { - let old_free = account.free; - account.free = new_free; - old_free - })?; - - // This will adjust the total issuance, which was not done by the `mutate_account` - // above. - match new_free.cmp(&old_free) { - cmp::Ordering::Greater => { - mem::drop(PositiveImbalance::::new(new_free - old_free)); - }, - cmp::Ordering::Less => { - mem::drop(NegativeImbalance::::new(old_free - new_free)); - }, - cmp::Ordering::Equal => {}, - } - - Self::deposit_event(Event::BalanceSet { who, free: new_free }); - Ok(()) - } - - /// Adjust the total issuance in a saturating way. - /// - /// Can only be called by root and always needs a positive `delta`. - /// - /// # Example - #[doc = docify::embed!("./src/tests/dispatchable_tests.rs", force_adjust_total_issuance_example)] - #[pallet::call_index(9)] - #[pallet::weight(T::WeightInfo::force_adjust_total_issuance())] - pub fn force_adjust_total_issuance( - origin: OriginFor, - direction: AdjustmentDirection, - #[pallet::compact] delta: T::Balance, - ) -> DispatchResult { - ensure_root(origin)?; - - ensure!(delta > Zero::zero(), Error::::DeltaZero); - - let old = TotalIssuance::::get(); - let new = match direction { - AdjustmentDirection::Increase => old.saturating_add(delta), - AdjustmentDirection::Decrease => old.saturating_sub(delta), - }; - - ensure!(InactiveIssuance::::get() <= new, Error::::IssuanceDeactivated); - TotalIssuance::::set(new); - - Self::deposit_event(Event::::TotalIssuanceForced { old, new }); - - Ok(()) - } - - /// Burn the specified liquid free balance from the origin account. - /// - /// If the origin's account ends up below the existential deposit as a result - /// of the burn and `keep_alive` is false, the account will be reaped. - /// - /// Unlike sending funds to a _burn_ address, which merely makes the funds inaccessible, - /// this `burn` operation will reduce total issuance by the amount _burned_. - #[pallet::call_index(10)] - #[pallet::weight(if *keep_alive {T::WeightInfo::burn_allow_death() } else {T::WeightInfo::burn_keep_alive()})] - pub fn burn( - origin: OriginFor, - #[pallet::compact] value: T::Balance, - keep_alive: bool, - ) -> DispatchResult { - let source = ensure_signed(origin)?; - let preservation = if keep_alive { Preserve } else { Expendable }; - >::burn_from( - &source, - value, - preservation, - Precision::Exact, - Polite, - )?; - Ok(()) - } - } - - impl, I: 'static> Pallet { - pub(crate) fn do_store_transfer_proof( - from: &T::AccountId, - to: &T::AccountId, - value: T::Balance, - ) { - if from != to { - let current_count = Self::transfer_count(); - TransferProof::::insert((current_count, from.clone(), to.clone(), value), ()); - TransferCount::::put(current_count.saturating_add(One::one())); - - Self::deposit_event(Event::TransferProofStored { - transfer_count: current_count, - source: from.clone(), - dest: to.clone(), - funding_amount: value, - }); - } - } - - pub(crate) fn transfer_proof_storage_key( - transfer_count: u64, - from: T::AccountId, - to: T::AccountId, - amount: T::Balance, - ) -> Vec { - let key = (transfer_count, from, to, amount); - TransferProof::::hashed_key_for(&key) - } - } - - impl, I: 'static> Pallet { - /// Public function to get the total issuance. - pub fn total_issuance() -> T::Balance { - TotalIssuance::::get() - } - - /// Public function to get the inactive issuance. - pub fn inactive_issuance() -> T::Balance { - InactiveIssuance::::get() - } - - /// Public function to access the Locks storage. - pub fn locks(who: &T::AccountId) -> WeakBoundedVec, T::MaxLocks> { - Locks::::get(who) - } - - /// Public function to access the reserves storage. - pub fn reserves( - who: &T::AccountId, - ) -> BoundedVec, T::MaxReserves> { - Reserves::::get(who) - } - - fn ed() -> T::Balance { - T::ExistentialDeposit::get() - } - /// Ensure the account `who` is using the new logic. - /// - /// Returns `true` if the account did get upgraded, `false` if it didn't need upgrading. - pub fn ensure_upgraded(who: &T::AccountId) -> bool { - let mut a = T::AccountStore::get(who); - if a.flags.is_new_logic() { - return false; - } - a.flags.set_new_logic(); - if !a.reserved.is_zero() && a.frozen.is_zero() { - if system::Pallet::::providers(who) == 0 { - // Gah!! We have no provider refs :( - // This shouldn't practically happen, but we need a failsafe anyway: let's give - // them enough for an ED. - log::warn!( - target: LOG_TARGET, - "account with a non-zero reserve balance has no provider refs, account_id: '{:?}'.", - who - ); - a.free = a.free.max(Self::ed()); - system::Pallet::::inc_providers(who); - } - let _ = system::Pallet::::inc_consumers_without_limit(who).defensive(); - } - // Should never fail - we're only setting a bit. - let _ = T::AccountStore::try_mutate_exists(who, |account| -> DispatchResult { - *account = Some(a); - Ok(()) - }); - Self::deposit_event(Event::Upgraded { who: who.clone() }); - true - } - - /// Get the free balance of an account. - pub fn free_balance(who: impl core::borrow::Borrow) -> T::Balance { - Self::account(who.borrow()).free - } - - /// Get the balance of an account that can be used for transfers, reservations, or any other - /// non-locking, non-transaction-fee activity. Will be at most `free_balance`. - pub fn usable_balance(who: impl core::borrow::Borrow) -> T::Balance { - >::reducible_balance(who.borrow(), Expendable, Polite) - } - - /// Get the balance of an account that can be used for paying transaction fees (not tipping, - /// or any other kind of fees, though). Will be at most `free_balance`. - /// - /// This requires that the account stays alive. - pub fn usable_balance_for_fees(who: impl core::borrow::Borrow) -> T::Balance { - >::reducible_balance(who.borrow(), Protect, Polite) - } - - /// Get the reserved balance of an account. - pub fn reserved_balance(who: impl core::borrow::Borrow) -> T::Balance { - Self::account(who.borrow()).reserved - } - - /// Get both the free and reserved balances of an account. - pub(crate) fn account(who: &T::AccountId) -> AccountData { - T::AccountStore::get(who) - } - - /// Mutate an account to some new value, or delete it entirely with `None`. Will enforce - /// `ExistentialDeposit` law, annulling the account as needed. - /// - /// It returns the result from the closure. Any dust is handled through the low-level - /// `fungible::Unbalanced` trap-door for legacy dust management. - /// - /// NOTE: Doesn't do any preparatory work for creating a new account, so should only be used - /// when it is known that the account already exists. - /// - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - pub(crate) fn mutate_account_handling_dust( - who: &T::AccountId, - f: impl FnOnce(&mut AccountData) -> R, - ) -> Result { - let (r, maybe_dust) = Self::mutate_account(who, f)?; - if let Some(dust) = maybe_dust { - >::handle_raw_dust(dust); - } - Ok(r) - } - - /// Mutate an account to some new value, or delete it entirely with `None`. Will enforce - /// `ExistentialDeposit` law, annulling the account as needed. - /// - /// It returns the result from the closure. Any dust is handled through the low-level - /// `fungible::Unbalanced` trap-door for legacy dust management. - /// - /// NOTE: Doesn't do any preparatory work for creating a new account, so should only be used - /// when it is known that the account already exists. - /// - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - pub(crate) fn try_mutate_account_handling_dust>( - who: &T::AccountId, - f: impl FnOnce(&mut AccountData, bool) -> Result, - ) -> Result { - let (r, maybe_dust) = Self::try_mutate_account(who, f)?; - if let Some(dust) = maybe_dust { - >::handle_raw_dust(dust); - } - Ok(r) - } - - /// Mutate an account to some new value, or delete it entirely with `None`. Will enforce - /// `ExistentialDeposit` law, annulling the account as needed. - /// - /// It returns both the result from the closure, and an optional amount of dust - /// which should be handled once it is known that all nested mutates that could affect - /// storage items what the dust handler touches have completed. - /// - /// NOTE: Doesn't do any preparatory work for creating a new account, so should only be used - /// when it is known that the account already exists. - /// - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - pub(crate) fn mutate_account( - who: &T::AccountId, - f: impl FnOnce(&mut AccountData) -> R, - ) -> Result<(R, Option), DispatchError> { - Self::try_mutate_account(who, |a, _| -> Result { Ok(f(a)) }) - } - - /// Returns `true` when `who` has some providers or `insecure_zero_ed` feature is disabled. - /// Returns `false` otherwise. - #[cfg(not(feature = "insecure_zero_ed"))] - fn have_providers_or_no_zero_ed(_: &T::AccountId) -> bool { - true - } - - /// Returns `true` when `who` has some providers or `insecure_zero_ed` feature is disabled. - /// Returns `false` otherwise. - #[cfg(feature = "insecure_zero_ed")] - fn have_providers_or_no_zero_ed(who: &T::AccountId) -> bool { - frame_system::Pallet::::providers(who) > 0 - } - - /// Mutate an account to some new value, or delete it entirely with `None`. Will enforce - /// `ExistentialDeposit` law, annulling the account as needed. This will do nothing if the - /// result of `f` is an `Err`. - /// - /// It returns both the result from the closure, and an optional amount of dust - /// which should be handled once it is known that all nested mutates that could affect - /// storage items what the dust handler touches have completed. - /// - /// NOTE: Doesn't do any preparatory work for creating a new account, so should only be used - /// when it is known that the account already exists. - /// - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - pub(crate) fn try_mutate_account>( - who: &T::AccountId, - f: impl FnOnce(&mut AccountData, bool) -> Result, - ) -> Result<(R, Option), E> { - Self::ensure_upgraded(who); - let result = T::AccountStore::try_mutate_exists(who, |maybe_account| { - let is_new = maybe_account.is_none(); - let mut account = maybe_account.take().unwrap_or_default(); - let did_provide = - account.free >= Self::ed() && Self::have_providers_or_no_zero_ed(who); - let did_consume = - !is_new && (!account.reserved.is_zero() || !account.frozen.is_zero()); - - let result = f(&mut account, is_new)?; - - let does_provide = account.free >= Self::ed(); - let does_consume = !account.reserved.is_zero() || !account.frozen.is_zero(); - - if !did_provide && does_provide { - frame_system::Pallet::::inc_providers(who); - } - if did_consume && !does_consume { - frame_system::Pallet::::dec_consumers(who); - } - if !did_consume && does_consume { - frame_system::Pallet::::inc_consumers(who)?; - } - if does_consume && frame_system::Pallet::::consumers(who) == 0 { - // NOTE: This is a failsafe and should not happen for normal accounts. A normal - // account should have gotten a consumer ref in `!did_consume && does_consume` - // at some point. - log::error!(target: LOG_TARGET, "Defensively bumping a consumer ref."); - frame_system::Pallet::::inc_consumers(who)?; - } - if did_provide && !does_provide { - // This could reap the account so must go last. - frame_system::Pallet::::dec_providers(who).inspect_err(|_| { - // best-effort revert consumer change. - if did_consume && !does_consume { - let _ = frame_system::Pallet::::inc_consumers(who).defensive(); - } - if !did_consume && does_consume { - frame_system::Pallet::::dec_consumers(who); - } - })?; - } - - let maybe_endowed = if is_new { Some(account.free) } else { None }; - - // Handle any steps needed after mutating an account. - // - // This includes DustRemoval unbalancing, in the case than the `new` account's total - // balance is non-zero but below ED. - // - // Updates `maybe_account` to `Some` iff the account has sufficient balance. - // Evaluates `maybe_dust`, which is `Some` containing the dust to be dropped, iff - // some dust should be dropped. - // - // We should never be dropping if reserved is non-zero. Reserved being non-zero - // should imply that we have a consumer ref, so this is economically safe. - let ed = Self::ed(); - let maybe_dust = if account.free < ed && account.reserved.is_zero() { - if account.free.is_zero() { - None - } else { - Some(account.free) - } - } else { - assert!( - account.free.is_zero() || account.free >= ed || !account.reserved.is_zero() - ); - *maybe_account = Some(account); - None - }; - Ok((maybe_endowed, maybe_dust, result)) - }); - result.map(|(maybe_endowed, maybe_dust, result)| { - if let Some(endowed) = maybe_endowed { - Self::deposit_event(Event::Endowed { - account: who.clone(), - free_balance: endowed, - }); - } - if let Some(amount) = maybe_dust { - Pallet::::deposit_event(Event::DustLost { account: who.clone(), amount }); - } - (result, maybe_dust) - }) - } - - /// Update the account entry for `who`, given the locks. - pub(crate) fn update_locks(who: &T::AccountId, locks: &[BalanceLock]) { - let bounded_locks = WeakBoundedVec::<_, T::MaxLocks>::force_from( - locks.to_vec(), - Some("Balances Update Locks"), - ); - - if locks.len() as u32 > T::MaxLocks::get() { - log::warn!( - target: LOG_TARGET, - "Warning: A user has more currency locks than expected. \ - A runtime configuration adjustment may be needed." - ); - } - let freezes = Freezes::::get(who); - let mut prev_frozen = Zero::zero(); - let mut after_frozen = Zero::zero(); - // No way this can fail since we do not alter the existential balances. - // TODO: Revisit this assumption. - let res = Self::mutate_account(who, |b| { - prev_frozen = b.frozen; - b.frozen = Zero::zero(); - for l in locks.iter() { - b.frozen = b.frozen.max(l.amount); - } - for l in freezes.iter() { - b.frozen = b.frozen.max(l.amount); - } - after_frozen = b.frozen; - }); - debug_assert!(res.is_ok()); - if let Ok((_, maybe_dust)) = res { - debug_assert!(maybe_dust.is_none(), "Not altering main balance; qed"); - } - - match locks.is_empty() { - true => Locks::::remove(who), - false => Locks::::insert(who, bounded_locks), - } - - match prev_frozen.cmp(&after_frozen) { - cmp::Ordering::Greater => { - let amount = prev_frozen.saturating_sub(after_frozen); - Self::deposit_event(Event::Unlocked { who: who.clone(), amount }); - }, - cmp::Ordering::Less => { - let amount = after_frozen.saturating_sub(prev_frozen); - Self::deposit_event(Event::Locked { who: who.clone(), amount }); - }, - cmp::Ordering::Equal => {}, - } - } - - /// Update the account entry for `who`, given the locks. - pub(crate) fn update_freezes( - who: &T::AccountId, - freezes: BoundedSlice, T::MaxFreezes>, - ) -> DispatchResult { - let mut prev_frozen = Zero::zero(); - let mut after_frozen = Zero::zero(); - let (_, maybe_dust) = Self::mutate_account(who, |b| { - prev_frozen = b.frozen; - b.frozen = Zero::zero(); - for l in Locks::::get(who).iter() { - b.frozen = b.frozen.max(l.amount); - } - for l in freezes.iter() { - b.frozen = b.frozen.max(l.amount); - } - after_frozen = b.frozen; - })?; - debug_assert!(maybe_dust.is_none(), "Not altering main balance; qed"); - if freezes.is_empty() { - Freezes::::remove(who); - } else { - Freezes::::insert(who, freezes); - } - match prev_frozen.cmp(&after_frozen) { - cmp::Ordering::Greater => { - let amount = prev_frozen.saturating_sub(after_frozen); - Self::deposit_event(Event::Thawed { who: who.clone(), amount }); - }, - cmp::Ordering::Less => { - let amount = after_frozen.saturating_sub(prev_frozen); - Self::deposit_event(Event::Frozen { who: who.clone(), amount }); - }, - cmp::Ordering::Equal => {}, - } - Ok(()) - } - - /// Move the reserved balance of one account into the balance of another, according to - /// `status`. This will respect freezes/locks only if `fortitude` is `Polite`. - /// - /// Is a no-op if the value to be moved is zero. - /// - /// NOTE: returns actual amount of transferred value in `Ok` case. - pub(crate) fn do_transfer_reserved( - slashed: &T::AccountId, - beneficiary: &T::AccountId, - value: T::Balance, - precision: Precision, - fortitude: Fortitude, - status: Status, - ) -> Result { - if value.is_zero() { - return Ok(Zero::zero()); - } - - let max = >::reducible_total_balance_on_hold( - slashed, fortitude, - ); - let actual = match precision { - Precision::BestEffort => value.min(max), - Precision::Exact => value, - }; - ensure!(actual <= max, TokenError::FundsUnavailable); - if slashed == beneficiary { - return match status { - Status::Free => Ok(actual.saturating_sub(Self::unreserve(slashed, actual))), - Status::Reserved => Ok(actual), - }; - } - - let ((_, maybe_dust_1), maybe_dust_2) = Self::try_mutate_account( - beneficiary, - |to_account, is_new| -> Result<((), Option), DispatchError> { - ensure!(!is_new, Error::::DeadAccount); - Self::try_mutate_account(slashed, |from_account, _| -> DispatchResult { - match status { - Status::Free => - to_account.free = to_account - .free - .checked_add(&actual) - .ok_or(ArithmeticError::Overflow)?, - Status::Reserved => - to_account.reserved = to_account - .reserved - .checked_add(&actual) - .ok_or(ArithmeticError::Overflow)?, - } - from_account.reserved.saturating_reduce(actual); - Ok(()) - }) - }, - )?; - - if let Some(dust) = maybe_dust_1 { - >::handle_raw_dust(dust); - } - if let Some(dust) = maybe_dust_2 { - >::handle_raw_dust(dust); - } - - Self::deposit_event(Event::ReserveRepatriated { - from: slashed.clone(), - to: beneficiary.clone(), - amount: actual, - destination_status: status, - }); - Ok(actual) - } - } -} diff --git a/pallets/balances/src/migration.rs b/pallets/balances/src/migration.rs deleted file mode 100644 index ac2f7e2f..00000000 --- a/pallets/balances/src/migration.rs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use super::*; -use frame_support::{ - pallet_prelude::*, - traits::{OnRuntimeUpgrade, PalletInfoAccess}, - weights::Weight, -}; - -fn migrate_v0_to_v1, I: 'static>(accounts: &[T::AccountId]) -> Weight { - let on_chain_version = Pallet::::on_chain_storage_version(); - - if on_chain_version == 0 { - let total = accounts - .iter() - .map(Pallet::::total_balance) - .fold(T::Balance::zero(), |a, e| a.saturating_add(e)); - Pallet::::deactivate(total); - - // Remove the old `StorageVersion` type. - frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix( - Pallet::::name().as_bytes(), - "StorageVersion".as_bytes(), - )); - - // Set storage version to `1`. - StorageVersion::new(1).put::>(); - - log::info!(target: LOG_TARGET, "Storage to version 1"); - T::DbWeight::get().reads_writes(2 + accounts.len() as u64, 3) - } else { - log::info!( - target: LOG_TARGET, - "Migration did not execute. This probably should be removed" - ); - T::DbWeight::get().reads(1) - } -} - -// NOTE: This must be used alongside the account whose balance is expected to be inactive. -// Generally this will be used for the XCM teleport checking account. -pub struct MigrateToTrackInactive(PhantomData<(T, A, I)>); -impl, A: Get, I: 'static> OnRuntimeUpgrade - for MigrateToTrackInactive -{ - fn on_runtime_upgrade() -> Weight { - migrate_v0_to_v1::(&[A::get()]) - } -} - -// NOTE: This must be used alongside the accounts whose balance is expected to be inactive. -// Generally this will be used for the XCM teleport checking accounts. -pub struct MigrateManyToTrackInactive(PhantomData<(T, A, I)>); -impl, A: Get>, I: 'static> OnRuntimeUpgrade - for MigrateManyToTrackInactive -{ - fn on_runtime_upgrade() -> Weight { - migrate_v0_to_v1::(&A::get()) - } -} - -pub struct ResetInactive(PhantomData<(T, I)>); -impl, I: 'static> OnRuntimeUpgrade for ResetInactive { - fn on_runtime_upgrade() -> Weight { - let on_chain_version = Pallet::::on_chain_storage_version(); - - if on_chain_version == 1 { - // Remove the old `StorageVersion` type. - frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix( - Pallet::::name().as_bytes(), - "StorageVersion".as_bytes(), - )); - - InactiveIssuance::::kill(); - - // Set storage version to `0`. - StorageVersion::new(0).put::>(); - - log::info!(target: LOG_TARGET, "Storage to version 0"); - T::DbWeight::get().reads_writes(1, 3) - } else { - log::info!( - target: LOG_TARGET, - "Migration did not execute. This probably should be removed" - ); - T::DbWeight::get().reads(1) - } - } -} diff --git a/pallets/balances/src/tests/currency_tests.rs b/pallets/balances/src/tests/currency_tests.rs deleted file mode 100644 index cf22405a..00000000 --- a/pallets/balances/src/tests/currency_tests.rs +++ /dev/null @@ -1,1643 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Tests regarding the functionality of the `Currency` trait set implementations. - -use super::*; -use crate::{Event, NegativeImbalance}; -use frame_support::{ - traits::{ - BalanceStatus::{Free, Reserved}, - Currency, - ExistenceRequirement::{self, AllowDeath, KeepAlive}, - Hooks, InspectLockableCurrency, LockIdentifier, LockableCurrency, NamedReservableCurrency, - ReservableCurrency, WithdrawReasons, - }, - StorageNoopGuard, -}; -use frame_system::Event as SysEvent; -use sp_runtime::traits::DispatchTransaction; - -const ID_1: LockIdentifier = *b"1 "; -const ID_2: LockIdentifier = *b"2 "; - -pub const CALL: &::RuntimeCall = - &RuntimeCall::Balances(crate::Call::transfer_allow_death { - dest: sp_core::crypto::AccountId32::new([0u8; 32]), - value: 0, - }); - -#[test] -fn ed_should_work() { - ExtBuilder::default().existential_deposit(1).build_and_execute_with(|| { - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(1), 1000)); - assert_noop!( - >::transfer(&account_id(1), &account_id(10), 1000, KeepAlive), - TokenError::NotExpendable - ); - assert_ok!(>::transfer( - &account_id(1), - &account_id(10), - 1000, - AllowDeath - )); - }); -} - -#[test] -fn set_lock_with_amount_zero_removes_lock() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), Balance::MAX, WithdrawReasons::all()); - Balances::set_lock(ID_1, &account_id(1), 0, WithdrawReasons::all()); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 1, - AllowDeath - )); - }); -} - -#[test] -fn set_lock_with_withdraw_reasons_empty_removes_lock() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), Balance::MAX, WithdrawReasons::all()); - Balances::set_lock(ID_1, &account_id(1), Balance::MAX, WithdrawReasons::empty()); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 1, - AllowDeath - )); - }); -} - -#[test] -fn basic_locking_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - assert_eq!(Balances::free_balance(account_id(1)), 10); - Balances::set_lock(ID_1, &account_id(1), 9, WithdrawReasons::all()); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 5, AllowDeath), - TokenError::Frozen - ); - }); -} - -#[test] -fn inspect_lock_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), 10, WithdrawReasons::all()); - Balances::set_lock(ID_2, &account_id(1), 10, WithdrawReasons::all()); - Balances::set_lock(ID_1, &account_id(2), 20, WithdrawReasons::all()); - - assert_eq!( - >::balance_locked(ID_1, &account_id(1)), - 10 - ); - assert_eq!( - >::balance_locked(ID_2, &account_id(1)), - 10 - ); - assert_eq!( - >::balance_locked(ID_1, &account_id(2)), - 20 - ); - assert_eq!( - >::balance_locked(ID_2, &account_id(2)), - 0 - ); - assert_eq!( - >::balance_locked(ID_1, &account_id(3)), - 0 - ); - }) -} - -#[test] -fn account_should_be_reaped() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - assert_eq!(Balances::free_balance(account_id(1)), 10); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 10, - AllowDeath - )); - assert_eq!(System::providers(&account_id(1)), 0); - assert_eq!(System::consumers(&account_id(1)), 0); - // Check that the account is dead. - assert!(!frame_system::Account::::contains_key(account_id(1))); - }); -} - -#[test] -fn reap_failed_due_to_provider_and_consumer() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // SCENARIO: only one provider and there are remaining consumers. - assert_ok!(System::inc_consumers(&account_id(1))); - assert!(!System::can_dec_provider(&account_id(1))); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 10, AllowDeath), - TokenError::Frozen - ); - assert!(System::account_exists(&account_id(1))); - assert_eq!(Balances::free_balance(account_id(1)), 10); - - // SCENARIO: more than one provider, but will not kill account due to other provider. - assert_eq!(System::inc_providers(&account_id(1)), frame_system::IncRefStatus::Existed); - assert_eq!(System::providers(&account_id(1)), 2); - assert!(System::can_dec_provider(&account_id(1))); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 10, - AllowDeath - )); - assert_eq!(System::providers(&account_id(1)), 1); - assert!(System::account_exists(&account_id(1))); - assert_eq!(Balances::free_balance(account_id(1)), 0); - }); -} - -#[test] -fn partial_locking_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), 5, WithdrawReasons::all()); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 1, - AllowDeath - )); - }); -} - -#[test] -fn lock_removal_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), Balance::MAX, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 1); - Balances::remove_lock(ID_1, &account_id(1)); - assert_eq!(System::consumers(&account_id(1)), 0); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 1, - AllowDeath - )); - }); -} - -#[test] -fn lock_replacement_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), Balance::MAX, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 1); - Balances::set_lock(ID_1, &account_id(1), 5, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 1); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 1, - AllowDeath - )); - }); -} - -#[test] -fn double_locking_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), 5, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 1); - Balances::set_lock(ID_2, &account_id(1), 5, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 1); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 1, - AllowDeath - )); - }); -} - -#[test] -fn combination_locking_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - assert_eq!(System::consumers(&account_id(1)), 0); - Balances::set_lock(ID_1, &account_id(1), Balance::MAX, WithdrawReasons::empty()); - assert_eq!(System::consumers(&account_id(1)), 0); - Balances::set_lock(ID_2, &account_id(1), 0, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 0); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 1, - AllowDeath - )); - }); -} - -#[test] -fn lock_value_extension_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), 5, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 1); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 6, AllowDeath), - TokenError::Frozen - ); - Balances::extend_lock(ID_1, &account_id(1), 2, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 1); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 6, AllowDeath), - TokenError::Frozen - ); - Balances::extend_lock(ID_1, &account_id(1), 8, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 1); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 3, AllowDeath), - TokenError::Frozen - ); - }); -} - -#[test] -fn lock_should_work_reserve() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - pallet_transaction_payment::NextFeeMultiplier::::put( - Multiplier::saturating_from_integer(1), - ); - Balances::set_lock(ID_1, &account_id(1), 10, WithdrawReasons::RESERVE); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 1, AllowDeath), - TokenError::Frozen - ); - assert_noop!( - Balances::reserve(&account_id(1), 1), - Error::::LiquidityRestrictions, - ); - assert!(ChargeTransactionPayment::::validate_and_prepare( - ChargeTransactionPayment::from(1), - Some(account_id(1)).into(), - CALL, - &crate::tests::info_from_weight(Weight::from_parts(1, 0)), - 1, - 0, - ) - .is_err()); - assert!(ChargeTransactionPayment::::validate_and_prepare( - ChargeTransactionPayment::from(0), - Some(account_id(1)).into(), - CALL, - &crate::tests::info_from_weight(Weight::from_parts(1, 0)), - 1, - 0, - ) - .is_err()); - }); -} - -#[test] -fn lock_should_work_tx_fee() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), 10, WithdrawReasons::TRANSACTION_PAYMENT); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 1, AllowDeath), - TokenError::Frozen - ); - assert_noop!( - Balances::reserve(&account_id(1), 1), - Error::::LiquidityRestrictions, - ); - assert!(ChargeTransactionPayment::::validate_and_prepare( - ChargeTransactionPayment::from(1), - Some(account_id(1)).into(), - CALL, - &crate::tests::info_from_weight(Weight::from_parts(1, 0)), - 1, - 0, - ) - .is_err()); - assert!(ChargeTransactionPayment::::validate_and_prepare( - ChargeTransactionPayment::from(0), - Some(account_id(1)).into(), - CALL, - &crate::tests::info_from_weight(Weight::from_parts(1, 0)), - 1, - 0, - ) - .is_err()); - }); -} - -#[test] -fn lock_block_number_extension_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), 10, WithdrawReasons::all()); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 6, AllowDeath), - TokenError::Frozen - ); - Balances::extend_lock(ID_1, &account_id(1), 10, WithdrawReasons::all()); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 6, AllowDeath), - TokenError::Frozen - ); - System::set_block_number(2); - Balances::extend_lock(ID_1, &account_id(1), 10, WithdrawReasons::all()); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 3, AllowDeath), - TokenError::Frozen - ); - }); -} - -#[test] -fn lock_reasons_extension_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - Balances::set_lock(ID_1, &account_id(1), 10, WithdrawReasons::TRANSFER); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 6, AllowDeath), - TokenError::Frozen - ); - Balances::extend_lock(ID_1, &account_id(1), 10, WithdrawReasons::empty()); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 6, AllowDeath), - TokenError::Frozen - ); - Balances::extend_lock(ID_1, &account_id(1), 10, WithdrawReasons::RESERVE); - assert_noop!( - >::transfer(&account_id(1), &account_id(2), 6, AllowDeath), - TokenError::Frozen - ); - }); -} - -#[test] -fn reserved_balance_should_prevent_reclaim_count() { - ExtBuilder::default() - .existential_deposit(256) - .monied(true) - .build_and_execute_with(|| { - System::inc_account_nonce(account_id(2)); - assert_eq!(Balances::total_balance(&account_id(2)), 256 * 20); - assert_eq!(System::providers(&account_id(2)), 1); - System::inc_providers(&account_id(2)); - assert_eq!(System::providers(&account_id(2)), 2); - - assert_ok!(Balances::reserve(&account_id(2), 256 * 19 + 1)); // account 2 becomes mostly reserved - assert_eq!(System::providers(&account_id(2)), 1); - assert_eq!(Balances::free_balance(account_id(2)), 255); // "free" account would be deleted. - assert_eq!(Balances::total_balance(&account_id(2)), 256 * 20); // reserve still exists. - assert_eq!(System::account_nonce(account_id(2)), 1); - - // account 4 tries to take index 1 for account 5. - assert_ok!(Balances::transfer_allow_death( - Some(account_id(4)).into(), - account_id(5), - 256 + 0x69 - )); - assert_eq!(Balances::total_balance(&account_id(5)), 256 + 0x69); - - assert!(Balances::slash_reserved(&account_id(2), 256 * 19 + 1).1.is_zero()); // account 2 gets slashed - - // "reserve" account reduced to 255 (below ED) so account no longer consuming - assert_ok!(System::dec_providers(&account_id(2))); - assert_eq!(System::providers(&account_id(2)), 0); - // account deleted - assert_eq!(System::account_nonce(account_id(2)), 0); // nonce zero - assert_eq!(Balances::total_balance(&account_id(2)), 0); - - // account 4 tries to take index 1 again for account 6. - assert_ok!(Balances::transfer_allow_death( - Some(account_id(4)).into(), - account_id(6), - 256 + 0x69 - )); - assert_eq!(Balances::total_balance(&account_id(6)), 256 + 0x69); - }); -} - -#[test] -fn reward_should_work() { - ExtBuilder::default().monied(true).build_and_execute_with(|| { - assert_eq!(Balances::total_balance(&account_id(1)), 10); - assert_ok!(Balances::deposit_into_existing(&account_id(1), 10).map(drop)); - assert_eq!( - events(), - [ - RuntimeEvent::Balances(crate::Event::Deposit { who: account_id(1), amount: 10 }), - RuntimeEvent::Balances(crate::Event::Issued { amount: 10 }), - ] - ); - assert_eq!(Balances::total_balance(&account_id(1)), 20); - assert_eq!(pallet_balances::TotalIssuance::::get(), 120); - }); -} - -#[test] -fn balance_works() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 42); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Deposit { - who: account_id(1), - amount: 42, - })); - assert_eq!(Balances::free_balance(account_id(1)), 42); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - assert_eq!(Balances::total_balance(&account_id(1)), 42); - assert_eq!(Balances::free_balance(account_id(2)), 0); - assert_eq!(Balances::reserved_balance(account_id(2)), 0); - assert_eq!(Balances::total_balance(&account_id(2)), 0); - }); -} - -#[test] -fn reserving_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - - assert_eq!(Balances::total_balance(&account_id(1)), 111); - assert_eq!(Balances::free_balance(account_id(1)), 111); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - - assert_ok!(Balances::reserve(&account_id(1), 69)); - - assert_eq!(Balances::total_balance(&account_id(1)), 111); - assert_eq!(Balances::free_balance(account_id(1)), 42); - assert_eq!(Balances::reserved_balance(account_id(1)), 69); - }); -} - -#[test] -fn deducting_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - assert_ok!(Balances::reserve(&account_id(1), 69)); - assert_eq!(Balances::free_balance(account_id(1)), 42); - }); -} - -#[test] -fn refunding_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 42); - System::set_block_number(2); - Balances::unreserve(&account_id(1), 69); - assert_eq!(Balances::free_balance(account_id(1)), 42); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - }); -} - -#[test] -fn slashing_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - assert_ok!(Balances::reserve(&account_id(1), 69)); - assert_eq!(Balances::slash_reserved(&account_id(1), 69).1, 0); - assert_eq!(Balances::free_balance(account_id(1)), 42); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - assert_eq!(pallet_balances::TotalIssuance::::get(), 42); - }); -} - -#[test] -fn withdrawing_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(2), 111); - let _ = Balances::withdraw( - &account_id(2), - 11, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive, - ); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Withdraw { - who: account_id(2), - amount: 11, - })); - assert_eq!(Balances::free_balance(account_id(2)), 100); - assert_eq!(pallet_balances::TotalIssuance::::get(), 100); - }); -} - -#[test] -fn withdrawing_balance_should_fail_when_not_expendable() { - ExtBuilder::default().build_and_execute_with(|| { - ExistentialDeposit::set(10); - let _ = Balances::deposit_creating(&account_id(2), 20); - assert_ok!(Balances::reserve(&account_id(2), 5)); - assert_noop!( - Balances::withdraw( - &account_id(2), - 6, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive - ), - Error::::Expendability, - ); - assert_ok!(Balances::withdraw( - &account_id(2), - 5, - WithdrawReasons::TRANSFER, - ExistenceRequirement::KeepAlive - ),); - }); -} - -#[test] -fn slashing_incomplete_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 42); - assert_ok!(Balances::reserve(&account_id(1), 21)); - assert_eq!(Balances::slash_reserved(&account_id(1), 69).1, 48); - assert_eq!(Balances::free_balance(account_id(1)), 21); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - assert_eq!(pallet_balances::TotalIssuance::::get(), 21); - }); -} - -#[test] -fn unreserving_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - assert_ok!(Balances::reserve(&account_id(1), 110)); - Balances::unreserve(&account_id(1), 41); - assert_eq!(Balances::reserved_balance(account_id(1)), 69); - assert_eq!(Balances::free_balance(account_id(1)), 42); - }); -} - -#[test] -fn slashing_reserved_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 112); - assert_ok!(Balances::reserve(&account_id(1), 111)); - assert_eq!(Balances::slash_reserved(&account_id(1), 42).1, 0); - assert_eq!(Balances::reserved_balance(account_id(1)), 69); - assert_eq!(Balances::free_balance(account_id(1)), 1); - assert_eq!(pallet_balances::TotalIssuance::::get(), 70); - }); -} - -#[test] -fn slashing_incomplete_reserved_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - assert_ok!(Balances::reserve(&account_id(1), 42)); - assert_eq!(Balances::slash_reserved(&account_id(1), 69).1, 27); - assert_eq!(Balances::free_balance(account_id(1)), 69); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - assert_eq!(pallet_balances::TotalIssuance::::get(), 69); - }); -} - -#[test] -fn repatriating_reserved_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - let _ = Balances::deposit_creating(&account_id(2), 1); - assert_ok!(Balances::reserve(&account_id(1), 110)); - assert_ok!(Balances::repatriate_reserved(&account_id(1), &account_id(2), 41, Free), 0); - System::assert_last_event(RuntimeEvent::Balances(crate::Event::ReserveRepatriated { - from: account_id(1), - to: account_id(2), - amount: 41, - destination_status: Free, - })); - assert_eq!(Balances::reserved_balance(account_id(1)), 69); - assert_eq!(Balances::free_balance(account_id(1)), 1); - assert_eq!(Balances::reserved_balance(account_id(2)), 0); - assert_eq!(Balances::free_balance(account_id(2)), 42); - }); -} - -#[test] -fn transferring_reserved_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - let _ = Balances::deposit_creating(&account_id(2), 1); - assert_ok!(Balances::reserve(&account_id(1), 110)); - assert_ok!(Balances::repatriate_reserved(&account_id(1), &account_id(2), 41, Reserved), 0); - assert_eq!(Balances::reserved_balance(account_id(1)), 69); - assert_eq!(Balances::free_balance(account_id(1)), 1); - assert_eq!(Balances::reserved_balance(account_id(2)), 41); - assert_eq!(Balances::free_balance(account_id(2)), 1); - }); -} - -#[test] -fn transferring_reserved_balance_to_yourself_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 110); - assert_ok!(Balances::reserve(&account_id(1), 50)); - assert_ok!(Balances::repatriate_reserved(&account_id(1), &account_id(1), 50, Free), 0); - assert_eq!(Balances::free_balance(account_id(1)), 110); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - - assert_ok!(Balances::reserve(&account_id(1), 50)); - assert_ok!(Balances::repatriate_reserved(&account_id(1), &account_id(1), 60, Free), 10); - assert_eq!(Balances::free_balance(account_id(1)), 110); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - }); -} - -#[test] -fn transferring_reserved_balance_to_nonexistent_should_fail() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - assert_ok!(Balances::reserve(&account_id(1), 110)); - assert_noop!( - Balances::repatriate_reserved(&account_id(1), &account_id(2), 42, Free), - Error::::DeadAccount - ); - }); -} - -#[test] -fn transferring_incomplete_reserved_balance_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 110); - let _ = Balances::deposit_creating(&account_id(2), 1); - assert_ok!(Balances::reserve(&account_id(1), 41)); - assert_ok!(Balances::repatriate_reserved(&account_id(1), &account_id(2), 69, Free), 28); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - assert_eq!(Balances::free_balance(account_id(1)), 69); - assert_eq!(Balances::reserved_balance(account_id(2)), 0); - assert_eq!(Balances::free_balance(account_id(2)), 42); - }); -} - -#[test] -fn transferring_too_high_value_should_not_panic() { - ExtBuilder::default().build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), Balance::MAX); - Balances::make_free_balance_be(&account_id(2), 1); - - assert_err!( - >::transfer( - &account_id(1), - &account_id(2), - Balance::MAX, - AllowDeath - ), - ArithmeticError::Overflow, - ); - - assert_eq!(Balances::free_balance(account_id(1)), Balance::MAX); - assert_eq!(Balances::free_balance(account_id(2)), 1); - }); -} - -#[test] -fn account_create_on_free_too_low_with_other() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 100); - assert_eq!(pallet_balances::TotalIssuance::::get(), 100); - - // No-op. - let _ = Balances::deposit_creating(&account_id(2), 50); - assert_eq!(Balances::free_balance(account_id(2)), 0); - assert_eq!(pallet_balances::TotalIssuance::::get(), 100); - }) -} - -#[test] -fn account_create_on_free_too_low() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - // No-op. - let _ = Balances::deposit_creating(&account_id(2), 50); - assert_eq!(Balances::free_balance(account_id(2)), 0); - assert_eq!(pallet_balances::TotalIssuance::::get(), 0); - }) -} - -#[test] -fn account_removal_on_free_too_low() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - assert_eq!(pallet_balances::TotalIssuance::::get(), 0); - - // Setup two accounts with free balance above the existential threshold. - let _ = Balances::deposit_creating(&account_id(1), 110); - let _ = Balances::deposit_creating(&account_id(2), 110); - - assert_eq!(Balances::free_balance(account_id(1)), 110); - assert_eq!(Balances::free_balance(account_id(2)), 110); - assert_eq!(pallet_balances::TotalIssuance::::get(), 220); - - // Transfer funds from account 1 of such amount that after this transfer - // the balance of account 1 will be below the existential threshold. - // This should lead to the removal of all balance of this account. - assert_ok!(Balances::transfer_allow_death(Some(account_id(1)).into(), account_id(2), 20)); - - // Verify free balance removal of account 1. - assert_eq!(Balances::free_balance(account_id(1)), 0); - assert_eq!(Balances::free_balance(account_id(2)), 130); - - // Verify that TotalIssuance tracks balance removal when free balance is too low. - assert_eq!(pallet_balances::TotalIssuance::::get(), 130); - }); -} - -#[test] -fn burn_must_work() { - ExtBuilder::default().monied(true).build_and_execute_with(|| { - let init_total_issuance = pallet_balances::TotalIssuance::::get(); - let imbalance = >::burn(10); - assert_eq!(pallet_balances::TotalIssuance::::get(), init_total_issuance - 10); - drop(imbalance); - assert_eq!(pallet_balances::TotalIssuance::::get(), init_total_issuance); - }); -} - -#[test] -#[should_panic = "the balance of any account should always be at least the existential deposit."] -fn cannot_set_genesis_value_below_ed() { - EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = 11); - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - crate::GenesisConfig:: { balances: vec![(account_id(1), 10)] } - .assimilate_storage(&mut t) - .unwrap(); -} - -#[test] -#[should_panic = "duplicate balances in genesis."] -fn cannot_set_genesis_value_twice() { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - crate::GenesisConfig:: { - balances: vec![(account_id(1), 10), (account_id(2), 20), (account_id(1), 15)], - } - .assimilate_storage(&mut t) - .unwrap(); -} - -#[test] -fn existential_deposit_respected_when_reserving() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - // Set balance to free and reserved at the existential deposit - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(1), 101)); - // Check balance - assert_eq!(Balances::free_balance(account_id(1)), 101); - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - - // Reserve some free balance - assert_ok!(Balances::reserve(&account_id(1), 1)); - // Check balance, the account should be ok. - assert_eq!(Balances::free_balance(account_id(1)), 100); - assert_eq!(Balances::reserved_balance(account_id(1)), 1); - - // Cannot reserve any more of the free balance. - assert_noop!(Balances::reserve(&account_id(1), 1), DispatchError::ConsumerRemaining); - }); -} - -#[test] -fn slash_fails_when_account_needed() { - ExtBuilder::default().existential_deposit(50).build_and_execute_with(|| { - // Set balance to free and reserved at the existential deposit - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(1), 52)); - assert_ok!(Balances::reserve(&account_id(1), 1)); - // Check balance - assert_eq!(Balances::free_balance(account_id(1)), 51); - assert_eq!(Balances::reserved_balance(account_id(1)), 1); - - // Slash a small amount - let res = Balances::slash(&account_id(1), 1); - assert_eq!(res, (NegativeImbalance::new(1), 0)); - - // The account should be dead. - assert_eq!(Balances::free_balance(account_id(1)), 50); - assert_eq!(Balances::reserved_balance(account_id(1)), 1); - - // Slashing again doesn't work since we require the ED - let res = Balances::slash(&account_id(1), 1); - assert_eq!(res, (NegativeImbalance::new(0), 1)); - - // The account should be dead. - assert_eq!(Balances::free_balance(account_id(1)), 50); - assert_eq!(Balances::reserved_balance(account_id(1)), 1); - }); -} - -#[test] -fn account_deleted_when_just_dust() { - ExtBuilder::default().existential_deposit(50).build_and_execute_with(|| { - // Set balance to free and reserved at the existential deposit - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(1), 50)); - // Check balance - assert_eq!(Balances::free_balance(account_id(1)), 50); - - // Slash a small amount - let res = Balances::slash(&account_id(1), 1); - assert_eq!(res, (NegativeImbalance::new(1), 0)); - - // The account should be dead. - assert_eq!(Balances::free_balance(account_id(1)), 0); - }); -} - -#[test] -fn emit_events_with_reserve_and_unreserve() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 100); - - System::set_block_number(2); - assert_ok!(Balances::reserve(&account_id(1), 10)); - - System::assert_last_event(RuntimeEvent::Balances(crate::Event::Reserved { - who: account_id(1), - amount: 10, - })); - - System::set_block_number(3); - assert!(Balances::unreserve(&account_id(1), 5).is_zero()); - - System::assert_last_event(RuntimeEvent::Balances(crate::Event::Unreserved { - who: account_id(1), - amount: 5, - })); - - System::set_block_number(4); - assert_eq!(Balances::unreserve(&account_id(1), 6), 1); - - // should only unreserve 5 - System::assert_last_event(RuntimeEvent::Balances(crate::Event::Unreserved { - who: account_id(1), - amount: 5, - })); - }); -} - -#[test] -fn emit_events_with_changing_locks() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 100); - System::reset_events(); - - // Locks = [] --> [10] - Balances::set_lock(*b"LOCK_000", &account_id(1), 10, WithdrawReasons::TRANSFER); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Locked { who: account_id(1), amount: 10 })] - ); - - // Locks = [10] --> [15] - Balances::set_lock(*b"LOCK_000", &account_id(1), 15, WithdrawReasons::TRANSFER); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Locked { who: account_id(1), amount: 5 })] - ); - - // Locks = [15] --> [15, 20] - Balances::set_lock(*b"LOCK_001", &account_id(1), 20, WithdrawReasons::TRANSACTION_PAYMENT); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Locked { who: account_id(1), amount: 5 })] - ); - - // Locks = [15, 20] --> [17, 20] - Balances::set_lock(*b"LOCK_000", &account_id(1), 17, WithdrawReasons::TRANSACTION_PAYMENT); - for event in events() { - match event { - RuntimeEvent::Balances(crate::Event::Locked { .. }) => { - assert!(false, "unexpected lock event") - }, - RuntimeEvent::Balances(crate::Event::Unlocked { .. }) => { - assert!(false, "unexpected unlock event") - }, - _ => continue, - } - } - - // Locks = [17, 20] --> [17, 15] - Balances::set_lock(*b"LOCK_001", &account_id(1), 15, WithdrawReasons::TRANSFER); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Unlocked { who: account_id(1), amount: 3 })] - ); - - // Locks = [17, 15] --> [15] - Balances::remove_lock(*b"LOCK_000", &account_id(1)); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Unlocked { who: account_id(1), amount: 2 })] - ); - - // Locks = [15] --> [] - Balances::remove_lock(*b"LOCK_001", &account_id(1)); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Unlocked { who: account_id(1), amount: 15 })] - ); - }); -} - -#[test] -fn emit_events_with_existential_deposit() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(1), 100)); - - assert_eq!( - events(), - [ - RuntimeEvent::System(system::Event::NewAccount { account: account_id(1) }), - RuntimeEvent::Balances(crate::Event::Endowed { - account: account_id(1), - free_balance: 100 - }), - RuntimeEvent::Balances(crate::Event::Issued { amount: 100 }), - RuntimeEvent::Balances(crate::Event::BalanceSet { who: account_id(1), free: 100 }), - ] - ); - - let res = Balances::slash(&account_id(1), 1); - assert_eq!(res, (NegativeImbalance::new(1), 0)); - - assert_eq!( - events(), - [ - RuntimeEvent::System(system::Event::KilledAccount { account: account_id(1) }), - RuntimeEvent::Balances(crate::Event::DustLost { - account: account_id(1), - amount: 99 - }), - RuntimeEvent::Balances(crate::Event::Slashed { who: account_id(1), amount: 1 }), - RuntimeEvent::Balances(crate::Event::Rescinded { amount: 1 }), - ] - ); - }); -} - -#[test] -fn emit_events_with_no_existential_deposit_suicide() { - ExtBuilder::default().existential_deposit(1).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 100); - - assert_eq!( - events(), - [ - RuntimeEvent::Balances(crate::Event::BalanceSet { who: account_id(1), free: 100 }), - RuntimeEvent::System(system::Event::NewAccount { account: account_id(1) }), - RuntimeEvent::Balances(crate::Event::Endowed { - account: account_id(1), - free_balance: 100 - }), - RuntimeEvent::Balances(crate::Event::Issued { amount: 100 }), - ] - ); - - let res = Balances::slash(&account_id(1), 100); - assert_eq!(res, (NegativeImbalance::new(100), 0)); - - assert_eq!( - events(), - [ - RuntimeEvent::System(system::Event::KilledAccount { account: account_id(1) }), - RuntimeEvent::Balances(crate::Event::Slashed { who: account_id(1), amount: 100 }), - RuntimeEvent::Balances(crate::Event::Rescinded { amount: 100 }), - ] - ); - }); -} - -#[test] -fn slash_over_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - // SCENARIO: Over-slash will kill account, and report missing slash amount. - Balances::make_free_balance_be(&account_id(1), 1_000); - // Slashed full free_balance, and reports 300 not slashed - assert_eq!(Balances::slash(&account_id(1), 1_300), (NegativeImbalance::new(1000), 300)); - // Account is dead - assert!(!System::account_exists(&account_id(1))); - }); -} - -#[test] -fn slash_full_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 1_000); - // Slashed completed in full - assert_eq!(Balances::slash(&account_id(1), 1_000), (NegativeImbalance::new(1000), 0)); - // Account is still alive - assert!(!System::account_exists(&account_id(1))); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Slashed { - who: account_id(1), - amount: 1000, - })); - }); -} - -#[test] -fn slash_partial_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 1_000); - // Slashed completed in full - assert_eq!(Balances::slash(&account_id(1), 900), (NegativeImbalance::new(900), 0)); - // Account is still alive - assert!(System::account_exists(&account_id(1))); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Slashed { - who: account_id(1), - amount: 900, - })); - }); -} - -#[test] -fn slash_dusting_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 1_000); - // Slashed completed in full - assert_eq!(Balances::slash(&account_id(1), 950), (NegativeImbalance::new(950), 0)); - assert!(!System::account_exists(&account_id(1))); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Slashed { - who: account_id(1), - amount: 950, - })); - }); -} - -#[test] -fn slash_does_not_take_from_reserve() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 1_000); - assert_ok!(Balances::reserve(&account_id(1), 100)); - // Slashed completed in full - assert_eq!(Balances::slash(&account_id(1), 900), (NegativeImbalance::new(800), 100)); - assert_eq!(Balances::reserved_balance(account_id(1)), 100); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Slashed { - who: account_id(1), - amount: 800, - })); - }); -} - -#[test] -fn slash_consumed_slash_full_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 1_000); - assert_ok!(System::inc_consumers(&account_id(1))); // <-- Reference counter added here is enough for all tests - // Slashed completed in full - assert_eq!(Balances::slash(&account_id(1), 900), (NegativeImbalance::new(900), 0)); - // Account is still alive - assert!(System::account_exists(&account_id(1))); - }); -} - -#[test] -fn slash_consumed_slash_over_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 1_000); - assert_ok!(System::inc_consumers(&account_id(1))); // <-- Reference counter added here is enough for all tests - // Slashed completed in full - assert_eq!(Balances::slash(&account_id(1), 1_000), (NegativeImbalance::new(900), 100)); - // Account is still alive - assert!(System::account_exists(&account_id(1))); - }); -} - -#[test] -fn slash_consumed_slash_partial_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 1_000); - assert_ok!(System::inc_consumers(&account_id(1))); // <-- Reference counter added here is enough for all tests - // Slashed completed in full - assert_eq!(Balances::slash(&account_id(1), 800), (NegativeImbalance::new(800), 0)); - // Account is still alive - assert!(System::account_exists(&account_id(1))); - }); -} - -#[test] -fn slash_on_non_existent_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - // Slash on non-existent account is okay. - assert_eq!(Balances::slash(&account_id(123), 1_300), (NegativeImbalance::new(0), 1300)); - }); -} - -#[test] -fn slash_reserved_slash_partial_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 1_000); - assert_ok!(Balances::reserve(&account_id(1), 900)); - // Slashed completed in full - assert_eq!(Balances::slash_reserved(&account_id(1), 800), (NegativeImbalance::new(800), 0)); - assert_eq!(System::consumers(&account_id(1)), 1); - assert_eq!(Balances::reserved_balance(account_id(1)), 100); - assert_eq!(Balances::free_balance(account_id(1)), 100); - }); -} - -#[test] -fn slash_reserved_slash_everything_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - Balances::make_free_balance_be(&account_id(1), 1_000); - assert_ok!(Balances::reserve(&account_id(1), 900)); - assert_eq!(System::consumers(&account_id(1)), 1); - // Slashed completed in full - assert_eq!(Balances::slash_reserved(&account_id(1), 900), (NegativeImbalance::new(900), 0)); - assert_eq!(System::consumers(&account_id(1)), 0); - // Account is still alive - assert!(System::account_exists(&account_id(1))); - }); -} - -#[test] -fn slash_reserved_overslash_does_not_touch_free_balance() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - // SCENARIO: Over-slash doesn't touch free balance. - Balances::make_free_balance_be(&account_id(1), 1_000); - assert_ok!(Balances::reserve(&account_id(1), 800)); - // Slashed done - assert_eq!( - Balances::slash_reserved(&account_id(1), 900), - (NegativeImbalance::new(800), 100) - ); - assert_eq!(Balances::free_balance(account_id(1)), 200); - }); -} - -#[test] -fn slash_reserved_on_non_existent_works() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - // Slash on non-existent account is okay. - assert_eq!( - Balances::slash_reserved(&account_id(123), 1_300), - (NegativeImbalance::new(0), 1300) - ); - }); -} - -#[test] -fn operations_on_dead_account_should_not_change_state() { - // These functions all use `mutate_account` which may introduce a storage change when - // the account never existed to begin with, and shouldn't exist in the end. - ExtBuilder::default().existential_deposit(1).build_and_execute_with(|| { - assert!(!frame_system::Account::::contains_key(account_id(137))); - - // Unreserve - assert_storage_noop!(assert_eq!(Balances::unreserve(&account_id(137), 42), 42)); - // Reserve - assert_noop!( - Balances::reserve(&account_id(137), 42), - Error::::InsufficientBalance - ); - // Slash Reserve - assert_storage_noop!(assert_eq!(Balances::slash_reserved(&account_id(137), 42).1, 42)); - // Repatriate Reserve - assert_noop!( - Balances::repatriate_reserved(&account_id(137), &account_id(138), 42, Free), - Error::::DeadAccount - ); - // Slash - assert_storage_noop!(assert_eq!(Balances::slash(&account_id(137), 42).1, 42)); - }); -} - -#[test] -#[should_panic = "The existential deposit must be greater than zero!"] -fn zero_ed_is_prohibited() { - // These functions all use `mutate_account` which may introduce a storage change when - // the account never existed to begin with, and shouldn't exist in the end. - ExtBuilder::default().existential_deposit(0).build_and_execute_with(|| { - Balances::integrity_test(); - }); -} - -#[test] -fn named_reserve_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - - let id_1 = TestId::Foo; - let id_2 = TestId::Bar; - let id_3 = TestId::Baz; - - // reserve - - assert_noop!( - Balances::reserve_named(&id_1, &account_id(1), 112), - Error::::InsufficientBalance - ); - - assert_ok!(Balances::reserve_named(&id_1, &account_id(1), 12)); - - assert_eq!(Balances::reserved_balance(account_id(1)), 12); - assert_eq!(Balances::reserved_balance_named(&id_1, &account_id(1)), 12); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 0); - - assert_ok!(Balances::reserve_named(&id_1, &account_id(1), 2)); - - assert_eq!(Balances::reserved_balance(account_id(1)), 14); - assert_eq!(Balances::reserved_balance_named(&id_1, &account_id(1)), 14); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 0); - - assert_ok!(Balances::reserve_named(&id_2, &account_id(1), 23)); - - assert_eq!(Balances::reserved_balance(account_id(1)), 37); - assert_eq!(Balances::reserved_balance_named(&id_1, &account_id(1)), 14); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 23); - - assert_ok!(Balances::reserve(&account_id(1), 34)); - - assert_eq!(Balances::reserved_balance(account_id(1)), 71); - assert_eq!(Balances::reserved_balance_named(&id_1, &account_id(1)), 14); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 23); - - assert_eq!(Balances::total_balance(&account_id(1)), 111); - assert_eq!(Balances::free_balance(account_id(1)), 40); - - assert_noop!( - Balances::reserve_named(&id_3, &account_id(1), 2), - Error::::TooManyReserves - ); - - // unreserve - - assert_eq!(Balances::unreserve_named(&id_1, &account_id(1), 10), 0); - - assert_eq!(Balances::reserved_balance(account_id(1)), 61); - assert_eq!(Balances::reserved_balance_named(&id_1, &account_id(1)), 4); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 23); - - assert_eq!(Balances::unreserve_named(&id_1, &account_id(1), 5), 1); - - assert_eq!(Balances::reserved_balance(account_id(1)), 57); - assert_eq!(Balances::reserved_balance_named(&id_1, &account_id(1)), 0); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 23); - - assert_eq!(Balances::unreserve_named(&id_2, &account_id(1), 3), 0); - - assert_eq!(Balances::reserved_balance(account_id(1)), 54); - assert_eq!(Balances::reserved_balance_named(&id_1, &account_id(1)), 0); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 20); - - assert_eq!(Balances::total_balance(&account_id(1)), 111); - assert_eq!(Balances::free_balance(account_id(1)), 57); - - // slash_reserved_named - - assert_ok!(Balances::reserve_named(&id_1, &account_id(1), 10)); - - assert_eq!(Balances::slash_reserved_named(&id_1, &account_id(1), 25).1, 15); - - assert_eq!(Balances::reserved_balance(account_id(1)), 54); - assert_eq!(Balances::reserved_balance_named(&id_1, &account_id(1)), 0); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 20); - assert_eq!(Balances::total_balance(&account_id(1)), 101); - - assert_eq!(Balances::slash_reserved_named(&id_2, &account_id(1), 5).1, 0); - - assert_eq!(Balances::reserved_balance(account_id(1)), 49); - assert_eq!(Balances::reserved_balance_named(&id_1, &account_id(1)), 0); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 15); - assert_eq!(Balances::total_balance(&account_id(1)), 96); - - // repatriate_reserved_named - - let _ = Balances::deposit_creating(&account_id(2), 100); - - assert_eq!( - Balances::repatriate_reserved_named( - &id_2, - &account_id(1), - &account_id(2), - 10, - Reserved - ) - .unwrap(), - 0 - ); - - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 5); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(2)), 10); - assert_eq!(Balances::reserved_balance(account_id(2)), 10); - - assert_eq!( - Balances::repatriate_reserved_named( - &id_2, - &account_id(2), - &account_id(1), - 11, - Reserved - ) - .unwrap(), - 1 - ); - - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 15); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(2)), 0); - assert_eq!(Balances::reserved_balance(account_id(2)), 0); - - assert_eq!( - Balances::repatriate_reserved_named(&id_2, &account_id(1), &account_id(2), 10, Free) - .unwrap(), - 0 - ); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 5); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(2)), 0); - assert_eq!(Balances::free_balance(account_id(2)), 110); - - // repatriate_reserved_named to self - - assert_eq!( - Balances::repatriate_reserved_named( - &id_2, - &account_id(1), - &account_id(1), - 10, - Reserved - ) - .unwrap(), - 5 - ); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 5); - - assert_eq!(Balances::free_balance(account_id(1)), 47); - - assert_eq!( - Balances::repatriate_reserved_named(&id_2, &account_id(1), &account_id(1), 15, Free) - .unwrap(), - 10 - ); - assert_eq!(Balances::reserved_balance_named(&id_2, &account_id(1)), 0); - - assert_eq!(Balances::free_balance(account_id(1)), 52); - }); -} - -#[test] -fn reserve_must_succeed_if_can_reserve_does() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 1); - let _ = Balances::deposit_creating(&account_id(2), 2); - assert!( - Balances::can_reserve(&account_id(1), 1) == - Balances::reserve(&account_id(1), 1).is_ok() - ); - assert!( - Balances::can_reserve(&account_id(2), 1) == - Balances::reserve(&account_id(2), 1).is_ok() - ); - }); -} - -#[test] -fn reserved_named_to_yourself_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 110); - - let id = TestId::Foo; - - assert_ok!(Balances::reserve_named(&id, &account_id(1), 50)); - assert_ok!( - Balances::repatriate_reserved_named(&id, &account_id(1), &account_id(1), 50, Free), - 0 - ); - assert_eq!(Balances::free_balance(account_id(1)), 110); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(1)), 0); - - assert_ok!(Balances::reserve_named(&id, &account_id(1), 50)); - assert_ok!( - Balances::repatriate_reserved_named(&id, &account_id(1), &account_id(1), 60, Free), - 10 - ); - assert_eq!(Balances::free_balance(account_id(1)), 110); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(1)), 0); - }); -} - -#[test] -fn ensure_reserved_named_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - - let id = TestId::Foo; - - assert_ok!(Balances::ensure_reserved_named(&id, &account_id(1), 15)); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(1)), 15); - - assert_ok!(Balances::ensure_reserved_named(&id, &account_id(1), 10)); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(1)), 10); - - assert_ok!(Balances::ensure_reserved_named(&id, &account_id(1), 20)); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(1)), 20); - }); -} - -#[test] -fn unreserve_all_named_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - - let id = TestId::Foo; - - assert_ok!(Balances::reserve_named(&id, &account_id(1), 15)); - - assert_eq!(Balances::unreserve_all_named(&id, &account_id(1)), 15); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(1)), 0); - assert_eq!(Balances::free_balance(account_id(1)), 111); - - assert_eq!(Balances::unreserve_all_named(&id, &account_id(1)), 0); - }); -} - -#[test] -fn slash_all_reserved_named_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - - let id = TestId::Foo; - - assert_ok!(Balances::reserve_named(&id, &account_id(1), 15)); - - assert_eq!(Balances::slash_all_reserved_named(&id, &account_id(1)).peek(), 15); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(1)), 0); - assert_eq!(Balances::free_balance(account_id(1)), 96); - - assert_eq!(Balances::slash_all_reserved_named(&id, &account_id(1)).peek(), 0); - }); -} - -#[test] -fn repatriate_all_reserved_named_should_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::deposit_creating(&account_id(1), 111); - let _ = Balances::deposit_creating(&account_id(2), 10); - let _ = Balances::deposit_creating(&account_id(3), 10); - - let id = TestId::Foo; - - assert_ok!(Balances::reserve_named(&id, &account_id(1), 15)); - - assert_ok!(Balances::repatriate_all_reserved_named( - &id, - &account_id(1), - &account_id(2), - Reserved - )); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(1)), 0); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(2)), 15); - - assert_ok!(Balances::repatriate_all_reserved_named( - &id, - &account_id(2), - &account_id(3), - Free - )); - assert_eq!(Balances::reserved_balance_named(&id, &account_id(2)), 0); - assert_eq!(Balances::free_balance(account_id(3)), 25); - }); -} - -#[test] -fn freezing_and_locking_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Consumer is shared between freezing and locking. - assert_eq!(System::consumers(&account_id(1)), 0); - assert_ok!(>::set_freeze( - &TestId::Foo, - &account_id(1), - 4 - )); - assert_eq!(System::consumers(&account_id(1)), 1); - Balances::set_lock(ID_1, &account_id(1), 5, WithdrawReasons::all()); - assert_eq!(System::consumers(&account_id(1)), 1); - - // Frozen and locked balances update correctly. - assert_eq!(Balances::account(&account_id(1)).frozen, 5); - assert_ok!(>::set_freeze( - &TestId::Foo, - &account_id(1), - 6 - )); - assert_eq!(Balances::account(&account_id(1)).frozen, 6); - assert_ok!(>::set_freeze( - &TestId::Foo, - &account_id(1), - 4 - )); - assert_eq!(Balances::account(&account_id(1)).frozen, 5); - Balances::set_lock(ID_1, &account_id(1), 3, WithdrawReasons::all()); - assert_eq!(Balances::account(&account_id(1)).frozen, 4); - Balances::set_lock(ID_1, &account_id(1), 5, WithdrawReasons::all()); - assert_eq!(Balances::account(&account_id(1)).frozen, 5); - - // Locks update correctly. - Balances::remove_lock(ID_1, &account_id(1)); - assert_eq!(Balances::account(&account_id(1)).frozen, 4); - assert_ok!(>::thaw(&TestId::Foo, &account_id(1))); - assert_eq!(Balances::account(&account_id(1)).frozen, 0); - assert_eq!(System::consumers(&account_id(1)), 0); - }); -} - -#[test] -fn self_transfer_noop() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - assert_eq!(pallet_balances::TotalIssuance::::get(), 0); - let _ = Balances::deposit_creating(&account_id(1), 100); - - // The account is set up properly: - assert_eq!( - events(), - [ - Event::Deposit { who: account_id(1), amount: 100 }.into(), - SysEvent::NewAccount { account: account_id(1) }.into(), - Event::Endowed { account: account_id(1), free_balance: 100 }.into(), - Event::Issued { amount: 100 }.into(), - ] - ); - assert_eq!(Balances::free_balance(account_id(1)), 100); - assert_eq!(pallet_balances::TotalIssuance::::get(), 100); - - // Transfers to self are No-OPs: - let _g = StorageNoopGuard::new(); - for i in 0..200 { - let r = Balances::transfer_allow_death(Some(account_id(1)).into(), account_id(1), i); - - if i <= 100 { - assert_ok!(r); - } else { - assert!(r.is_err()); - } - - assert!(events().is_empty()); - assert_eq!( - Balances::free_balance(account_id(1)), - 100, - "Balance unchanged by self transfer" - ); - assert_eq!( - pallet_balances::TotalIssuance::::get(), - 100, - "TI unchanged by self transfers" - ); - } - }); -} diff --git a/pallets/balances/src/tests/dispatchable_tests.rs b/pallets/balances/src/tests/dispatchable_tests.rs deleted file mode 100644 index 94991c96..00000000 --- a/pallets/balances/src/tests/dispatchable_tests.rs +++ /dev/null @@ -1,410 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Tests regarding the functionality of the dispatchables/extrinsics. - -use super::*; -use crate::{ - AdjustmentDirection::{Decrease as Dec, Increase as Inc}, - Event, -}; -use frame_support::traits::{fungible::Unbalanced, tokens::Preservation::Expendable}; -use fungible::{hold::Mutate as HoldMutate, Inspect, Mutate}; - -/// Alice account ID for more readable tests. -fn alice() -> AccountId { - account_id(1) -} - -#[test] -fn default_indexing_on_new_accounts_should_not_work2() { - ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .build_and_execute_with(|| { - // account 5 should not exist - // ext_deposit is 10, value is 9, not satisfies for ext_deposit - assert_noop!( - Balances::transfer_allow_death(Some(account_id(1)).into(), account_id(5), 9), - TokenError::BelowMinimum, - ); - assert_eq!(Balances::free_balance(account_id(1)), 100); - }); -} - -#[test] -fn dust_account_removal_should_work() { - ExtBuilder::default() - .existential_deposit(100) - .monied(true) - .build_and_execute_with(|| { - System::inc_account_nonce(account_id(2)); - assert_eq!(System::account_nonce(account_id(2)), 1); - assert_eq!(Balances::total_balance(&account_id(2)), 2000); - // index 1 (account 2) becomes zombie - assert_ok!(Balances::transfer_allow_death( - Some(account_id(2)).into(), - account_id(5), - 1901 - )); - assert_eq!(Balances::total_balance(&account_id(2)), 0); - assert_eq!(Balances::total_balance(&account_id(5)), 1901); - assert_eq!(System::account_nonce(account_id(2)), 0); - }); -} - -#[test] -fn balance_transfer_works() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::mint_into(&account_id(1), 111); - assert_ok!(Balances::transfer_allow_death(Some(account_id(1)).into(), account_id(2), 69)); - assert_eq!(Balances::total_balance(&account_id(1)), 42); - assert_eq!(Balances::total_balance(&account_id(2)), 69); - }); -} - -#[test] -fn force_transfer_works() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::mint_into(&account_id(1), 111); - assert_noop!( - Balances::force_transfer(Some(account_id(2)).into(), account_id(1), account_id(2), 69), - BadOrigin, - ); - assert_ok!(Balances::force_transfer( - RawOrigin::Root.into(), - account_id(1), - account_id(2), - 69 - )); - assert_eq!(Balances::total_balance(&account_id(1)), 42); - assert_eq!(Balances::total_balance(&account_id(2)), 69); - }); -} - -#[test] -fn balance_transfer_when_on_hold_should_not_work() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::mint_into(&account_id(1), 111); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(1), 69)); - assert_noop!( - Balances::transfer_allow_death(Some(account_id(1)).into(), account_id(2), 69), - TokenError::FundsUnavailable, - ); - }); -} - -#[test] -fn transfer_keep_alive_works() { - ExtBuilder::default().existential_deposit(1).build_and_execute_with(|| { - let _ = Balances::mint_into(&account_id(1), 100); - assert_noop!( - Balances::transfer_keep_alive(Some(account_id(1)).into(), account_id(2), 100), - TokenError::NotExpendable - ); - assert_eq!(Balances::total_balance(&account_id(1)), 100); - assert_eq!(Balances::total_balance(&account_id(2)), 0); - }); -} - -#[test] -fn transfer_keep_alive_all_free_succeed() { - ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| { - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(1), 300)); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(1), 100)); - assert_ok!(Balances::transfer_keep_alive(Some(account_id(1)).into(), account_id(2), 100)); - assert_eq!(Balances::total_balance(&account_id(1)), 200); - assert_eq!(Balances::total_balance(&account_id(2)), 100); - }); -} - -#[test] -fn transfer_all_works_1() { - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - // setup - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(1), 200)); - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(2), 0)); - // transfer all and allow death - assert_ok!(Balances::transfer_all(Some(account_id(1)).into(), account_id(2), false)); - assert_eq!(Balances::total_balance(&account_id(1)), 0); - assert_eq!(Balances::total_balance(&account_id(2)), 200); - }); -} - -#[test] -fn transfer_all_works_2() { - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - // setup - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(1), 200)); - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(2), 0)); - // transfer all and keep alive - assert_ok!(Balances::transfer_all(Some(account_id(1)).into(), account_id(2), true)); - assert_eq!(Balances::total_balance(&account_id(1)), 100); - assert_eq!(Balances::total_balance(&account_id(2)), 100); - }); -} - -#[test] -fn transfer_all_works_3() { - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - // setup - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(1), 210)); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(1), 10)); - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(2), 0)); - // transfer all and allow death w/ reserved - assert_ok!(Balances::transfer_all(Some(account_id(1)).into(), account_id(2), false)); - assert_eq!(Balances::total_balance(&account_id(1)), 110); - assert_eq!(Balances::total_balance(&account_id(2)), 100); - }); -} - -#[test] -fn transfer_all_works_4() { - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - // setup - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(1), 210)); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(1), 10)); - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(2), 0)); - // transfer all and keep alive w/ reserved - assert_ok!(Balances::transfer_all(Some(account_id(1)).into(), account_id(2), true)); - assert_eq!(Balances::total_balance(&account_id(1)), 110); - assert_eq!(Balances::total_balance(&account_id(2)), 100); - }); -} - -#[test] -fn set_balance_handles_killing_account() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::mint_into(&account_id(1), 111); - assert_ok!(frame_system::Pallet::::inc_consumers(&account_id(1))); - assert_noop!( - Balances::force_set_balance(RuntimeOrigin::root(), account_id(1), 0), - DispatchError::ConsumerRemaining, - ); - }); -} - -#[test] -fn set_balance_handles_total_issuance() { - ExtBuilder::default().build_and_execute_with(|| { - let old_total_issuance = pallet_balances::TotalIssuance::::get(); - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(137), 69)); - assert_eq!(pallet_balances::TotalIssuance::::get(), old_total_issuance + 69); - assert_eq!(Balances::total_balance(&account_id(137)), 69); - assert_eq!(Balances::free_balance(account_id(137)), 69); - }); -} - -#[test] -fn upgrade_accounts_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - System::inc_providers(&account_id(7)); - assert_ok!(::AccountStore::try_mutate_exists( - &account_id(7), - |a| -> DispatchResult { - *a = Some(AccountData { - free: 5, - reserved: 5, - frozen: Zero::zero(), - flags: crate::types::ExtraFlags::old_logic(), - }); - Ok(()) - } - )); - assert!(!Balances::account(&account_id(7)).flags.is_new_logic()); - assert_eq!(System::providers(&account_id(7)), 1); - assert_eq!(System::consumers(&account_id(7)), 0); - assert_ok!(Balances::upgrade_accounts(Some(account_id(1)).into(), vec![account_id(7)])); - assert!(Balances::account(&account_id(7)).flags.is_new_logic()); - assert_eq!(System::providers(&account_id(7)), 1); - assert_eq!(System::consumers(&account_id(7)), 1); - - >::unreserve( - &account_id(7), - 5, - ); - assert_ok!(>::transfer( - &account_id(7), - &account_id(1), - 10, - Expendable - )); - assert_eq!(Balances::total_balance(&account_id(7)), 0); - assert_eq!(System::providers(&account_id(7)), 0); - assert_eq!(System::consumers(&account_id(7)), 0); - }); -} - -#[test] -#[docify::export] -fn force_adjust_total_issuance_example() { - ExtBuilder::default().build_and_execute_with(|| { - // First we set the TotalIssuance to 64 by giving Alice a balance of 64. - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), alice(), 64)); - let old_ti = pallet_balances::TotalIssuance::::get(); - assert_eq!(old_ti, 64, "TI should be 64"); - - // Now test the increase: - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Inc, 32)); - let new_ti = pallet_balances::TotalIssuance::::get(); - assert_eq!(old_ti + 32, new_ti, "Should increase by 32"); - - // If Alice tries to call it, it errors: - assert_noop!( - Balances::force_adjust_total_issuance(RawOrigin::Signed(alice()).into(), Inc, 69), - BadOrigin, - ); - }); -} - -#[test] -fn force_adjust_total_issuance_works() { - ExtBuilder::default().build_and_execute_with(|| { - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(137), 64)); - let ti = pallet_balances::TotalIssuance::::get(); - - // Increase works: - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Inc, 32)); - assert_eq!(pallet_balances::TotalIssuance::::get(), ti + 32); - System::assert_last_event(RuntimeEvent::Balances(Event::TotalIssuanceForced { - old: 64, - new: 96, - })); - - // Decrease works: - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Dec, 64)); - assert_eq!(pallet_balances::TotalIssuance::::get(), ti - 32); - System::assert_last_event(RuntimeEvent::Balances(Event::TotalIssuanceForced { - old: 96, - new: 32, - })); - }); -} - -#[test] -fn force_adjust_total_issuance_saturates() { - ExtBuilder::default().build_and_execute_with(|| { - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(137), 64)); - let ti = pallet_balances::TotalIssuance::::get(); - let max = ::Balance::max_value(); - assert_eq!(ti, 64); - - // Increment saturates: - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Inc, max)); - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Inc, 123)); - assert_eq!(pallet_balances::TotalIssuance::::get(), max); - - // Decrement saturates: - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Dec, max)); - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Dec, 123)); - assert_eq!(pallet_balances::TotalIssuance::::get(), 0); - }); -} - -#[test] -fn force_adjust_total_issuance_rejects_zero_delta() { - ExtBuilder::default().build_and_execute_with(|| { - assert_noop!( - Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Inc, 0), - Error::::DeltaZero, - ); - assert_noop!( - Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Dec, 0), - Error::::DeltaZero, - ); - }); -} - -#[test] -fn force_adjust_total_issuance_rejects_more_than_inactive() { - ExtBuilder::default().build_and_execute_with(|| { - assert_ok!(Balances::force_set_balance(RuntimeOrigin::root(), account_id(137), 64)); - Balances::deactivate(16u32.into()); - - assert_eq!(pallet_balances::TotalIssuance::::get(), 64); - assert_eq!(Balances::active_issuance(), 48); - - // Works with up to 48: - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Dec, 40),); - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Dec, 8),); - assert_eq!(pallet_balances::TotalIssuance::::get(), 16); - assert_eq!(Balances::active_issuance(), 0); - // Errors with more than 48: - assert_noop!( - Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Dec, 1), - Error::::IssuanceDeactivated, - ); - // Increasing again increases the inactive issuance: - assert_ok!(Balances::force_adjust_total_issuance(RawOrigin::Root.into(), Inc, 10),); - assert_eq!(pallet_balances::TotalIssuance::::get(), 26); - assert_eq!(Balances::active_issuance(), 10); - }); -} - -#[test] -fn burn_works() { - ExtBuilder::default().build().execute_with(|| { - // Prepare account with initial balance - let (account, init_balance) = (account_id(1), 37); - assert_ok!(Balances::force_set_balance( - RuntimeOrigin::root(), - account.clone(), - init_balance - )); - let init_issuance = pallet_balances::TotalIssuance::::get(); - let (keep_alive, allow_death) = (true, false); - - // 1. Cannot burn more than what's available - assert_noop!( - Balances::burn(Some(account.clone()).into(), init_balance + 1, allow_death), - TokenError::FundsUnavailable, - ); - - // 2. Burn some funds, without reaping the account - let burn_amount_1 = 1; - assert_ok!(Balances::burn(Some(account.clone()).into(), burn_amount_1, allow_death)); - System::assert_last_event(RuntimeEvent::Balances(Event::Burned { - who: account.clone(), - amount: burn_amount_1, - })); - assert_eq!(pallet_balances::TotalIssuance::::get(), init_issuance - burn_amount_1); - assert_eq!(Balances::total_balance(&account), init_balance - burn_amount_1); - - // 3. Cannot burn funds below existential deposit if `keep_alive` is `true` - let burn_amount_2 = - init_balance - burn_amount_1 - ::ExistentialDeposit::get() + 1; - assert_noop!( - Balances::burn(Some(account.clone()).into(), init_balance + 1, keep_alive), - TokenError::FundsUnavailable, - ); - - // 4. Burn some more funds, this time reaping the account - assert_ok!(Balances::burn(Some(account.clone()).into(), burn_amount_2, allow_death)); - System::assert_last_event(RuntimeEvent::Balances(Event::Burned { - who: account.clone(), - amount: burn_amount_2, - })); - assert_eq!( - pallet_balances::TotalIssuance::::get(), - init_issuance - burn_amount_1 - burn_amount_2 - ); - assert!(Balances::total_balance(&account).is_zero()); - }); -} diff --git a/pallets/balances/src/tests/fungible_conformance_tests.rs b/pallets/balances/src/tests/fungible_conformance_tests.rs deleted file mode 100644 index 5c0c19a5..00000000 --- a/pallets/balances/src/tests/fungible_conformance_tests.rs +++ /dev/null @@ -1,141 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use super::*; -use frame_support::traits::fungible::{conformance_tests, Inspect, Mutate}; -use paste::paste; - -macro_rules! generate_tests { - // Handle a conformance test that requires special testing with and without a dust trap. - (dust_trap_variation, $base_path:path, $scope:expr, $trait:ident, $ext_deposit:expr, $($test_name:ident),*) => { - $( - paste! { - #[test] - fn [<$trait _ $scope _ $test_name _existential_deposit_ $ext_deposit _dust_trap_on >]() { - // Some random trap account. - let trap_account = ::AccountId::from(65174286u64); - let builder = ExtBuilder::default().existential_deposit($ext_deposit).dust_trap(trap_account); - builder.build_and_execute_with(|| { - Balances::set_balance(&trap_account, Balances::minimum_balance()); - $base_path::$scope::$trait::$test_name::< - Balances, - ::AccountId, - >(Some(trap_account)); - }); - } - - #[test] - fn [< $trait _ $scope _ $test_name _existential_deposit_ $ext_deposit _dust_trap_off >]() { - let builder = ExtBuilder::default().existential_deposit($ext_deposit); - builder.build_and_execute_with(|| { - $base_path::$scope::$trait::$test_name::< - Balances, - ::AccountId, - >(None); - }); - } - } - )* - }; - // Regular conformance test - ($base_path:path, $scope:expr, $trait:ident, $ext_deposit:expr, $($test_name:ident),*) => { - $( - paste! { - #[test] - fn [< $trait _ $scope _ $test_name _existential_deposit_ $ext_deposit>]() { - let builder = ExtBuilder::default().existential_deposit($ext_deposit); - builder.build_and_execute_with(|| { - $base_path::$scope::$trait::$test_name::< - Balances, - ::AccountId, - >(); - }); - } - } - )* - }; - ($base_path:path, $ext_deposit:expr) => { - // regular::mutate - generate_tests!( - dust_trap_variation, - $base_path, - regular, - mutate, - $ext_deposit, - transfer_expendable_dust - ); - generate_tests!( - $base_path, - regular, - mutate, - $ext_deposit, - mint_into_success, - mint_into_overflow, - mint_into_below_minimum, - burn_from_exact_success, - burn_from_best_effort_success, - burn_from_exact_insufficient_funds, - restore_success, - restore_overflow, - restore_below_minimum, - shelve_success, - shelve_insufficient_funds, - transfer_success, - transfer_expendable_all, - transfer_protect_preserve, - set_balance_mint_success, - set_balance_burn_success, - can_deposit_success, - can_deposit_below_minimum, - can_deposit_overflow, - can_withdraw_success, - can_withdraw_reduced_to_zero, - can_withdraw_balance_low, - reducible_balance_expendable, - reducible_balance_protect_preserve - ); - // regular::unbalanced - generate_tests!( - $base_path, - regular, - unbalanced, - $ext_deposit, - write_balance, - decrease_balance_expendable, - decrease_balance_preserve, - increase_balance, - set_total_issuance, - deactivate_and_reactivate - ); - // regular::balanced - generate_tests!( - $base_path, - regular, - balanced, - $ext_deposit, - issue_and_resolve_credit, - rescind_and_settle_debt, - deposit, - withdraw, - pair - ); - }; -} - -generate_tests!(conformance_tests, 1); -generate_tests!(conformance_tests, 5); -generate_tests!(conformance_tests, 1000); diff --git a/pallets/balances/src/tests/fungible_tests.rs b/pallets/balances/src/tests/fungible_tests.rs deleted file mode 100644 index 4840258e..00000000 --- a/pallets/balances/src/tests/fungible_tests.rs +++ /dev/null @@ -1,883 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Tests regarding the functionality of the `fungible` trait set implementations. - -use super::*; -use frame_support::traits::{ - tokens::{ - Fortitude::{Force, Polite}, - Precision::{BestEffort, Exact}, - Preservation::{Expendable, Preserve, Protect}, - Restriction::Free, - }, - Consideration, Footprint, LinearStoragePrice, MaybeConsideration, -}; -use fungible::{ - FreezeConsideration, HoldConsideration, Inspect, InspectFreeze, InspectHold, - LoneFreezeConsideration, LoneHoldConsideration, Mutate, MutateFreeze, MutateHold, Unbalanced, -}; -use sp_core::ConstU128; - -#[test] -fn inspect_trait_reducible_balance_basic_works() { - ExtBuilder::default().existential_deposit(10).build_and_execute_with(|| { - Balances::set_balance(&account_id(1), 100); - assert_eq!(Balances::reducible_balance(&account_id(1), Expendable, Polite), 100); - assert_eq!(Balances::reducible_balance(&account_id(1), Protect, Polite), 90); - assert_eq!(Balances::reducible_balance(&account_id(1), Preserve, Polite), 90); - assert_eq!(Balances::reducible_balance(&account_id(1), Expendable, Force), 100); - assert_eq!(Balances::reducible_balance(&account_id(1), Protect, Force), 90); - assert_eq!(Balances::reducible_balance(&account_id(1), Preserve, Force), 90); - }); -} - -#[test] -fn inspect_trait_reducible_balance_other_provide_works() { - ExtBuilder::default().existential_deposit(10).build_and_execute_with(|| { - Balances::set_balance(&account_id(1), 100); - System::inc_providers(&account_id(1)); - assert_eq!(Balances::reducible_balance(&account_id(1), Expendable, Polite), 100); - assert_eq!(Balances::reducible_balance(&account_id(1), Protect, Polite), 100); - assert_eq!(Balances::reducible_balance(&account_id(1), Preserve, Polite), 90); - assert_eq!(Balances::reducible_balance(&account_id(1), Expendable, Force), 100); - assert_eq!(Balances::reducible_balance(&account_id(1), Protect, Force), 100); - assert_eq!(Balances::reducible_balance(&account_id(1), Preserve, Force), 90); - }); -} - -#[test] -fn inspect_trait_reducible_balance_frozen_works() { - ExtBuilder::default().existential_deposit(10).build_and_execute_with(|| { - Balances::set_balance(&account_id(1), 100); - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 50)); - assert_eq!(Balances::reducible_balance(&account_id(1), Expendable, Polite), 50); - assert_eq!(Balances::reducible_balance(&account_id(1), Protect, Polite), 50); - assert_eq!(Balances::reducible_balance(&account_id(1), Preserve, Polite), 50); - assert_eq!(Balances::reducible_balance(&account_id(1), Expendable, Force), 90); - assert_eq!(Balances::reducible_balance(&account_id(1), Protect, Force), 90); - assert_eq!(Balances::reducible_balance(&account_id(1), Preserve, Force), 90); - }); -} - -#[test] -fn unbalanced_trait_set_balance_works() { - ExtBuilder::default().build_and_execute_with(|| { - assert_eq!(>::balance(&account_id(137)), 0); - assert_ok!(Balances::write_balance(&account_id(137), 100)); - assert_eq!(>::balance(&account_id(137)), 100); - - assert_ok!(>::hold(&TestId::Foo, &account_id(137), 60)); - assert_eq!(>::balance(&account_id(137)), 40); - assert_eq!( - >::total_balance_on_hold(&account_id(137)), - 60 - ); - assert_eq!( - >::balance_on_hold(&TestId::Foo, &account_id(137)), - 60 - ); - - assert_noop!( - Balances::write_balance(&account_id(137), 0), - Error::::InsufficientBalance - ); - - assert_ok!(Balances::write_balance(&account_id(137), 1)); - assert_eq!(>::balance(&account_id(137)), 1); - assert_eq!( - >::balance_on_hold(&TestId::Foo, &account_id(137)), - 60 - ); - - assert_ok!(>::release( - &TestId::Foo, - &account_id(137), - 60, - Exact - )); - assert_eq!( - >::balance_on_hold(&TestId::Foo, &account_id(137)), - 0 - ); - assert_eq!( - >::total_balance_on_hold(&account_id(137)), - 0 - ); - }); -} - -#[test] -fn unbalanced_trait_set_total_issuance_works() { - ExtBuilder::default().build_and_execute_with(|| { - assert_eq!(>::total_issuance(), 0); - Balances::set_total_issuance(100); - assert_eq!(>::total_issuance(), 100); - }); -} - -#[test] -fn unbalanced_trait_decrease_balance_simple_works() { - ExtBuilder::default().build_and_execute_with(|| { - // An Account that starts at 100 - assert_ok!(Balances::write_balance(&account_id(137), 100)); - assert_eq!(>::balance(&account_id(137)), 100); - // and reserves 50 - assert_ok!(>::hold(&TestId::Foo, &account_id(137), 50)); - assert_eq!(>::balance(&account_id(137)), 50); - // and is decreased by 20 - assert_ok!(Balances::decrease_balance(&account_id(137), 20, Exact, Expendable, Polite)); - assert_eq!(>::balance(&account_id(137)), 30); - }); -} - -#[test] -fn unbalanced_trait_decrease_balance_works_1() { - ExtBuilder::default().build_and_execute_with(|| { - assert_ok!(Balances::write_balance(&account_id(137), 100)); - assert_eq!(>::balance(&account_id(137)), 100); - - assert_noop!( - Balances::decrease_balance(&account_id(137), 101, Exact, Expendable, Polite), - TokenError::FundsUnavailable - ); - assert_eq!( - Balances::decrease_balance(&account_id(137), 100, Exact, Expendable, Polite), - Ok(100) - ); - assert_eq!(>::balance(&account_id(137)), 0); - }); -} - -#[test] -fn unbalanced_trait_decrease_balance_works_2() { - ExtBuilder::default().build_and_execute_with(|| { - // free: 40, reserved: 60 - assert_ok!(Balances::write_balance(&account_id(137), 100)); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(137), 60)); - assert_eq!(>::balance(&account_id(137)), 40); - assert_eq!(Balances::total_balance_on_hold(&account_id(137)), 60); - assert_noop!( - Balances::decrease_balance(&account_id(137), 40, Exact, Expendable, Polite), - TokenError::FundsUnavailable - ); - assert_eq!( - Balances::decrease_balance(&account_id(137), 39, Exact, Expendable, Polite), - Ok(39) - ); - assert_eq!(>::balance(&account_id(137)), 1); - assert_eq!(Balances::total_balance_on_hold(&account_id(137)), 60); - }); -} - -#[test] -fn unbalanced_trait_decrease_balance_at_most_works_1() { - ExtBuilder::default().build_and_execute_with(|| { - assert_ok!(Balances::write_balance(&account_id(137), 100)); - assert_eq!(>::balance(&account_id(137)), 100); - - assert_eq!( - Balances::decrease_balance(&account_id(137), 101, BestEffort, Expendable, Polite), - Ok(100) - ); - assert_eq!(>::balance(&account_id(137)), 0); - }); -} - -#[test] -fn unbalanced_trait_decrease_balance_at_most_works_2() { - ExtBuilder::default().build_and_execute_with(|| { - assert_ok!(Balances::write_balance(&account_id(137), 99)); - assert_eq!( - Balances::decrease_balance(&account_id(137), 99, BestEffort, Expendable, Polite), - Ok(99) - ); - assert_eq!(>::balance(&account_id(137)), 0); - }); -} - -#[test] -fn unbalanced_trait_decrease_balance_at_most_works_3() { - ExtBuilder::default().build_and_execute_with(|| { - // free: 40, reserved: 60 - assert_ok!(Balances::write_balance(&account_id(137), 100)); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(137), 60)); - assert_eq!(Balances::free_balance(account_id(137)), 40); - assert_eq!(Balances::total_balance_on_hold(&account_id(137)), 60); - assert_eq!( - Balances::decrease_balance(&account_id(137), 0, BestEffort, Expendable, Polite), - Ok(0) - ); - assert_eq!(Balances::free_balance(account_id(137)), 40); - assert_eq!(Balances::total_balance_on_hold(&account_id(137)), 60); - assert_eq!( - Balances::decrease_balance(&account_id(137), 10, BestEffort, Expendable, Polite), - Ok(10) - ); - assert_eq!(Balances::free_balance(account_id(137)), 30); - assert_eq!( - Balances::decrease_balance(&account_id(137), 200, BestEffort, Expendable, Polite), - Ok(29) - ); - assert_eq!(>::balance(&account_id(137)), 1); - assert_eq!(Balances::free_balance(account_id(137)), 1); - assert_eq!(Balances::total_balance_on_hold(&account_id(137)), 60); - }); -} - -#[test] -fn unbalanced_trait_increase_balance_works() { - ExtBuilder::default().build_and_execute_with(|| { - assert_noop!( - Balances::increase_balance(&account_id(137), 0, Exact), - TokenError::BelowMinimum - ); - assert_eq!(Balances::increase_balance(&account_id(137), 1, Exact), Ok(1)); - assert_noop!( - Balances::increase_balance(&account_id(137), Balance::MAX, Exact), - ArithmeticError::Overflow - ); - }); -} - -#[test] -fn unbalanced_trait_increase_balance_at_most_works() { - ExtBuilder::default().build_and_execute_with(|| { - assert_eq!(Balances::increase_balance(&account_id(137), 0, BestEffort), Ok(0)); - assert_eq!(Balances::increase_balance(&account_id(137), 1, BestEffort), Ok(1)); - assert_eq!( - Balances::increase_balance(&account_id(137), Balance::MAX, BestEffort), - Ok(Balance::MAX - 1) - ); - }); -} - -#[test] -fn freezing_and_holds_should_overlap() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 10)); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(1), 9)); - assert_eq!(Balances::account(&account_id(1)).free, 1); - assert_eq!(System::consumers(&account_id(1)), 1); - assert_eq!(Balances::account(&account_id(1)).free, 1); - assert_eq!(Balances::account(&account_id(1)).frozen, 10); - assert_eq!(Balances::account(&account_id(1)).reserved, 9); - assert_eq!(Balances::total_balance_on_hold(&account_id(1)), 9); - }); -} - -#[test] -fn frozen_hold_balance_cannot_be_moved_without_force() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 10)); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(1), 9)); - assert_eq!(Balances::reducible_total_balance_on_hold(&account_id(1), Force), 9); - assert_eq!(Balances::reducible_total_balance_on_hold(&account_id(1), Polite), 0); - let e = TokenError::Frozen; - assert_noop!( - Balances::transfer_on_hold( - &TestId::Foo, - &account_id(1), - &account_id(2), - 1, - Exact, - Free, - Polite - ), - e - ); - assert_ok!(Balances::transfer_on_hold( - &TestId::Foo, - &account_id(1), - &account_id(2), - 1, - Exact, - Free, - Force - )); - }); -} - -#[test] -fn frozen_hold_balance_best_effort_transfer_works() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 5)); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(1), 9)); - assert_eq!(Balances::reducible_total_balance_on_hold(&account_id(1), Force), 9); - assert_eq!(Balances::reducible_total_balance_on_hold(&account_id(1), Polite), 5); - assert_ok!(Balances::transfer_on_hold( - &TestId::Foo, - &account_id(1), - &account_id(2), - 10, - BestEffort, - Free, - Polite - )); - assert_eq!(Balances::total_balance(&account_id(1)), 5); - assert_eq!(Balances::total_balance(&account_id(2)), 25); - }); -} - -#[test] -fn partial_freezing_should_work() { - ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 5)); - assert_eq!(System::consumers(&account_id(1)), 1); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 5, - Expendable - )); - // After transferring 5, balance is 95. With 10 frozen, can transfer up to 85 more - // (95-10=85) - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 85, - Expendable - )); - // Now balance is 10. Transferring 1 more would leave 9, which is < 10 frozen, so should - // fail - assert_noop!( - >::transfer( - &account_id(1), - &account_id(2), - 1, - Expendable - ), - TokenError::Frozen - ); - }); -} - -#[test] -fn thaw_should_work() { - ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), Balance::MAX)); - assert_ok!(Balances::thaw(&TestId::Foo, &account_id(1))); - assert_eq!(System::consumers(&account_id(1)), 0); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &account_id(1)), 0); - assert_eq!(Balances::account(&account_id(1)).frozen, 0); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 10, - Expendable - )); - }); -} - -#[test] -fn set_freeze_zero_should_work() { - ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), Balance::MAX)); - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 0)); - assert_eq!(System::consumers(&account_id(1)), 0); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &account_id(1)), 0); - assert_eq!(Balances::account(&account_id(1)).frozen, 0); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 10, - Expendable - )); - }); -} - -#[test] -fn set_freeze_should_work() { - ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), Balance::MAX)); - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 5)); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 5, - Expendable - )); - // After transferring 5, balance is 95. With 10 frozen, can transfer up to 85 more - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 85, - Expendable - )); - // Now balance is 10. Transferring 1 more would leave 9, which is < 10 frozen, so should - // fail - assert_noop!( - >::transfer( - &account_id(1), - &account_id(2), - 1, - Expendable - ), - TokenError::Frozen - ); - }); -} - -#[test] -fn extend_freeze_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 5)); - assert_ok!(Balances::extend_freeze(&TestId::Foo, &account_id(1), 10)); - assert_eq!(Balances::account(&account_id(1)).frozen, 10); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &account_id(1)), 10); - assert_noop!( - >::transfer( - &account_id(1), - &account_id(2), - 1, - Expendable - ), - TokenError::Frozen - ); - }); -} - -#[test] -fn debug_freeze_behavior() { - ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .build_and_execute_with(|| { - println!("=== Debug freeze behavior ==="); - println!("Initial balance: {}", Balances::free_balance(account_id(1))); - - // Set a freeze - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 10)); - println!("After freeze(10):"); - println!(" Free balance: {}", Balances::free_balance(account_id(1))); - println!(" Frozen amount: {}", Balances::balance_frozen(&TestId::Foo, &account_id(1))); - println!(" Account frozen: {}", Balances::account(&account_id(1)).frozen); - - // Try transfers of different amounts - for amount in [1, 5, 10, 89, 90, 91] { - let balance_before = Balances::free_balance(account_id(1)); - let result = >::transfer( - &account_id(1), - &account_id(2), - amount, - Expendable, - ); - let balance_after = Balances::free_balance(account_id(1)); - - println!( - "Transfer {} units: {:?} (balance: {} -> {})", - amount, result, balance_before, balance_after - ); - - // Restore balance for next test - if result.is_ok() { - let _ = >::transfer( - &account_id(2), - &account_id(1), - amount, - Expendable, - ); - } - } - }); -} - -#[test] -fn double_freezing_should_work() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 5)); - assert_ok!(Balances::set_freeze(&TestId::Bar, &account_id(1), 5)); - assert_eq!(System::consumers(&account_id(1)), 1); - assert_ok!(>::transfer( - &account_id(1), - &account_id(2), - 5, - Expendable - )); - assert_noop!( - >::transfer( - &account_id(1), - &account_id(2), - 1, - Expendable - ), - TokenError::Frozen - ); - }); -} - -#[test] -fn can_hold_entire_balance_when_second_provider() { - ExtBuilder::default() - .existential_deposit(1) - .monied(false) - .build_and_execute_with(|| { - >::set_balance(&account_id(1), 100); - assert_noop!( - Balances::hold(&TestId::Foo, &account_id(1), 100), - TokenError::FundsUnavailable - ); - System::inc_providers(&account_id(1)); - assert_eq!(System::providers(&account_id(1)), 2); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(1), 100)); - assert_eq!(System::providers(&account_id(1)), 1); - assert_noop!(System::dec_providers(&account_id(1)), DispatchError::ConsumerRemaining); - }); -} - -#[test] -fn unholding_frees_hold_slot() { - ExtBuilder::default() - .existential_deposit(1) - .monied(false) - .build_and_execute_with(|| { - >::set_balance(&account_id(1), 100); - assert_ok!(Balances::hold(&TestId::Foo, &account_id(1), 10)); - assert_ok!(Balances::hold(&TestId::Bar, &account_id(1), 10)); - assert_ok!(Balances::release(&TestId::Foo, &account_id(1), 10, Exact)); - assert_ok!(Balances::hold(&TestId::Baz, &account_id(1), 10)); - }); -} - -#[test] -fn sufficients_work_properly_with_reference_counting() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Only run PoC when the system pallet is enabled, since the underlying bug is in the - // system pallet it won't work with BalancesAccountStore - if UseSystem::get() { - // Start with a balance of 100 - >::set_balance(&account_id(1), 100); - // Emulate a sufficient, in reality this could be reached by transferring a - // sufficient asset to the account - System::inc_sufficients(&account_id(1)); - // Spend the same balance multiple times - assert_ok!(>::transfer( - &account_id(1), - &account_id(137), - 100, - Expendable - )); - assert_eq!(Balances::free_balance(account_id(1)), 0); - assert_noop!( - >::transfer( - &account_id(1), - &account_id(137), - 100, - Expendable - ), - TokenError::FundsUnavailable - ); - } - }); -} - -#[test] -fn emit_events_with_changing_freezes() { - ExtBuilder::default().build_and_execute_with(|| { - let _ = Balances::set_balance(&account_id(1), 100); - System::reset_events(); - - // Freeze = [] --> [10] - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 10)); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Frozen { who: account_id(1), amount: 10 })] - ); - - // Freeze = [10] --> [15] - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 15)); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Frozen { who: account_id(1), amount: 5 })] - ); - - // Freeze = [15] --> [15, 20] - assert_ok!(Balances::set_freeze(&TestId::Bar, &account_id(1), 20)); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Frozen { who: account_id(1), amount: 5 })] - ); - - // Freeze = [15, 20] --> [17, 20] - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 17)); - for event in events() { - match event { - RuntimeEvent::Balances(crate::Event::Frozen { .. }) => { - assert!(false, "unexpected freeze event") - }, - RuntimeEvent::Balances(crate::Event::Thawed { .. }) => { - assert!(false, "unexpected thaw event") - }, - _ => continue, - } - } - - // Freeze = [17, 20] --> [17, 15] - assert_ok!(Balances::set_freeze(&TestId::Bar, &account_id(1), 15)); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Thawed { who: account_id(1), amount: 3 })] - ); - - // Freeze = [17, 15] --> [15] - assert_ok!(Balances::thaw(&TestId::Foo, &account_id(1))); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Thawed { who: account_id(1), amount: 2 })] - ); - - // Freeze = [15] --> [] - assert_ok!(Balances::thaw(&TestId::Bar, &account_id(1))); - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Thawed { who: account_id(1), amount: 15 })] - ); - }); -} - -#[test] -fn withdraw_precision_exact_works() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - assert_ok!(Balances::set_freeze(&TestId::Foo, &account_id(1), 10)); - assert_eq!(Balances::account(&account_id(1)).free, 10); - assert_eq!(Balances::account(&account_id(1)).frozen, 10); - - // `BestEffort` will not reduce anything - assert_ok!(>::withdraw( - &account_id(1), - 5, - BestEffort, - Preserve, - Polite - )); - - assert_eq!(Balances::account(&account_id(1)).free, 10); - assert_eq!(Balances::account(&account_id(1)).frozen, 10); - - assert_noop!( - >::withdraw( - &account_id(1), - 5, - Exact, - Preserve, - Polite - ), - TokenError::FundsUnavailable - ); - }); -} - -#[test] -fn freeze_consideration_works() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - type Consideration = FreezeConsideration< - AccountId, - Balances, - FooReason, - LinearStoragePrice, ConstU128<1>, Balance>, - Footprint, - >; - - let who = account_id(4); - // freeze amount taken somewhere outside of our (Consideration) scope. - let extend_freeze = 15; - - let ticket = Consideration::new(&who, Footprint::from_parts(0, 0)).unwrap(); - assert!(ticket.is_none()); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 0); - - let ticket = Consideration::new(&who, Footprint::from_parts(10, 1)).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 10); - - let ticket = ticket.update(&who, Footprint::from_parts(4, 1)).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 4); - - assert_ok!(Balances::increase_frozen(&TestId::Foo, &who, extend_freeze)); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 4 + extend_freeze); - - let ticket = ticket.update(&who, Footprint::from_parts(8, 1)).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 8 + extend_freeze); - - let ticket = ticket.update(&who, Footprint::from_parts(0, 0)).unwrap(); - assert!(ticket.is_none()); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), extend_freeze); - - let ticket = Consideration::new(&who, Footprint::from_parts(10, 1)).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 10 + extend_freeze); - - ticket.drop(&who).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), extend_freeze); - }); -} - -#[test] -fn hold_consideration_works() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - type Consideration = HoldConsideration< - AccountId, - Balances, - FooReason, - LinearStoragePrice, ConstU128<1>, Balance>, - Footprint, - >; - - let who = account_id(4); - // hold amount taken somewhere outside of our (Consideration) scope. - let extend_hold = 15; - - let ticket = Consideration::new(&who, Footprint::from_parts(0, 0)).unwrap(); - assert!(ticket.is_none()); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 0); - - let ticket = ticket.update(&who, Footprint::from_parts(10, 1)).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 10); - - let ticket = ticket.update(&who, Footprint::from_parts(4, 1)).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 4); - - assert_ok!(Balances::hold(&TestId::Foo, &who, extend_hold)); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 4 + extend_hold); - - let ticket = ticket.update(&who, Footprint::from_parts(8, 1)).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 8 + extend_hold); - - let ticket = ticket.update(&who, Footprint::from_parts(0, 0)).unwrap(); - assert!(ticket.is_none()); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), extend_hold); - - let ticket = Consideration::new(&who, Footprint::from_parts(10, 1)).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 10 + extend_hold); - - ticket.drop(&who).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), extend_hold); - }); -} - -#[test] -fn lone_freeze_consideration_works() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - type Consideration = LoneFreezeConsideration< - AccountId, - Balances, - FooReason, - LinearStoragePrice, ConstU128<1>, Balance>, - Footprint, - >; - - let who = account_id(4); - let zero_ticket = Consideration::new(&who, Footprint::from_parts(0, 0)).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 0); - - let ticket = Consideration::new(&who, Footprint::from_parts(10, 1)).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 10); - - assert_ok!(Balances::increase_frozen(&TestId::Foo, &who, 5)); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 15); - - let ticket = ticket.update(&who, Footprint::from_parts(4, 1)).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 4); - - assert_eq!(ticket.update(&who, Footprint::from_parts(0, 0)).unwrap(), zero_ticket); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 0); - - let ticket = Consideration::new(&who, Footprint::from_parts(10, 1)).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 10); - - ticket.drop(&who).unwrap(); - assert_eq!(Balances::balance_frozen(&TestId::Foo, &who), 0); - }); -} - -#[test] -fn lone_hold_consideration_works() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - type Consideration = LoneHoldConsideration< - AccountId, - Balances, - FooReason, - LinearStoragePrice, ConstU128<1>, Balance>, - Footprint, - >; - - let who = account_id(4); - let zero_ticket = Consideration::new(&who, Footprint::from_parts(0, 0)).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 0); - - let ticket = Consideration::new(&who, Footprint::from_parts(10, 1)).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 10); - - assert_ok!(Balances::hold(&TestId::Foo, &who, 5)); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 15); - - let ticket = ticket.update(&who, Footprint::from_parts(4, 1)).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 4); - - assert_eq!(ticket.update(&who, Footprint::from_parts(0, 0)).unwrap(), zero_ticket); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 0); - - let ticket = Consideration::new(&who, Footprint::from_parts(10, 1)).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 10); - - ticket.drop(&who).unwrap(); - assert_eq!(Balances::balance_on_hold(&TestId::Foo, &who), 0); - }); -} diff --git a/pallets/balances/src/tests/general_tests.rs b/pallets/balances/src/tests/general_tests.rs deleted file mode 100644 index a56f9f98..00000000 --- a/pallets/balances/src/tests/general_tests.rs +++ /dev/null @@ -1,143 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![cfg(test)] - -use crate::{ - system::AccountInfo, - tests::{account_id, ensure_ti_valid, Balances, ExtBuilder, System, Test, TestId, UseSystem}, - AccountData, ExtraFlags, TotalIssuance, -}; -use frame_support::{ - assert_noop, assert_ok, hypothetically, - traits::{ - fungible::{Mutate, MutateHold}, - tokens::Precision, - }, -}; -use sp_runtime::DispatchError; - -/// There are some accounts that have one consumer ref too few. These accounts are at risk of losing -/// their held (reserved) balance. They do not just lose it - it is also not accounted for in the -/// Total Issuance. Here we test the case that the account does not reap in such a case, but gets -/// one consumer ref for its reserved balance. -#[test] -fn regression_historic_acc_does_not_evaporate_reserve() { - ExtBuilder::default().build_and_execute_with(|| { - UseSystem::set(true); - let (alice, bob) = (account_id(0), account_id(1)); - // Alice is in a bad state with consumer == 0 && reserved > 0: - Balances::set_balance(&alice, 100); - TotalIssuance::::put(100); - ensure_ti_valid(); - - assert_ok!(Balances::hold(&TestId::Foo, &alice, 10)); - // This is the issue of the account: - System::dec_consumers(&alice); - - assert_eq!( - System::account(&alice), - AccountInfo { - data: AccountData { - free: 90, - reserved: 10, - frozen: 0, - flags: ExtraFlags(1u128 << 127), - }, - nonce: 0, - consumers: 0, // should be 1 on a good acc - providers: 1, - sufficients: 0, - } - ); - - ensure_ti_valid(); - - // Reaping the account is prevented by the new logic: - assert_noop!( - Balances::transfer_allow_death(Some(alice.clone()).into(), bob.clone(), 90), - DispatchError::ConsumerRemaining - ); - assert_noop!( - Balances::transfer_all(Some(alice.clone()).into(), bob.clone(), false), - DispatchError::ConsumerRemaining - ); - - // normal transfers still work: - hypothetically!({ - assert_ok!(Balances::transfer_keep_alive(Some(alice.clone()).into(), bob.clone(), 40)); - // Alice got back her consumer ref: - assert_eq!(System::consumers(&alice), 1); - ensure_ti_valid(); - }); - hypothetically!({ - assert_ok!(Balances::transfer_all(Some(alice.clone()).into(), bob.clone(), true)); - // Alice got back her consumer ref: - assert_eq!(System::consumers(&alice), 1); - ensure_ti_valid(); - }); - - // un-reserving all does not add a consumer ref: - hypothetically!({ - assert_ok!(Balances::release(&TestId::Foo, &alice, 10, Precision::Exact)); - assert_eq!(System::consumers(&alice), 0); - assert_ok!(Balances::transfer_keep_alive(Some(alice.clone()).into(), bob.clone(), 40)); - assert_eq!(System::consumers(&alice), 0); - ensure_ti_valid(); - }); - // un-reserving some does add a consumer ref: - hypothetically!({ - assert_ok!(Balances::release(&TestId::Foo, &alice, 5, Precision::Exact)); - assert_eq!(System::consumers(&alice), 1); - assert_ok!(Balances::transfer_keep_alive(Some(alice.clone()).into(), bob.clone(), 40)); - assert_eq!(System::consumers(&alice), 1); - ensure_ti_valid(); - }); - }); -} - -#[cfg(feature = "try-runtime")] -#[test] -fn try_state_works() { - use crate::{Config, Freezes, Holds}; - use frame_support::{ - storage, - traits::{Get, Hooks, VariantCount}, - }; - - ExtBuilder::default().build_and_execute_with(|| { - storage::unhashed::put( - &Holds::::hashed_key_for(account_id(1)), - &vec![0u8; ::RuntimeHoldReason::VARIANT_COUNT as usize + 1], - ); - - assert!(format!("{:?}", Balances::try_state(0).unwrap_err()) - .contains("Found `Hold` with too many elements")); - }); - - ExtBuilder::default().build_and_execute_with(|| { - let max_freezes: u32 = ::MaxFreezes::get(); - - storage::unhashed::put( - &Freezes::::hashed_key_for(account_id(1)), - &vec![0u8; max_freezes as usize + 1], - ); - - assert!(format!("{:?}", Balances::try_state(0).unwrap_err()) - .contains("Found `Freeze` with too many elements")); - }); -} diff --git a/pallets/balances/src/tests/mod.rs b/pallets/balances/src/tests/mod.rs deleted file mode 100644 index cc469066..00000000 --- a/pallets/balances/src/tests/mod.rs +++ /dev/null @@ -1,330 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Tests. - -#![cfg(test)] - -use crate::{self as pallet_balances, AccountData, Config, CreditOf, Error, Pallet, TotalIssuance}; -use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; -use frame_support::{ - assert_err, assert_noop, assert_ok, assert_storage_noop, derive_impl, - dispatch::{DispatchInfo, GetDispatchInfo}, - parameter_types, - traits::{ - fungible, ConstU32, ConstU8, Imbalance as ImbalanceT, OnUnbalanced, StorageMapShim, - StoredMap, VariantCount, VariantCountOf, WhitelistedStorageKeys, - }, - weights::{IdentityFee, Weight}, -}; -use frame_system::{self as system, RawOrigin}; -use pallet_transaction_payment::{ChargeTransactionPayment, FungibleAdapter, Multiplier}; -use scale_info::TypeInfo; -use sp_core::hexdisplay::HexDisplay; -use sp_runtime::{ - traits::{BadOrigin, Zero}, - ArithmeticError, BuildStorage, DispatchError, DispatchResult, FixedPointNumber, RuntimeDebug, - TokenError, -}; -use std::collections::BTreeSet; - -mod currency_tests; -mod dispatchable_tests; -// mod fungible_conformance_tests; // Commented out due to AccountId32 incompatibility -mod fungible_tests; -mod general_tests; -mod reentrancy_tests; -mod transfer_counter_tests; -type Block = frame_system::mocking::MockBlock; -type AccountId = sp_core::crypto::AccountId32; - -#[derive( - Encode, - Decode, - Copy, - Clone, - Eq, - PartialEq, - Ord, - PartialOrd, - MaxEncodedLen, - TypeInfo, - DecodeWithMemTracking, - RuntimeDebug, -)] -pub enum TestId { - Foo, - Bar, - Baz, -} - -impl VariantCount for TestId { - const VARIANT_COUNT: u32 = 3; -} - -frame_support::construct_runtime!( - pub enum Test { - System: frame_system, - Balances: pallet_balances, - TransactionPayment: pallet_transaction_payment, - } -); - -type Balance = u128; - -parameter_types! { - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::simple_max( - frame_support::weights::Weight::from_parts(1024, u64::MAX), - ); - pub static ExistentialDeposit: Balance = 1; -} - -#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] -impl frame_system::Config for Test { - type Block = Block; - type AccountId = AccountId; - type Lookup = sp_runtime::traits::IdentityLookup; - type AccountData = super::AccountData; -} - -#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig)] -impl pallet_transaction_payment::Config for Test { - type OnChargeTransaction = FungibleAdapter, ()>; - type OperationalFeeMultiplier = ConstU8<5>; - type WeightToFee = IdentityFee; - type LengthToFee = IdentityFee; -} - -parameter_types! { - pub FooReason: TestId = TestId::Foo; -} - -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] -impl Config for Test { - type Balance = Balance; - type DustRemoval = DustTrap; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = TestAccountStore; - type MaxReserves = ConstU32<2>; - type ReserveIdentifier = TestId; - type RuntimeHoldReason = TestId; - type RuntimeFreezeReason = TestId; - type FreezeIdentifier = TestId; - type MaxFreezes = VariantCountOf; -} - -#[derive(Clone)] -pub struct ExtBuilder { - existential_deposit: Balance, - monied: bool, - dust_trap: Option, -} -impl Default for ExtBuilder { - fn default() -> Self { - Self { existential_deposit: 1, monied: false, dust_trap: None } - } -} -impl ExtBuilder { - pub fn existential_deposit(mut self, existential_deposit: Balance) -> Self { - self.existential_deposit = existential_deposit; - self - } - pub fn monied(mut self, monied: bool) -> Self { - self.monied = monied; - if self.existential_deposit == 0 { - self.existential_deposit = 1; - } - self - } - pub fn dust_trap(mut self, account: u64) -> Self { - self.dust_trap = Some(account); - self - } - pub fn set_associated_consts(&self) { - DUST_TRAP_TARGET.with(|v| v.replace(self.dust_trap)); - EXISTENTIAL_DEPOSIT.with(|v| v.replace(self.existential_deposit)); - } - pub fn build(self) -> sp_io::TestExternalities { - self.set_associated_consts(); - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - pallet_balances::GenesisConfig:: { - balances: if self.monied { - vec![ - (account_id(1), 10 * self.existential_deposit), - (account_id(2), 20 * self.existential_deposit), - (account_id(3), 30 * self.existential_deposit), - (account_id(4), 40 * self.existential_deposit), - (account_id(12), 10 * self.existential_deposit), - ] - } else { - vec![] - }, - } - .assimilate_storage(&mut t) - .unwrap(); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } - pub fn build_and_execute_with(self, f: impl Fn()) { - let other = self.clone(); - UseSystem::set(false); - other.build().execute_with(&f); - UseSystem::set(true); - self.build().execute_with(f); - } -} - -parameter_types! { - static DustTrapTarget: Option = None; -} - -pub struct DustTrap; - -impl OnUnbalanced> for DustTrap { - fn on_nonzero_unbalanced(amount: CreditOf) { - match DustTrapTarget::get() { - None => drop(amount), - Some(a) => { - let account = account_id(a as u8); - let result = >::resolve(&account, amount); - debug_assert!(result.is_ok()); - }, - } - } -} - -parameter_types! { - pub static UseSystem: bool = false; -} - -type BalancesAccountStore = - StorageMapShim, AccountId, super::AccountData>; -type SystemAccountStore = frame_system::Pallet; - -pub struct TestAccountStore; -impl StoredMap> for TestAccountStore { - fn get(k: &AccountId) -> super::AccountData { - if UseSystem::get() { - >::get(k) - } else { - >::get(k) - } - } - fn try_mutate_exists>( - k: &AccountId, - f: impl FnOnce(&mut Option>) -> Result, - ) -> Result { - if UseSystem::get() { - >::try_mutate_exists(k, f) - } else { - >::try_mutate_exists(k, f) - } - } - fn mutate( - k: &AccountId, - f: impl FnOnce(&mut super::AccountData) -> R, - ) -> Result { - if UseSystem::get() { - >::mutate(k, f) - } else { - >::mutate(k, f) - } - } - fn mutate_exists( - k: &AccountId, - f: impl FnOnce(&mut Option>) -> R, - ) -> Result { - if UseSystem::get() { - >::mutate_exists(k, f) - } else { - >::mutate_exists(k, f) - } - } - fn insert(k: &AccountId, t: super::AccountData) -> Result<(), DispatchError> { - if UseSystem::get() { - >::insert(k, t) - } else { - >::insert(k, t) - } - } - fn remove(k: &AccountId) -> Result<(), DispatchError> { - if UseSystem::get() { - >::remove(k) - } else { - >::remove(k) - } - } -} - -pub fn events() -> Vec { - let evt = System::events().into_iter().map(|evt| evt.event).collect::>(); - System::reset_events(); - evt -} - -/// create a transaction info struct from weight. Handy to avoid building the whole struct. -pub fn info_from_weight(w: Weight) -> DispatchInfo { - DispatchInfo { call_weight: w, ..Default::default() } -} - -/// Helper function to convert a u8 to an AccountId32 -pub fn account_id(id: u8) -> AccountId { - sp_core::crypto::AccountId32::from([id; 32]) -} - -/// Check that the total-issuance matches the sum of all accounts' total balances. -pub fn ensure_ti_valid() { - let mut sum = 0; - - for acc in frame_system::Account::::iter_keys() { - if UseSystem::get() { - let data = frame_system::Pallet::::account(acc); - sum += data.data.total(); - } else { - let data = crate::Account::::get(acc); - sum += data.total(); - } - } - - assert_eq!(TotalIssuance::::get(), sum, "Total Issuance wrong"); -} - -#[test] -fn weights_sane() { - let info = crate::Call::::transfer_allow_death { dest: account_id(10), value: 4 } - .get_dispatch_info(); - assert_eq!(<() as crate::WeightInfo>::transfer_allow_death(), info.call_weight); - - let info = - crate::Call::::force_unreserve { who: account_id(10), amount: 4 }.get_dispatch_info(); - assert_eq!(<() as crate::WeightInfo>::force_unreserve(), info.call_weight); -} - -#[test] -fn check_whitelist() { - let whitelist: BTreeSet = AllPalletsWithSystem::whitelisted_storage_keys() - .iter() - .map(|s| HexDisplay::from(&s.key).to_string()) - .collect(); - // Inactive Issuance - assert!(whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f1ccde6872881f893a21de93dfe970cd5")); - // Total Issuance - assert!(whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80")); -} diff --git a/pallets/balances/src/tests/reentrancy_tests.rs b/pallets/balances/src/tests/reentrancy_tests.rs deleted file mode 100644 index 767f3ddf..00000000 --- a/pallets/balances/src/tests/reentrancy_tests.rs +++ /dev/null @@ -1,212 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Tests regarding the reentrancy functionality. - -use super::*; -use frame_support::traits::tokens::{ - Fortitude::Force, - Precision::BestEffort, - Preservation::{Expendable, Protect}, -}; -use fungible::Balanced; - -#[test] -fn transfer_dust_removal_tst1_should_work() { - ExtBuilder::default() - .existential_deposit(100) - .dust_trap(1) - .build_and_execute_with(|| { - // Verification of reentrancy in dust removal - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(1), 1000)); - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(2), 500)); - - // In this transaction, account 2 free balance - // drops below existential balance - // and dust balance is removed from account 2 - assert_ok!(Balances::transfer_allow_death( - RawOrigin::Signed(account_id(2)).into(), - account_id(3), - 450 - )); - - // As expected dust balance is removed. - assert_eq!(Balances::free_balance(account_id(2)), 0); - - // As expected beneficiary account 3 - // received the transferred fund. - assert_eq!(Balances::free_balance(account_id(3)), 450); - - // Dust balance is deposited to account 1 - // during the process of dust removal. - assert_eq!(Balances::free_balance(account_id(1)), 1050); - - // Verify the events - assert_eq!(System::events().len(), 15); - - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Transfer { - from: account_id(2), - to: account_id(3), - amount: 450, - })); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::DustLost { - account: account_id(2), - amount: 50, - })); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Deposit { - who: account_id(1), - amount: 50, - })); - }); -} - -#[test] -fn transfer_dust_removal_tst2_should_work() { - ExtBuilder::default() - .existential_deposit(100) - .dust_trap(1) - .build_and_execute_with(|| { - // Verification of reentrancy in dust removal - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(1), 1000)); - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(2), 500)); - - // In this transaction, account 2 free balance - // drops below existential balance - // and dust balance is removed from account 2 - assert_ok!(Balances::transfer_allow_death( - RawOrigin::Signed(account_id(2)).into(), - account_id(1), - 450 - )); - - // As expected dust balance is removed. - assert_eq!(Balances::free_balance(account_id(2)), 0); - - // Dust balance is deposited to account 1 - assert_eq!(Balances::free_balance(account_id(1)), 1000 + 450 + 50); - // Verify the events - assert_eq!(System::events().len(), 13); - - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Transfer { - from: account_id(2), - to: account_id(1), - amount: 450, - })); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::DustLost { - account: account_id(2), - amount: 50, - })); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Deposit { - who: account_id(1), - amount: 50, - })); - }); -} - -#[test] -fn repatriating_reserved_balance_dust_removal_should_work() { - ExtBuilder::default() - .existential_deposit(100) - .dust_trap(1) - .build_and_execute_with(|| { - // Verification of reentrancy in dust removal - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(1), 1000)); - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(2), 500)); - - // Reserve a value on account 2, - // Such that free balance is lower than - // Existential deposit. - assert_ok!(Balances::transfer_allow_death( - RuntimeOrigin::signed(account_id(2)), - account_id(1), - 450 - )); - - // Since free balance of account 2 is lower than - // existential deposit, dust amount is - // removed from the account 2 - assert_eq!(Balances::reserved_balance(account_id(2)), 0); - assert_eq!(Balances::free_balance(account_id(2)), 0); - - // account 1 is credited with reserved amount - // together with dust balance during dust - // removal. - assert_eq!(Balances::reserved_balance(account_id(1)), 0); - assert_eq!(Balances::free_balance(account_id(1)), 1500); - - // Verify the events - assert_eq!(System::events().len(), 13); - - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Transfer { - from: account_id(2), - to: account_id(1), - amount: 450, - })); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::DustLost { - account: account_id(2), - amount: 50, - })); - System::assert_has_event(RuntimeEvent::Balances(crate::Event::Deposit { - who: account_id(1), - amount: 50, - })); - }); -} - -#[test] -fn emit_events_with_no_existential_deposit_suicide_with_dust() { - ExtBuilder::default().existential_deposit(2).build_and_execute_with(|| { - assert_ok!(Balances::force_set_balance(RawOrigin::Root.into(), account_id(1), 100)); - - assert_eq!( - events(), - [ - RuntimeEvent::System(system::Event::NewAccount { account: account_id(1) }), - RuntimeEvent::Balances(crate::Event::Endowed { - account: account_id(1), - free_balance: 100 - }), - RuntimeEvent::Balances(crate::Event::Issued { amount: 100 }), - RuntimeEvent::Balances(crate::Event::BalanceSet { who: account_id(1), free: 100 }), - ] - ); - - let res = Balances::withdraw(&account_id(1), 98, BestEffort, Protect, Force); - assert_eq!(res.unwrap().peek(), 98); - - // no events - assert_eq!( - events(), - [RuntimeEvent::Balances(crate::Event::Withdraw { who: account_id(1), amount: 98 })] - ); - - let res = Balances::withdraw(&account_id(1), 1, BestEffort, Expendable, Force); - assert_eq!(res.unwrap().peek(), 1); - - assert_eq!( - events(), - [ - RuntimeEvent::System(system::Event::KilledAccount { account: account_id(1) }), - RuntimeEvent::Balances(crate::Event::DustLost { - account: account_id(1), - amount: 1 - }), - RuntimeEvent::Balances(crate::Event::Withdraw { who: account_id(1), amount: 1 }), - ] - ); - }); -} diff --git a/pallets/balances/src/tests/transfer_counter_tests.rs b/pallets/balances/src/tests/transfer_counter_tests.rs deleted file mode 100644 index 92cb360e..00000000 --- a/pallets/balances/src/tests/transfer_counter_tests.rs +++ /dev/null @@ -1,336 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Tests for the global transfer counter functionality. - -use super::*; -use crate::{TransferCount, TransferProof}; -use sp_runtime::{ArithmeticError::Underflow, DispatchError::Arithmetic}; - -/// Alice account ID for more readable tests. -fn alice() -> AccountId { - account_id(1) -} -/// Bob account ID for more readable tests. -fn bob() -> AccountId { - account_id(2) -} -/// Charlie account ID for more readable tests. -fn charlie() -> AccountId { - account_id(3) -} - -#[test] -fn transfer_counter_starts_at_zero() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Transfer counter should start at 0 - assert_eq!(Balances::transfer_count(), 0); - }); -} - -#[test] -fn transfer_allow_death_increments_counter() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Initial counter should be 0 - assert_eq!(Balances::transfer_count(), 0); - - // Perform a transfer - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), bob(), 5)); - - // Counter should increment to 1 - assert_eq!(Balances::transfer_count(), 1); - - // Perform another transfer - assert_ok!(Balances::transfer_allow_death(Some(bob()).into(), charlie(), 3)); - - // Counter should increment to 2 - assert_eq!(Balances::transfer_count(), 2); - }); -} - -#[test] -fn transfer_keep_alive_increments_counter() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Initial counter should be 0 - assert_eq!(Balances::transfer_count(), 0); - - // Perform a transfer_keep_alive - assert_ok!(Balances::transfer_keep_alive(Some(alice()).into(), bob(), 5)); - - // Counter should increment to 1 - assert_eq!(Balances::transfer_count(), 1); - }); -} - -#[test] -fn force_transfer_increments_counter() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Initial counter should be 0 - assert_eq!(Balances::transfer_count(), 0); - - // Perform a force transfer - assert_ok!(Balances::force_transfer(RuntimeOrigin::root(), alice(), bob(), 5)); - - // Counter should increment to 1 - assert_eq!(Balances::transfer_count(), 1); - }); -} - -#[test] -fn transfer_all_increments_counter() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Initial counter should be 0 - assert_eq!(Balances::transfer_count(), 0); - - // Perform a transfer_all - assert_ok!(Balances::transfer_all(Some(alice()).into(), bob(), false)); - - // Counter should increment to 1 - assert_eq!(Balances::transfer_count(), 1); - }); -} - -#[test] -fn self_transfer_does_not_increment_counter() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Initial counter should be 0 - assert_eq!(Balances::transfer_count(), 0); - - // Self transfer should not increment counter - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), alice(), 5)); - - // Counter should remain 0 since it's a self-transfer - assert_eq!(Balances::transfer_count(), 0); - }); -} - -#[test] -fn transfer_proof_storage_is_created() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Perform a transfer - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), bob(), 5)); - - // Check that transfer proof was stored with correct key - let key = (0u64, alice(), bob(), 5); - assert!(TransferProof::::contains_key(&key)); - }); -} - -#[test] -fn multiple_transfers_create_sequential_proofs() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // First transfer - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), bob(), 5)); - assert_eq!(Balances::transfer_count(), 1); - - // Check first proof exists - let key1 = (0u64, alice(), bob(), 5u128); - assert!(TransferProof::::contains_key(&key1)); - - // Second transfer - assert_ok!(Balances::transfer_allow_death(Some(bob()).into(), charlie(), 3)); - assert_eq!(Balances::transfer_count(), 2); - - // Check second proof exists - let key2 = (1u64, bob(), charlie(), 3u128); - assert!(TransferProof::::contains_key(&key2)); - - // Third transfer with different amount - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), charlie(), 1)); - assert_eq!(Balances::transfer_count(), 3); - - // Check third proof exists - let key3 = (2u64, alice(), charlie(), 1u128); - assert!(TransferProof::::contains_key(&key3)); - }); -} - -#[test] -fn failed_transfers_do_not_increment_counter() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Initial counter should be 0 - assert_eq!(Balances::transfer_count(), 0); - - // Attempt transfer with insufficient funds - assert_noop!( - Balances::transfer_allow_death(Some(alice()).into(), bob(), 1000), - Arithmetic(Underflow) - ); - - // Counter should remain 0 since transfer failed - assert_eq!(Balances::transfer_count(), 0); - }); -} - -#[test] -fn transfer_proof_storage_key_generation() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - let transfer_count = 5u64; - let from = alice(); - let to = bob(); - let amount = 100u128; - - // Generate storage key - let key = Balances::transfer_proof_storage_key( - transfer_count, - from.clone(), - to.clone(), - amount, - ); - - // Key should not be empty - assert!(!key.is_empty()); - - // The same parameters should generate the same key - let key2 = Balances::transfer_proof_storage_key( - transfer_count, - from.clone(), - to.clone(), - amount, - ); - assert_eq!(key, key2); - - // Different parameters should generate different keys - let key3 = Balances::transfer_proof_storage_key(transfer_count + 1, from, to, amount); - assert_ne!(key, key3); - }); -} - -#[test] -fn counter_saturates_at_max_value() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Set counter to near maximum value (u64::MAX - 1) - let near_max = u64::MAX - 1; - TransferCount::::put(near_max); - - assert_eq!(Balances::transfer_count(), near_max); - - // Perform a transfer - should increment to u64::MAX - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), bob(), 5)); - assert_eq!(Balances::transfer_count(), u64::MAX); - - // Perform another transfer - should saturate at u64::MAX - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), charlie(), 3)); - assert_eq!(Balances::transfer_count(), u64::MAX); - }); -} - -#[test] -fn transfer_counter_persists_across_blocks() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Perform transfer in block 1 - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), bob(), 5)); - assert_eq!(Balances::transfer_count(), 1); - - // Move to block 2 - System::set_block_number(2); - - // Counter should persist - assert_eq!(Balances::transfer_count(), 1); - - // Perform another transfer in block 2 - assert_ok!(Balances::transfer_allow_death(Some(bob()).into(), charlie(), 3)); - assert_eq!(Balances::transfer_count(), 2); - }); -} - -#[test] -fn zero_value_transfers_increment_counter() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Initial counter should be 0 - assert_eq!(Balances::transfer_count(), 0); - - // Perform a zero-value transfer - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), bob(), 0)); - - // Counter should increment even for zero-value transfers - assert_eq!(Balances::transfer_count(), 1); - - // Transfer proof should be created - let key = (0u64, alice(), bob(), 0u128); - assert!(TransferProof::::contains_key(&key)); - }); -} - -#[test] -fn different_transfer_types_all_increment_counter() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build_and_execute_with(|| { - // Initial counter should be 0 - assert_eq!(Balances::transfer_count(), 0); - - // transfer_allow_death - assert_ok!(Balances::transfer_allow_death(Some(alice()).into(), bob(), 1)); - assert_eq!(Balances::transfer_count(), 1); - - // transfer_keep_alive - assert_ok!(Balances::transfer_keep_alive(Some(alice()).into(), charlie(), 1)); - assert_eq!(Balances::transfer_count(), 2); - - // force_transfer - assert_ok!(Balances::force_transfer(RuntimeOrigin::root(), bob(), charlie(), 1)); - assert_eq!(Balances::transfer_count(), 3); - - // transfer_all (transfer remaining balance) - let remaining = Balances::free_balance(alice()); - if remaining > 1 { - assert_ok!(Balances::transfer_all(Some(alice()).into(), bob(), false)); - assert_eq!(Balances::transfer_count(), 4); - } - }); -} diff --git a/pallets/balances/src/types.rs b/pallets/balances/src/types.rs deleted file mode 100644 index a7ccfd3d..00000000 --- a/pallets/balances/src/types.rs +++ /dev/null @@ -1,164 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Types used in the pallet. - -use crate::{Config, CreditOf, Event, Pallet}; -use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; -use core::ops::BitOr; -use frame_support::traits::{Imbalance, LockIdentifier, OnUnbalanced, WithdrawReasons}; -use scale_info::TypeInfo; -use sp_runtime::{RuntimeDebug, Saturating}; - -/// Simplified reasons for withdrawing balance. -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub enum Reasons { - /// Paying system transaction fees. - Fee = 0, - /// Any reason other than paying system transaction fees. - Misc = 1, - /// Any reason at all. - All = 2, -} - -impl From for Reasons { - fn from(r: WithdrawReasons) -> Reasons { - if r == WithdrawReasons::TRANSACTION_PAYMENT { - Reasons::Fee - } else if r.contains(WithdrawReasons::TRANSACTION_PAYMENT) { - Reasons::All - } else { - Reasons::Misc - } - } -} - -impl BitOr for Reasons { - type Output = Reasons; - fn bitor(self, other: Reasons) -> Reasons { - if self == other { - return self; - } - Reasons::All - } -} - -/// A single lock on a balance. There can be many of these on an account and they "overlap", so the -/// same balance is frozen by multiple locks. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct BalanceLock { - /// An identifier for this lock. Only one lock may be in existence for each identifier. - pub id: LockIdentifier, - /// The amount which the free balance may not drop below when this lock is in effect. - pub amount: Balance, - /// If true, then the lock remains in effect even for payment of transaction fees. - pub reasons: Reasons, -} - -/// Store named reserved balance. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct ReserveData { - /// The identifier for the named reserve. - pub id: ReserveIdentifier, - /// The amount of the named reserve. - pub amount: Balance, -} - -/// All balance information for an account. -#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct AccountData { - /// Non-reserved part of the balance which the account holder may be able to control. - /// - /// This is the only balance that matters in terms of most operations on tokens. - pub free: Balance, - /// Balance which is has active holds on it and may not be used at all. - /// - /// This is the sum of all individual holds together with any sums still under the (deprecated) - /// reserves API. - pub reserved: Balance, - /// The amount that `free + reserved` may not drop below when reducing the balance, except for - /// actions where the account owner cannot reasonably benefit from the balance reduction, such - /// as slashing. - pub frozen: Balance, - /// Extra information about this account. The MSB is a flag indicating whether the new ref- - /// counting logic is in place for this account. - pub flags: ExtraFlags, -} - -const IS_NEW_LOGIC: u128 = 0x80000000_00000000_00000000_00000000u128; - -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct ExtraFlags(pub(crate) u128); -impl Default for ExtraFlags { - fn default() -> Self { - Self(IS_NEW_LOGIC) - } -} -impl ExtraFlags { - pub fn old_logic() -> Self { - Self(0) - } - pub fn set_new_logic(&mut self) { - self.0 |= IS_NEW_LOGIC - } - pub fn is_new_logic(&self) -> bool { - (self.0 & IS_NEW_LOGIC) == IS_NEW_LOGIC - } -} - -impl AccountData { - pub fn usable(&self) -> Balance { - self.free.saturating_sub(self.frozen) - } - - /// The total balance in this account including any that is reserved and ignoring any frozen. - pub fn total(&self) -> Balance { - self.free.saturating_add(self.reserved) - } -} - -pub struct DustCleaner, I: 'static = ()>( - pub(crate) Option<(T::AccountId, CreditOf)>, -); - -impl, I: 'static> Drop for DustCleaner { - fn drop(&mut self) { - if let Some((who, dust)) = self.0.take() { - Pallet::::deposit_event(Event::DustLost { account: who, amount: dust.peek() }); - T::DustRemoval::on_unbalanced(dust); - } - } -} - -/// Whether something should be interpreted as an increase or a decrease. -#[derive( - Encode, - Decode, - Clone, - PartialEq, - Eq, - RuntimeDebug, - MaxEncodedLen, - TypeInfo, - DecodeWithMemTracking, -)] -pub enum AdjustmentDirection { - /// Increase the amount. - Increase, - /// Decrease the amount. - Decrease, -} diff --git a/pallets/balances/src/weights.rs b/pallets/balances/src/weights.rs deleted file mode 100644 index 0c7a1354..00000000 --- a/pallets/balances/src/weights.rs +++ /dev/null @@ -1,300 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Autogenerated weights for `pallet_balances` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-11-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-wiukf8gn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` - -// Executed Command: -// ./target/production/substrate-node -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_balances -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/balances/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -/// Weight functions needed for `pallet_balances`. -pub trait WeightInfo { - fn transfer_allow_death() -> Weight; - fn transfer_keep_alive() -> Weight; - fn force_set_balance_creating() -> Weight; - fn force_set_balance_killing() -> Weight; - fn force_transfer() -> Weight; - fn transfer_all() -> Weight; - fn force_unreserve() -> Weight; - fn upgrade_accounts(u: u32, ) -> Weight; - fn force_adjust_total_issuance() -> Weight; - fn burn_allow_death() -> Weight; - fn burn_keep_alive() -> Weight; -} - -/// Weights for `pallet_balances` using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn transfer_allow_death() -> Weight { - // Proof Size summary in bytes: - // Measured: `52` - // Estimated: `3593` - // Minimum execution time: 50_023_000 picoseconds. - Weight::from_parts(51_105_000, 3593) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn transfer_keep_alive() -> Weight { - // Proof Size summary in bytes: - // Measured: `52` - // Estimated: `3593` - // Minimum execution time: 39_923_000 picoseconds. - Weight::from_parts(40_655_000, 3593) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn force_set_balance_creating() -> Weight { - // Proof Size summary in bytes: - // Measured: `174` - // Estimated: `3593` - // Minimum execution time: 15_062_000 picoseconds. - Weight::from_parts(15_772_000, 3593) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn force_set_balance_killing() -> Weight { - // Proof Size summary in bytes: - // Measured: `174` - // Estimated: `3593` - // Minimum execution time: 21_797_000 picoseconds. - Weight::from_parts(22_287_000, 3593) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn force_transfer() -> Weight { - // Proof Size summary in bytes: - // Measured: `155` - // Estimated: `6196` - // Minimum execution time: 51_425_000 picoseconds. - Weight::from_parts(52_600_000, 6196) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn transfer_all() -> Weight { - // Proof Size summary in bytes: - // Measured: `52` - // Estimated: `3593` - // Minimum execution time: 49_399_000 picoseconds. - Weight::from_parts(51_205_000, 3593) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn force_unreserve() -> Weight { - // Proof Size summary in bytes: - // Measured: `174` - // Estimated: `3593` - // Minimum execution time: 18_119_000 picoseconds. - Weight::from_parts(18_749_000, 3593) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:999 w:999) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// The range of component `u` is `[1, 1000]`. - fn upgrade_accounts(u: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + u * (135 ±0)` - // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 16_783_000 picoseconds. - Weight::from_parts(17_076_000, 990) - // Standard Error: 15_126 - .saturating_add(Weight::from_parts(14_834_157, 0).saturating_mul(u.into())) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) - .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) - } - fn force_adjust_total_issuance() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_048_000 picoseconds. - Weight::from_parts(6_346_000, 0) - } - fn burn_allow_death() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 30_215_000 picoseconds. - Weight::from_parts(30_848_000, 0) - } - fn burn_keep_alive() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 20_813_000 picoseconds. - Weight::from_parts(21_553_000, 0) - } -} - -// For backwards compatibility and tests. -impl WeightInfo for () { - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn transfer_allow_death() -> Weight { - // Proof Size summary in bytes: - // Measured: `52` - // Estimated: `3593` - // Minimum execution time: 50_023_000 picoseconds. - Weight::from_parts(51_105_000, 3593) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn transfer_keep_alive() -> Weight { - // Proof Size summary in bytes: - // Measured: `52` - // Estimated: `3593` - // Minimum execution time: 39_923_000 picoseconds. - Weight::from_parts(40_655_000, 3593) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn force_set_balance_creating() -> Weight { - // Proof Size summary in bytes: - // Measured: `174` - // Estimated: `3593` - // Minimum execution time: 15_062_000 picoseconds. - Weight::from_parts(15_772_000, 3593) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn force_set_balance_killing() -> Weight { - // Proof Size summary in bytes: - // Measured: `174` - // Estimated: `3593` - // Minimum execution time: 21_797_000 picoseconds. - Weight::from_parts(22_287_000, 3593) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:2 w:2) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn force_transfer() -> Weight { - // Proof Size summary in bytes: - // Measured: `155` - // Estimated: `6196` - // Minimum execution time: 51_425_000 picoseconds. - Weight::from_parts(52_600_000, 6196) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn transfer_all() -> Weight { - // Proof Size summary in bytes: - // Measured: `52` - // Estimated: `3593` - // Minimum execution time: 49_399_000 picoseconds. - Weight::from_parts(51_205_000, 3593) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn force_unreserve() -> Weight { - // Proof Size summary in bytes: - // Measured: `174` - // Estimated: `3593` - // Minimum execution time: 18_119_000 picoseconds. - Weight::from_parts(18_749_000, 3593) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `System::Account` (r:999 w:999) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - /// The range of component `u` is `[1, 1000]`. - fn upgrade_accounts(u: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + u * (135 ±0)` - // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 16_783_000 picoseconds. - Weight::from_parts(17_076_000, 990) - // Standard Error: 15_126 - .saturating_add(Weight::from_parts(14_834_157, 0).saturating_mul(u.into())) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(u.into()))) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(u.into()))) - .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) - } - fn force_adjust_total_issuance() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 6_048_000 picoseconds. - Weight::from_parts(6_346_000, 0) - } - fn burn_allow_death() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 30_215_000 picoseconds. - Weight::from_parts(30_848_000, 0) - } - fn burn_keep_alive() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 20_813_000 picoseconds. - Weight::from_parts(21_553_000, 0) - } -} diff --git a/pallets/merkle-airdrop/src/mock.rs b/pallets/merkle-airdrop/src/mock.rs index 0a5c865c..a2486392 100644 --- a/pallets/merkle-airdrop/src/mock.rs +++ b/pallets/merkle-airdrop/src/mock.rs @@ -80,6 +80,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeFreezeReason = (); type DoneSlashHandler = (); + type RuntimeEvent = RuntimeEvent; } parameter_types! { @@ -121,6 +122,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); pallet_balances::GenesisConfig:: { balances: vec![(1, 10_000_000), (MerkleAirdrop::account_id(), 1)], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); diff --git a/pallets/mining-rewards/src/lib.rs b/pallets/mining-rewards/src/lib.rs index cd2a8a32..e135ff79 100644 --- a/pallets/mining-rewards/src/lib.rs +++ b/pallets/mining-rewards/src/lib.rs @@ -26,7 +26,7 @@ pub mod pallet { }, }; use frame_system::pallet_prelude::*; - use qp_wormhole::TransferProofs; + use qp_wormhole::TransferProofRecorder; use sp_consensus_pow::POW_ENGINE_ID; use sp_runtime::{ generic::DigestItem, @@ -48,9 +48,18 @@ pub mod pallet { /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; - /// Currency type that also stores zk proofs - type Currency: Mutate - + qp_wormhole::TransferProofs, Self::AccountId>; + /// Currency type for minting rewards + type Currency: Mutate; + + /// Asset ID type for the proof recorder + type AssetId: Default; + + /// Proof recorder for storing wormhole transfer proofs + type ProofRecorder: qp_wormhole::TransferProofRecorder< + Self::AccountId, + Self::AssetId, + BalanceOf, + >; /// The base block reward given to miners #[pallet::constant] @@ -165,7 +174,12 @@ pub mod pallet { Some(miner) => { let _ = T::Currency::mint_into(&miner, reward).defensive(); - T::Currency::store_transfer_proof(&mint_account, &miner, reward); + let _ = T::ProofRecorder::record_transfer_proof( + None, + mint_account.clone(), + miner.clone(), + reward, + ); Self::deposit_event(Event::MinerRewarded { miner: miner.clone(), reward }); @@ -180,7 +194,12 @@ pub mod pallet { let treasury = T::TreasuryPalletId::get().into_account_truncating(); let _ = T::Currency::mint_into(&treasury, reward).defensive(); - T::Currency::store_transfer_proof(&mint_account, &treasury, reward); + let _ = T::ProofRecorder::record_transfer_proof( + None, + mint_account.clone(), + treasury.clone(), + reward, + ); Self::deposit_event(Event::TreasuryRewarded { reward }); diff --git a/pallets/mining-rewards/src/mock.rs b/pallets/mining-rewards/src/mock.rs index e69e6012..1b036245 100644 --- a/pallets/mining-rewards/src/mock.rs +++ b/pallets/mining-rewards/src/mock.rs @@ -67,6 +67,7 @@ impl frame_system::Config for Test { } impl pallet_balances::Config for Test { + type RuntimeEvent = RuntimeEvent; type RuntimeHoldReason = (); type RuntimeFreezeReason = (); type WeightInfo = (); @@ -87,8 +88,27 @@ parameter_types! { pub const MintingAccount: sp_core::crypto::AccountId32 = sp_core::crypto::AccountId32::new([99u8; 32]); } +// Mock proof recorder that does nothing +pub struct MockProofRecorder; +impl qp_wormhole::TransferProofRecorder + for MockProofRecorder +{ + type Error = (); + + fn record_transfer_proof( + _asset_id: Option, + _from: sp_core::crypto::AccountId32, + _to: sp_core::crypto::AccountId32, + _amount: u128, + ) -> Result<(), Self::Error> { + Ok(()) + } +} + impl pallet_mining_rewards::Config for Test { type Currency = Balances; + type AssetId = u32; + type ProofRecorder = MockProofRecorder; type WeightInfo = (); type MinerBlockReward = BlockReward; type TreasuryBlockReward = TreasuryBlockReward; @@ -115,6 +135,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { pallet_balances::GenesisConfig:: { balances: vec![(miner(), ExistentialDeposit::get()), (miner2(), ExistentialDeposit::get())], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); diff --git a/pallets/reversible-transfers/src/tests/mock.rs b/pallets/reversible-transfers/src/tests/mock.rs index 39aa6052..3c078314 100644 --- a/pallets/reversible-transfers/src/tests/mock.rs +++ b/pallets/reversible-transfers/src/tests/mock.rs @@ -349,6 +349,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { // Treasury account for fee collection tests (must meet existential deposit) (account_id(99), 1), ], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); diff --git a/pallets/wormhole/Cargo.toml b/pallets/wormhole/Cargo.toml index 78e624e7..a1a1d064 100644 --- a/pallets/wormhole/Cargo.toml +++ b/pallets/wormhole/Cargo.toml @@ -27,10 +27,12 @@ scale-info = { workspace = true, default-features = false, features = [ ] } sp-core.workspace = true sp-io.workspace = true +sp-metadata-ir.workspace = true sp-runtime.workspace = true [dev-dependencies] hex = { workspace = true, features = ["alloc"] } +pallet-assets = { workspace = true, features = ["std"] } qp-dilithium-crypto = { workspace = true, features = ["std"] } qp-plonky2 = { workspace = true, default-features = false } qp-poseidon-core.workspace = true diff --git a/pallets/wormhole/common.bin b/pallets/wormhole/common.bin index 9232df9c3bdbf92f77f73c7a28db999bdfafe660..5fbea0f3cae044a80d0ad7def777f01eaf656179 100644 GIT binary patch delta 14 Vcmey!_mOXdC^MtjW-;by762x)1PK5D delta 14 Vcmey!_mOXdC^MtzW-;by762x!1PA~C diff --git a/pallets/wormhole/src/lib.rs b/pallets/wormhole/src/lib.rs index 86d8281a..ec635407 100644 --- a/pallets/wormhole/src/lib.rs +++ b/pallets/wormhole/src/lib.rs @@ -2,8 +2,13 @@ extern crate alloc; +use core::marker::PhantomData; + +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::StorageHasher; use lazy_static::lazy_static; pub use pallet::*; +use qp_poseidon::PoseidonHasher as PoseidonCore; use qp_wormhole_verifier::WormholeVerifier; #[cfg(test)] @@ -11,6 +16,7 @@ mod mock; #[cfg(test)] mod tests; pub mod weights; +use sp_metadata_ir::StorageHasherIR; pub use weights::*; #[cfg(feature = "runtime-benchmarks")] @@ -29,43 +35,86 @@ pub fn get_wormhole_verifier() -> Result<&'static WormholeVerifier, &'static str WORMHOLE_VERIFIER.as_ref().ok_or("Wormhole verifier not available") } +pub struct PoseidonStorageHasher(PhantomData); + +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) + } + + fn max_len() -> usize { + 32 + } +} + #[frame_support::pallet] pub mod pallet { - use crate::WeightInfo; + use crate::{PoseidonStorageHasher, WeightInfo}; use alloc::vec::Vec; use codec::Decode; use frame_support::{ pallet_prelude::*, traits::{ fungible::{Mutate, Unbalanced}, + fungibles::{self, Inspect as FungiblesInspect, Mutate as FungiblesMutate}, + tokens::Preservation, Currency, ExistenceRequirement, WithdrawReasons, }, weights::WeightToFee, }; use frame_system::pallet_prelude::*; - use qp_wormhole::TransferProofs; use qp_wormhole_circuit::inputs::PublicCircuitInputs; use qp_wormhole_verifier::ProofWithPublicInputs; use qp_zk_circuits_common::circuit::{C, D, F}; use sp_runtime::{ - traits::{Saturating, Zero}, + traits::{Saturating, StaticLookup, Zero}, Perbill, }; pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; + pub type AssetIdOf = <::Assets as fungibles::Inspect< + ::AccountId, + >>::AssetId; + pub type AssetBalanceOf = <::Assets as fungibles::Inspect< + ::AccountId, + >>::Balance; + pub type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; #[pallet::pallet] pub struct Pallet(_); #[pallet::config] - pub trait Config: frame_system::Config { - /// Currency type used for minting tokens and handling wormhole transfers + pub trait Config: frame_system::Config + where + AssetIdOf: Default + From + Clone, + BalanceOf: Default, + AssetBalanceOf: Into> + From>, + { + /// Currency type used for native token transfers and minting type Currency: Mutate> - + TransferProofs, Self::AccountId> + Unbalanced + Currency; + /// Assets type used for managing fungible assets + type Assets: fungibles::Inspect + + fungibles::Mutate + + fungibles::Create; + + /// Transfer count type used in storage + type TransferCount: Parameter + + MaxEncodedLen + + Default + + Saturating + + Copy + + sp_runtime::traits::One; + /// Account ID used as the "from" account when creating transfer proofs for minted tokens #[pallet::constant] type MintingAccount: Get; @@ -81,10 +130,41 @@ pub mod pallet { pub(super) type UsedNullifiers = StorageMap<_, Blake2_128Concat, [u8; 32], bool, ValueQuery>; + /// Transfer proofs for wormhole transfers (both native and assets) + #[pallet::storage] + #[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) */ + (), + OptionQuery, + >; + + /// Transfer count for all wormhole transfers + #[pallet::storage] + #[pallet::getter(fn transfer_count)] + pub type TransferCount = StorageValue<_, T::TransferCount, ValueQuery>; + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - ProofVerified { exit_amount: BalanceOf }, + 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, + }, } #[pallet::error] @@ -99,6 +179,8 @@ pub mod pallet { StorageRootMismatch, BlockNotFound, InvalidBlockNumber, + AssetNotFound, + SelfTransfer, } #[pallet::call] @@ -167,6 +249,10 @@ pub mod pallet { let exit_account = T::AccountId::decode(&mut &exit_account_bytes[..]) .map_err(|_| Error::::InvalidPublicInputs)?; + // Extract asset_id from public inputs + let asset_id_u32 = public_inputs.asset_id; + let asset_id: AssetIdOf = asset_id_u32.into(); + // Calculate fees first let weight = ::WeightInfo::verify_wormhole_proof(); let weight_fee = T::WeightToFee::weight_to_fee(&weight); @@ -174,34 +260,154 @@ pub mod pallet { let volume_fee = volume_fee_perbill * exit_balance; let total_fee = weight_fee.saturating_add(volume_fee); - // Mint tokens to the exit account - // This does not affect total issuance and does not create an imbalance - >::increase_balance( - &exit_account, - exit_balance, - frame_support::traits::tokens::Precision::Exact, - )?; + // Handle native (asset_id = 0) or asset transfers + if asset_id == AssetIdOf::::default() { + // Native token transfer + // Mint tokens to the exit account + // This does not affect total issuance and does not create an imbalance + >::increase_balance( + &exit_account, + exit_balance, + frame_support::traits::tokens::Precision::Exact, + )?; - // Withdraw fee from exit account if fees are non-zero - // This creates a negative imbalance that will be handled by the transaction payment - // pallet - if !total_fee.is_zero() { - let _fee_imbalance = T::Currency::withdraw( + // Withdraw fee from exit account if fees are non-zero + // This creates a negative imbalance that will be handled by the transaction payment + // pallet + if !total_fee.is_zero() { + let _fee_imbalance = T::Currency::withdraw( + &exit_account, + total_fee, + WithdrawReasons::TRANSACTION_PAYMENT, + ExistenceRequirement::KeepAlive, + )?; + } + } else { + // Asset transfer + let asset_balance: AssetBalanceOf = exit_balance.into(); + >::mint_into( + asset_id.clone(), &exit_account, - total_fee, - WithdrawReasons::TRANSACTION_PAYMENT, - ExistenceRequirement::KeepAlive, + asset_balance, )?; + + // For assets, we still need to charge fees in native currency + // The exit account must have enough native balance to pay fees + if !total_fee.is_zero() { + let _fee_imbalance = T::Currency::withdraw( + &exit_account, + total_fee, + WithdrawReasons::TRANSACTION_PAYMENT, + ExistenceRequirement::AllowDeath, + )?; + } } // Create a transfer proof for the minted tokens let mint_account = T::MintingAccount::get(); - T::Currency::store_transfer_proof(&mint_account, &exit_account, exit_balance); + Self::record_transfer(asset_id, mint_account, exit_account, exit_balance)?; // Emit event Self::deposit_event(Event::ProofVerified { exit_amount: exit_balance }); Ok(()) } + + /// Transfer native tokens and store proof for wormhole + #[pallet::call_index(1)] + #[pallet::weight(T::DbWeight::get().reads_writes(1, 2))] + pub fn transfer_native( + origin: OriginFor, + dest: AccountIdLookupOf, + #[pallet::compact] amount: BalanceOf, + ) -> DispatchResult { + let source = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + + // Prevent self-transfers + ensure!(source != dest, Error::::SelfTransfer); + + // Perform the transfer + >::transfer(&source, &dest, amount, Preservation::Expendable)?; + + // Store proof with asset_id = Default (0 for native) + Self::record_transfer(AssetIdOf::::default(), source, dest, amount)?; + + Ok(()) + } + + /// Transfer asset tokens and store proof for wormhole + #[pallet::call_index(2)] + #[pallet::weight(T::DbWeight::get().reads_writes(2, 2))] + pub fn transfer_asset( + origin: OriginFor, + asset_id: AssetIdOf, + dest: AccountIdLookupOf, + #[pallet::compact] amount: AssetBalanceOf, + ) -> DispatchResult { + let source = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + + // Prevent self-transfers + ensure!(source != dest, Error::::SelfTransfer); + + // Check if asset exists + ensure!( + >::asset_exists(asset_id.clone()), + Error::::AssetNotFound + ); + + // Perform the transfer + >::transfer( + asset_id.clone(), + &source, + &dest, + amount, + Preservation::Expendable, + )?; + + // Store proof + Self::record_transfer(asset_id, source, dest, amount.into())?; + + Ok(()) + } + } + + // Helper functions for recording transfer proofs + impl Pallet { + /// Record a transfer proof + /// This should be called by transaction extensions or other runtime components + pub fn record_transfer( + asset_id: AssetIdOf, + from: T::AccountId, + to: T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let current_count = TransferCount::::get(); + TransferProof::::insert( + (asset_id, current_count, from.clone(), to.clone(), amount), + (), + ); + TransferCount::::put(current_count.saturating_add(T::TransferCount::one())); + + Ok(()) + } + } + + // Implement the TransferProofRecorder trait for other pallets to use + impl qp_wormhole::TransferProofRecorder, BalanceOf> + for Pallet + { + type Error = DispatchError; + + fn record_transfer_proof( + asset_id: Option>, + from: T::AccountId, + to: T::AccountId, + amount: BalanceOf, + ) -> Result<(), Self::Error> { + let asset_id_value = asset_id.unwrap_or_default(); + Self::record_transfer(asset_id_value, from, to, amount) + } } } diff --git a/pallets/wormhole/src/mock.rs b/pallets/wormhole/src/mock.rs index c902099c..7f0a4024 100644 --- a/pallets/wormhole/src/mock.rs +++ b/pallets/wormhole/src/mock.rs @@ -1,19 +1,19 @@ use crate as pallet_wormhole; use frame_support::{ construct_runtime, parameter_types, - traits::{ConstU32, Everything}, + traits::{ConstU128, ConstU32, Everything}, weights::IdentityFee, }; use frame_system::mocking::MockUncheckedExtrinsic; use qp_poseidon::PoseidonHasher; use sp_core::H256; use sp_runtime::{traits::IdentityLookup, BuildStorage}; -// --- MOCK RUNTIME --- construct_runtime!( pub enum Test { System: frame_system, Balances: pallet_balances, + Assets: pallet_assets, Wormhole: pallet_wormhole, } ); @@ -32,8 +32,6 @@ pub fn account_id(id: u64) -> AccountId { AccountId::new(bytes) } -// --- FRAME SYSTEM --- - parameter_types! { pub const BlockHashCount: u64 = 250; } @@ -71,8 +69,6 @@ impl frame_system::Config for Test { type PostTransactions = (); } -// --- PALLET BALANCES --- - parameter_types! { pub const ExistentialDeposit: Balance = 1; } @@ -91,9 +87,31 @@ impl pallet_balances::Config for Test { type MaxReserves = (); type MaxFreezes = (); type DoneSlashHandler = (); + type RuntimeEvent = RuntimeEvent; } -// --- PALLET WORMHOLE --- +impl pallet_assets::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = u32; + type AssetIdParameter = u32; + type Currency = Balances; + type CreateOrigin = + frame_support::traits::AsEnsureOriginWithArg>; + type ForceOrigin = frame_system::EnsureRoot; + type AssetDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<1>; + type MetadataDepositBase = ConstU128<1>; + type MetadataDepositPerByte = ConstU128<1>; + type ApprovalDeposit = ConstU128<1>; + type StringLimit = ConstU32<50>; + type Freezer = (); + type Extra = (); + type WeightInfo = (); + type RemoveItemsLimit = ConstU32<1000>; + type CallbackHandle = (); + type Holder = (); +} parameter_types! { pub const MintingAccount: AccountId = AccountId::new([ @@ -106,19 +124,13 @@ impl pallet_wormhole::Config for Test { type WeightInfo = crate::weights::SubstrateWeight; type WeightToFee = IdentityFee; type Currency = Balances; + type Assets = Assets; + type TransferCount = u64; type MintingAccount = MintingAccount; } // Helper function to build a genesis configuration pub fn new_test_ext() -> sp_state_machine::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - let endowment = 1e18 as Balance; - pallet_balances::GenesisConfig:: { - balances: vec![(account_id(1), endowment), (account_id(2), endowment)], - } - .assimilate_storage(&mut t) - .unwrap(); - + let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); t.into() } diff --git a/pallets/wormhole/src/tests.rs b/pallets/wormhole/src/tests.rs index ae2a7de1..74054d08 100644 --- a/pallets/wormhole/src/tests.rs +++ b/pallets/wormhole/src/tests.rs @@ -21,7 +21,6 @@ mod wormhole_tests { }; use sp_runtime::{traits::Header, DigestItem}; - // Helper function to generate proof and inputs for fn generate_proof(inputs: CircuitInputs) -> ProofWithPublicInputs { let config = CircuitConfig::standard_recursion_config(); let prover = WormholeProver::new(config); @@ -32,7 +31,6 @@ mod wormhole_tests { #[test] fn test_wormhole_transfer_proof_generation() { - // Setup accounts let alice = account_id(1); let secret: BytesDigest = [1u8; 32].try_into().expect("valid secret"); let unspendable_account = @@ -49,12 +47,10 @@ mod wormhole_tests { let mut ext = new_test_ext(); - // Execute the transfer and get the header let (storage_key, state_root, leaf_hash, event_transfer_count, header) = ext.execute_with(|| { System::set_block_number(1); - // Add dummy digest items to match expected format let pre_runtime_data = vec![ 233, 182, 183, 107, 158, 1, 115, 19, 219, 126, 253, 86, 30, 208, 176, 70, 21, 45, 180, 229, 9, 62, 91, 4, 6, 53, 245, 52, 48, 38, 123, 225, @@ -68,18 +64,18 @@ mod wormhole_tests { System::deposit_log(DigestItem::PreRuntime(*b"pow_", pre_runtime_data)); System::deposit_log(DigestItem::Seal(*b"pow_", seal_data)); - assert_ok!(Balances::mint_into(&unspendable_account_id, funding_amount)); - assert_ok!(Balances::transfer_keep_alive( + assert_ok!(Balances::mint_into(&alice, funding_amount)); + assert_ok!(Wormhole::transfer_native( frame_system::RawOrigin::Signed(alice.clone()).into(), unspendable_account_id.clone(), funding_amount, )); - let transfer_count = pallet_balances::TransferCount::::get(); - let event_transfer_count = transfer_count - 1; + let event_transfer_count = 0u64; let leaf_hash = PoseidonHasher::hash_storage::( &( + 0u32, event_transfer_count, alice.clone(), unspendable_account_id.clone(), @@ -88,7 +84,8 @@ mod wormhole_tests { .encode(), ); - let proof_address = pallet_balances::TransferProof::::hashed_key_for(&( + let proof_address = crate::pallet::TransferProof::::hashed_key_for(&( + 0u32, event_transfer_count, alice.clone(), unspendable_account_id.clone(), @@ -103,36 +100,31 @@ mod wormhole_tests { (storage_key, state_root, leaf_hash, event_transfer_count, header) }); - // Generate a storage proof for the specific storage key use sp_state_machine::prove_read; let proof = prove_read(ext.as_backend(), &[&storage_key]) .expect("failed to generate storage proof"); let proof_nodes_vec: Vec> = proof.iter_nodes().map(|n| n.to_vec()).collect(); - // Prepare the storage proof for the circuit let processed_storage_proof = prepare_proof_for_circuit(proof_nodes_vec, hex::encode(&state_root), leaf_hash) .expect("failed to prepare proof for circuit"); - // Build the header components let parent_hash = *header.parent_hash(); let extrinsics_root = *header.extrinsics_root(); let digest = header.digest().encode(); let digest_array: [u8; 110] = digest.try_into().expect("digest should be 110 bytes"); let block_number: u32 = (*header.number()).try_into().expect("block number fits in u32"); - // Compute block hash let block_hash = header.hash(); - // Assemble circuit inputs let circuit_inputs = CircuitInputs { private: PrivateCircuitInputs { secret, + storage_proof: processed_storage_proof, transfer_count: event_transfer_count, funding_account: BytesDigest::try_from(alice.as_ref() as &[u8]) .expect("account is 32 bytes"), - storage_proof: processed_storage_proof, unspendable_account: Digest::from(unspendable_account).into(), state_root: BytesDigest::try_from(state_root.as_ref()) .expect("state root is 32 bytes"), @@ -141,6 +133,7 @@ mod wormhole_tests { digest: digest_array, }, public: PublicCircuitInputs { + asset_id: 0u32, funding_amount, nullifier: Nullifier::from_preimage(secret, event_transfer_count).hash.into(), exit_account: BytesDigest::try_from(exit_account_id.as_ref() as &[u8]) @@ -153,33 +146,25 @@ mod wormhole_tests { }, }; - // Generate the ZK proof let proof = generate_proof(circuit_inputs); - // Verify the proof can be parsed let public_inputs = PublicCircuitInputs::try_from(&proof).expect("failed to parse public inputs"); - // Verify that the public inputs match what we expect assert_eq!(public_inputs.funding_amount, funding_amount); assert_eq!( public_inputs.exit_account, BytesDigest::try_from(exit_account_id.as_ref() as &[u8]).unwrap() ); - // Verify the proof using the verifier let verifier = get_wormhole_verifier().expect("verifier should be available"); verifier.verify(proof.clone()).expect("proof should verify"); - // Serialize the proof to bytes for extrinsic testing let proof_bytes = proof.to_bytes(); - // Now test the extrinsic in a new environment new_test_ext().execute_with(|| { - // Set up the blockchain state to have block 1 System::set_block_number(1); - // Add the same digest items let pre_runtime_data = vec![ 233, 182, 183, 107, 158, 1, 115, 19, 219, 126, 253, 86, 30, 208, 176, 70, 21, 45, 180, 229, 9, 62, 91, 4, 6, 53, 245, 52, 48, 38, 123, 225, @@ -193,36 +178,28 @@ mod wormhole_tests { System::deposit_log(DigestItem::PreRuntime(*b"pow_", pre_runtime_data)); System::deposit_log(DigestItem::Seal(*b"pow_", seal_data)); - // Execute the same transfer to recreate the exact state - assert_ok!(Balances::mint_into(&unspendable_account_id, funding_amount)); - assert_ok!(Balances::transfer_keep_alive( + assert_ok!(Balances::mint_into(&alice, funding_amount)); + assert_ok!(Wormhole::transfer_native( frame_system::RawOrigin::Signed(alice.clone()).into(), unspendable_account_id.clone(), funding_amount, )); - // Finalize the block to get the same header and store the block hash let block_1_header = System::finalize(); - // Initialize block 2 to store block 1's hash System::reset_events(); System::initialize(&2, &block_1_header.hash(), block_1_header.digest()); - // Check exit account balance before verification let balance_before = Balances::balance(&exit_account_id); assert_eq!(balance_before, 0); - // Call the verify_wormhole_proof extrinsic assert_ok!(Wormhole::verify_wormhole_proof( frame_system::RawOrigin::None.into(), proof_bytes.clone() )); - // Check that the exit account received the funds (minus fees) let balance_after = Balances::balance(&exit_account_id); - // The balance should be funding_amount minus fees - // Weight fee + 0.1% volume fee assert!(balance_after > 0, "Exit account should have received funds"); assert!( balance_after < funding_amount, @@ -230,33 +207,160 @@ mod wormhole_tests { ); }); - // Test that proof fails when state doesn't match new_test_ext().execute_with(|| { - // Set up block 1 but DON'T recreate the exact same state System::set_block_number(1); - // Add different digest items with same 110-byte format but different content - let pre_runtime_data = vec![1u8; 32]; // Different data - let seal_data = vec![2u8; 64]; // Different data + let pre_runtime_data = vec![1u8; 32]; + let seal_data = vec![2u8; 64]; System::deposit_log(DigestItem::PreRuntime(*b"pow_", pre_runtime_data)); System::deposit_log(DigestItem::Seal(*b"pow_", seal_data)); - // Finalize block 1 with different state let different_header = System::finalize(); - // Initialize block 2 System::reset_events(); System::initialize(&2, &different_header.hash(), different_header.digest()); - // Try to use the proof with the original header (which has different block hash) let result = Wormhole::verify_wormhole_proof( frame_system::RawOrigin::None.into(), proof_bytes.clone(), ); - // This should fail because the block hash in the proof doesn't match assert!(result.is_err(), "Proof verification should fail with mismatched state"); }); } + + #[test] + fn transfer_native_works() { + new_test_ext().execute_with(|| { + let alice = account_id(1); + let bob = account_id(2); + let amount = 1000u128; + + assert_ok!(Balances::mint_into(&alice, amount * 2)); + + let count_before = Wormhole::transfer_count(); + assert_ok!(Wormhole::transfer_native( + frame_system::RawOrigin::Signed(alice.clone()).into(), + bob.clone(), + amount, + )); + + assert_eq!(Balances::balance(&alice), amount); + assert_eq!(Balances::balance(&bob), amount); + assert_eq!(Wormhole::transfer_count(), count_before + 1); + assert!(Wormhole::transfer_proof((0u32, count_before, alice, bob, amount)).is_some()); + }); + } + + #[test] + fn transfer_native_fails_on_self_transfer() { + new_test_ext().execute_with(|| { + let alice = account_id(1); + let amount = 1000u128; + + assert_ok!(Balances::mint_into(&alice, amount)); + + let result = Wormhole::transfer_native( + frame_system::RawOrigin::Signed(alice.clone()).into(), + alice.clone(), + amount, + ); + + assert!(result.is_err()); + }); + } + + #[test] + fn transfer_asset_works() { + new_test_ext().execute_with(|| { + let alice = account_id(1); + let bob = account_id(2); + let asset_id = 1u32; + let amount = 1000u128; + + assert_ok!(Balances::mint_into(&alice, 1000)); + assert_ok!(Balances::mint_into(&bob, 1000)); + + assert_ok!(Assets::create( + frame_system::RawOrigin::Signed(alice.clone()).into(), + asset_id.into(), + alice.clone(), + 1, + )); + assert_ok!(Assets::mint( + frame_system::RawOrigin::Signed(alice.clone()).into(), + asset_id.into(), + alice.clone(), + amount * 2, + )); + + let count_before = Wormhole::transfer_count(); + assert_ok!(Wormhole::transfer_asset( + frame_system::RawOrigin::Signed(alice.clone()).into(), + asset_id, + bob.clone(), + amount, + )); + + assert_eq!(Assets::balance(asset_id, &alice), amount); + assert_eq!(Assets::balance(asset_id, &bob), amount); + assert_eq!(Wormhole::transfer_count(), count_before + 1); + assert!( + Wormhole::transfer_proof((asset_id, count_before, alice, bob, amount)).is_some() + ); + }); + } + + #[test] + fn transfer_asset_fails_on_nonexistent_asset() { + new_test_ext().execute_with(|| { + let alice = account_id(1); + let bob = account_id(2); + let asset_id = 999u32; + let amount = 1000u128; + + let result = Wormhole::transfer_asset( + frame_system::RawOrigin::Signed(alice.clone()).into(), + asset_id, + bob.clone(), + amount, + ); + + assert!(result.is_err()); + }); + } + + #[test] + fn transfer_asset_fails_on_self_transfer() { + new_test_ext().execute_with(|| { + let alice = account_id(1); + let asset_id = 1u32; + let amount = 1000u128; + + assert_ok!(Balances::mint_into(&alice, 1000)); + + assert_ok!(Assets::create( + frame_system::RawOrigin::Signed(alice.clone()).into(), + asset_id.into(), + alice.clone(), + 1, + )); + assert_ok!(Assets::mint( + frame_system::RawOrigin::Signed(alice.clone()).into(), + asset_id.into(), + alice.clone(), + amount, + )); + + let result = Wormhole::transfer_asset( + frame_system::RawOrigin::Signed(alice.clone()).into(), + asset_id, + alice.clone(), + amount, + ); + + assert!(result.is_err()); + }); + } } diff --git a/pallets/wormhole/verifier.bin b/pallets/wormhole/verifier.bin index 121eb2b02d5badfed2fbdcc2c29e9d7a7ffec909..229b59d97d5e8e140b16a1bc97e9549f0e4bc250 100644 GIT binary patch literal 552 zcmV+@0@wWn000000001mTjTr3B2agUHfFrUGtEY?c|aBKvf6rpL30{-^KRXXhj{y2 zz8rIqg$hj))SW(&TT7nI=r=es;;pp^jB9#{Wjfz5a$)`k+E?!pk^>&gHRX$Ingu`y8n-c zJ4+g-gc+nLhyn3)HX@t(d~8{_e(RT+vai%?7x2){Ce*}7_VylH$PGOLr)tkX#p})s zr7qItfqi#*J=?eEk2o=|CDSY_n{R`|O1U8T??>5(E688U=+Uj_pQxX(RL~e&kD1Pi z_i`~Yi$@m0KytTd7b+bf7E}nZ_#UPwlzOM)`cxy{9CBMxTGcWQxCcW?M<{4g+(VC~ z4v$C+4f{RIosj!{M*%kuv>w@IFe22t-faOfu;e#vsJH)K`f9dloD`s(J){@l1q|hK qi>>->!lCIbJkXVcY)vNi24;Io?*Yn7P+jd*v`UX^%^YUdrQkHvuml_sF!}-T;4qK!GOD-UtYyb zZfVj=Uoi;ph0JLtv6@F>U9H=K?8W=9Um3#E&28RBK*imrCh|tLm``n>T0iw%B&g~U zLHCzUTEj;0(O=t!{eN>!%#+cA6Jn(-a7yeFbw!h6R3ADGoPx(lp`OJ9E9cB0yYUCvl07q z2E9l&(l;2u;gF8HIhzbxcX&Omio1+M9&4fZM%uPN(d_}gXv3BeaZh4RY>l>s?G9bk z&ekwT5?b=MPr;MuP0MkQ%(e&ddMhGQVUJ5L>W-xNqo|R;gFc|_#5f`v2^nITGT}?g z)0Gs3-u}JJUGbhZm!M0U++70}*uA7{Dveh_&fT$~77p?a*$|iW9q^4&?iN?J93InB z_r-UE{N^JNuC9aIJk+lv!L++*S;2N+gcngm8J6`v+%Xqm<$jET;|f!$tR5)JxbPf~ qKk { + /// Error type for proof recording failures + type Error; -/// Trait for managing wormhole transfer proofs. -pub trait TransferProofs { - /// Get transfer proof, if any - fn transfer_proof_exists( - count: TxCount, - from: &AccountId, - to: &AccountId, - value: Balance, - ) -> bool; - - /// Get transfer proof key - fn transfer_proof_key( - count: TxCount, + /// Record a transfer proof for native or asset tokens + /// - `None` for native tokens (asset_id = 0) + /// - `Some(asset_id)` for specific assets + fn record_transfer_proof( + asset_id: Option, from: AccountId, to: AccountId, - value: Balance, - ) -> Vec; - - /// Store transfer proofs for a given wormhole transfer. - fn store_transfer_proof(from: &AccountId, to: &AccountId, value: Balance); + amount: Balance, + ) -> Result<(), Self::Error>; } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index d236ac50..9bb0e64b 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -53,6 +53,10 @@ qp-dilithium-crypto.workspace = true qp-header = { workspace = true, features = ["serde"] } qp-poseidon = { workspace = true, features = ["serde"] } qp-scheduler.workspace = true +qp-wormhole.workspace = true +qp-wormhole-circuit = { workspace = true, default-features = false } +qp-wormhole-verifier = { workspace = true, default-features = false } +qp-zk-circuits-common = { workspace = true, default-features = false } scale-info = { features = ["derive", "serde"], workspace = true } serde_json = { workspace = true, default-features = false, features = [ "alloc", diff --git a/runtime/src/configs/mod.rs b/runtime/src/configs/mod.rs index 693319cf..c50898d8 100644 --- a/runtime/src/configs/mod.rs +++ b/runtime/src/configs/mod.rs @@ -63,10 +63,10 @@ use sp_version::RuntimeVersion; // Local module imports use super::{ - AccountId, Balance, Balances, Block, BlockNumber, Hash, Nonce, OriginCaller, PalletInfo, - Preimage, Referenda, Runtime, RuntimeCall, RuntimeEvent, RuntimeFreezeReason, - RuntimeHoldReason, RuntimeOrigin, RuntimeTask, Scheduler, System, Timestamp, Vesting, DAYS, - EXISTENTIAL_DEPOSIT, MICRO_UNIT, TARGET_BLOCK_TIME_MS, UNIT, VERSION, + AccountId, Assets, Balance, Balances, Block, BlockNumber, Hash, Nonce, OriginCaller, + PalletInfo, Preimage, Referenda, Runtime, RuntimeCall, RuntimeEvent, RuntimeFreezeReason, + RuntimeHoldReason, RuntimeOrigin, RuntimeTask, Scheduler, System, Timestamp, Vesting, Wormhole, + DAYS, EXISTENTIAL_DEPOSIT, MICRO_UNIT, TARGET_BLOCK_TIME_MS, UNIT, VERSION, }; use sp_core::U512; @@ -130,6 +130,8 @@ parameter_types! { impl pallet_mining_rewards::Config for Runtime { type Currency = Balances; + type AssetId = AssetId; + type ProofRecorder = Wormhole; type WeightInfo = pallet_mining_rewards::weights::SubstrateWeight; type MinerBlockReward = ConstU128<{ 10 * UNIT }>; // 10 tokens type TreasuryBlockReward = ConstU128<0>; // 0 tokens @@ -181,6 +183,7 @@ parameter_types! { } impl pallet_balances::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type WeightInfo = pallet_balances::weights::SubstrateWeight; @@ -630,5 +633,7 @@ impl pallet_wormhole::Config for Runtime { type MintingAccount = WormholeMintingAccount; type WeightInfo = (); type Currency = Balances; + type Assets = Assets; + type TransferCount = u64; type WeightToFee = IdentityFee; } diff --git a/runtime/src/genesis_config_presets.rs b/runtime/src/genesis_config_presets.rs index 57eb5182..c86a093c 100644 --- a/runtime/src/genesis_config_presets.rs +++ b/runtime/src/genesis_config_presets.rs @@ -19,14 +19,15 @@ #![allow(clippy::expect_used)] use crate::{ - configs::TreasuryPalletId, AccountId, BalancesConfig, RuntimeGenesisConfig, SudoConfig, UNIT, + configs::TreasuryPalletId, AccountId, AssetsConfig, BalancesConfig, RuntimeGenesisConfig, + SudoConfig, EXISTENTIAL_DEPOSIT, UNIT, }; use alloc::{vec, vec::Vec}; use qp_dilithium_crypto::pair::{crystal_alice, crystal_charlie, dilithium_bob}; use serde_json::Value; use sp_core::crypto::Ss58Codec; use sp_genesis_builder::{self, PresetId}; -use sp_runtime::traits::{AccountIdConversion, IdentifyAccount}; +use sp_runtime::traits::{AccountIdConversion, IdentifyAccount, Zero}; /// Identifier for the heisenberg runtime preset. pub const HEISENBERG_RUNTIME_PRESET: &str = "heisenberg"; @@ -62,8 +63,16 @@ fn genesis_template(endowed_accounts: Vec, root: AccountId) -> Value balances.push((treasury_account, ONE_BILLION * UNIT)); let config = RuntimeGenesisConfig { - balances: BalancesConfig { balances }, + balances: BalancesConfig { balances, dev_accounts: None }, sudo: SudoConfig { key: Some(root.clone()) }, + assets: AssetsConfig { + // We need to initialize and reserve the first asset id for the native token transfers + // with wormhole. + assets: vec![(Zero::zero(), root.clone(), false, EXISTENTIAL_DEPOSIT)], /* (asset_id, + * owner, is_sufficient, + * min_balance) */ + ..Default::default() + }, ..Default::default() }; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index d0835494..876fb79c 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -159,6 +159,7 @@ pub type TxExtension = ( pallet_transaction_payment::ChargeTransactionPayment, frame_metadata_hash_extension::CheckMetadataHash, transaction_extensions::ReversibleTransactionExtension, + transaction_extensions::WormholeProofRecorderExtension, ); /// Unchecked extrinsic type as expected by this runtime. diff --git a/runtime/src/transaction_extensions.rs b/runtime/src/transaction_extensions.rs index 5afed1e6..6216b96d 100644 --- a/runtime/src/transaction_extensions.rs +++ b/runtime/src/transaction_extensions.rs @@ -2,12 +2,17 @@ use crate::*; use codec::{Decode, DecodeWithMemTracking, Encode}; use core::marker::PhantomData; -use frame_support::pallet_prelude::{InvalidTransaction, ValidTransaction}; - +use frame_support::pallet_prelude::{ + InvalidTransaction, TransactionValidityError, ValidTransaction, +}; use frame_system::ensure_signed; +use qp_wormhole::TransferProofRecorder; use scale_info::TypeInfo; use sp_core::Get; -use sp_runtime::{traits::TransactionExtension, Weight}; +use sp_runtime::{ + traits::{DispatchInfoOf, PostDispatchInfoOf, StaticLookup, TransactionExtension}, + DispatchResult, Weight, +}; /// Transaction extension for reversible accounts /// @@ -45,7 +50,7 @@ impl _call: &RuntimeCall, _info: &sp_runtime::traits::DispatchInfoOf, _len: usize, - ) -> Result { + ) -> Result { Ok(()) } @@ -59,11 +64,8 @@ impl _inherited_implication: &impl sp_runtime::traits::Implication, _source: frame_support::pallet_prelude::TransactionSource, ) -> sp_runtime::traits::ValidateResult { - let who = ensure_signed(origin.clone()).map_err(|_| { - frame_support::pallet_prelude::TransactionValidityError::Invalid( - InvalidTransaction::BadSigner, - ) - })?; + let who = ensure_signed(origin.clone()) + .map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::BadSigner))?; if ReversibleTransfers::is_high_security(&who).is_some() { // High-security accounts can only call schedule_transfer and cancel @@ -80,9 +82,7 @@ impl return Ok((ValidTransaction::default(), (), origin)); }, _ => { - return Err(frame_support::pallet_prelude::TransactionValidityError::Invalid( - InvalidTransaction::Custom(1), - )); + return Err(TransactionValidityError::Invalid(InvalidTransaction::Custom(1))); }, } } @@ -91,6 +91,165 @@ impl } } +/// Details of a transfer to be recorded +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TransferDetails { + from: AccountId, + to: AccountId, + amount: Balance, + asset_id: AssetId, +} + +/// Transaction extension that records transfer proofs in the wormhole pallet +/// +/// This extension: +/// - Extracts transfer details from balance/asset transfer calls +/// - Records proofs in wormhole storage after successful execution +/// - Increments transfer count +/// - Emits events +/// - Fails the transaction if proof recording fails +#[derive(Encode, Decode, Clone, Eq, PartialEq, Default, TypeInfo, Debug, DecodeWithMemTracking)] +#[scale_info(skip_type_params(T))] +pub struct WormholeProofRecorderExtension(PhantomData); + +impl WormholeProofRecorderExtension { + /// Creates new extension + pub fn new() -> Self { + Self(PhantomData) + } + + /// Helper to convert lookup errors to transaction validity errors + fn lookup(address: &Address) -> Result { + ::Lookup::lookup(address.clone()) + .map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::BadSigner)) + } + + /// Extract transfer details from a runtime call + fn extract_transfer_details( + origin: &RuntimeOrigin, + call: &RuntimeCall, + ) -> Result, TransactionValidityError> { + // Only process signed transactions + let who = match ensure_signed(origin.clone()) { + Ok(signer) => signer, + Err(_) => return Ok(None), + }; + + let details = match call { + // Native balance transfers + RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { dest, value }) => { + let to = Self::lookup(dest)?; + Some(TransferDetails { from: who, to, amount: *value, asset_id: 0 }) + }, + RuntimeCall::Balances(pallet_balances::Call::transfer_allow_death { dest, value }) => { + let to = Self::lookup(dest)?; + Some(TransferDetails { from: who, to, amount: *value, asset_id: 0 }) + }, + RuntimeCall::Balances(pallet_balances::Call::transfer_all { .. }) => None, + + // Asset transfers + RuntimeCall::Assets(pallet_assets::Call::transfer { id, target, amount }) => { + let to = Self::lookup(target)?; + Some(TransferDetails { asset_id: id.0, from: who, to, amount: *amount }) + }, + RuntimeCall::Assets(pallet_assets::Call::transfer_keep_alive { + id, + target, + amount, + }) => { + let to = Self::lookup(target)?; + Some(TransferDetails { asset_id: id.0, from: who, to, amount: *amount }) + }, + + _ => None, + }; + + Ok(details) + } + + /// Record the transfer proof using the TransferProofRecorder trait + fn record_proof(details: TransferDetails) -> Result<(), TransactionValidityError> { + let asset_id = if details.asset_id == 0 { None } else { Some(details.asset_id) }; + + >::record_transfer_proof( + asset_id, + details.from, + details.to, + details.amount, + ) + .map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::Custom(100))) + } +} + +impl TransactionExtension + for WormholeProofRecorderExtension +{ + type Pre = Option; + type Val = (); + type Implicit = (); + + const IDENTIFIER: &'static str = "WormholeProofRecorderExtension"; + + 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 { .. }) => { + // 2 writes: TransferProof insert + TransferCount update + // 1 read: TransferCount get + T::DbWeight::get().reads_writes(1, 2) + }, + _ => Weight::zero(), + } + } + + fn prepare( + self, + _val: Self::Val, + origin: &sp_runtime::traits::DispatchOriginOf, + call: &RuntimeCall, + _info: &sp_runtime::traits::DispatchInfoOf, + _len: usize, + ) -> Result { + // Extract transfer details to pass to post_dispatch + Self::extract_transfer_details(origin, call) + } + + fn validate( + &self, + _origin: sp_runtime::traits::DispatchOriginOf, + _call: &RuntimeCall, + _info: &DispatchInfoOf, + _len: usize, + _self_implicit: Self::Implicit, + _inherited_implication: &impl sp_runtime::traits::Implication, + _source: frame_support::pallet_prelude::TransactionSource, + ) -> sp_runtime::traits::ValidateResult { + // No validation needed - just return Ok + Ok((ValidTransaction::default(), (), _origin)) + } + + fn post_dispatch( + pre: Self::Pre, + _info: &DispatchInfoOf, + post_info: &mut PostDispatchInfoOf, + _len: usize, + _result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + // Only record proof if the transaction succeeded (no error in post_info) + if post_info.actual_weight.is_some() || _result.is_ok() { + if let Some(details) = pre { + // Record the proof - if this fails, fail the whole transaction + Self::record_proof(details)?; + } + } + + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -117,6 +276,7 @@ mod tests { (bob(), EXISTENTIAL_DEPOSIT * 2), (charlie(), EXISTENTIAL_DEPOSIT * 100), ], + dev_accounts: None, } .assimilate_storage(&mut t) .unwrap(); @@ -326,8 +486,73 @@ mod tests { RuntimeCall::ReversibleTransfers(pallet_reversible_transfers::Call::cancel { tx_id: sp_core::H256::default(), }); - // High-security accounts can call cancel assert_ok!(check_call(call)); }); } + + #[test] + fn wormhole_proof_recorder_native_transfer() { + new_test_ext().execute_with(|| { + let alice_origin = RuntimeOrigin::signed(alice()); + let call = RuntimeCall::Balances(pallet_balances::Call::transfer_keep_alive { + dest: MultiAddress::Id(bob()), + value: 100 * UNIT, + }); + + let details = WormholeProofRecorderExtension::::extract_transfer_details( + &alice_origin, + &call, + ) + .unwrap(); + + assert!(details.is_some()); + let details = details.unwrap(); + assert_eq!(details.from, alice()); + assert_eq!(details.to, bob()); + assert_eq!(details.amount, 100 * UNIT); + assert_eq!(details.asset_id, 0); + }); + } + + #[test] + fn wormhole_proof_recorder_asset_transfer() { + new_test_ext().execute_with(|| { + let alice_origin = RuntimeOrigin::signed(alice()); + let asset_id = 42u32; + let call = RuntimeCall::Assets(pallet_assets::Call::transfer { + id: codec::Compact(asset_id), + target: MultiAddress::Id(bob()), + amount: 500, + }); + + let details = WormholeProofRecorderExtension::::extract_transfer_details( + &alice_origin, + &call, + ) + .unwrap(); + + assert!(details.is_some()); + let details = details.unwrap(); + assert_eq!(details.from, alice()); + assert_eq!(details.to, bob()); + assert_eq!(details.amount, 500); + assert_eq!(details.asset_id, asset_id); + }); + } + + #[test] + fn wormhole_proof_recorder_ignores_non_transfer() { + new_test_ext().execute_with(|| { + let alice_origin = RuntimeOrigin::signed(alice()); + let call = RuntimeCall::System(frame_system::Call::remark { remark: vec![1, 2, 3] }); + + let details = WormholeProofRecorderExtension::::extract_transfer_details( + &alice_origin, + &call, + ) + .unwrap(); + + assert!(details.is_none()); + }); + } } diff --git a/runtime/tests/governance/treasury.rs b/runtime/tests/governance/treasury.rs index 3b4fe933..3218957a 100644 --- a/runtime/tests/governance/treasury.rs +++ b/runtime/tests/governance/treasury.rs @@ -88,9 +88,12 @@ mod tests { pub fn build(self) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - pallet_balances::GenesisConfig:: { balances: self.balances } - .assimilate_storage(&mut t) - .unwrap(); + pallet_balances::GenesisConfig:: { + balances: self.balances, + dev_accounts: None, + } + .assimilate_storage(&mut t) + .unwrap(); // Pallet Treasury genesis (optional, as we fund it manually) // If your pallet_treasury::GenesisConfig needs setup, do it here. From 365eb946862d6340c6d8e0d0f012dc3c0e1920eb Mon Sep 17 00:00:00 2001 From: Dastan <88332432+dastansam@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:53:51 +0600 Subject: [PATCH 4/4] Use `ToFelts` trait in the wormhole pallet (#347) * Apply ToFelts changes to wormhole * Fix checks * Passing tests * Revert unit test line * Rename explicit AccountId --- Cargo.lock | 8 +-- Cargo.toml | 4 +- pallets/wormhole/src/lib.rs | 128 +++++++++++++++++++++++----------- pallets/wormhole/src/mock.rs | 1 + pallets/wormhole/src/tests.rs | 2 +- runtime/src/configs/mod.rs | 3 +- 6 files changed, 98 insertions(+), 48 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..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; }