#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "std")] use zeroize::Zeroize; #[cfg(feature = "borsh")] use borsh::{BorshSerialize, BorshDeserialize}; #[cfg(feature = "serde")] use serde::{Serialize, Deserialize}; use scale::{Encode, Decode, MaxEncodedLen}; use scale_info::TypeInfo; #[cfg(test)] use sp_io::TestExternalities; #[cfg(test)] use frame_support::{pallet_prelude::*, Identity, traits::StorageInstance}; use sp_core::{ConstU32, bounded::BoundedVec}; pub use sp_application_crypto as crypto; mod amount; pub use amount::*; mod block; pub use block::*; mod networks; pub use networks::*; mod balance; pub use balance::*; mod account; pub use account::*; mod constants; pub use constants::*; mod dex; #[allow(unused_imports)] pub use dex::*; pub type BlockNumber = u64; pub type Header = sp_runtime::generic::Header; #[cfg(feature = "borsh")] pub fn borsh_serialize_bounded_vec( bounded: &BoundedVec>, writer: &mut W, ) -> Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(bounded.as_slice(), writer) } #[cfg(feature = "borsh")] pub fn borsh_deserialize_bounded_vec( reader: &mut R, ) -> Result>, borsh::io::Error> { let vec: Vec = borsh::BorshDeserialize::deserialize_reader(reader)?; vec.try_into().map_err(|_| borsh::io::Error::other("bound exceeded")) } pub const MAX_ADDRESS_LEN: u32 = 512; #[derive(Clone, PartialEq, Eq, Debug, Encode, Decode, MaxEncodedLen, TypeInfo)] #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ExternalAddress( #[cfg_attr( feature = "borsh", borsh( serialize_with = "borsh_serialize_bounded_vec", deserialize_with = "borsh_deserialize_bounded_vec" ) )] BoundedVec>, ); #[cfg(feature = "std")] impl Zeroize for ExternalAddress { fn zeroize(&mut self) { self.0.as_mut().zeroize() } } impl ExternalAddress { #[cfg(feature = "std")] pub fn new(address: Vec) -> Result { Ok(ExternalAddress(address.try_into().map_err(|_| "address length exceeds {MAX_ADDRESS_LEN}")?)) } #[cfg(feature = "std")] pub fn consume(self) -> Vec { self.0.into_inner() } } impl AsRef<[u8]> for ExternalAddress { fn as_ref(&self) -> &[u8] { self.0.as_ref() } } /// Lexicographically reverses a given byte array. pub fn reverse_lexicographic_order(bytes: [u8; N]) -> [u8; N] { let mut res = [0u8; N]; for (i, byte) in bytes.iter().enumerate() { res[i] = !*byte; } res } #[test] fn test_reverse_lexicographic_order() { TestExternalities::default().execute_with(|| { use rand_core::{RngCore, OsRng}; struct Storage; impl StorageInstance for Storage { fn pallet_prefix() -> &'static str { "LexicographicOrder" } const STORAGE_PREFIX: &'static str = "storage"; } type Map = StorageMap; struct StorageReverse; impl StorageInstance for StorageReverse { fn pallet_prefix() -> &'static str { "LexicographicOrder" } const STORAGE_PREFIX: &'static str = "storagereverse"; } type MapReverse = StorageMap; // populate the maps let mut amounts = vec![]; for _ in 0 .. 100 { amounts.push(OsRng.next_u64()); } let mut amounts_sorted = amounts.clone(); amounts_sorted.sort(); for a in amounts { Map::set(a.to_be_bytes(), Some(())); MapReverse::set(reverse_lexicographic_order(a.to_be_bytes()), Some(())); } // retrive back and check whether they are sorted as expected let total_size = amounts_sorted.len(); let mut map_iter = Map::iter_keys(); let mut reverse_map_iter = MapReverse::iter_keys(); for i in 0 .. amounts_sorted.len() { let first = map_iter.next().unwrap(); let second = reverse_map_iter.next().unwrap(); assert_eq!(u64::from_be_bytes(first), amounts_sorted[i]); assert_eq!( u64::from_be_bytes(reverse_lexicographic_order(second)), amounts_sorted[total_size - (i + 1)] ); } }); }