From a04d02ec15f136ce7fa728102ab3d868fb22e4a3 Mon Sep 17 00:00:00 2001 From: Malte Kliemann Date: Fri, 4 Oct 2024 14:46:54 +0200 Subject: [PATCH] Implement zrml-combo extrinsics (#1369) * Extend `Config` * wip * Some refactors * Implement splitting tokens * Implement merging tokens --- Cargo.lock | 1 + primitives/src/asset.rs | 5 +- primitives/src/types.rs | 3 + zrml/combo/Cargo.toml | 1 + zrml/combo/src/lib.rs | 241 +++++++++++++++++- ...manager.rs => combinatorial_id_manager.rs} | 12 +- zrml/combo/src/traits/mod.rs | 4 +- .../decompressor/mod.rs | 24 +- .../tests/decompress_collection_id.rs | 4 +- .../decompressor/tests/decompress_hash.rs | 2 +- .../decompressor/tests/get_collection_id.rs | 6 +- .../cryptographic_id_manager/hash_tuple.rs | 8 +- .../src/types/cryptographic_id_manager/mod.rs | 23 +- .../cryptographic_id_manager/typedefs.rs | 1 - zrml/combo/src/types/hash.rs | 1 + zrml/combo/src/types/mod.rs | 4 +- 16 files changed, 283 insertions(+), 57 deletions(-) rename zrml/combo/src/traits/{id_manager.rs => combinatorial_id_manager.rs} (56%) delete mode 100644 zrml/combo/src/types/cryptographic_id_manager/typedefs.rs create mode 100644 zrml/combo/src/types/hash.rs diff --git a/Cargo.lock b/Cargo.lock index 71c880a47..77640a1b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15270,6 +15270,7 @@ dependencies = [ "frame-support", "frame-system", "halo2curves", + "orml-traits", "parity-scale-codec", "rstest", "scale-info", diff --git a/primitives/src/asset.rs b/primitives/src/asset.rs index d5c923537..2730a7a84 100644 --- a/primitives/src/asset.rs +++ b/primitives/src/asset.rs @@ -20,7 +20,7 @@ use crate::traits::ZeitgeistAssetEnumerator; use crate::{ traits::PoolSharesId, - types::{CategoryIndex, PoolId}, + types::{CategoryIndex, PoolId, CombinatorialId}, }; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -48,13 +48,14 @@ use serde::{Deserialize, Serialize}; pub enum Asset { CategoricalOutcome(MarketId, CategoryIndex), ScalarOutcome(MarketId, ScalarPosition), - CombinatorialOutcome, + CombinatorialToken(CombinatorialId), PoolShare(PoolId), #[default] Ztg, ForeignAsset(u32), ParimutuelShare(MarketId, CategoryIndex), } +// TODO Needs storage migration #[cfg(feature = "runtime-benchmarks")] impl ZeitgeistAssetEnumerator for Asset { diff --git a/primitives/src/types.rs b/primitives/src/types.rs index f361dd568..9b14f097f 100644 --- a/primitives/src/types.rs +++ b/primitives/src/types.rs @@ -54,6 +54,9 @@ pub type BlockNumber = u64; /// The index of the category for a `CategoricalOutcome` asset. pub type CategoryIndex = u16; +/// The type used to identify combinatorial outcomes. +pub type CombinatorialId = [u8; 32]; + /// Multihash for digest sizes up to 384 bit. /// The multicodec encoding the hash algorithm uses only 1 byte, /// effecitvely limiting the number of available hash types. diff --git a/zrml/combo/Cargo.toml b/zrml/combo/Cargo.toml index cee14a362..f7e005123 100644 --- a/zrml/combo/Cargo.toml +++ b/zrml/combo/Cargo.toml @@ -4,6 +4,7 @@ frame-benchmarking = { workspace = true, optional = true } frame-support = { workspace = true } frame-system = { workspace = true } halo2curves = { workspace = true } +orml-traits = { workspace = true } parity-scale-codec = { workspace = true, features = ["derive", "max-encoded-len"] } scale-info = { workspace = true, features = ["derive"] } sp-runtime = { workspace = true } diff --git a/zrml/combo/src/lib.rs b/zrml/combo/src/lib.rs index 2c8826368..0ac8350f6 100644 --- a/zrml/combo/src/lib.rs +++ b/zrml/combo/src/lib.rs @@ -29,16 +29,42 @@ pub use pallet::*; #[frame_support::pallet] mod pallet { + use crate::traits::CombinatorialIdManager; use core::marker::PhantomData; use frame_support::{ + ensure, pallet_prelude::{IsType, StorageVersion}, - require_transactional, transactional, + require_transactional, transactional, PalletId, + }; + use frame_system::{ + ensure_signed, + pallet_prelude::{BlockNumberFor, OriginFor}, + }; + use orml_traits::MultiCurrency; + use sp_runtime::{ + traits::{AccountIdConversion, Get}, + DispatchError, DispatchResult, + }; + use zeitgeist_primitives::{ + traits::MarketCommonsPalletApi, + types::{Asset, CombinatorialId}, }; - use frame_system::{ensure_signed, pallet_prelude::OriginFor}; - use sp_runtime::DispatchResult; #[pallet::config] pub trait Config: frame_system::Config { + type CombinatorialIdManager: CombinatorialIdManager< + Asset = AssetOf, + MarketId = MarketIdOf, + CombinatorialId = CombinatorialId, + >; + + type MarketCommons: MarketCommonsPalletApi>; + + type MultiCurrency: MultiCurrency>; + + #[pallet::constant] + type PalletId: Get; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; } @@ -46,6 +72,15 @@ mod pallet { #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(PhantomData); + pub(crate) type AccountIdOf = ::AccountId; + pub(crate) type AssetOf = Asset>; + pub(crate) type BalanceOf = + <::MultiCurrency as MultiCurrency>>::Balance; + pub(crate) type CombinatorialIdOf = + <::CombinatorialIdManager as CombinatorialIdManager>::CombinatorialId; + pub(crate) type MarketIdOf = + <::MarketCommons as MarketCommonsPalletApi>::MarketId; + // TODO Types pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); @@ -58,36 +93,218 @@ mod pallet { T: Config, {} #[pallet::error] - pub enum Error {} + pub enum Error { + /// The specified partition is empty, contains overlaps or is too long. + InvalidPartition, + + /// The specified collection ID is invalid. + InvalidCollectionId, + } #[pallet::call] impl Pallet { #[pallet::call_index(0)] #[pallet::weight(0)] // TODO #[transactional] - pub fn split_position(origin: OriginFor) -> DispatchResult { - let _ = ensure_signed(origin)?; - Self::do_split_position() + pub fn split_position( + origin: OriginFor, + // TODO Abstract this into a separate type. + parent_collection_id: Option>, + market_id: MarketIdOf, + partition: Vec>, + amount: BalanceOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_split_position(who, parent_collection_id, market_id, partition, amount) } #[pallet::call_index(1)] #[pallet::weight(0)] // TODO #[transactional] - pub fn merge_position(origin: OriginFor) -> DispatchResult { - let _ = ensure_signed(origin)?; - Self::do_merge_position() + pub fn merge_position( + origin: OriginFor, + parent_collection_id: Option>, + market_id: MarketIdOf, + partition: Vec>, + amount: BalanceOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_merge_position(who, parent_collection_id, market_id, partition, amount) } } impl Pallet { #[require_transactional] - fn do_split_position() -> DispatchResult { + fn do_split_position( + who: AccountIdOf, + parent_collection_id: Option>, + market_id: MarketIdOf, + partition: Vec>, + amount: BalanceOf, + ) -> DispatchResult { + let market = T::MarketCommons::market(&market_id)?; + let collateral_token = market.base_asset; + + let free_index_set = Self::free_index_set(parent_collection_id, market_id, &partition)?; + + // Destroy/store the tokens to be split. + if free_index_set.iter().any(|&i| i) { + // Vertical split. + if let Some(pci) = parent_collection_id { + // Split combinatorial token into higher level position. Destroy the tokens. + let position_id = + T::CombinatorialIdManager::get_position_id(collateral_token, pci); + let position = Asset::CombinatorialToken(position_id); + T::MultiCurrency::withdraw(position, &who, amount)?; + } else { + // Split collateral into first level position. Store the collateral in the + // pallet account. This is the legacy `buy_complete_set`. + T::MultiCurrency::transfer( + collateral_token, + &who, + &Self::account_id(), + amount, + )?; + } + } else { + // Horizontal split. + let remaining_index_set = free_index_set.into_iter().map(|i| !i).collect(); + let position = Self::position_from_collection( + parent_collection_id, + market_id, + remaining_index_set, + )?; + T::MultiCurrency::withdraw(position, &who, amount)?; + } + + // Deposit the new tokens. + let position_ids = partition + .iter() + .cloned() + .map(|index_set| { + Self::position_from_collection(parent_collection_id, market_id, index_set) + }) + .collect::, _>>()?; + for &position in position_ids.iter() { + T::MultiCurrency::deposit(position, &who, amount)?; + } + Ok(()) } #[require_transactional] - fn do_merge_position() -> DispatchResult { + fn do_merge_position( + who: AccountIdOf, + parent_collection_id: Option>, + market_id: MarketIdOf, + partition: Vec>, + amount: BalanceOf, + ) -> DispatchResult { + let market = T::MarketCommons::market(&market_id)?; + let collateral_token = market.base_asset; + + let free_index_set = Self::free_index_set(parent_collection_id, market_id, &partition)?; + + // Destory the old tokens. + let position_ids = partition + .iter() + .cloned() + .map(|index_set| { + Self::position_from_collection(parent_collection_id, market_id, index_set) + }) + .collect::, _>>()?; + for &position in position_ids.iter() { + T::MultiCurrency::withdraw(position, &who, amount)?; + } + + // Destroy/store the tokens to be split. + if free_index_set.iter().any(|&i| i) { + // Vertical merge. + if let Some(pci) = parent_collection_id { + // Merge combinatorial token into higher level position. Destroy the tokens. + let position_id = + T::CombinatorialIdManager::get_position_id(collateral_token, pci); + let position = Asset::CombinatorialToken(position_id); + T::MultiCurrency::deposit(position, &who, amount)?; + } else { + // Merge first-level tokens into collateral. Move collateral from the pallet + // account to the user's wallet. This is the legacy `sell_complete_set`. + T::MultiCurrency::transfer( + collateral_token, + &Self::account_id(), + &who, + amount, + )?; + } + } else { + // Horizontal merge. + let remaining_index_set = free_index_set.into_iter().map(|i| !i).collect(); + let position = Self::position_from_collection( + parent_collection_id, + market_id, + remaining_index_set, + )?; + T::MultiCurrency::deposit(position, &who, amount)?; + } + Ok(()) } + + fn free_index_set( + parent_collection_id: Option>, + market_id: MarketIdOf, + partition: &Vec>, + ) -> Result, DispatchError> { + let market = T::MarketCommons::market(&market_id)?; + let asset_count = market.outcomes() as usize; + let mut free_index_set = vec![true; asset_count]; + + for index_set in partition.iter() { + // Ensure that the partition is not trivial. + let ones = index_set.iter().fold(0usize, |acc, &val| acc + (val as usize)); + ensure!(ones > 0, Error::::InvalidPartition); + ensure!(ones < asset_count, Error::::InvalidPartition); + + // Ensure that `index_set` is disjoint from the previously iterated elements of the + // partition. + ensure!( + free_index_set.iter().zip(index_set.iter()).all(|(i, j)| *i || !*j), + Error::::InvalidPartition + ); + + // Remove indices of `index_set` from `free_index_set`. + free_index_set = + free_index_set.iter().zip(index_set.iter()).map(|(i, j)| *i && !*j).collect(); + } + + Ok(free_index_set) + } + + fn position_from_collection( + parent_collection_id: Option>, + market_id: MarketIdOf, + index_set: Vec, + ) -> Result, DispatchError> { + let market = T::MarketCommons::market(&market_id)?; + let collateral_token = market.base_asset; + + let collection_id = T::CombinatorialIdManager::get_collection_id( + parent_collection_id, + market_id, + index_set, + false, // TODO Expose this parameter! + ) + .ok_or(Error::::InvalidCollectionId)?; + + let position_id = + T::CombinatorialIdManager::get_position_id(collateral_token, collection_id); + let asset = Asset::CombinatorialToken(position_id); + + Ok(asset) + } + + fn account_id() -> T::AccountId { + T::PalletId::get().into_account_truncating() + } } } diff --git a/zrml/combo/src/traits/id_manager.rs b/zrml/combo/src/traits/combinatorial_id_manager.rs similarity index 56% rename from zrml/combo/src/traits/id_manager.rs rename to zrml/combo/src/traits/combinatorial_id_manager.rs index 04c83ddc9..d74766668 100644 --- a/zrml/combo/src/traits/id_manager.rs +++ b/zrml/combo/src/traits/combinatorial_id_manager.rs @@ -1,20 +1,20 @@ use sp_runtime::DispatchError; -pub(crate) trait IdManager { +pub(crate) trait CombinatorialIdManager { type Asset; type MarketId; - type Id; + type CombinatorialId; // TODO Replace `Vec` with a more effective bit mask type. fn get_collection_id( - parent_collection_id: Option, + parent_collection_id: Option, market_id: Self::MarketId, index_set: Vec, force_max_work: bool, - ) -> Option; + ) -> Option; fn get_position_id( collateral: Self::Asset, - collection_id: Self::Id, - ) -> Option; + collection_id: Self::CombinatorialId, + ) -> Self::CombinatorialId; } diff --git a/zrml/combo/src/traits/mod.rs b/zrml/combo/src/traits/mod.rs index 2685f5d14..ff38688d4 100644 --- a/zrml/combo/src/traits/mod.rs +++ b/zrml/combo/src/traits/mod.rs @@ -1,3 +1,3 @@ -mod id_manager; +mod combinatorial_id_manager; -pub(crate) use id_manager::IdManager; +pub(crate) use combinatorial_id_manager::CombinatorialIdManager; diff --git a/zrml/combo/src/types/cryptographic_id_manager/decompressor/mod.rs b/zrml/combo/src/types/cryptographic_id_manager/decompressor/mod.rs index f7d46f50d..11e3f5ba4 100644 --- a/zrml/combo/src/types/cryptographic_id_manager/decompressor/mod.rs +++ b/zrml/combo/src/types/cryptographic_id_manager/decompressor/mod.rs @@ -1,7 +1,7 @@ /// Highest/lowest bit always refers to the big endian representation of each bit sequence. mod tests; -use super::typedefs::Hash; +use zeitgeist_primitives::types::CombinatorialId; use core::num::ParseIntError; use ethnum::U256; use halo2curves::{ @@ -12,10 +12,10 @@ use halo2curves::{ /// Will return `None` if and only if `parent_collection_id` is not a valid collection ID. pub(crate) fn get_collection_id( - hash: Hash, - parent_collection_id: Option, + hash: CombinatorialId, + parent_collection_id: Option, force_max_work: bool, -) -> Option { +) -> Option { let mut u = decompress_hash(hash, force_max_work)?; if let Some(pci) = parent_collection_id { @@ -47,7 +47,7 @@ const DECOMPRESS_HASH_MAX_ITERS: usize = 1_000; /// will use `1_000` iterations as maximum for now. /// /// Provided the assumption above is correct, this function cannot return `None`. -fn decompress_hash(hash: Hash, force_max_work: bool) -> Option { +fn decompress_hash(hash: CombinatorialId, force_max_work: bool) -> Option { // Calculate `odd` first, then get congruent point `x` in `Fq`. As `hash` might represent a // larger big endian number than `field_modulus()`, the MSB of `x` might be different from the // MSB of `x_u256`. @@ -89,8 +89,8 @@ fn decompress_hash(hash: Hash, force_max_work: bool) -> Option { } } } - std::mem::forget(dummy_x); // Ensure that the dummies are considered "read" by rustc. - std::mem::forget(dummy_y); + std::hint::black_box(dummy_x); // Ensure that the dummies are considered "read" by rustc. + std::hint::black_box(dummy_y); let mut y = y_opt?; // This **should** be infallible. // We have two options for the y-coordinate of the corresponding point: `y` and `P - y`. If @@ -102,7 +102,7 @@ fn decompress_hash(hash: Hash, force_max_work: bool) -> Option { G1Affine::from_xy(x, y).into() } -fn decompress_collection_id(mut collection_id: Hash) -> Option { +fn decompress_collection_id(mut collection_id: CombinatorialId) -> Option { let odd = is_second_msb_set(&collection_id); chop_off_two_highest_bits(&mut collection_id); collection_id.reverse(); // Big-endian to little-endian. @@ -129,22 +129,22 @@ fn field_modulus() -> U256 { } /// Flips the second highests bit of big-endian `bytes`. -fn flip_second_highest_bit(bytes: &mut Hash) { +fn flip_second_highest_bit(bytes: &mut CombinatorialId) { bytes[0] ^= 0b01000000; } /// Checks if the most significant bit of the big-endian `bytes` is set. -fn is_msb_set(bytes: &Hash) -> bool { +fn is_msb_set(bytes: &CombinatorialId) -> bool { (bytes[0] & 0b10000000) != 0 } /// Checks if the second most significant bit of the big-endian `bytes` is set. -fn is_second_msb_set(bytes: &Hash) -> bool { +fn is_second_msb_set(bytes: &CombinatorialId) -> bool { (bytes[0] & 0b01000000) != 0 } /// Zeroes out the two most significant bits off the big-endian `bytes`. -fn chop_off_two_highest_bits(bytes: &mut Hash) { +fn chop_off_two_highest_bits(bytes: &mut CombinatorialId) { bytes[0] &= 0b00111111; } diff --git a/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/decompress_collection_id.rs b/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/decompress_collection_id.rs index 2308e8d2b..2bdd239f9 100644 --- a/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/decompress_collection_id.rs +++ b/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/decompress_collection_id.rs @@ -390,7 +390,7 @@ use test_case::test_case; [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], ("0x1", "0x2") )] -fn decompress_collection_id_works(collection_id: Hash, expected: (&str, &str)) { +fn decompress_collection_id_works(collection_id: CombinatorialId, expected: (&str, &str)) { let x = Fq::from_str_prefixed(expected.0).unwrap(); let y = Fq::from_str_prefixed(expected.1).unwrap(); let expected = G1Affine::from_xy(x, y).unwrap(); @@ -555,7 +555,7 @@ fn decompress_collection_id_works(collection_id: Hash, expected: (&str, &str)) { #[test_case( [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe] )] -fn decompress_collection_id_fails_on_invalid_collection_id(collection_id: Hash) { +fn decompress_collection_id_fails_on_invalid_collection_id(collection_id: CombinatorialId) { let actual = decompress_collection_id(collection_id); assert_eq!(actual, None); } diff --git a/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/decompress_hash.rs b/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/decompress_hash.rs index 1ba11da48..49fc4eeed 100644 --- a/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/decompress_hash.rs +++ b/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/decompress_hash.rs @@ -745,7 +745,7 @@ use rstest::rstest; ) )] fn decompress_hash_works( - #[case] hash: Hash, + #[case] hash: CombinatorialId, #[values(false, true)] force_max_work: bool, #[case] expected: (&str, &str), ) { diff --git a/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/get_collection_id.rs b/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/get_collection_id.rs index 7f4a2f03c..6c214ec97 100644 --- a/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/get_collection_id.rs +++ b/zrml/combo/src/types/cryptographic_id_manager/decompressor/tests/get_collection_id.rs @@ -64,10 +64,10 @@ use rstest::rstest; ]) )] fn get_collection_id_works( - #[case] hash: Hash, - #[case] parent_collection_id: Option, + #[case] hash: CombinatorialId, + #[case] parent_collection_id: Option, #[values(false, true)] force_max_work: bool, - #[case] expected: Option, + #[case] expected: Option, ) { assert_eq!(get_collection_id(hash, parent_collection_id, force_max_work), expected); } diff --git a/zrml/combo/src/types/cryptographic_id_manager/hash_tuple.rs b/zrml/combo/src/types/cryptographic_id_manager/hash_tuple.rs index 94cc20648..955f56f96 100644 --- a/zrml/combo/src/types/cryptographic_id_manager/hash_tuple.rs +++ b/zrml/combo/src/types/cryptographic_id_manager/hash_tuple.rs @@ -1,4 +1,4 @@ -use super::typedefs::Hash; +use crate::types::Hash256; use frame_support::{Blake2_256, StorageHasher}; use parity_scale_codec::Encode; use zeitgeist_primitives::types::Asset; @@ -8,14 +8,14 @@ pub trait ToBytes { } pub trait HashTuple { - fn hash_tuple(tuple: (T1, T2)) -> Hash + fn hash_tuple(tuple: (T1, T2)) -> Hash256 where T1: ToBytes, T2: ToBytes; } impl HashTuple for Blake2_256 { - fn hash_tuple(tuple: (T1, T2)) -> Hash + fn hash_tuple(tuple: (T1, T2)) -> Hash256 where T1: ToBytes, T2: ToBytes, @@ -50,7 +50,7 @@ impl ToBytes for bool { } } -impl ToBytes for Hash { +impl ToBytes for Hash256 { fn to_bytes(&self) -> Vec { self.to_vec() } diff --git a/zrml/combo/src/types/cryptographic_id_manager/mod.rs b/zrml/combo/src/types/cryptographic_id_manager/mod.rs index 1f1e5facf..eb5f25cc7 100644 --- a/zrml/combo/src/types/cryptographic_id_manager/mod.rs +++ b/zrml/combo/src/types/cryptographic_id_manager/mod.rs @@ -1,41 +1,42 @@ mod decompressor; mod hash_tuple; -mod typedefs; -use crate::traits::IdManager; +use crate::traits::CombinatorialIdManager; use core::marker::PhantomData; use ethnum::U256; use frame_support::{Blake2_256, StorageHasher}; use hash_tuple::{HashTuple, ToBytes}; use parity_scale_codec::Encode; use sp_runtime::DispatchError; -use typedefs::Hash; -use zeitgeist_primitives::types::Asset; +use zeitgeist_primitives::types::{Asset, CombinatorialId}; pub(crate) struct CryptographicIdManager(PhantomData<(MarketId, Hasher)>); -impl IdManager for CryptographicIdManager +impl CombinatorialIdManager for CryptographicIdManager where MarketId: ToBytes + Encode, - Hasher: HashTuple + Hasher: HashTuple, { type Asset = Asset; - type Id = Hash; + type CombinatorialId = CombinatorialId; type MarketId = MarketId; fn get_collection_id( - parent_collection_id: Option, + parent_collection_id: Option, market_id: Self::MarketId, index_set: Vec, force_max_work: bool, - ) -> Option { + ) -> Option { let input = (market_id, index_set); let hash = Hasher::hash_tuple(input); decompressor::get_collection_id(hash, parent_collection_id, force_max_work) } - fn get_position_id(collateral: Self::Asset, collection_id: Self::Id) -> Option { + fn get_position_id( + collateral: Self::Asset, + collection_id: Self::CombinatorialId, + ) -> Self::CombinatorialId { let input = (collateral, collection_id); - Some(Hasher::hash_tuple(input)) + Hasher::hash_tuple(input) } } diff --git a/zrml/combo/src/types/cryptographic_id_manager/typedefs.rs b/zrml/combo/src/types/cryptographic_id_manager/typedefs.rs deleted file mode 100644 index 224b450a9..000000000 --- a/zrml/combo/src/types/cryptographic_id_manager/typedefs.rs +++ /dev/null @@ -1 +0,0 @@ -pub type Hash = [u8; 32]; diff --git a/zrml/combo/src/types/hash.rs b/zrml/combo/src/types/hash.rs new file mode 100644 index 000000000..bc57e98ec --- /dev/null +++ b/zrml/combo/src/types/hash.rs @@ -0,0 +1 @@ +pub type Hash256 = [u8; 32]; diff --git a/zrml/combo/src/types/mod.rs b/zrml/combo/src/types/mod.rs index 3dad26231..842c44ddd 100644 --- a/zrml/combo/src/types/mod.rs +++ b/zrml/combo/src/types/mod.rs @@ -1,3 +1,5 @@ -mod cryptographic_id_manager; +pub(crate) mod cryptographic_id_manager; +pub(crate) mod hash; pub(crate) use cryptographic_id_manager::CryptographicIdManager; +pub(crate) use hash::Hash256;