diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..e47fd12f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +root = true +[*] +indent_style=tab +indent_size=tab +tab_width=4 +end_of_line=lf +charset=utf-8 +trim_trailing_whitespace=true +max_line_length=120 +insert_final_newline=true + +[*.{yml,sh}] +indent_style=space +indent_size=2 +tab_width=8 +end_of_line=lf diff --git a/.github/workflows/clippy_check.yml b/.github/workflows/clippy_check.yml index 49527c92..b6bf9625 100644 --- a/.github/workflows/clippy_check.yml +++ b/.github/workflows/clippy_check.yml @@ -1,15 +1,22 @@ -on: [push] -name: Clippy check +on: [push, pull_request] +name: Clippy jobs: - clippy_check: + check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install stable + uses: actions-rs/toolchain@v1 with: - toolchain: nightly + profile: minimal + toolchain: stable components: clippy override: true - - uses: actions-rs/clippy-check@v1 + + - name: Run clippy + uses: actions-rs/cargo@v1 with: - token: ${{ secrets.GITHUB_TOKEN }} + command: clippy + args: -- -D warnings diff --git a/.github/workflows/grcov.yml b/.github/workflows/coverage.yml similarity index 51% rename from .github/workflows/grcov.yml rename to .github/workflows/coverage.yml index 2772254d..3d65a36b 100644 --- a/.github/workflows/grcov.yml +++ b/.github/workflows/coverage.yml @@ -1,37 +1,38 @@ on: [push] -name: Code coverage with grcov +name: Code Coverage jobs: grcov: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: - - ubuntu-latest + runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v2 + - name: Checkout Repository + uses: actions/checkout@v1 - - name: Install toolchain + - name: Install Nightly toolchain uses: actions-rs/toolchain@v1 with: toolchain: nightly override: true - - name: Execute tests + - name: Cargo Clean + uses: actions-rs/cargo@v1 + with: + command: clean + + - name: Run Tests for Coverage uses: actions-rs/cargo@v1 with: command: test args: --all --all-features env: CARGO_INCREMENTAL: 0 - RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Zno-landing-pads" + RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off" + RUST_LOG: info - - name: Gather coverage data - id: coverage + - id: coverage uses: actions-rs/grcov@v0.1 - with: - coveralls-token: ${{ secrets.COVERALLS_TOKEN }} - name: Coveralls upload uses: coverallsapp/github-action@master @@ -39,13 +40,3 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} parallel: true path-to-lcov: ${{ steps.coverage.outputs.report }} - - grcov_finalize: - runs-on: ubuntu-latest - needs: grcov - steps: - - name: Coveralls finalization - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - parallel-finished: true diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000..2a4fd387 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,5 @@ +hard_tabs = true +max_width = 120 +use_small_heuristics = "Max" +edition = "2018" +newline_style = "Unix" diff --git a/core/src/decoder.rs b/core/src/decoder.rs index ca2881c6..89073e04 100644 --- a/core/src/decoder.rs +++ b/core/src/decoder.rs @@ -28,9 +28,7 @@ pub mod metadata; mod storage; pub use self::extrinsics::{ExtrinsicArgument, GenericCall, GenericExtrinsic, GenericSignature}; -pub use self::storage::{ - GenericStorage, StorageInfo, StorageKey, StorageKeyData, StorageLookupTable, StorageValue, -}; +pub use self::storage::{GenericStorage, StorageInfo, StorageKey, StorageKeyData, StorageLookupTable, StorageValue}; #[cfg(test)] pub use self::metadata::test_suite; @@ -39,9 +37,9 @@ pub use self::metadata::{Metadata, MetadataError, ModuleIndex, StorageType}; pub use runtime_metadata_latest::{StorageEntryModifier, StorageEntryType, StorageHasher}; use crate::{ - error::Error, - substrate_types::{self, StructField, StructUnitOrTuple, SubstrateType}, - CommonTypes, RustTypeMarker, TypeDetective, + error::Error, + substrate_types::{self, StructField, StructUnitOrTuple, SubstrateType}, + CommonTypes, RustTypeMarker, TypeDetective, }; use codec::{Compact, CompactLen, Decode}; use std::{collections::HashMap, convert::TryFrom}; @@ -54,20 +52,16 @@ type SpecVersion = u32; /// type-metadata #[derive(Debug)] pub struct Decoder { - // reference to an item in 'versions' vector - versions: HashMap, - types: Box, - chain: String, + // reference to an item in 'versions' vector + versions: HashMap, + types: Box, + chain: String, } impl Clone for Decoder { - fn clone(&self) -> Self { - Self { - versions: self.versions.clone(), - types: dyn_clone::clone_box(&*self.types), - chain: self.chain.clone(), - } - } + fn clone(&self) -> Self { + Self { versions: self.versions.clone(), types: dyn_clone::clone_box(&*self.types), chain: self.chain.clone() } + } } /// The type of Entry @@ -78,1212 +72,1037 @@ impl Clone for Decoder { /// used in #[derive(Debug)] pub enum Entry { - Call, - Storage, - Event, - Constant, + Call, + Storage, + Event, + Constant, } #[derive(Debug, Clone)] pub enum Chain { - Polkadot, - Kusama, - Centrifuge, - Westend, - Rococo, - Custom(String), + Polkadot, + Kusama, + Centrifuge, + Westend, + Rococo, + Custom(String), } impl std::fmt::Display for Chain { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Chain::Polkadot => write!(f, "polkadot"), - Chain::Kusama => write!(f, "kusama"), - Chain::Centrifuge => write!(f, "centrifuge-chain"), - Chain::Westend => write!(f, "westend"), - Chain::Rococo => write!(f, "rococo"), - Chain::Custom(s) => write!(f, "{}", s), - } - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Chain::Polkadot => write!(f, "polkadot"), + Chain::Kusama => write!(f, "kusama"), + Chain::Centrifuge => write!(f, "centrifuge-chain"), + Chain::Westend => write!(f, "westend"), + Chain::Rococo => write!(f, "rococo"), + Chain::Custom(s) => write!(f, "{}", s), + } + } } impl Decoder { - /// Create new Decoder with specified types - pub fn new(types: impl TypeDetective + 'static, chain: Chain) -> Self { - Self { - versions: HashMap::default(), - types: Box::new(types), - chain: chain.to_string(), - } - } + /// Create new Decoder with specified types + pub fn new(types: impl TypeDetective + 'static, chain: Chain) -> Self { + Self { versions: HashMap::default(), types: Box::new(types), chain: chain.to_string() } + } - /// Check if a metadata version has already been registered - pub fn has_version(&self, version: &SpecVersion) -> bool { - self.versions.contains_key(&version) - } + /// Check if a metadata version has already been registered + pub fn has_version(&self, version: &SpecVersion) -> bool { + self.versions.contains_key(&version) + } - /// Insert a Metadata with Version attached - /// If version exists, it's corresponding metadata will be updated - pub fn register_version>(&mut self, version: SpecVersion, metadata: M) { - let meta: Metadata = metadata.into(); - self.versions.insert(version, meta); - } + /// Insert a Metadata with Version attached + /// If version exists, it's corresponding metadata will be updated + pub fn register_version>(&mut self, version: SpecVersion, metadata: M) { + let meta: Metadata = metadata.into(); + self.versions.insert(version, meta); + } - /// internal api to get runtime version - /// panics if a version is not found - /// - /// get runtime version in less than linear time with binary search - /// - /// # Note - /// Returns None if version is nonexistant - pub fn get_version_metadata(&self, version: SpecVersion) -> Option<&Metadata> { - self.versions.get(&version) - } + /// internal api to get runtime version + /// panics if a version is not found + /// + /// get runtime version in less than linear time with binary search + /// + /// # Note + /// Returns None if version is nonexistant + pub fn get_version_metadata(&self, version: SpecVersion) -> Option<&Metadata> { + self.versions.get(&version) + } - fn decode_key_len(&self, key: &[u8], hasher: &StorageHasher) -> Vec { - match hasher { - StorageHasher::Blake2_128 - | StorageHasher::Twox128 - | StorageHasher::Blake2_128Concat => key[..16].to_vec(), - StorageHasher::Blake2_256 | StorageHasher::Twox256 => key[..32].to_vec(), - StorageHasher::Twox64Concat => key[..8].to_vec(), - StorageHasher::Identity => todo!(), - } - } + fn decode_key_len(&self, key: &[u8], hasher: &StorageHasher) -> Vec { + match hasher { + StorageHasher::Blake2_128 | StorageHasher::Twox128 | StorageHasher::Blake2_128Concat => key[..16].to_vec(), + StorageHasher::Blake2_256 | StorageHasher::Twox256 => key[..32].to_vec(), + StorageHasher::Twox64Concat => key[..8].to_vec(), + StorageHasher::Identity => todo!(), + } + } - fn get_key_data( - &self, - key: &[u8], - info: &StorageInfo, - lookup_table: &StorageLookupTable, - ) -> StorageKey { - let key = if let Some(k) = lookup_table.extra_key_data(key) { - k - } else { - return StorageKey { - module: info.module.name().into(), - prefix: info.meta.prefix().to_string(), - extra: None, - }; - }; + fn get_key_data(&self, key: &[u8], info: &StorageInfo, lookup_table: &StorageLookupTable) -> StorageKey { + let key = if let Some(k) = lookup_table.extra_key_data(key) { + k + } else { + return StorageKey { + module: info.module.name().into(), + prefix: info.meta.prefix().to_string(), + extra: None, + }; + }; - match &info.meta.ty { - StorageType::Plain(_) => StorageKey { - module: info.module.name().into(), - prefix: info.meta.prefix().to_string(), - extra: None, - }, - StorageType::Map { - hasher, - key: key_type, - .. - } => { - let key = self.decode_key_len(key, &hasher); - StorageKey { - module: info.module.name().into(), - prefix: info.meta.prefix().to_string(), - extra: Some(StorageKeyData::Map { - key: key.to_vec(), - hasher: hasher.clone(), - key_type: key_type.clone(), - }), - } - } - StorageType::DoubleMap { - hasher, - key1, - key2, - key2_hasher, - .. - } => { - let key1_bytes = self.decode_key_len(key, &hasher); - let key2_bytes = self.decode_key_len(&key[key1_bytes.len()..], &key2_hasher); - StorageKey { - module: info.module.name().into(), - prefix: info.meta.prefix().to_string(), - extra: Some(StorageKeyData::DoubleMap { - hasher: hasher.clone(), - key2_hasher: key2_hasher.clone(), - key1: key1_bytes, - key2: key2_bytes, - key1_type: key1.clone(), - key2_type: key2.clone(), - }), - } - } - } - } + match &info.meta.ty { + StorageType::Plain(_) => { + StorageKey { module: info.module.name().into(), prefix: info.meta.prefix().to_string(), extra: None } + } + StorageType::Map { hasher, key: key_type, .. } => { + let key = self.decode_key_len(key, &hasher); + StorageKey { + module: info.module.name().into(), + prefix: info.meta.prefix().to_string(), + extra: Some(StorageKeyData::Map { + key: key.to_vec(), + hasher: hasher.clone(), + key_type: key_type.clone(), + }), + } + } + StorageType::DoubleMap { hasher, key1, key2, key2_hasher, .. } => { + let key1_bytes = self.decode_key_len(key, &hasher); + let key2_bytes = self.decode_key_len(&key[key1_bytes.len()..], &key2_hasher); + StorageKey { + module: info.module.name().into(), + prefix: info.meta.prefix().to_string(), + extra: Some(StorageKeyData::DoubleMap { + hasher: hasher.clone(), + key2_hasher: key2_hasher.clone(), + key1: key1_bytes, + key2: key2_bytes, + key1_type: key1.clone(), + key2_type: key2.clone(), + }), + } + } + } + } - /// Decode the Key/Value pair of a storage entry - pub fn decode_storage, O: AsRef<[u8]>>( - &self, - spec: SpecVersion, - data: (V, Option), - ) -> Result { - let (key, value): (&[u8], Option) = (data.0.as_ref(), data.1); - let meta = self.versions.get(&spec).expect("Spec does not exist"); - let lookup_table = meta.storage_lookup_table(); - let storage_info = lookup_table.meta_for_key(key).ok_or_else(|| { - Error::from(format!( - "Storage not found key={:#X?}, spec={}, chain={}", - key, - spec, - self.chain.as_str() - )) - })?; + /// Decode the Key/Value pair of a storage entry + pub fn decode_storage, O: AsRef<[u8]>>( + &self, + spec: SpecVersion, + data: (V, Option), + ) -> Result { + let (key, value): (&[u8], Option) = (data.0.as_ref(), data.1); + let meta = self.versions.get(&spec).expect("Spec does not exist"); + let lookup_table = meta.storage_lookup_table(); + let storage_info = lookup_table.meta_for_key(key).ok_or_else(|| { + Error::from(format!("Storage not found key={:#X?}, spec={}, chain={}", key, spec, self.chain.as_str())) + })?; - if value.is_none() { - let key = self.get_key_data(key, &storage_info, &lookup_table); - return Ok(GenericStorage::new(key, None)); - } - let value = value.unwrap(); - let value = value.as_ref(); + if value.is_none() { + let key = self.get_key_data(key, &storage_info, &lookup_table); + return Ok(GenericStorage::new(key, None)); + } + let value = value.unwrap(); + let value = value.as_ref(); - match &storage_info.meta.ty { - StorageType::Plain(rtype) => { - log::trace!( - "{:?}, module {}, spec {}", - rtype, - storage_info.module.name(), - spec - ); - let mut cursor = 0; - let value = self.decode_single( - storage_info.module.name(), - spec, - &rtype, - value, - &mut cursor, - false, - )?; - let key = self.get_key_data(key, &storage_info, &lookup_table); - let storage = GenericStorage::new(key, Some(StorageValue::new(value))); - Ok(storage) - } - StorageType::Map { - value: val_rtype, - unused: _unused, - .. - } => { - let key = self.get_key_data(key, &storage_info, &lookup_table); - let mut cursor = 0; - let value = self.decode_single( - storage_info.module.name(), - spec, - &val_rtype, - value, - &mut cursor, - false, - )?; - let storage = GenericStorage::new(key, Some(StorageValue::new(value))); - Ok(storage) - } - StorageType::DoubleMap { - value: val_rtype, .. - } => { - let key = self.get_key_data(key, &storage_info, &lookup_table); - let mut cursor = 0; - let value = self.decode_single( - storage_info.module.name(), - spec, - &val_rtype, - value, - &mut cursor, - false, - )?; - let storage = GenericStorage::new(key, Some(StorageValue::new(value))); - Ok(storage) - } - } - } + match &storage_info.meta.ty { + StorageType::Plain(rtype) => { + log::trace!("{:?}, module {}, spec {}", rtype, storage_info.module.name(), spec); + let mut cursor = 0; + let value = self.decode_single(storage_info.module.name(), spec, &rtype, value, &mut cursor, false)?; + let key = self.get_key_data(key, &storage_info, &lookup_table); + let storage = GenericStorage::new(key, Some(StorageValue::new(value))); + Ok(storage) + } + StorageType::Map { value: val_rtype, unused: _unused, .. } => { + let key = self.get_key_data(key, &storage_info, &lookup_table); + let mut cursor = 0; + let value = + self.decode_single(storage_info.module.name(), spec, &val_rtype, value, &mut cursor, false)?; + let storage = GenericStorage::new(key, Some(StorageValue::new(value))); + Ok(storage) + } + StorageType::DoubleMap { value: val_rtype, .. } => { + let key = self.get_key_data(key, &storage_info, &lookup_table); + let mut cursor = 0; + let value = + self.decode_single(storage_info.module.name(), spec, &val_rtype, value, &mut cursor, false)?; + let storage = GenericStorage::new(key, Some(StorageValue::new(value))); + Ok(storage) + } + } + } - /// Decode an extrinsic - pub fn decode_extrinsic( - &self, - spec: SpecVersion, - data: &[u8], - ) -> Result { - let meta = self.versions.get(&spec).expect("Spec does not exist"); + /// Decode an extrinsic + pub fn decode_extrinsic(&self, spec: SpecVersion, data: &[u8]) -> Result { + let meta = self.versions.get(&spec).expect("Spec does not exist"); - // first byte -> vector length - // second byte -> extrinsic version - // third byte -> Outer enum index - // fourth byte -> inner enum index (function index) - // can check if signed via a simple & too - let length = Self::scale_length(data)?; - let mut cursor: usize = length.1; + // first byte -> vector length + // second byte -> extrinsic version + // third byte -> Outer enum index + // fourth byte -> inner enum index (function index) + // can check if signed via a simple & too + let length = Self::scale_length(data)?; + let mut cursor: usize = length.1; - let signature = self.decode_signature(spec, data, &mut cursor)?; + let signature = self.decode_signature(spec, data, &mut cursor)?; - if let Some(s) = &signature { - log::debug!("signature={}", s); - } + if let Some(s) = &signature { + log::debug!("signature={}", s); + } - let mut temp_cursor = cursor; - let module = meta - .module_by_index(ModuleIndex::Call(data[temp_cursor])) - .map_err(|e| Error::DetailedMetaFail(e, temp_cursor, hex::encode(data)))?; - temp_cursor += 1; - let call_meta = module - .call(data[temp_cursor]) - .map_err(|e| Error::DetailedMetaFail(e, temp_cursor, hex::encode(data)))?; - let types = self.decode_call(spec, data, &mut cursor)?; + let mut temp_cursor = cursor; + let module = meta + .module_by_index(ModuleIndex::Call(data[temp_cursor])) + .map_err(|e| Error::DetailedMetaFail(e, temp_cursor, hex::encode(data)))?; + temp_cursor += 1; + let call_meta = + module.call(data[temp_cursor]).map_err(|e| Error::DetailedMetaFail(e, temp_cursor, hex::encode(data)))?; + let types = self.decode_call(spec, data, &mut cursor)?; - Ok(GenericExtrinsic::new( - signature, - types, - call_meta.name(), - module.name().into(), - )) - } + Ok(GenericExtrinsic::new(signature, types, call_meta.name(), module.name().into())) + } - /// Decode the signature part of an UncheckedExtrinsic - fn decode_signature( - &self, - spec: SpecVersion, - data: &[u8], - cursor: &mut usize, - ) -> Result, Error> { - let version = data[*cursor]; - let is_signed = version & 0b1000_0000 != 0; - let version = version & 0b0111_1111; - log::trace!("Extrinsic Version: {}", version); - *cursor += 1; + /// Decode the signature part of an UncheckedExtrinsic + fn decode_signature( + &self, + spec: SpecVersion, + data: &[u8], + cursor: &mut usize, + ) -> Result, Error> { + let version = data[*cursor]; + let is_signed = version & 0b1000_0000 != 0; + let version = version & 0b0111_1111; + log::trace!("Extrinsic Version: {}", version); + *cursor += 1; - if is_signed { - log::trace!("SIGNED EXTRINSIC"); - log::trace!( - "Getting signature for spec: {}, chain: {}", - spec, - self.chain.as_str() - ); - let signature = self - .types - .get_extrinsic_ty(self.chain.as_str(), spec, "signature") - .expect("Signature must not be empty"); - Ok(Some(self.decode_single( - "runtime", spec, signature, data, cursor, false, - )?)) - } else { - Ok(None) - } - } + if is_signed { + log::trace!("SIGNED EXTRINSIC"); + log::trace!("Getting signature for spec: {}, chain: {}", spec, self.chain.as_str()); + let signature = self + .types + .get_extrinsic_ty(self.chain.as_str(), spec, "signature") + .expect("Signature must not be empty"); + Ok(Some(self.decode_single("runtime", spec, signature, data, cursor, false)?)) + } else { + Ok(None) + } + } - fn decode_call( - &self, - spec: SpecVersion, - data: &[u8], - cursor: &mut usize, - ) -> Result, Error> { - let meta = self.versions.get(&spec).expect("Spec does not exist"); + fn decode_call( + &self, + spec: SpecVersion, + data: &[u8], + cursor: &mut usize, + ) -> Result, Error> { + let meta = self.versions.get(&spec).expect("Spec does not exist"); - log::trace!("data = {:?}", &data[*cursor..]); - log::trace!("cursor = {}", cursor); - let module = meta.module_by_index(ModuleIndex::Call(data[*cursor]))?; - *cursor += 1; - log::trace!("cursor = {}", cursor); - let call_meta = module.call(data[*cursor])?; - *cursor += 1; - log::trace!("cursor = {}", cursor); - log::trace!("data = {:X?}", &data[*cursor..]); + log::trace!("data = {:?}", &data[*cursor..]); + log::trace!("cursor = {}", cursor); + let module = meta.module_by_index(ModuleIndex::Call(data[*cursor]))?; + *cursor += 1; + log::trace!("cursor = {}", cursor); + let call_meta = module.call(data[*cursor])?; + *cursor += 1; + log::trace!("cursor = {}", cursor); + log::trace!("data = {:X?}", &data[*cursor..]); - // TODO: tuple of argument name -> value - let mut types: Vec<(String, SubstrateType)> = Vec::new(); - for arg in call_meta.arguments() { - log::trace!("arg = {:?}", arg); - let val = self.decode_single(module.name(), spec, &arg.ty, data, cursor, false)?; - types.push((arg.name.to_string(), val)); - } - Ok(types) - } + // TODO: tuple of argument name -> value + let mut types: Vec<(String, SubstrateType)> = Vec::new(); + for arg in call_meta.arguments() { + log::trace!("arg = {:?}", arg); + let val = self.decode_single(module.name(), spec, &arg.ty, data, cursor, false)?; + types.push((arg.name.to_string(), val)); + } + Ok(types) + } - /// Internal function to handle - /// decoding of a single rust type marker - /// from data and the curent position within the data - /// - /// # Panics - /// panics if a type cannot be decoded - #[track_caller] - fn decode_single( - &self, - module: &str, - spec: SpecVersion, - ty: &RustTypeMarker, - data: &[u8], - cursor: &mut usize, - is_compact: bool, - ) -> Result { - let ty = match ty { - RustTypeMarker::TypePointer(v) => { - log::trace!("Resolving: {}", v); + /// Internal function to handle + /// decoding of a single rust type marker + /// from data and the curent position within the data + /// + /// # Panics + /// panics if a type cannot be decoded + #[track_caller] + fn decode_single( + &self, + module: &str, + spec: SpecVersion, + ty: &RustTypeMarker, + data: &[u8], + cursor: &mut usize, + is_compact: bool, + ) -> Result { + let ty = match ty { + RustTypeMarker::TypePointer(v) => { + log::trace!("Resolving: {}", v); - if let Some(t) = self.decode_sub_type(spec, v, data, cursor, is_compact)? { - t - } else { - let new_type = self - .types - .get(self.chain.as_str(), spec, module, v) - .ok_or_else(|| { - Error::from(format!( - "Name Resolution Failure: module={}, v={}, spec={}, chain={}", - module, - v, - spec, - self.chain.as_str() - )) - })?; - log::trace!("Resolved {:?}", new_type); - self.decode_single(module, spec, new_type, data, cursor, is_compact)? - } - } - RustTypeMarker::Struct(v) => { - log::trace!("Struct::cursor = {:?}", cursor); - let ty = self.decode_structlike(v, module, spec, data, cursor, is_compact)?; - SubstrateType::Struct(ty) - } - // TODO: test - RustTypeMarker::Set(v) => { - log::trace!("Set::cursor = {}", *cursor); - // a set item must be an u8 - // can decode this right away - let index = data[*cursor]; - *cursor += 1; - SubstrateType::Set(v[index as usize].clone()) - } - RustTypeMarker::Tuple(v) => { - log::trace!("Tuple::cursor={}", *cursor); - let ty = v - .iter() - .map(|v| self.decode_single(module, spec, &v, data, cursor, is_compact)) - .collect::, Error>>(); - SubstrateType::Composite(ty?) - } - RustTypeMarker::Enum(v) => { - log::trace!("Enum::cursor={}", *cursor); - let index = data[*cursor]; - *cursor += 1; - let variant = &v[index as usize]; - match &variant.ty { - crate::StructUnitOrTuple::Struct(ref v) => { - let ty = - self.decode_structlike(v, module, spec, data, cursor, is_compact)?; - SubstrateType::Enum(StructUnitOrTuple::Struct(ty)) - } - crate::StructUnitOrTuple::Unit(v) => { - SubstrateType::Enum(StructUnitOrTuple::Unit(v.clone())) - } - crate::StructUnitOrTuple::Tuple(ref v) => { - let ty = self.decode_single(module, spec, v, data, cursor, is_compact)?; - let name = variant - .variant_name - .as_ref() - .expect("Tuple Variant must have a name") - .clone(); - SubstrateType::Enum(StructUnitOrTuple::Tuple { - name, - ty: Box::new(ty), - }) - } - } - } - RustTypeMarker::Array { size, ty } => { - log::trace!("Array::cursor={}", *cursor); - let mut decoded_arr = Vec::with_capacity(*size); - if *size == 0 as usize { - log::trace!("Returning Empty Vector"); - return Ok(SubstrateType::Composite(Vec::new())); - } else { - for _ in 0..*size { - decoded_arr - .push(self.decode_single(module, spec, ty, &data, cursor, is_compact)?) - } - } - // rely on cursor increments in sub-types (U32/substrate specific types) - SubstrateType::Composite(decoded_arr) - } - RustTypeMarker::Std(v) => match v { - CommonTypes::Vec(v) => { - log::trace!("Vec::cursor={}", *cursor); - let length = Self::scale_length(&data[*cursor..])?; - *cursor += length.1; - // we can just decode this as an "array" now - self.decode_single( - module, - spec, - &RustTypeMarker::Array { - size: length.0, - ty: v.clone(), - }, - data, - cursor, - is_compact, - )? - } - CommonTypes::Option(v) => { - log::trace!("Option::cursor={}", *cursor); - match data[*cursor] { - // None - 0x00 => { - *cursor += 1; - SubstrateType::Option(Box::new(None)) - } - // Some - 0x01 => { - *cursor += 1; - let ty = - self.decode_single(module, spec, v, data, cursor, is_compact)?; - SubstrateType::Option(Box::new(Some(ty))) - } - _ => { - panic!("Cannot deduce correct Option enum variant"); - } - } - } - CommonTypes::Result(v, e) => { - log::trace!("Result::cursor={}", *cursor); - match data[*cursor] { - // Ok - 0x00 => { - *cursor += 1; - let ty = - self.decode_single(module, spec, v, data, cursor, is_compact)?; - SubstrateType::Result(Box::new(Ok(ty))) - } - // Err - 0x01 => { - *cursor += 1; - let ty = - self.decode_single(module, spec, e, data, cursor, is_compact)?; - SubstrateType::Result(Box::new(Err(ty))) - } - _ => { - panic!("Cannot deduce correct Result Enum Variant"); - } - } - } - // TODO: test - CommonTypes::Compact(v) => { - log::trace!("Compact::cursor={}", cursor); - self.decode_single(module, spec, v, data, cursor, true)? - } - }, - RustTypeMarker::Generic((outer, _)) => { - log::trace!("Generic Type"); - // disregard 'inner' type of a generic - self.decode_single(module, spec, outer, data, cursor, is_compact)? - } - RustTypeMarker::U8 => { - let num: u8 = if is_compact { - let num: Compact = Decode::decode(&mut &data[*cursor..])?; - *cursor += Compact::compact_len(&u8::from(num)); - num.into() - } else { - let num: u8 = Decode::decode(&mut &data[*cursor..])?; - *cursor += 1; - num - }; - num.into() - } - RustTypeMarker::U16 => { - let num: u16 = if is_compact { - let num: Compact = Decode::decode(&mut &data[*cursor..])?; - *cursor += Compact::compact_len(&u16::from(num)); - num.into() - } else { - let num: u16 = Decode::decode(&mut &data[*cursor..])?; - *cursor += 2; - num - }; - num.into() - } - RustTypeMarker::U32 => { - let num: u32 = if is_compact { - let num: Compact = Decode::decode(&mut &data[*cursor..])?; - let len = Compact::compact_len(&u32::from(num)); - log::trace!("Compact len: {}", len); - *cursor += len; - num.into() - } else { - let num: u32 = Decode::decode(&mut &data[*cursor..])?; - *cursor += 4; - num - }; - num.into() - } - RustTypeMarker::U64 => { - let num: u64 = if is_compact { - let num: Compact = Decode::decode(&mut &data[*cursor..])?; - *cursor += Compact::compact_len(&u64::from(num)); - num.into() - } else { - let num: u64 = Decode::decode(&mut &data[*cursor..])?; - *cursor += 8; - num - }; - num.into() - } - RustTypeMarker::U128 => { - log::trace!("data = {:?}", &data[*cursor..]); - let num: u128 = if is_compact { - let num: Compact = Decode::decode(&mut &data[*cursor..])?; - *cursor += Compact::compact_len(&u128::from(num)); - num.into() - } else { - let num: u128 = Decode::decode(&mut &data[*cursor..])?; - *cursor += 16; - num - }; - num.into() - } - RustTypeMarker::USize => { - panic!("usize decoding not possible!") - /* let size = std::mem::size_of::(); - let num: usize = - Decode::decode(&mut &data[*cursor..=*cursor+size])?; - *cursor += std::mem::size_of::(); - num.into() - */ - } - RustTypeMarker::I8 => { - let num: i8 = if is_compact { - unimplemented!() - } else { - Decode::decode(&mut &data[*cursor..])? - }; - *cursor += 1; - num.into() - } - RustTypeMarker::I16 => { - let num: i16 = if is_compact { - unimplemented!() - } else { - Decode::decode(&mut &data[*cursor..])? - }; - *cursor += 2; - num.into() - } - RustTypeMarker::I32 => { - let num: i32 = if is_compact { - unimplemented!() - } else { - Decode::decode(&mut &data[*cursor..])? - }; - *cursor += 4; - num.into() - } - RustTypeMarker::I64 => { - let num: i64 = if is_compact { - // let num: Compact = Decode::decode(&mut &data[*cursor..*cursor+8])?; - // num.into() - unimplemented!() - } else { - Decode::decode(&mut &data[*cursor..])? - }; - *cursor += 8; - num.into() - } - RustTypeMarker::I128 => { - let num: i128 = if is_compact { - unimplemented!() - } else { - Decode::decode(&mut &data[*cursor..])? - }; - *cursor += 16; - num.into() - } - RustTypeMarker::ISize => { - panic!("isize decoding impossible!") - /* - let idx = std::mem::size_of::(); - let num: isize = - Decode::decode(&mut &data[*cursor..=*cursor + idx])?; - *cursor += std::mem::size_of::(); - num.into() - */ - } - RustTypeMarker::F32 => { - /* - let num: f32 = Decode::decode(&mut &data[*cursor..=*cursor + 4])?; - *cursor += 5; - num.into() - */ - panic!("f32 decoding impossible!"); - } - RustTypeMarker::F64 => { - /* - let num: f64 = Decode::decode(&mut &data[*cursor..=*cursor + 8])?; - *cursor += 9; - num.into() - */ - panic!("f64 decoding impossible!"); - } - RustTypeMarker::String => unimplemented!(), - RustTypeMarker::Bool => { - let boo: bool = Decode::decode(&mut &data[*cursor..=*cursor])?; - *cursor += 1; - // . - . - // ( o o ) - // | 0 \ - // \ \ - // `~~~~~' boo! - boo.into() - } - RustTypeMarker::Null => SubstrateType::Null, - }; - Ok(ty) - } + if let Some(t) = self.decode_sub_type(spec, v, data, cursor, is_compact)? { + t + } else { + let new_type = self.types.get(self.chain.as_str(), spec, module, v).ok_or_else(|| { + Error::from(format!( + "Name Resolution Failure: module={}, v={}, spec={}, chain={}", + module, + v, + spec, + self.chain.as_str() + )) + })?; + log::trace!("Resolved {:?}", new_type); + self.decode_single(module, spec, new_type, data, cursor, is_compact)? + } + } + RustTypeMarker::Struct(v) => { + log::trace!("Struct::cursor = {:?}", cursor); + let ty = self.decode_structlike(v, module, spec, data, cursor, is_compact)?; + SubstrateType::Struct(ty) + } + // TODO: test + RustTypeMarker::Set(v) => { + log::trace!("Set::cursor = {}", *cursor); + // a set item must be an u8 + // can decode this right away + let index = data[*cursor]; + *cursor += 1; + SubstrateType::Set(v[index as usize].clone()) + } + RustTypeMarker::Tuple(v) => { + log::trace!("Tuple::cursor={}", *cursor); + let ty = v + .iter() + .map(|v| self.decode_single(module, spec, &v, data, cursor, is_compact)) + .collect::, Error>>(); + SubstrateType::Composite(ty?) + } + RustTypeMarker::Enum(v) => { + log::trace!("Enum::cursor={}", *cursor); + let index = data[*cursor]; + *cursor += 1; + let variant = &v[index as usize]; + match &variant.ty { + crate::StructUnitOrTuple::Struct(ref v) => { + let ty = self.decode_structlike(v, module, spec, data, cursor, is_compact)?; + SubstrateType::Enum(StructUnitOrTuple::Struct(ty)) + } + crate::StructUnitOrTuple::Unit(v) => SubstrateType::Enum(StructUnitOrTuple::Unit(v.clone())), + crate::StructUnitOrTuple::Tuple(ref v) => { + let ty = self.decode_single(module, spec, v, data, cursor, is_compact)?; + let name = variant.variant_name.as_ref().expect("Tuple Variant must have a name").clone(); + SubstrateType::Enum(StructUnitOrTuple::Tuple { name, ty: Box::new(ty) }) + } + } + } + RustTypeMarker::Array { size, ty } => { + log::trace!("Array::cursor={}", *cursor); + let mut decoded_arr = Vec::with_capacity(*size); + if *size == 0 as usize { + log::trace!("Returning Empty Vector"); + return Ok(SubstrateType::Composite(Vec::new())); + } else { + for _ in 0..*size { + decoded_arr.push(self.decode_single(module, spec, ty, &data, cursor, is_compact)?) + } + } + // rely on cursor increments in sub-types (U32/substrate specific types) + SubstrateType::Composite(decoded_arr) + } + RustTypeMarker::Std(v) => match v { + CommonTypes::Vec(v) => { + log::trace!("Vec::cursor={}", *cursor); + let length = Self::scale_length(&data[*cursor..])?; + *cursor += length.1; + // we can just decode this as an "array" now + self.decode_single( + module, + spec, + &RustTypeMarker::Array { size: length.0, ty: v.clone() }, + data, + cursor, + is_compact, + )? + } + CommonTypes::Option(v) => { + log::trace!("Option::cursor={}", *cursor); + match data[*cursor] { + // None + 0x00 => { + *cursor += 1; + SubstrateType::Option(Box::new(None)) + } + // Some + 0x01 => { + *cursor += 1; + let ty = self.decode_single(module, spec, v, data, cursor, is_compact)?; + SubstrateType::Option(Box::new(Some(ty))) + } + _ => { + panic!("Cannot deduce correct Option enum variant"); + } + } + } + CommonTypes::Result(v, e) => { + log::trace!("Result::cursor={}", *cursor); + match data[*cursor] { + // Ok + 0x00 => { + *cursor += 1; + let ty = self.decode_single(module, spec, v, data, cursor, is_compact)?; + SubstrateType::Result(Box::new(Ok(ty))) + } + // Err + 0x01 => { + *cursor += 1; + let ty = self.decode_single(module, spec, e, data, cursor, is_compact)?; + SubstrateType::Result(Box::new(Err(ty))) + } + _ => { + panic!("Cannot deduce correct Result Enum Variant"); + } + } + } + // TODO: test + CommonTypes::Compact(v) => { + log::trace!("Compact::cursor={}", cursor); + self.decode_single(module, spec, v, data, cursor, true)? + } + }, + RustTypeMarker::Generic((outer, _)) => { + log::trace!("Generic Type"); + // disregard 'inner' type of a generic + self.decode_single(module, spec, outer, data, cursor, is_compact)? + } + RustTypeMarker::U8 => { + let num: u8 = if is_compact { + let num: Compact = Decode::decode(&mut &data[*cursor..])?; + *cursor += Compact::compact_len(&u8::from(num)); + num.into() + } else { + let num: u8 = Decode::decode(&mut &data[*cursor..])?; + *cursor += 1; + num + }; + num.into() + } + RustTypeMarker::U16 => { + let num: u16 = if is_compact { + let num: Compact = Decode::decode(&mut &data[*cursor..])?; + *cursor += Compact::compact_len(&u16::from(num)); + num.into() + } else { + let num: u16 = Decode::decode(&mut &data[*cursor..])?; + *cursor += 2; + num + }; + num.into() + } + RustTypeMarker::U32 => { + let num: u32 = if is_compact { + let num: Compact = Decode::decode(&mut &data[*cursor..])?; + let len = Compact::compact_len(&u32::from(num)); + log::trace!("Compact len: {}", len); + *cursor += len; + num.into() + } else { + let num: u32 = Decode::decode(&mut &data[*cursor..])?; + *cursor += 4; + num + }; + num.into() + } + RustTypeMarker::U64 => { + let num: u64 = if is_compact { + let num: Compact = Decode::decode(&mut &data[*cursor..])?; + *cursor += Compact::compact_len(&u64::from(num)); + num.into() + } else { + let num: u64 = Decode::decode(&mut &data[*cursor..])?; + *cursor += 8; + num + }; + num.into() + } + RustTypeMarker::U128 => { + log::trace!("data = {:?}", &data[*cursor..]); + let num: u128 = if is_compact { + let num: Compact = Decode::decode(&mut &data[*cursor..])?; + *cursor += Compact::compact_len(&u128::from(num)); + num.into() + } else { + let num: u128 = Decode::decode(&mut &data[*cursor..])?; + *cursor += 16; + num + }; + num.into() + } + RustTypeMarker::USize => { + panic!("usize decoding not possible!") + /* let size = std::mem::size_of::(); + let num: usize = + Decode::decode(&mut &data[*cursor..=*cursor+size])?; + *cursor += std::mem::size_of::(); + num.into() + */ + } + RustTypeMarker::I8 => { + let num: i8 = if is_compact { unimplemented!() } else { Decode::decode(&mut &data[*cursor..])? }; + *cursor += 1; + num.into() + } + RustTypeMarker::I16 => { + let num: i16 = if is_compact { unimplemented!() } else { Decode::decode(&mut &data[*cursor..])? }; + *cursor += 2; + num.into() + } + RustTypeMarker::I32 => { + let num: i32 = if is_compact { unimplemented!() } else { Decode::decode(&mut &data[*cursor..])? }; + *cursor += 4; + num.into() + } + RustTypeMarker::I64 => { + let num: i64 = if is_compact { + // let num: Compact = Decode::decode(&mut &data[*cursor..*cursor+8])?; + // num.into() + unimplemented!() + } else { + Decode::decode(&mut &data[*cursor..])? + }; + *cursor += 8; + num.into() + } + RustTypeMarker::I128 => { + let num: i128 = if is_compact { unimplemented!() } else { Decode::decode(&mut &data[*cursor..])? }; + *cursor += 16; + num.into() + } + RustTypeMarker::ISize => { + panic!("isize decoding impossible!") + /* + let idx = std::mem::size_of::(); + let num: isize = + Decode::decode(&mut &data[*cursor..=*cursor + idx])?; + *cursor += std::mem::size_of::(); + num.into() + */ + } + RustTypeMarker::F32 => { + /* + let num: f32 = Decode::decode(&mut &data[*cursor..=*cursor + 4])?; + *cursor += 5; + num.into() + */ + panic!("f32 decoding impossible!"); + } + RustTypeMarker::F64 => { + /* + let num: f64 = Decode::decode(&mut &data[*cursor..=*cursor + 8])?; + *cursor += 9; + num.into() + */ + panic!("f64 decoding impossible!"); + } + RustTypeMarker::String => unimplemented!(), + RustTypeMarker::Bool => { + let boo: bool = Decode::decode(&mut &data[*cursor..=*cursor])?; + *cursor += 1; + // . - . + // ( o o ) + // | 0 \ + // \ \ + // `~~~~~' boo! + boo.into() + } + RustTypeMarker::Null => SubstrateType::Null, + }; + Ok(ty) + } - /// internal API to decode 'special' substrate types. - /// Or, types that have a special encode/decode scheme - /// that may include packing bytes in a struct. - /// Packing for example implies that a struct with two u32 fields - /// may be encoded as a u8 (one byte). - /// These types override anything defined in JSON - /// Tries to decode a type that is native to substrate - /// for example, H256. Returns none if type cannot be deduced - /// Supported types: - /// - H256 - /// - H512 - // TODO: test this with the substrate types used - fn decode_sub_type( - &self, - spec: SpecVersion, - ty: &str, - data: &[u8], - cursor: &mut usize, - is_compact: bool, - ) -> Result, Error> { - match ty { - // checks if the metadata includes types for the SignedExtensions - // If not defaults to whatever is in extrinsics.json - "SignedExtra" => { - let meta = self - .versions - .get(&spec) - .ok_or(format!("Metadata for spec {} not found", spec))?; - if let Some(extensions) = meta.signed_extensions() { - let extensions = RustTypeMarker::Tuple(extensions.to_vec()); - self.decode_single("", spec, &extensions, data, cursor, is_compact) - .map(Option::Some) - } else { - let ty = self - .types - .get_extrinsic_ty(self.chain.as_str(), spec, "SignedExtra") - .ok_or_else(|| Error::from("Could not find type `SignedExtra`"))?; - self.decode_single("", spec, &ty, data, cursor, is_compact) - .map(Option::Some) - } - } - // identity info may be added to in the future - "IdentityInfo" => { - let additional = self.decode_single( - "identity", - spec, - &RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::TypePointer( - "IdentityInfoAdditional".to_string(), - )))), - data, - cursor, - is_compact, - )?; - let display = self - .decode_sub_type(spec, "Data", data, cursor, is_compact)? - .ok_or_else(|| Error::from("Data not resolved"))?; - let legal = self - .decode_sub_type(spec, "Data", data, cursor, is_compact)? - .ok_or_else(|| Error::from("Data not resolved"))?; - let web = self - .decode_sub_type(spec, "Data", data, cursor, is_compact)? - .ok_or_else(|| Error::from("Data not resolved"))?; - let riot = self - .decode_sub_type(spec, "Data", data, cursor, is_compact)? - .ok_or_else(|| Error::from("Data not resolved"))?; - let email = self - .decode_sub_type(spec, "Data", data, cursor, is_compact)? - .ok_or_else(|| Error::from("Data not resolved"))?; - let pgp_fingerprint = self.decode_single( - "identity", - spec, - &RustTypeMarker::Std(CommonTypes::Option(Box::new( - RustTypeMarker::TypePointer("H160".to_string()), - ))), - data, - cursor, - is_compact, - )?; - let image = self - .decode_sub_type(spec, "Data", data, cursor, is_compact)? - .ok_or_else(|| Error::from("Data not resolved"))?; - let twitter = self.decode_sub_type(spec, "Data", data, cursor, is_compact); + /// internal API to decode 'special' substrate types. + /// Or, types that have a special encode/decode scheme + /// that may include packing bytes in a struct. + /// Packing for example implies that a struct with two u32 fields + /// may be encoded as a u8 (one byte). + /// These types override anything defined in JSON + /// Tries to decode a type that is native to substrate + /// for example, H256. Returns none if type cannot be deduced + /// Supported types: + /// - H256 + /// - H512 + // TODO: test this with the substrate types used + fn decode_sub_type( + &self, + spec: SpecVersion, + ty: &str, + data: &[u8], + cursor: &mut usize, + is_compact: bool, + ) -> Result, Error> { + match ty { + // checks if the metadata includes types for the SignedExtensions + // If not defaults to whatever is in extrinsics.json + "SignedExtra" => { + let meta = self.versions.get(&spec).ok_or(format!("Metadata for spec {} not found", spec))?; + if let Some(extensions) = meta.signed_extensions() { + let extensions = RustTypeMarker::Tuple(extensions.to_vec()); + self.decode_single("", spec, &extensions, data, cursor, is_compact).map(Option::Some) + } else { + let ty = self + .types + .get_extrinsic_ty(self.chain.as_str(), spec, "SignedExtra") + .ok_or_else(|| Error::from("Could not find type `SignedExtra`"))?; + self.decode_single("", spec, &ty, data, cursor, is_compact).map(Option::Some) + } + } + // identity info may be added to in the future + "IdentityInfo" => { + let additional = self.decode_single( + "identity", + spec, + &RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::TypePointer( + "IdentityInfoAdditional".to_string(), + )))), + data, + cursor, + is_compact, + )?; + let display = self + .decode_sub_type(spec, "Data", data, cursor, is_compact)? + .ok_or_else(|| Error::from("Data not resolved"))?; + let legal = self + .decode_sub_type(spec, "Data", data, cursor, is_compact)? + .ok_or_else(|| Error::from("Data not resolved"))?; + let web = self + .decode_sub_type(spec, "Data", data, cursor, is_compact)? + .ok_or_else(|| Error::from("Data not resolved"))?; + let riot = self + .decode_sub_type(spec, "Data", data, cursor, is_compact)? + .ok_or_else(|| Error::from("Data not resolved"))?; + let email = self + .decode_sub_type(spec, "Data", data, cursor, is_compact)? + .ok_or_else(|| Error::from("Data not resolved"))?; + let pgp_fingerprint = self.decode_single( + "identity", + spec, + &RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::TypePointer( + "H160".to_string(), + )))), + data, + cursor, + is_compact, + )?; + let image = self + .decode_sub_type(spec, "Data", data, cursor, is_compact)? + .ok_or_else(|| Error::from("Data not resolved"))?; + let twitter = self.decode_sub_type(spec, "Data", data, cursor, is_compact); - Ok(Some(SubstrateType::Struct(vec![ - StructField::new(Some("additional"), additional), - StructField::new(Some("display"), display), - StructField::new(Some("legal"), legal), - StructField::new(Some("web"), web), - StructField::new(Some("riot"), riot), - StructField::new(Some("email"), email), - StructField::new(Some("pgpFingerprint"), pgp_fingerprint), - StructField::new(Some("image"), image), - StructField::new( - Some("twitter"), - twitter - .unwrap_or(Some(SubstrateType::Null)) - .ok_or_else(|| Error::from("Data not resolved"))?, - ), - ]))) - } - "Data" => { - log::trace!("Data::cursor={}", *cursor); - let identity_data: pallet_identity::Data = Decode::decode(&mut &data[*cursor..])?; - match &identity_data { - pallet_identity::Data::None => (), - pallet_identity::Data::Raw(v) => *cursor += v.len(), - _ => *cursor += 32, - }; - // for the enum byte - *cursor += 1; - Ok(Some(SubstrateType::Data(identity_data))) - } - "Call" | "GenericCall" => { - let types = self.decode_call(spec, data, cursor)?; - Ok(Some(SubstrateType::Call(types))) - } - "GenericVote" => { - let vote: pallet_democracy::Vote = Decode::decode(&mut &data[*cursor..])?; - // a vote is one byte - *cursor += 1; - Ok(Some(SubstrateType::GenericVote(vote))) - } - "Lookup" | "GenericAddress" | "GenericLookupSource" | "GenericAccountId" => { - // a specific type that is ::Lookup concatenated to just 'Lookup' - log::trace!("cursor={}, data length={}", cursor, data.len()); - let inc: usize; - // TODO: requires more investigation - // cursor increments for 0x00 .. 0xfe may be incorrect - match data[*cursor] { - 0x00..=0xef => { - inc = 0; - } - 0xfc => { - inc = 2; - } - 0xfd => { - inc = 4; - } - 0xfe => { - inc = 8; - } - 0xff => { - inc = 32; - } - _ => return Err(Error::Fail("Invalid Address".to_string())), - } + Ok(Some(SubstrateType::Struct(vec![ + StructField::new(Some("additional"), additional), + StructField::new(Some("display"), display), + StructField::new(Some("legal"), legal), + StructField::new(Some("web"), web), + StructField::new(Some("riot"), riot), + StructField::new(Some("email"), email), + StructField::new(Some("pgpFingerprint"), pgp_fingerprint), + StructField::new(Some("image"), image), + StructField::new( + Some("twitter"), + twitter.unwrap_or(Some(SubstrateType::Null)).ok_or_else(|| Error::from("Data not resolved"))?, + ), + ]))) + } + "Data" => { + log::trace!("Data::cursor={}", *cursor); + let identity_data: pallet_identity::Data = Decode::decode(&mut &data[*cursor..])?; + match &identity_data { + pallet_identity::Data::None => (), + pallet_identity::Data::Raw(v) => *cursor += v.len(), + _ => *cursor += 32, + }; + // for the enum byte + *cursor += 1; + Ok(Some(SubstrateType::Data(identity_data))) + } + "Call" | "GenericCall" => { + let types = self.decode_call(spec, data, cursor)?; + Ok(Some(SubstrateType::Call(types))) + } + "GenericVote" => { + let vote: pallet_democracy::Vote = Decode::decode(&mut &data[*cursor..])?; + // a vote is one byte + *cursor += 1; + Ok(Some(SubstrateType::GenericVote(vote))) + } + "Lookup" | "GenericAddress" | "GenericLookupSource" | "GenericAccountId" => { + // a specific type that is ::Lookup concatenated to just 'Lookup' + log::trace!("cursor={}, data length={}", cursor, data.len()); + let inc: usize; + // TODO: requires more investigation + // cursor increments for 0x00 .. 0xfe may be incorrect + match data[*cursor] { + 0x00..=0xef => { + inc = 0; + } + 0xfc => { + inc = 2; + } + 0xfd => { + inc = 4; + } + 0xfe => { + inc = 8; + } + 0xff => { + inc = 32; + } + _ => return Err(Error::Fail("Invalid Address".to_string())), + } - let val: substrate_types::Address = Decode::decode(&mut &data[*cursor..])?; + let val: substrate_types::Address = Decode::decode(&mut &data[*cursor..])?; - *cursor += inc + 1; // +1 for byte 0x00-0xff - Ok(Some(SubstrateType::Address(val))) - } - "Era" => { - log::trace!("ERA DATA: {:X?}", &data[*cursor..]); - let val: runtime_primitives::generic::Era = Decode::decode(&mut &data[*cursor..])?; - log::trace!("Resolved Era: {:?}", val); - match val { - // although phase and period are both u64, era is Encoded - // in only two bytes - runtime_primitives::generic::Era::Immortal => *cursor += 1, - runtime_primitives::generic::Era::Mortal(_, _) => *cursor += 2, - }; - Ok(Some(SubstrateType::Era(val))) - } - "H256" => { - let val: primitives::H256 = Decode::decode(&mut &data[*cursor..])?; - *cursor += 32; - Ok(Some(SubstrateType::H256(val))) - } - "H512" => { - let val: primitives::H512 = Decode::decode(&mut &data[*cursor..])?; - log::trace!("H512: {}", hex::encode(val.as_bytes())); - *cursor += 64; - Ok(Some(SubstrateType::H512(val))) - } - _ => Ok(None), - } - } + *cursor += inc + 1; // +1 for byte 0x00-0xff + Ok(Some(SubstrateType::Address(val))) + } + "Era" => { + log::trace!("ERA DATA: {:X?}", &data[*cursor..]); + let val: runtime_primitives::generic::Era = Decode::decode(&mut &data[*cursor..])?; + log::trace!("Resolved Era: {:?}", val); + match val { + // although phase and period are both u64, era is Encoded + // in only two bytes + runtime_primitives::generic::Era::Immortal => *cursor += 1, + runtime_primitives::generic::Era::Mortal(_, _) => *cursor += 2, + }; + Ok(Some(SubstrateType::Era(val))) + } + "H256" => { + let val: primitives::H256 = Decode::decode(&mut &data[*cursor..])?; + *cursor += 32; + Ok(Some(SubstrateType::H256(val))) + } + "H512" => { + let val: primitives::H512 = Decode::decode(&mut &data[*cursor..])?; + log::trace!("H512: {}", hex::encode(val.as_bytes())); + *cursor += 64; + Ok(Some(SubstrateType::H512(val))) + } + _ => Ok(None), + } + } - /// internal api to get the number of items in a encoded series - /// returns a tuple of (number_of_items, length_of_prefix) - /// length of prefix is the length in bytes that the prefix took up - /// in the encoded data - fn scale_length(mut data: &[u8]) -> Result<(usize, usize), Error> { - // alternative to `DecodeLength` trait, to avoid casting from a trait - let u32_length = u32::from(Compact::::decode(&mut data)?); - let length_of_prefix: usize = Compact::compact_len(&u32_length); - let usize_length = usize::try_from(u32_length) - .map_err(|_| Error::from("Failed convert decoded size into usize."))?; - Ok((usize_length, length_of_prefix)) - } + /// internal api to get the number of items in a encoded series + /// returns a tuple of (number_of_items, length_of_prefix) + /// length of prefix is the length in bytes that the prefix took up + /// in the encoded data + fn scale_length(mut data: &[u8]) -> Result<(usize, usize), Error> { + // alternative to `DecodeLength` trait, to avoid casting from a trait + let u32_length = u32::from(Compact::::decode(&mut data)?); + let length_of_prefix: usize = Compact::compact_len(&u32_length); + let usize_length = + usize::try_from(u32_length).map_err(|_| Error::from("Failed convert decoded size into usize."))?; + Ok((usize_length, length_of_prefix)) + } - /// internal api to decode a vector of struct IdentityFields - fn decode_structlike( - &self, - fields: &[crate::StructField], - module: &str, - spec: SpecVersion, - data: &[u8], - cursor: &mut usize, - is_compact: bool, - ) -> Result, Error> { - fields - .iter() - .map(|field| { - log::trace!("name={:?}, field={}", field.name, field.ty); - let ty = self.decode_single(module, spec, &field.ty, data, cursor, is_compact)?; - Ok(StructField { - name: Some(field.name.clone()), - ty, - }) - }) - .collect::, Error>>() - } + /// internal api to decode a vector of struct IdentityFields + fn decode_structlike( + &self, + fields: &[crate::StructField], + module: &str, + spec: SpecVersion, + data: &[u8], + cursor: &mut usize, + is_compact: bool, + ) -> Result, Error> { + fields + .iter() + .map(|field| { + log::trace!("name={:?}, field={}", field.name, field.ty); + let ty = self.decode_single(module, spec, &field.ty, data, cursor, is_compact)?; + Ok(StructField { name: Some(field.name.clone()), ty }) + }) + .collect::, Error>>() + } } #[cfg(test)] mod tests { - use super::*; - use crate::{ - decoder::metadata::test_suite as meta_test_suite, substrate_types::StructField, test_suite, - EnumField, - }; - use codec::Encode; + use super::*; + use crate::{ + decoder::metadata::test_suite as meta_test_suite, substrate_types::StructField, test_suite, EnumField, + }; + use codec::Encode; - #[derive(Debug, Clone)] - struct GenericTypes; + #[derive(Debug, Clone)] + struct GenericTypes; - impl TypeDetective for GenericTypes { - fn get( - &self, - _chain: &str, - _spec: u32, - _module: &str, - _ty: &str, - ) -> Option<&RustTypeMarker> { - Some(&RustTypeMarker::I128) - } + impl TypeDetective for GenericTypes { + fn get(&self, _chain: &str, _spec: u32, _module: &str, _ty: &str) -> Option<&RustTypeMarker> { + Some(&RustTypeMarker::I128) + } - fn get_extrinsic_ty(&self, _chain: &str, _spec: u32, _ty: &str) -> Option<&RustTypeMarker> { - None - } - } + fn get_extrinsic_ty(&self, _chain: &str, _spec: u32, _ty: &str) -> Option<&RustTypeMarker> { + None + } + } - #[test] - fn should_insert_metadata() { - let mut decoder = Decoder::new(GenericTypes, Chain::Kusama); - decoder.register_version( - test_suite::mock_runtime(0).spec_version, - &meta_test_suite::test_metadata(), - ); - decoder.register_version( - test_suite::mock_runtime(1).spec_version, - &meta_test_suite::test_metadata(), - ); - decoder.register_version( - test_suite::mock_runtime(2).spec_version, - &meta_test_suite::test_metadata(), - ); - assert!(decoder - .versions - .contains_key(&test_suite::mock_runtime(0).spec_version)); - assert!(decoder - .versions - .contains_key(&test_suite::mock_runtime(1).spec_version)); - assert!(decoder - .versions - .contains_key(&test_suite::mock_runtime(2).spec_version)) - } + #[test] + fn should_insert_metadata() { + let mut decoder = Decoder::new(GenericTypes, Chain::Kusama); + decoder.register_version(test_suite::mock_runtime(0).spec_version, &meta_test_suite::test_metadata()); + decoder.register_version(test_suite::mock_runtime(1).spec_version, &meta_test_suite::test_metadata()); + decoder.register_version(test_suite::mock_runtime(2).spec_version, &meta_test_suite::test_metadata()); + assert!(decoder.versions.contains_key(&test_suite::mock_runtime(0).spec_version)); + assert!(decoder.versions.contains_key(&test_suite::mock_runtime(1).spec_version)); + assert!(decoder.versions.contains_key(&test_suite::mock_runtime(2).spec_version)) + } - #[test] - fn should_get_version_metadata() { - // let types = PolkadotTypes::new().unwrap(); - let mut decoder = Decoder::new(GenericTypes, Chain::Kusama); - let rt_version = test_suite::mock_runtime(0); - let meta = meta_test_suite::test_metadata(); - decoder.register_version(rt_version.spec_version.clone(), &meta); - let _other_meta = decoder.get_version_metadata(rt_version.spec_version); - assert_eq!(Some(&meta), _other_meta.clone()) - } + #[test] + fn should_get_version_metadata() { + // let types = PolkadotTypes::new().unwrap(); + let mut decoder = Decoder::new(GenericTypes, Chain::Kusama); + let rt_version = test_suite::mock_runtime(0); + let meta = meta_test_suite::test_metadata(); + decoder.register_version(rt_version.spec_version.clone(), &meta); + let _other_meta = decoder.get_version_metadata(rt_version.spec_version); + assert_eq!(Some(&meta), _other_meta.clone()) + } - #[test] - fn should_get_scale_length() { - let encoded = vec![32, 4].encode(); - for v in encoded.iter() { - print!("{:08b} ", v); - } - let len = Decoder::scale_length(encoded.as_slice()).unwrap(); - assert_eq!(len.0, 2); - } + #[test] + fn should_get_scale_length() { + let encoded = vec![32, 4].encode(); + for v in encoded.iter() { + print!("{:08b} ", v); + } + let len = Decoder::scale_length(encoded.as_slice()).unwrap(); + assert_eq!(len.0, 2); + } - macro_rules! decode_test { - ( $v: expr, $x:expr, $r: expr) => {{ - let val = $v.encode(); - let decoder = Decoder::new(GenericTypes, Chain::Kusama); - let res = decoder - .decode_single("", 1031, &$x, val.as_slice(), &mut 0, false) - .unwrap(); + macro_rules! decode_test { + ( $v: expr, $x:expr, $r: expr) => {{ + let val = $v.encode(); + let decoder = Decoder::new(GenericTypes, Chain::Kusama); + let res = decoder.decode_single("", 1031, &$x, val.as_slice(), &mut 0, false).unwrap(); - assert_eq!($r, res) - }}; - } + assert_eq!($r, res) + }}; + } - #[test] - fn should_decode_option() { - let val: Option = Some(0x1337); - decode_test!( - val, - RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::U32))), - SubstrateType::Option(Box::new(Some(SubstrateType::U32(0x1337)))) - ); - let val: Option = None; - decode_test!( - val, - RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::U32))), - SubstrateType::Option(Box::new(None)) - ); - } + #[test] + fn should_decode_option() { + let val: Option = Some(0x1337); + decode_test!( + val, + RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::U32))), + SubstrateType::Option(Box::new(Some(SubstrateType::U32(0x1337)))) + ); + let val: Option = None; + decode_test!( + val, + RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::U32))), + SubstrateType::Option(Box::new(None)) + ); + } - #[test] - fn should_decode_result() { - let val: Result = Ok(0x1337); - decode_test!( - val, - RustTypeMarker::Std(CommonTypes::Result( - Box::new(RustTypeMarker::U32), - Box::new(RustTypeMarker::U32) - )), - SubstrateType::Result(Box::new(Ok(SubstrateType::U32(0x1337)))) - ); + #[test] + fn should_decode_result() { + let val: Result = Ok(0x1337); + decode_test!( + val, + RustTypeMarker::Std(CommonTypes::Result(Box::new(RustTypeMarker::U32), Box::new(RustTypeMarker::U32))), + SubstrateType::Result(Box::new(Ok(SubstrateType::U32(0x1337)))) + ); - let val: Result = Err(0x1337); - decode_test!( - val, - RustTypeMarker::Std(CommonTypes::Result( - Box::new(RustTypeMarker::U32), - Box::new(RustTypeMarker::U32), - )), - SubstrateType::Result(Box::new(Err(SubstrateType::U32(0x1337)))) - ); - } + let val: Result = Err(0x1337); + decode_test!( + val, + RustTypeMarker::Std(CommonTypes::Result(Box::new(RustTypeMarker::U32), Box::new(RustTypeMarker::U32),)), + SubstrateType::Result(Box::new(Err(SubstrateType::U32(0x1337)))) + ); + } - #[test] - fn should_decode_vector() { - let val: Vec = vec![12, 32, 0x1337, 62]; - decode_test!( - val, - RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U32))), - SubstrateType::Composite(vec![ - SubstrateType::U32(12), - SubstrateType::U32(32), - SubstrateType::U32(0x1337), - SubstrateType::U32(62) - ]) - ); + #[test] + fn should_decode_vector() { + let val: Vec = vec![12, 32, 0x1337, 62]; + decode_test!( + val, + RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U32))), + SubstrateType::Composite(vec![ + SubstrateType::U32(12), + SubstrateType::U32(32), + SubstrateType::U32(0x1337), + SubstrateType::U32(62) + ]) + ); - let val: Vec = vec![12, 32, 0x1337, 62]; - decode_test!( - val, - RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U128))), - SubstrateType::Composite(vec![ - SubstrateType::U128(12), - SubstrateType::U128(32), - SubstrateType::U128(0x1337), - SubstrateType::U128(62) - ]) - ); - } + let val: Vec = vec![12, 32, 0x1337, 62]; + decode_test!( + val, + RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U128))), + SubstrateType::Composite(vec![ + SubstrateType::U128(12), + SubstrateType::U128(32), + SubstrateType::U128(0x1337), + SubstrateType::U128(62) + ]) + ); + } - #[test] - fn should_decode_array() { - let val: [u32; 4] = [12, 32, 0x1337, 62]; - decode_test!( - val, - RustTypeMarker::Array { - size: 4, - ty: Box::new(RustTypeMarker::U32), - }, - SubstrateType::Composite(vec![ - SubstrateType::U32(12), - SubstrateType::U32(32), - SubstrateType::U32(0x1337), - SubstrateType::U32(62) - ]) - ) - } + #[test] + fn should_decode_array() { + let val: [u32; 4] = [12, 32, 0x1337, 62]; + decode_test!( + val, + RustTypeMarker::Array { size: 4, ty: Box::new(RustTypeMarker::U32) }, + SubstrateType::Composite(vec![ + SubstrateType::U32(12), + SubstrateType::U32(32), + SubstrateType::U32(0x1337), + SubstrateType::U32(62) + ]) + ) + } - #[test] - fn should_decode_struct() { - #[derive(Encode, Decode)] - struct ToDecode { - foo: u32, - name: Vec, - } - let val = ToDecode { - foo: 0x1337, - name: vec![8, 16, 30, 40], - }; - decode_test!( - val, - RustTypeMarker::Struct(vec![ - crate::StructField { - name: "foo".to_string(), - ty: RustTypeMarker::U32, - }, - crate::StructField { - name: "name".to_string(), - ty: RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U8,))), - }, - ]), - SubstrateType::Struct(vec![ - StructField { - name: Some("foo".to_string()), - ty: SubstrateType::U32(0x1337) - }, - StructField { - name: Some("name".to_string()), - ty: SubstrateType::Composite(vec![ - SubstrateType::U8(8), - SubstrateType::U8(16), - SubstrateType::U8(30), - SubstrateType::U8(40) - ]) - } - ]) - ); - } + #[test] + fn should_decode_struct() { + #[derive(Encode, Decode)] + struct ToDecode { + foo: u32, + name: Vec, + } + let val = ToDecode { foo: 0x1337, name: vec![8, 16, 30, 40] }; + decode_test!( + val, + RustTypeMarker::Struct(vec![ + crate::StructField { name: "foo".to_string(), ty: RustTypeMarker::U32 }, + crate::StructField { + name: "name".to_string(), + ty: RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U8,))), + }, + ]), + SubstrateType::Struct(vec![ + StructField { name: Some("foo".to_string()), ty: SubstrateType::U32(0x1337) }, + StructField { + name: Some("name".to_string()), + ty: SubstrateType::Composite(vec![ + SubstrateType::U8(8), + SubstrateType::U8(16), + SubstrateType::U8(30), + SubstrateType::U8(40) + ]) + } + ]) + ); + } - #[test] - fn should_decode_tuple() { - let val: (u32, u32, u32, u32) = (18, 32, 42, 0x1337); - decode_test!( - val, - RustTypeMarker::Tuple(vec![ - RustTypeMarker::U32, - RustTypeMarker::U32, - RustTypeMarker::U32, - RustTypeMarker::U32, - ]), - SubstrateType::Composite(vec![ - SubstrateType::U32(18), - SubstrateType::U32(32), - SubstrateType::U32(42), - SubstrateType::U32(0x1337) - ]) - ) - } + #[test] + fn should_decode_tuple() { + let val: (u32, u32, u32, u32) = (18, 32, 42, 0x1337); + decode_test!( + val, + RustTypeMarker::Tuple(vec![ + RustTypeMarker::U32, + RustTypeMarker::U32, + RustTypeMarker::U32, + RustTypeMarker::U32, + ]), + SubstrateType::Composite(vec![ + SubstrateType::U32(18), + SubstrateType::U32(32), + SubstrateType::U32(42), + SubstrateType::U32(0x1337) + ]) + ) + } - #[test] - fn should_decode_unit_enum() { - #[derive(Encode, Decode)] - enum Foo { - Zoo, - Wraith, - Spree, - } - let val = Foo::Wraith; - decode_test!( - val, - RustTypeMarker::Enum(vec![ - EnumField::new(None, crate::StructUnitOrTuple::Unit("Zoo".into())), - EnumField::new(None, crate::StructUnitOrTuple::Unit("Wraith".into())), - EnumField::new(None, crate::StructUnitOrTuple::Unit("Spree".into())), - ]), - SubstrateType::Enum(StructUnitOrTuple::Unit("Wraith".into())) - ); - } + #[test] + fn should_decode_unit_enum() { + #[derive(Encode, Decode)] + enum Foo { + Zoo, + Wraith, + Spree, + } + let val = Foo::Wraith; + decode_test!( + val, + RustTypeMarker::Enum(vec![ + EnumField::new(None, crate::StructUnitOrTuple::Unit("Zoo".into())), + EnumField::new(None, crate::StructUnitOrTuple::Unit("Wraith".into())), + EnumField::new(None, crate::StructUnitOrTuple::Unit("Spree".into())), + ]), + SubstrateType::Enum(StructUnitOrTuple::Unit("Wraith".into())) + ); + } - #[test] - fn should_decode_tuple_enum() { - #[derive(Encode, Decode)] - struct TestStruct(i128); + #[test] + fn should_decode_tuple_enum() { + #[derive(Encode, Decode)] + struct TestStruct(i128); - #[derive(Encode, Decode)] - enum Foo { - Zoo(TestStruct), - Wraith(TestStruct), - } - let val = Foo::Wraith(TestStruct(0x1337)); - decode_test!( - val, - RustTypeMarker::Enum(vec![ - EnumField::new( - Some("Zoo".into()), - crate::StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer( - "TestStruct".into(), - )), - ), - EnumField::new( - Some("Wraith".into()), - crate::StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer( - "TestStruct".into(), - )), - ), - ]), - SubstrateType::Enum(StructUnitOrTuple::Tuple { - name: "Wraith".into(), - ty: Box::new(SubstrateType::I128(0x1337)) - }) - ); - } + #[derive(Encode, Decode)] + enum Foo { + Zoo(TestStruct), + Wraith(TestStruct), + } + let val = Foo::Wraith(TestStruct(0x1337)); + decode_test!( + val, + RustTypeMarker::Enum(vec![ + EnumField::new( + Some("Zoo".into()), + crate::StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer("TestStruct".into(),)), + ), + EnumField::new( + Some("Wraith".into()), + crate::StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer("TestStruct".into(),)), + ), + ]), + SubstrateType::Enum(StructUnitOrTuple::Tuple { + name: "Wraith".into(), + ty: Box::new(SubstrateType::I128(0x1337)) + }) + ); + } - #[test] - fn should_decode_structlike_enum() { - #[derive(Encode, Decode)] - enum Foo { - Zoo { name: Vec, id: u32 }, - Wraith { name: Vec, id: u64 }, - } - let val = Foo::Wraith { - name: vec![0x13, 0x37], - id: 15, - }; + #[test] + fn should_decode_structlike_enum() { + #[derive(Encode, Decode)] + enum Foo { + Zoo { name: Vec, id: u32 }, + Wraith { name: Vec, id: u64 }, + } + let val = Foo::Wraith { name: vec![0x13, 0x37], id: 15 }; - decode_test!( - val, - RustTypeMarker::Enum(vec![ - EnumField::new( - Some("Zoo".into()), - crate::StructUnitOrTuple::Struct(vec![ - crate::StructField::new( - "name", - RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U8,))), - ), - crate::StructField::new("id", RustTypeMarker::U32), - ]), - ), - EnumField::new( - Some("Wraith".into()), - crate::StructUnitOrTuple::Struct(vec![ - crate::StructField::new( - "name", - RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U16,))), - ), - crate::StructField::new("id", RustTypeMarker::U64), - ]), - ), - ]), - SubstrateType::Enum(StructUnitOrTuple::Struct(vec![ - StructField { - name: Some("name".into()), - ty: SubstrateType::Composite(vec![ - SubstrateType::U16(0x13), - SubstrateType::U16(0x37) - ]) - }, - StructField { - name: Some("id".into()), - ty: SubstrateType::U64(15) - } - ])) - ); - } + decode_test!( + val, + RustTypeMarker::Enum(vec![ + EnumField::new( + Some("Zoo".into()), + crate::StructUnitOrTuple::Struct(vec![ + crate::StructField::new( + "name", + RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U8,))), + ), + crate::StructField::new("id", RustTypeMarker::U32), + ]), + ), + EnumField::new( + Some("Wraith".into()), + crate::StructUnitOrTuple::Struct(vec![ + crate::StructField::new( + "name", + RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U16,))), + ), + crate::StructField::new("id", RustTypeMarker::U64), + ]), + ), + ]), + SubstrateType::Enum(StructUnitOrTuple::Struct(vec![ + StructField { + name: Some("name".into()), + ty: SubstrateType::Composite(vec![SubstrateType::U16(0x13), SubstrateType::U16(0x37)]) + }, + StructField { name: Some("id".into()), ty: SubstrateType::U64(15) } + ])) + ); + } } diff --git a/core/src/decoder/extrinsics.rs b/core/src/decoder/extrinsics.rs index b2ea343b..797ad955 100644 --- a/core/src/decoder/extrinsics.rs +++ b/core/src/decoder/extrinsics.rs @@ -20,211 +20,187 @@ use serde::Serialize; use std::fmt; #[derive(Debug, Serialize)] pub struct ExtrinsicArgument { - pub name: String, - pub arg: SubstrateType, + pub name: String, + pub arg: SubstrateType, } impl fmt::Display for ExtrinsicArgument { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, " arg: {}, Ty: {} ", self.name, self.arg) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, " arg: {}, Ty: {} ", self.name, self.arg) + } } #[derive(Debug, Serialize)] pub struct GenericCall { - name: String, - module: String, - args: Vec, + name: String, + module: String, + args: Vec, } impl fmt::Display for GenericCall { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut s = String::from(""); - s.push_str(&self.name); - s.push_str(": "); - for val in self.args.iter() { - s.push_str(&format!("{}", val)); - } - write!(f, "{}", s) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut s = String::from(""); + s.push_str(&self.name); + s.push_str(": "); + for val in self.args.iter() { + s.push_str(&format!("{}", val)); + } + write!(f, "{}", s) + } } /// Generic Extrinsic Type #[derive(Debug, Serialize)] pub struct GenericExtrinsic { - signature: Option, - call: GenericCall, + signature: Option, + call: GenericCall, } impl fmt::Display for GenericExtrinsic { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut s = String::from(""); - if let Some(v) = &self.signature { - s.push_str(&format!("{}", v)); - } else { - s.push_str(&"None".to_string()); - } - s.push('\n'); - s.push_str("CALL"); - s.push('\n'); - s.push_str(&format!("{}", self.call)); - write!(f, "{}", s) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut s = String::from(""); + if let Some(v) = &self.signature { + s.push_str(&format!("{}", v)); + } else { + s.push_str(&"None".to_string()); + } + s.push('\n'); + s.push_str("CALL"); + s.push('\n'); + s.push_str(&format!("{}", self.call)); + write!(f, "{}", s) + } } impl GenericExtrinsic { - /// create a new generic extrinsic type - pub fn new( - sig: Option, - call: Vec<(String, SubstrateType)>, - name: String, - module: String, - ) -> Self { - let call = call - .into_iter() - .map(|c| ExtrinsicArgument { - name: c.0, - arg: c.1, - }) - .collect::>(); - let call = GenericCall { - name, - module, - args: call, - }; - Self { - signature: sig.map(GenericSignature::new), - call, - } - } - - pub fn is_signed(&self) -> bool { - self.signature.is_some() - } - - pub fn signature(&self) -> Option<&GenericSignature> { - self.signature.as_ref() - } - - pub fn call(&self) -> &GenericCall { - &self.call - } - - pub fn ext_module(&self) -> &str { - &self.call.module - } - - pub fn ext_call(&self) -> &str { - &self.call.name - } - - pub fn args(&self) -> &[ExtrinsicArgument] { - &self.call.args - } + /// create a new generic extrinsic type + pub fn new(sig: Option, call: Vec<(String, SubstrateType)>, name: String, module: String) -> Self { + let call = + call.into_iter().map(|c| ExtrinsicArgument { name: c.0, arg: c.1 }).collect::>(); + let call = GenericCall { name, module, args: call }; + Self { signature: sig.map(GenericSignature::new), call } + } + + pub fn is_signed(&self) -> bool { + self.signature.is_some() + } + + pub fn signature(&self) -> Option<&GenericSignature> { + self.signature.as_ref() + } + + pub fn call(&self) -> &GenericCall { + &self.call + } + + pub fn ext_module(&self) -> &str { + &self.call.module + } + + pub fn ext_call(&self) -> &str { + &self.call.name + } + + pub fn args(&self) -> &[ExtrinsicArgument] { + &self.call.args + } } #[derive(Debug, Serialize)] pub struct GenericSignature { - #[serde(serialize_with = "crate::util::as_substrate_address")] - address: SubstrateType, - signature: SubstrateType, - extra: SubstrateType, + #[serde(serialize_with = "crate::util::as_substrate_address")] + address: SubstrateType, + signature: SubstrateType, + extra: SubstrateType, } impl GenericSignature { - pub fn new(signature: SubstrateType) -> Self { - Self::split(signature) - } - - /// returns address signature and extra as a tuple - pub fn parts(&self) -> (&SubstrateType, &SubstrateType, &SubstrateType) { - (&self.address, &self.signature, &self.extra) - } - - fn split(sig: SubstrateType) -> Self { - match sig { - SubstrateType::Composite(mut v) => { - v.reverse(); - Self { - address: v.pop().expect("Address must must be present in signature"), - signature: v.pop().expect("Signature must be present"), - extra: v.pop().expect("Extra must be present"), - } - } - _ => panic!("Signature should always be a tuple of Address, Signature, Extra"), - } - } + pub fn new(signature: SubstrateType) -> Self { + Self::split(signature) + } + + /// returns address signature and extra as a tuple + pub fn parts(&self) -> (&SubstrateType, &SubstrateType, &SubstrateType) { + (&self.address, &self.signature, &self.extra) + } + + fn split(sig: SubstrateType) -> Self { + match sig { + SubstrateType::Composite(mut v) => { + v.reverse(); + Self { + address: v.pop().expect("Address must must be present in signature"), + signature: v.pop().expect("Signature must be present"), + extra: v.pop().expect("Extra must be present"), + } + } + _ => panic!("Signature should always be a tuple of Address, Signature, Extra"), + } + } } impl fmt::Display for GenericSignature { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "Address {}\n Signature {}\n SignedExtra {}\n", - self.address, self.signature, self.extra - ) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Address {}\n Signature {}\n SignedExtra {}\n", self.address, self.signature, self.extra) + } } #[cfg(test)] mod tests { - use super::*; - - #[test] - fn should_serialize_generic_extrinsic() { - let call = GenericCall { - name: "set".to_string(), - module: "Timestamp".to_string(), - args: vec![ExtrinsicArgument { - name: "Some Arg".to_string(), - arg: SubstrateType::U32(32), - }], - }; - let ext = GenericExtrinsic { - signature: Some(GenericSignature::new(SubstrateType::Composite(vec![ - SubstrateType::Composite(vec![ - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - 0u8.into(), - ]), - SubstrateType::U64(64), - SubstrateType::U128(128), - ]))), - call, - }; - let serialized = serde_json::to_string(&ext).unwrap(); - assert_eq!( - serialized, - r#"{"signature":{"address":"5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM","signature":64,"extra":128},"call":{"name":"set","module":"Timestamp","args":[{"name":"Some Arg","arg":32}]}}"# - ); - } + use super::*; + + #[test] + fn should_serialize_generic_extrinsic() { + let call = GenericCall { + name: "set".to_string(), + module: "Timestamp".to_string(), + args: vec![ExtrinsicArgument { name: "Some Arg".to_string(), arg: SubstrateType::U32(32) }], + }; + let ext = GenericExtrinsic { + signature: Some(GenericSignature::new(SubstrateType::Composite(vec![ + SubstrateType::Composite(vec![ + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + 0u8.into(), + ]), + SubstrateType::U64(64), + SubstrateType::U128(128), + ]))), + call, + }; + let serialized = serde_json::to_string(&ext).unwrap(); + assert_eq!( + serialized, + r#"{"signature":{"address":"5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM","signature":64,"extra":128},"call":{"name":"set","module":"Timestamp","args":[{"name":"Some Arg","arg":32}]}}"# + ); + } } diff --git a/core/src/decoder/metadata.rs b/core/src/decoder/metadata.rs index e568be66..c05c5c7f 100644 --- a/core/src/decoder/metadata.rs +++ b/core/src/decoder/metadata.rs @@ -43,12 +43,12 @@ use primitives::{storage::StorageKey, twox_128}; use runtime_metadata_latest::{StorageEntryModifier, StorageHasher}; use std::{ - collections::{HashMap, HashSet}, - convert::TryInto, - fmt, - marker::PhantomData, - str::FromStr, - sync::Arc, + collections::{HashMap, HashSet}, + convert::TryInto, + fmt, + marker::PhantomData, + str::FromStr, + sync::Arc, }; use thiserror::Error; @@ -57,475 +57,443 @@ use thiserror::Error; pub struct Encoded(pub Vec); impl Encode for Encoded { - fn encode(&self) -> Vec { - self.0.to_owned() - } + fn encode(&self) -> Vec { + self.0.to_owned() + } } #[allow(dead_code)] pub fn compact(t: T) -> Encoded { - let encodable: <::Type as EncodeAsRef<'_, T>>::RefType = From::from(&t); - Encoded(encodable.encode()) + let encodable: <::Type as EncodeAsRef<'_, T>>::RefType = From::from(&t); + Encoded(encodable.encode()) } #[derive(Debug, Clone, Error)] pub enum MetadataError { - #[error("Module {0} not found")] - ModuleNotFound(String), - #[error("Call {0} not found")] - CallNotFound(&'static str), - #[error("Module index {0} not found")] - ModuleIndexNotFound(ModuleIndex), - #[error("Storage {0} not found")] - StorageNotFound(&'static str), - #[error("StorageType Error")] - StorageTypeError, - #[error("MapValueType Error")] - MapValueTypeError, + #[error("Module {0} not found")] + ModuleNotFound(String), + #[error("Call {0} not found")] + CallNotFound(&'static str), + #[error("Module index {0} not found")] + ModuleIndexNotFound(ModuleIndex), + #[error("Storage {0} not found")] + StorageNotFound(&'static str), + #[error("StorageType Error")] + StorageTypeError, + #[error("MapValueType Error")] + MapValueTypeError, } #[derive(Debug, Clone, derive_more::Display)] pub enum ModuleIndex { - Call(u8), - Storage(u8), - Event(u8), + Call(u8), + Storage(u8), + Event(u8), } #[derive(Clone, Debug, PartialEq)] /// Metadata struct encompassing calls, storage, and events pub struct Metadata { - /// Hashmap of Modules (name -> module-specific metadata) - modules: HashMap>, - /// modules by their index in the event enum - modules_by_event_index: HashMap, - /// modules by their index in the Call Enum - modules_by_call_index: HashMap, - /// Optional extrinsic metadata. Only chains which use meta - /// version 11+ support this. - extrinsics: Option, + /// Hashmap of Modules (name -> module-specific metadata) + modules: HashMap>, + /// modules by their index in the event enum + modules_by_event_index: HashMap, + /// modules by their index in the Call Enum + modules_by_call_index: HashMap, + /// Optional extrinsic metadata. Only chains which use meta + /// version 11+ support this. + extrinsics: Option, } impl From> for Metadata { - fn from(bytes: Vec) -> Metadata { - Metadata::new(bytes.as_slice()) - } + fn from(bytes: Vec) -> Metadata { + Metadata::new(bytes.as_slice()) + } } impl From<&[u8]> for Metadata { - fn from(bytes: &[u8]) -> Metadata { - Metadata::new(bytes) - } + fn from(bytes: &[u8]) -> Metadata { + Metadata::new(bytes) + } } impl From<&Metadata> for Metadata { - fn from(meta: &Metadata) -> Metadata { - meta.clone() - } + fn from(meta: &Metadata) -> Metadata { + meta.clone() + } } impl Metadata { - /// Create a new Metadata type from raw encoded bytes - /// - /// # Panics - /// Panics is the metadata version is not supported, - /// or the versiondebug is invalid - /// - /// Panics if decoding into metadata prefixed fails - pub fn new(bytes: &[u8]) -> Self { - // Runtime metadata is a tuple struct with the following fields: - // RuntimeMetadataPrefixed(u32, RuntimeMetadata) - // this means when it's SCALE encoded, the first four bytes - // are the 'u32' prefix, and since `RuntimeMetadata` is an enum, - // the first byte is the index of the enum item. - // Since RuntimeMetadata is versioned starting from 0, this also corresponds to - // the Metadata version - let version = bytes[4]; - - match version { - /* 0x07 => { - let meta: runtime_metadata07::RuntimeMetadataPrefixed = - OldDecode::decode(&mut &bytes[..]).expect("Decode failed"); - meta.try_into().expect("Conversion failed") - } */ - 0x08 => { - log::debug!("Metadata V8"); - let meta: runtime_metadata08::RuntimeMetadataPrefixed = - Decode::decode(&mut &bytes[..]).expect("Decode failed"); - meta.try_into().expect("Conversion failed") - } - 0x09 => { - log::debug!("Metadata V9"); - let meta: runtime_metadata09::RuntimeMetadataPrefixed = - Decode::decode(&mut &bytes[..]).expect("Decode Failed"); - meta.try_into().expect("Conversion Failed") - } - 0xA => { - log::debug!("Metadata V10"); - let meta: runtime_metadata10::RuntimeMetadataPrefixed = - Decode::decode(&mut &bytes[..]).expect("Decode failed"); - meta.try_into().expect("Conversion failed") - } - 0xB => { - log::debug!("Metadata V11"); - let meta: runtime_metadata11::RuntimeMetadataPrefixed = - Decode::decode(&mut &bytes[..]).expect("Decode failed"); - meta.try_into().expect("Conversion failed") - } - 0xC => { - log::debug!("Metadata V12"); - let meta: runtime_metadata_latest::RuntimeMetadataPrefixed = - Decode::decode(&mut &bytes[..]).expect("Decode failed"); - meta.try_into().expect("Conversion failed") - } - /* TODO remove panics */ - e => panic!( - "substrate metadata version {} is unknown, invalid or unsupported", - e - ), - } - } - - /// returns an iterate over all Modules - pub fn modules(&self) -> impl Iterator { - self.modules.values().map(|v| v.as_ref()) - } - - /// returns a weak reference to a module from it's name - pub fn module(&self, name: S) -> Result, MetadataError> - where - S: ToString, - { - let name = name.to_string(); - self.modules - .get(&name) - .ok_or(MetadataError::ModuleNotFound(name)) - .map(|m| (*m).clone()) - } - - pub fn signed_extensions(&self) -> Option<&[RustTypeMarker]> { - self.extrinsics.as_ref().map(|e| e.extensions.as_slice()) - } - - /// Check if a module exists - pub fn module_exists(&self, name: S) -> bool - where - S: ToString, - { - let name = name.to_string(); - self.modules.get(&name).is_some() - } - - /// get the name of a module given it's event index - pub fn module_name(&self, module_index: u8) -> Result { - self.modules_by_event_index - .get(&module_index) - .cloned() - .ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Event( - module_index, - ))) - } - - /// get a module by it's index - pub fn module_by_index( - &self, - module_index: ModuleIndex, - ) -> Result, MetadataError> { - Ok(match module_index { - ModuleIndex::Call(i) => { - let name = self - .modules_by_call_index - .get(&i) - .ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Call(i)))?; - self.modules - .get(name) - .ok_or_else(|| MetadataError::ModuleNotFound(name.to_string()))? - .clone() - } - ModuleIndex::Event(i) => { - let name = self - .modules_by_event_index - .get(&i) - .ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Event(i)))?; - self.modules - .get(name) - .ok_or_else(|| MetadataError::ModuleNotFound(name.to_string()))? - .clone() - } - ModuleIndex::Storage(_) => { - // TODO remove panics - panic!("No storage index stored") - } - }) - } - - /// Returns a hashmap of a Hash -> StorageMetadata - /// Hash is prefix of storage entries in metadata - pub fn storage_lookup_table(&self) -> StorageLookupTable { - let mut lookup = HashMap::new(); - for module in self.modules.values() { - for (_name, storage_meta) in module.storage.iter() { - let key = Self::generate_key(&storage_meta.prefix); - lookup.insert(key, StorageInfo::new(storage_meta.clone(), module.clone())); - } - } - StorageLookupTable::new(lookup) - } - - fn generate_key>(prefix: S) -> Vec { - let prefix: String = prefix.into(); - prefix - .split_ascii_whitespace() - .map(|s| twox_128(s.as_bytes()).to_vec()) - .flatten() - .collect() - } - - /// print out a detailed but human readable description of the module - /// metadata - pub fn detailed_pretty(&self) -> String { - let mut string = String::new(); - for (name, module) in &self.modules { - string.push_str(name.as_str()); - string.push('\n'); - for (storage, meta) in &module.storage { - string.push_str(" S "); - string.push_str(storage.as_str()); - string.push_str(format!(" TYPE {:?}", meta.ty).as_str()); - string.push_str(format!(" MOD {:?}", meta.modifier).as_str()); - string.push('\n'); - } - for call in module.calls.keys() { - string.push_str(" C "); - string.push_str(call.as_str()); - string.push('\n'); - } - for event in module.events.values() { - string.push_str(" E "); - string.push_str(event.name.as_str()); - string.push('\n'); - } - } - string - } - - /// print out a human readable description of the metadata - pub fn pretty(&self) -> String { - let mut string = String::new(); - for (name, module) in &self.modules { - string.push_str(name.as_str()); - string.push('\n'); - for storage in module.storage.keys() { - string.push_str(" s "); - string.push_str(storage.as_str()); - string.push('\n'); - } - for call in module.calls.values() { - string.push_str(" c "); - string.push_str(&call.to_string()); - string.push('\n'); - } - for event in module.events.values() { - string.push_str(" e "); - string.push_str(event.name.as_str()); - string.push('\n'); - } - } - string - } + /// Create a new Metadata type from raw encoded bytes + /// + /// # Panics + /// Panics is the metadata version is not supported, + /// or the versiondebug is invalid + /// + /// Panics if decoding into metadata prefixed fails + pub fn new(bytes: &[u8]) -> Self { + // Runtime metadata is a tuple struct with the following fields: + // RuntimeMetadataPrefixed(u32, RuntimeMetadata) + // this means when it's SCALE encoded, the first four bytes + // are the 'u32' prefix, and since `RuntimeMetadata` is an enum, + // the first byte is the index of the enum item. + // Since RuntimeMetadata is versioned starting from 0, this also corresponds to + // the Metadata version + let version = bytes[4]; + + match version { + /* 0x07 => { + let meta: runtime_metadata07::RuntimeMetadataPrefixed = + OldDecode::decode(&mut &bytes[..]).expect("Decode failed"); + meta.try_into().expect("Conversion failed") + } */ + 0x08 => { + log::debug!("Metadata V8"); + let meta: runtime_metadata08::RuntimeMetadataPrefixed = + Decode::decode(&mut &bytes[..]).expect("Decode failed"); + meta.try_into().expect("Conversion failed") + } + 0x09 => { + log::debug!("Metadata V9"); + let meta: runtime_metadata09::RuntimeMetadataPrefixed = + Decode::decode(&mut &bytes[..]).expect("Decode Failed"); + meta.try_into().expect("Conversion Failed") + } + 0xA => { + log::debug!("Metadata V10"); + let meta: runtime_metadata10::RuntimeMetadataPrefixed = + Decode::decode(&mut &bytes[..]).expect("Decode failed"); + meta.try_into().expect("Conversion failed") + } + 0xB => { + log::debug!("Metadata V11"); + let meta: runtime_metadata11::RuntimeMetadataPrefixed = + Decode::decode(&mut &bytes[..]).expect("Decode failed"); + meta.try_into().expect("Conversion failed") + } + 0xC => { + log::debug!("Metadata V12"); + let meta: runtime_metadata_latest::RuntimeMetadataPrefixed = + Decode::decode(&mut &bytes[..]).expect("Decode failed"); + meta.try_into().expect("Conversion failed") + } + /* TODO remove panics */ + e => panic!("substrate metadata version {} is unknown, invalid or unsupported", e), + } + } + + /// returns an iterate over all Modules + pub fn modules(&self) -> impl Iterator { + self.modules.values().map(|v| v.as_ref()) + } + + /// returns a weak reference to a module from it's name + pub fn module(&self, name: S) -> Result, MetadataError> + where + S: ToString, + { + let name = name.to_string(); + self.modules.get(&name).ok_or(MetadataError::ModuleNotFound(name)).map(|m| (*m).clone()) + } + + pub fn signed_extensions(&self) -> Option<&[RustTypeMarker]> { + self.extrinsics.as_ref().map(|e| e.extensions.as_slice()) + } + + /// Check if a module exists + pub fn module_exists(&self, name: S) -> bool + where + S: ToString, + { + let name = name.to_string(); + self.modules.get(&name).is_some() + } + + /// get the name of a module given it's event index + pub fn module_name(&self, module_index: u8) -> Result { + self.modules_by_event_index + .get(&module_index) + .cloned() + .ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Event(module_index))) + } + + /// get a module by it's index + pub fn module_by_index(&self, module_index: ModuleIndex) -> Result, MetadataError> { + Ok(match module_index { + ModuleIndex::Call(i) => { + let name = self + .modules_by_call_index + .get(&i) + .ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Call(i)))?; + self.modules.get(name).ok_or_else(|| MetadataError::ModuleNotFound(name.to_string()))?.clone() + } + ModuleIndex::Event(i) => { + let name = self + .modules_by_event_index + .get(&i) + .ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Event(i)))?; + self.modules.get(name).ok_or_else(|| MetadataError::ModuleNotFound(name.to_string()))?.clone() + } + ModuleIndex::Storage(_) => { + // TODO remove panics + panic!("No storage index stored") + } + }) + } + + /// Returns a hashmap of a Hash -> StorageMetadata + /// Hash is prefix of storage entries in metadata + pub fn storage_lookup_table(&self) -> StorageLookupTable { + let mut lookup = HashMap::new(); + for module in self.modules.values() { + for (_name, storage_meta) in module.storage.iter() { + let key = Self::generate_key(&storage_meta.prefix); + lookup.insert(key, StorageInfo::new(storage_meta.clone(), module.clone())); + } + } + StorageLookupTable::new(lookup) + } + + fn generate_key>(prefix: S) -> Vec { + let prefix: String = prefix.into(); + prefix.split_ascii_whitespace().map(|s| twox_128(s.as_bytes()).to_vec()).flatten().collect() + } + + /// print out a detailed but human readable description of the module + /// metadata + pub fn detailed_pretty(&self) -> String { + let mut string = String::new(); + for (name, module) in &self.modules { + string.push_str(name.as_str()); + string.push('\n'); + for (storage, meta) in &module.storage { + string.push_str(" S "); + string.push_str(storage.as_str()); + string.push_str(format!(" TYPE {:?}", meta.ty).as_str()); + string.push_str(format!(" MOD {:?}", meta.modifier).as_str()); + string.push('\n'); + } + for call in module.calls.keys() { + string.push_str(" C "); + string.push_str(call.as_str()); + string.push('\n'); + } + for event in module.events.values() { + string.push_str(" E "); + string.push_str(event.name.as_str()); + string.push('\n'); + } + } + string + } + + /// print out a human readable description of the metadata + pub fn pretty(&self) -> String { + let mut string = String::new(); + for (name, module) in &self.modules { + string.push_str(name.as_str()); + string.push('\n'); + for storage in module.storage.keys() { + string.push_str(" s "); + string.push_str(storage.as_str()); + string.push('\n'); + } + for call in module.calls.values() { + string.push_str(" c "); + string.push_str(&call.to_string()); + string.push('\n'); + } + for event in module.events.values() { + string.push_str(" e "); + string.push_str(event.name.as_str()); + string.push('\n'); + } + } + string + } } #[derive(Clone, Debug, PartialEq)] pub struct ExtrinsicMetadata { - version: u8, - extensions: Vec, + version: u8, + extensions: Vec, } impl ExtrinsicMetadata { - pub fn new(version: u8, extensions: Vec) -> Self { - Self { - version, - extensions, - } - } + pub fn new(version: u8, extensions: Vec) -> Self { + Self { version, extensions } + } } #[derive(Clone, Debug, PartialEq)] pub struct ModuleMetadata { - /// index of the module within StorageMetadata 'Entries' - index: u8, - /// name of the module - name: String, - /// Name of storage entry -> Metadata of storage entry - pub storage: HashMap, - /// Calls in the module, CallName -> encoded calls - calls: HashMap, - events: HashMap, - // constants + /// index of the module within StorageMetadata 'Entries' + index: u8, + /// name of the module + name: String, + /// Name of storage entry -> Metadata of storage entry + pub storage: HashMap, + /// Calls in the module, CallName -> encoded calls + calls: HashMap, + events: HashMap, + // constants } impl ModuleMetadata { - pub fn name(&self) -> &str { - &self.name - } - - /// Return a storage entry by its key - pub fn storage(&self, key: &'static str) -> Result<&StorageMetadata, MetadataError> { - self.storage - .get(key) - .ok_or(MetadataError::StorageNotFound(key)) - } - - /// an iterator over all possible events for this module - pub fn events(&self) -> impl Iterator { - self.events.values() - } - - // TODO Transfer to Subxt - /// iterator over all possible calls in this module - pub fn calls(&self) -> impl Iterator { - self.calls.values() - } - - /// iterator over all storage keys in this module - pub fn storage_keys(&self) -> impl Iterator { - self.storage.iter() - } - - /// get an event by its index in the module - pub fn event(&self, index: u8) -> Result<&ModuleEventMetadata, MetadataError> { - self.events - .get(&index) - .ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Event( - index, - ))) - } - - pub fn call(&self, index: u8) -> Result<&CallMetadata, MetadataError> { - self.calls() - .find(|c| c.index == index) - .ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Call(index))) - } + pub fn name(&self) -> &str { + &self.name + } + + /// Return a storage entry by its key + pub fn storage(&self, key: &'static str) -> Result<&StorageMetadata, MetadataError> { + self.storage.get(key).ok_or(MetadataError::StorageNotFound(key)) + } + + /// an iterator over all possible events for this module + pub fn events(&self) -> impl Iterator { + self.events.values() + } + + // TODO Transfer to Subxt + /// iterator over all possible calls in this module + pub fn calls(&self) -> impl Iterator { + self.calls.values() + } + + /// iterator over all storage keys in this module + pub fn storage_keys(&self) -> impl Iterator { + self.storage.iter() + } + + /// get an event by its index in the module + pub fn event(&self, index: u8) -> Result<&ModuleEventMetadata, MetadataError> { + self.events.get(&index).ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Event(index))) + } + + pub fn call(&self, index: u8) -> Result<&CallMetadata, MetadataError> { + self.calls().find(|c| c.index == index).ok_or(MetadataError::ModuleIndexNotFound(ModuleIndex::Call(index))) + } } #[derive(Clone, Debug, PartialEq)] /// Metadata for Calls in Substrate pub struct CallMetadata { - /// Name of the function of the call - name: String, - /// encoded byte index of call - index: u8, - /// Arguments that the function accepts - arguments: Vec, + /// Name of the function of the call + name: String, + /// encoded byte index of call + index: u8, + /// Arguments that the function accepts + arguments: Vec, } impl CallMetadata { - /// Returns an iterator for all arguments for this call - pub fn arguments(&self) -> impl Iterator { - self.arguments.iter() - } - pub fn name(&self) -> String { - self.name.clone() - } + /// Returns an iterator for all arguments for this call + pub fn arguments(&self) -> impl Iterator { + self.arguments.iter() + } + pub fn name(&self) -> String { + self.name.clone() + } } impl fmt::Display for CallMetadata { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut arg_str = String::from(""); - for a in self.arguments.iter() { - arg_str.push_str(&format!("{}, ", a)); - } - write!(f, "fn {}({})", self.name, arg_str) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut arg_str = String::from(""); + for a in self.arguments.iter() { + arg_str.push_str(&format!("{}, ", a)); + } + write!(f, "fn {}({})", self.name, arg_str) + } } #[derive(Clone, Debug, PartialEq)] /// Metadata for Function Arguments to a Call pub struct CallArgMetadata { - /// name of argument - pub name: String, - /// Type of the Argument - pub ty: RustTypeMarker, + /// name of argument + pub name: String, + /// Type of the Argument + pub ty: RustTypeMarker, } impl fmt::Display for CallArgMetadata { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}: {}", self.name, self.ty) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}: {}", self.name, self.ty) + } } #[derive(Clone, Debug, PartialEq)] pub enum StorageType { - Plain(RustTypeMarker), - Map { - hasher: StorageHasher, - key: RustTypeMarker, - value: RustTypeMarker, - unused: bool, - }, - DoubleMap { - hasher: StorageHasher, - key1: RustTypeMarker, - key2: RustTypeMarker, - value: RustTypeMarker, - key2_hasher: StorageHasher, - }, + Plain(RustTypeMarker), + Map { + hasher: StorageHasher, + key: RustTypeMarker, + value: RustTypeMarker, + unused: bool, + }, + DoubleMap { + hasher: StorageHasher, + key1: RustTypeMarker, + key2: RustTypeMarker, + value: RustTypeMarker, + key2_hasher: StorageHasher, + }, } #[derive(Clone, Debug, PartialEq)] pub struct StorageMetadata { - prefix: String, - modifier: StorageEntryModifier, - pub ty: StorageType, - default: Vec, - documentation: Vec, + prefix: String, + modifier: StorageEntryModifier, + pub ty: StorageType, + default: Vec, + documentation: Vec, } impl StorageMetadata { - pub fn prefix(&self) -> &str { - &self.prefix - } + pub fn prefix(&self) -> &str { + &self.prefix + } } #[derive(Clone, Debug)] pub struct StorageMap { - _marker: PhantomData, - prefix: Vec, - hasher: StorageHasher, - default: V, + _marker: PhantomData, + prefix: Vec, + hasher: StorageHasher, + default: V, } impl StorageMap { - pub fn key(&self, key: K) -> StorageKey { - let mut bytes = self.prefix.clone(); - bytes.extend(key.encode()); - let hash = match self.hasher { - StorageHasher::Blake2_128 => primitives::blake2_128(&bytes).to_vec(), - StorageHasher::Blake2_256 => primitives::blake2_256(&bytes).to_vec(), - StorageHasher::Blake2_128Concat => primitives::blake2_128(&bytes).to_vec(), - StorageHasher::Twox128 => primitives::twox_128(&bytes).to_vec(), - StorageHasher::Twox256 => primitives::twox_256(&bytes).to_vec(), - StorageHasher::Twox64Concat => primitives::twox_64(&bytes).to_vec(), - // TODO figure out which substrate hash function is the 'identity' function - StorageHasher::Identity => panic!("Unkown Hash"), - }; - StorageKey(hash) - } - - pub fn default(&self) -> V { - self.default.clone() - } + pub fn key(&self, key: K) -> StorageKey { + let mut bytes = self.prefix.clone(); + bytes.extend(key.encode()); + let hash = match self.hasher { + StorageHasher::Blake2_128 => primitives::blake2_128(&bytes).to_vec(), + StorageHasher::Blake2_256 => primitives::blake2_256(&bytes).to_vec(), + StorageHasher::Blake2_128Concat => primitives::blake2_128(&bytes).to_vec(), + StorageHasher::Twox128 => primitives::twox_128(&bytes).to_vec(), + StorageHasher::Twox256 => primitives::twox_256(&bytes).to_vec(), + StorageHasher::Twox64Concat => primitives::twox_64(&bytes).to_vec(), + // TODO figure out which substrate hash function is the 'identity' function + StorageHasher::Identity => panic!("Unkown Hash"), + }; + StorageKey(hash) + } + + pub fn default(&self) -> V { + self.default.clone() + } } #[derive(Clone, Debug, PartialEq)] pub struct ModuleEventMetadata { - pub name: String, - pub(crate) arguments: HashSet, + pub name: String, + pub(crate) arguments: HashSet, } impl ModuleEventMetadata { - pub fn arguments(&self) -> Vec { - self.arguments.iter().cloned().collect() - } + pub fn arguments(&self) -> Vec { + self.arguments.iter().cloned().collect() + } } /// Naive representation of event argument types, supports current set of @@ -537,85 +505,79 @@ impl ModuleEventMetadata { /// `Vec>` (without `E` defined). #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum EventArg { - Primitive(String), - Vec(Box), - Tuple(Vec), + Primitive(String), + Vec(Box), + Tuple(Vec), } impl FromStr for EventArg { - type Err = Error; - - fn from_str(s: &str) -> Result { - if s.starts_with("Vec<") { - if s.ends_with('>') { - Ok(EventArg::Vec(Box::new(s[4..s.len() - 1].parse()?))) - } else { - Err(Error::InvalidEventArg( - s.to_string(), - "Expected closing `>` for `Vec`", - )) - } - } else if s.starts_with('(') { - if s.ends_with(')') { - let mut args = Vec::new(); - for arg in s[1..s.len() - 1].split(',') { - let arg = arg.trim().parse()?; - args.push(arg) - } - Ok(EventArg::Tuple(args)) - } else { - Err(Error::InvalidEventArg( - s.to_string(), - "Expecting closing `)` for tuple", - )) - } - } else { - Ok(EventArg::Primitive(s.to_string())) - } - } + type Err = Error; + + fn from_str(s: &str) -> Result { + if s.starts_with("Vec<") { + if s.ends_with('>') { + Ok(EventArg::Vec(Box::new(s[4..s.len() - 1].parse()?))) + } else { + Err(Error::InvalidEventArg(s.to_string(), "Expected closing `>` for `Vec`")) + } + } else if s.starts_with('(') { + if s.ends_with(')') { + let mut args = Vec::new(); + for arg in s[1..s.len() - 1].split(',') { + let arg = arg.trim().parse()?; + args.push(arg) + } + Ok(EventArg::Tuple(args)) + } else { + Err(Error::InvalidEventArg(s.to_string(), "Expecting closing `)` for tuple")) + } + } else { + Ok(EventArg::Primitive(s.to_string())) + } + } } impl EventArg { - /// Returns all primitive types for this EventArg - pub fn primitives(&self) -> Vec { - match self { - EventArg::Primitive(p) => vec![p.clone()], - EventArg::Vec(arg) => arg.primitives(), - EventArg::Tuple(args) => { - let mut primitives = Vec::new(); - for arg in args { - primitives.extend(arg.primitives()) - } - primitives - } - } - } + /// Returns all primitive types for this EventArg + pub fn primitives(&self) -> Vec { + match self { + EventArg::Primitive(p) => vec![p.clone()], + EventArg::Vec(arg) => arg.primitives(), + EventArg::Tuple(args) => { + let mut primitives = Vec::new(); + for arg in args { + primitives.extend(arg.primitives()) + } + primitives + } + } + } } #[derive(Error, Debug)] pub enum Error { - #[error("Invalid Prefix")] - InvalidPrefix, - #[error(" Invalid Version")] - InvalidVersion, - #[error("Expected Decoded")] - ExpectedDecoded, - #[error("Invalid Event {0}:{1}")] - InvalidEventArg(String, &'static str), - #[error("Invalid Type {0}")] - InvalidType(String), + #[error("Invalid Prefix")] + InvalidPrefix, + #[error(" Invalid Version")] + InvalidVersion, + #[error("Expected Decoded")] + ExpectedDecoded, + #[error("Invalid Event {0}:{1}")] + InvalidEventArg(String, &'static str), + #[error("Invalid Type {0}")] + InvalidType(String), } #[cfg(test)] pub mod tests { - use super::*; + use super::*; - #[test] - fn should_generate_correct_key() { - let first_key = Metadata::generate_key("System Account"); + #[test] + fn should_generate_correct_key() { + let first_key = Metadata::generate_key("System Account"); - let mut key = twox_128("System".as_bytes()).to_vec(); - key.extend(twox_128("Account".as_bytes()).to_vec()); - assert_eq!(first_key, key); - } + let mut key = twox_128("System".as_bytes()).to_vec(); + key.extend(twox_128("Account".as_bytes()).to_vec()); + assert_eq!(first_key, key); + } } diff --git a/core/src/decoder/metadata/test_suite.rs b/core/src/decoder/metadata/test_suite.rs index 07cbe173..f33bb5a2 100644 --- a/core/src/decoder/metadata/test_suite.rs +++ b/core/src/decoder/metadata/test_suite.rs @@ -21,171 +21,159 @@ use crate::RustTypeMarker; use std::sync::Arc; pub fn test_metadata() -> Metadata { - Metadata { - modules: module_metadata_mock(), - modules_by_event_index: HashMap::new(), - modules_by_call_index: HashMap::new(), - extrinsics: None, - } + Metadata { + modules: module_metadata_mock(), + modules_by_event_index: HashMap::new(), + modules_by_call_index: HashMap::new(), + extrinsics: None, + } } fn module_metadata_mock() -> HashMap> { - let mut map = HashMap::new(); - - map.insert( - "TestModule0".to_string(), - Arc::new(ModuleMetadata { - index: 0, - name: "TestModule0".to_string(), - storage: storage_mock(), - calls: call_mock(), - events: event_mock(), - }), - ); - - map.insert( - "TestModule1".to_string(), - Arc::new(ModuleMetadata { - index: 1, - name: "TestModule1".to_string(), - storage: storage_mock(), - calls: call_mock(), - events: event_mock(), - }), - ); - - map.insert( - "TestModule2".to_string(), - Arc::new(ModuleMetadata { - index: 2, - name: "TestModule2".to_string(), - storage: storage_mock(), - calls: call_mock(), - events: event_mock(), - }), - ); - - map + let mut map = HashMap::new(); + + map.insert( + "TestModule0".to_string(), + Arc::new(ModuleMetadata { + index: 0, + name: "TestModule0".to_string(), + storage: storage_mock(), + calls: call_mock(), + events: event_mock(), + }), + ); + + map.insert( + "TestModule1".to_string(), + Arc::new(ModuleMetadata { + index: 1, + name: "TestModule1".to_string(), + storage: storage_mock(), + calls: call_mock(), + events: event_mock(), + }), + ); + + map.insert( + "TestModule2".to_string(), + Arc::new(ModuleMetadata { + index: 2, + name: "TestModule2".to_string(), + storage: storage_mock(), + calls: call_mock(), + events: event_mock(), + }), + ); + + map } fn storage_mock() -> HashMap { - let mut map = HashMap::new(); - let moment = RustTypeMarker::TypePointer("T::Moment".to_string()); - let precision = RustTypeMarker::U32; - let usize_t = RustTypeMarker::USize; - - map.insert( - "TestStorage0".to_string(), - StorageMetadata { - prefix: "TestStorage0".to_string(), - modifier: StorageEntryModifier::Default, - ty: StorageType::Plain(moment.clone()), - default: vec![112, 23, 0, 0, 0, 0, 0, 0], - documentation: vec!["Some Kind of docs".to_string()], - }, - ); - - map.insert( - "TestStorage1".to_string(), - StorageMetadata { - prefix: "TestStorage1".to_string(), - modifier: StorageEntryModifier::Default, - ty: StorageType::Plain(usize_t), - default: vec![0, 0, 0, 0, 0, 0, 0, 0], - documentation: vec!["Some Kind of docs 2".to_string()], - }, - ); - - map.insert( - "TestStorage2".to_string(), - StorageMetadata { - prefix: "TestStorage2".to_string(), - modifier: StorageEntryModifier::Optional, - ty: StorageType::Plain(moment), - default: vec![0, 0, 0, 0, 0, 0, 0, 0], - documentation: vec!["Some Kind of docs 2".to_string()], - }, - ); - - map.insert( - "TestStorage3".to_string(), - StorageMetadata { - prefix: "TestStorage3".to_string(), - modifier: StorageEntryModifier::Optional, - ty: StorageType::Plain(precision), - default: vec![0, 0, 0, 0, 0, 0, 0, 0], - documentation: vec!["Some Kind of docs 3".to_string()], - }, - ); - map + let mut map = HashMap::new(); + let moment = RustTypeMarker::TypePointer("T::Moment".to_string()); + let precision = RustTypeMarker::U32; + let usize_t = RustTypeMarker::USize; + + map.insert( + "TestStorage0".to_string(), + StorageMetadata { + prefix: "TestStorage0".to_string(), + modifier: StorageEntryModifier::Default, + ty: StorageType::Plain(moment.clone()), + default: vec![112, 23, 0, 0, 0, 0, 0, 0], + documentation: vec!["Some Kind of docs".to_string()], + }, + ); + + map.insert( + "TestStorage1".to_string(), + StorageMetadata { + prefix: "TestStorage1".to_string(), + modifier: StorageEntryModifier::Default, + ty: StorageType::Plain(usize_t), + default: vec![0, 0, 0, 0, 0, 0, 0, 0], + documentation: vec!["Some Kind of docs 2".to_string()], + }, + ); + + map.insert( + "TestStorage2".to_string(), + StorageMetadata { + prefix: "TestStorage2".to_string(), + modifier: StorageEntryModifier::Optional, + ty: StorageType::Plain(moment), + default: vec![0, 0, 0, 0, 0, 0, 0, 0], + documentation: vec!["Some Kind of docs 2".to_string()], + }, + ); + + map.insert( + "TestStorage3".to_string(), + StorageMetadata { + prefix: "TestStorage3".to_string(), + modifier: StorageEntryModifier::Optional, + ty: StorageType::Plain(precision), + default: vec![0, 0, 0, 0, 0, 0, 0, 0], + documentation: vec!["Some Kind of docs 3".to_string()], + }, + ); + map } fn call_mock() -> HashMap { - let mut map = HashMap::new(); - - map.insert( - "TestCall0".to_string(), - CallMetadata { - name: "foo_function0".to_string(), - index: 3, - arguments: vec![CallArgMetadata { - name: "foo_arg".to_string(), - ty: RustTypeMarker::I8, - }], - }, - ); - map.insert( - "TestCall1".to_string(), - CallMetadata { - name: "foo_function1".to_string(), - index: 2, - arguments: vec![CallArgMetadata { - name: "foo_arg".to_string(), - ty: RustTypeMarker::U64, - }], - }, - ); - map.insert( - "TestCall2".to_string(), - CallMetadata { - name: "foo_function2".to_string(), - index: 1, - arguments: vec![CallArgMetadata { - name: "foo_arg".to_string(), - ty: RustTypeMarker::TypePointer("SomeType".to_string()), - }], - }, - ); - map.insert( - "TestCall3".to_string(), - CallMetadata { - name: "foo_function3".to_string(), - index: 0, - arguments: vec![CallArgMetadata { - name: "foo_arg".to_string(), - ty: RustTypeMarker::F32, - }], - }, - ); - map + let mut map = HashMap::new(); + + map.insert( + "TestCall0".to_string(), + CallMetadata { + name: "foo_function0".to_string(), + index: 3, + arguments: vec![CallArgMetadata { name: "foo_arg".to_string(), ty: RustTypeMarker::I8 }], + }, + ); + map.insert( + "TestCall1".to_string(), + CallMetadata { + name: "foo_function1".to_string(), + index: 2, + arguments: vec![CallArgMetadata { name: "foo_arg".to_string(), ty: RustTypeMarker::U64 }], + }, + ); + map.insert( + "TestCall2".to_string(), + CallMetadata { + name: "foo_function2".to_string(), + index: 1, + arguments: vec![CallArgMetadata { + name: "foo_arg".to_string(), + ty: RustTypeMarker::TypePointer("SomeType".to_string()), + }], + }, + ); + map.insert( + "TestCall3".to_string(), + CallMetadata { + name: "foo_function3".to_string(), + index: 0, + arguments: vec![CallArgMetadata { name: "foo_arg".to_string(), ty: RustTypeMarker::F32 }], + }, + ); + map } fn event_mock() -> HashMap { - let mut map = HashMap::new(); - - let event_arg_0 = EventArg::Primitive("TestEvent0".to_string()); - let event_arg_1 = EventArg::Primitive("TestEvent1".to_string()); - let event_arg_2 = EventArg::Primitive("TestEvent2".to_string()); - - let mut arguments = HashSet::new(); - arguments.insert(event_arg_0); - arguments.insert(event_arg_1); - arguments.insert(event_arg_2); - let module_event_metadata = ModuleEventMetadata { - name: "TestEvent0".to_string(), - arguments, - }; - - map.insert(0, module_event_metadata); - map + let mut map = HashMap::new(); + + let event_arg_0 = EventArg::Primitive("TestEvent0".to_string()); + let event_arg_1 = EventArg::Primitive("TestEvent1".to_string()); + let event_arg_2 = EventArg::Primitive("TestEvent2".to_string()); + + let mut arguments = HashSet::new(); + arguments.insert(event_arg_0); + arguments.insert(event_arg_1); + arguments.insert(event_arg_2); + let module_event_metadata = ModuleEventMetadata { name: "TestEvent0".to_string(), arguments }; + + map.insert(0, module_event_metadata); + map } diff --git a/core/src/decoder/metadata/version_08.rs b/core/src/decoder/metadata/version_08.rs index 299665c3..95419d79 100644 --- a/core/src/decoder/metadata/version_08.rs +++ b/core/src/decoder/metadata/version_08.rs @@ -18,237 +18,202 @@ // https://github.com/paritytech/substrate-subxt use super::{ - CallArgMetadata, CallMetadata, Error, EventArg, Metadata, ModuleEventMetadata, ModuleMetadata, - StorageMetadata, StorageType, + CallArgMetadata, CallMetadata, Error, EventArg, Metadata, ModuleEventMetadata, ModuleMetadata, StorageMetadata, + StorageType, }; use crate::regex; use runtime_metadata08::{ - DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryModifier, - StorageEntryType, StorageHasher, META_RESERVED, + DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryModifier, StorageEntryType, StorageHasher, + META_RESERVED, }; use std::{ - collections::{HashMap, HashSet}, - convert::{TryFrom, TryInto}, + collections::{HashMap, HashSet}, + convert::{TryFrom, TryInto}, }; type DecodeDifferentStr = DecodeDifferent<&'static str, String>; type LatestDecodeDifferentStr = runtime_metadata_latest::DecodeDifferent<&'static str, String>; impl TryFrom for Metadata { - type Error = Error; + type Error = Error; - fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { - if metadata.0 != META_RESERVED { - // 'meta' warn endiannes - return Err(Error::InvalidPrefix); - } - let meta = match metadata.1 { - RuntimeMetadata::V8(meta) => meta, - _ => return Err(Error::InvalidVersion), - }; - let mut modules = HashMap::new(); - let (mut modules_by_event_index, mut modules_by_call_index) = - (HashMap::new(), HashMap::new()); - let (mut event_index, mut call_index) = (0, 0); - for (i, module) in convert(meta.modules)?.into_iter().enumerate() { - let module_name = convert(module.name.clone())?; - if module.calls.is_some() { - modules_by_call_index.insert(call_index, module_name.clone()); - call_index += 1; - } - if module.event.is_none() { - modules_by_event_index.insert(event_index, module_name.clone()); - event_index += 1; - } - let module_metadata = convert_module(i, module)?; - modules.insert(module_name, std::sync::Arc::new(module_metadata)); - } + fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { + if metadata.0 != META_RESERVED { + // 'meta' warn endiannes + return Err(Error::InvalidPrefix); + } + let meta = match metadata.1 { + RuntimeMetadata::V8(meta) => meta, + _ => return Err(Error::InvalidVersion), + }; + let mut modules = HashMap::new(); + let (mut modules_by_event_index, mut modules_by_call_index) = (HashMap::new(), HashMap::new()); + let (mut event_index, mut call_index) = (0, 0); + for (i, module) in convert(meta.modules)?.into_iter().enumerate() { + let module_name = convert(module.name.clone())?; + if module.calls.is_some() { + modules_by_call_index.insert(call_index, module_name.clone()); + call_index += 1; + } + if module.event.is_none() { + modules_by_event_index.insert(event_index, module_name.clone()); + event_index += 1; + } + let module_metadata = convert_module(i, module)?; + modules.insert(module_name, std::sync::Arc::new(module_metadata)); + } - Ok(Metadata { - modules, - modules_by_event_index, - modules_by_call_index, - extrinsics: None, - }) - } + Ok(Metadata { modules, modules_by_event_index, modules_by_call_index, extrinsics: None }) + } } fn convert(dd: DecodeDifferent) -> Result { - match dd { - DecodeDifferent::Decoded(value) => Ok(value), - _ => Err(Error::ExpectedDecoded), - } + match dd { + DecodeDifferent::Decoded(value) => Ok(value), + _ => Err(Error::ExpectedDecoded), + } } -fn convert_module( - index: usize, - module: runtime_metadata08::ModuleMetadata, -) -> Result { - let mut storage_map = HashMap::new(); - if let Some(storage) = module.storage { - let storage = convert(storage)?; - let prefix = convert(storage.prefix)?; - for entry in convert(storage.entries)?.into_iter() { - let entry_name = convert(entry.name.clone())?; - let entry_prefix = format!("{} {}", prefix, entry_name); - let entry = convert_entry(entry_prefix, entry)?; - storage_map.insert(entry_name, entry); - } - } - let mut call_map = HashMap::new(); - if let Some(calls) = module.calls { - for (index, call) in convert(calls)?.into_iter().enumerate() { - let name = convert(call.name)?; - let args = convert(call.arguments)? - .iter() - .map(|a| { - let ty = convert(a.ty.clone())?; - let name = convert(a.name.clone())?; - let arg = CallArgMetadata { - name, - ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))?, - }; - Ok(arg) - }) - .collect::, Error>>()?; - let meta = CallMetadata { - name: name.clone(), - index: index as u8, - arguments: args, - }; - call_map.insert(name, meta); - } - } - let mut event_map = HashMap::new(); - if let Some(events) = module.event { - for (index, event) in convert(events)?.into_iter().enumerate() { - event_map.insert(index as u8, convert_event(event)?); - } - } +fn convert_module(index: usize, module: runtime_metadata08::ModuleMetadata) -> Result { + let mut storage_map = HashMap::new(); + if let Some(storage) = module.storage { + let storage = convert(storage)?; + let prefix = convert(storage.prefix)?; + for entry in convert(storage.entries)?.into_iter() { + let entry_name = convert(entry.name.clone())?; + let entry_prefix = format!("{} {}", prefix, entry_name); + let entry = convert_entry(entry_prefix, entry)?; + storage_map.insert(entry_name, entry); + } + } + let mut call_map = HashMap::new(); + if let Some(calls) = module.calls { + for (index, call) in convert(calls)?.into_iter().enumerate() { + let name = convert(call.name)?; + let args = convert(call.arguments)? + .iter() + .map(|a| { + let ty = convert(a.ty.clone())?; + let name = convert(a.name.clone())?; + let arg = CallArgMetadata { name, ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))? }; + Ok(arg) + }) + .collect::, Error>>()?; + let meta = CallMetadata { name: name.clone(), index: index as u8, arguments: args }; + call_map.insert(name, meta); + } + } + let mut event_map = HashMap::new(); + if let Some(events) = module.event { + for (index, event) in convert(events)?.into_iter().enumerate() { + event_map.insert(index as u8, convert_event(event)?); + } + } - Ok(ModuleMetadata { - index: index as u8, - name: convert(module.name)?, - storage: storage_map, - calls: call_map, - events: event_map, - }) + Ok(ModuleMetadata { + index: index as u8, + name: convert(module.name)?, + storage: storage_map, + calls: call_map, + events: event_map, + }) } fn convert_event(event: runtime_metadata08::EventMetadata) -> Result { - let name = convert(event.name)?; - let mut arguments = HashSet::new(); - for arg in convert(event.arguments)? { - let arg = arg.parse::()?; - arguments.insert(arg); - } - Ok(ModuleEventMetadata { name, arguments }) + let name = convert(event.name)?; + let mut arguments = HashSet::new(); + for arg in convert(event.arguments)? { + let arg = arg.parse::()?; + arguments.insert(arg); + } + Ok(ModuleEventMetadata { name, arguments }) } -fn convert_entry( - prefix: String, - entry: runtime_metadata08::StorageEntryMetadata, -) -> Result { - let default = convert(entry.default)?; - let documentation = convert(entry.documentation)?; - Ok(StorageMetadata { - prefix, - modifier: StorageEntryModifierTemp(entry.modifier).into(), - ty: entry.ty.try_into()?, - default, - documentation: documentation - .iter() - .map(|s| s.to_string()) - .collect::>(), - }) +fn convert_entry(prefix: String, entry: runtime_metadata08::StorageEntryMetadata) -> Result { + let default = convert(entry.default)?; + let documentation = convert(entry.documentation)?; + Ok(StorageMetadata { + prefix, + modifier: StorageEntryModifierTemp(entry.modifier).into(), + ty: entry.ty.try_into()?, + default, + documentation: documentation.iter().map(|s| s.to_string()).collect::>(), + }) } /// Temporary struct for converting between `StorageEntryModifier` /// and `runtime_metadata_latest::StorageEntryModifier` struct StorageEntryModifierTemp(StorageEntryModifier); impl From for runtime_metadata_latest::StorageEntryModifier { - fn from(entry: StorageEntryModifierTemp) -> runtime_metadata_latest::StorageEntryModifier { - let entry = entry.0; - match entry { - StorageEntryModifier::Optional => { - runtime_metadata_latest::StorageEntryModifier::Optional - } - StorageEntryModifier::Default => runtime_metadata_latest::StorageEntryModifier::Default, - } - } + fn from(entry: StorageEntryModifierTemp) -> runtime_metadata_latest::StorageEntryModifier { + let entry = entry.0; + match entry { + StorageEntryModifier::Optional => runtime_metadata_latest::StorageEntryModifier::Optional, + StorageEntryModifier::Default => runtime_metadata_latest::StorageEntryModifier::Default, + } + } } /// Temprorary struct for converting between `StorageHasher` and /// `runtime_metadata_latest::StorageHasher` struct TempStorageHasher(StorageHasher); impl From for runtime_metadata_latest::StorageHasher { - fn from(hasher: TempStorageHasher) -> runtime_metadata_latest::StorageHasher { - let hasher = hasher.0; - match hasher { - StorageHasher::Blake2_128 => runtime_metadata_latest::StorageHasher::Blake2_128, - StorageHasher::Blake2_256 => runtime_metadata_latest::StorageHasher::Blake2_256, - StorageHasher::Twox128 => runtime_metadata_latest::StorageHasher::Twox128, - StorageHasher::Twox256 => runtime_metadata_latest::StorageHasher::Twox256, - StorageHasher::Twox64Concat => runtime_metadata_latest::StorageHasher::Twox64Concat, - } - } + fn from(hasher: TempStorageHasher) -> runtime_metadata_latest::StorageHasher { + let hasher = hasher.0; + match hasher { + StorageHasher::Blake2_128 => runtime_metadata_latest::StorageHasher::Blake2_128, + StorageHasher::Blake2_256 => runtime_metadata_latest::StorageHasher::Blake2_256, + StorageHasher::Twox128 => runtime_metadata_latest::StorageHasher::Twox128, + StorageHasher::Twox256 => runtime_metadata_latest::StorageHasher::Twox256, + StorageHasher::Twox64Concat => runtime_metadata_latest::StorageHasher::Twox64Concat, + } + } } /// Temporary struct for converting between `DecodeDifferentStr` and /// `DecodeDifferentStrLatest` struct TempDecodeDifferentStr(DecodeDifferentStr); impl From for LatestDecodeDifferentStr { - fn from(decode_str: TempDecodeDifferentStr) -> LatestDecodeDifferentStr { - let decode_str = decode_str.0; - match decode_str { - DecodeDifferent::Encode(b) => runtime_metadata_latest::DecodeDifferent::Encode(b), - DecodeDifferent::Decoded(o) => runtime_metadata_latest::DecodeDifferent::Decoded(o), - } - } + fn from(decode_str: TempDecodeDifferentStr) -> LatestDecodeDifferentStr { + let decode_str = decode_str.0; + match decode_str { + DecodeDifferent::Encode(b) => runtime_metadata_latest::DecodeDifferent::Encode(b), + DecodeDifferent::Decoded(o) => runtime_metadata_latest::DecodeDifferent::Decoded(o), + } + } } impl TryFrom for StorageType { - type Error = Error; - fn try_from(entry: StorageEntryType) -> Result { - let entry = match entry { - StorageEntryType::Plain(v) => { - let ty = convert(v)?; - StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) - } - StorageEntryType::Map { - hasher, - key, - value, - is_linked, - } => { - let key = convert(key)?; - let value = convert(value)?; - StorageType::Map { - hasher: TempStorageHasher(hasher).into(), - key: regex::parse(&key).ok_or(Error::InvalidType(key))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - unused: is_linked, - } - } - StorageEntryType::DoubleMap { - hasher, - key1, - key2, - value, - key2_hasher, - } => { - let key1 = convert(key1)?; - let key2 = convert(key2)?; - let value = convert(value)?; - StorageType::DoubleMap { - hasher: TempStorageHasher(hasher).into(), - key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, - key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - key2_hasher: TempStorageHasher(key2_hasher).into(), - } - } - }; - Ok(entry) - } + type Error = Error; + fn try_from(entry: StorageEntryType) -> Result { + let entry = match entry { + StorageEntryType::Plain(v) => { + let ty = convert(v)?; + StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) + } + StorageEntryType::Map { hasher, key, value, is_linked } => { + let key = convert(key)?; + let value = convert(value)?; + StorageType::Map { + hasher: TempStorageHasher(hasher).into(), + key: regex::parse(&key).ok_or(Error::InvalidType(key))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + unused: is_linked, + } + } + StorageEntryType::DoubleMap { hasher, key1, key2, value, key2_hasher } => { + let key1 = convert(key1)?; + let key2 = convert(key2)?; + let value = convert(value)?; + StorageType::DoubleMap { + hasher: TempStorageHasher(hasher).into(), + key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, + key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + key2_hasher: TempStorageHasher(key2_hasher).into(), + } + } + }; + Ok(entry) + } } diff --git a/core/src/decoder/metadata/version_09.rs b/core/src/decoder/metadata/version_09.rs index ff0cac93..790e6fa8 100644 --- a/core/src/decoder/metadata/version_09.rs +++ b/core/src/decoder/metadata/version_09.rs @@ -18,240 +18,203 @@ // https://github.com/paritytech/substrate-subxt use super::{ - CallArgMetadata, CallMetadata, Error, EventArg, Metadata, ModuleEventMetadata, ModuleMetadata, - StorageMetadata, StorageType, + CallArgMetadata, CallMetadata, Error, EventArg, Metadata, ModuleEventMetadata, ModuleMetadata, StorageMetadata, + StorageType, }; use crate::regex; use runtime_metadata09::{ - DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryModifier, - StorageEntryType, StorageHasher, META_RESERVED, + DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryModifier, StorageEntryType, StorageHasher, + META_RESERVED, }; use std::{ - collections::{HashMap, HashSet}, - convert::{TryFrom, TryInto}, + collections::{HashMap, HashSet}, + convert::{TryFrom, TryInto}, }; type DecodeDifferentStr = DecodeDifferent<&'static str, String>; type LatestDecodeDifferentStr = runtime_metadata_latest::DecodeDifferent<&'static str, String>; impl TryFrom for Metadata { - type Error = Error; + type Error = Error; - fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { - if metadata.0 != META_RESERVED { - // 'meta' warn endiannes - return Err(Error::InvalidPrefix); - } - let meta = match metadata.1 { - RuntimeMetadata::V9(meta) => meta, - _ => return Err(Error::InvalidVersion), - }; - let mut modules = HashMap::new(); - let (mut modules_by_event_index, mut modules_by_call_index) = - (HashMap::new(), HashMap::new()); - let (mut event_index, mut call_index) = (0, 0); - for (i, module) in convert(meta.modules)?.into_iter().enumerate() { - let module_name = convert(module.name.clone())?; - if module.calls.is_some() { - modules_by_call_index.insert(call_index, module_name.clone()); - call_index += 1; - } - if module.event.is_none() { - modules_by_event_index.insert(event_index, module_name.clone()); - event_index += 1; - } - let module_metadata = convert_module(i, module)?; - modules.insert(module_name, std::sync::Arc::new(module_metadata)); - } - Ok(Metadata { - modules, - modules_by_event_index, - modules_by_call_index, - extrinsics: None, - }) - } + fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { + if metadata.0 != META_RESERVED { + // 'meta' warn endiannes + return Err(Error::InvalidPrefix); + } + let meta = match metadata.1 { + RuntimeMetadata::V9(meta) => meta, + _ => return Err(Error::InvalidVersion), + }; + let mut modules = HashMap::new(); + let (mut modules_by_event_index, mut modules_by_call_index) = (HashMap::new(), HashMap::new()); + let (mut event_index, mut call_index) = (0, 0); + for (i, module) in convert(meta.modules)?.into_iter().enumerate() { + let module_name = convert(module.name.clone())?; + if module.calls.is_some() { + modules_by_call_index.insert(call_index, module_name.clone()); + call_index += 1; + } + if module.event.is_none() { + modules_by_event_index.insert(event_index, module_name.clone()); + event_index += 1; + } + let module_metadata = convert_module(i, module)?; + modules.insert(module_name, std::sync::Arc::new(module_metadata)); + } + Ok(Metadata { modules, modules_by_event_index, modules_by_call_index, extrinsics: None }) + } } fn convert(dd: DecodeDifferent) -> Result { - match dd { - DecodeDifferent::Decoded(value) => Ok(value), - _ => Err(Error::ExpectedDecoded), - } + match dd { + DecodeDifferent::Decoded(value) => Ok(value), + _ => Err(Error::ExpectedDecoded), + } } -fn convert_module( - index: usize, - module: runtime_metadata09::ModuleMetadata, -) -> Result { - let mut storage_map = HashMap::new(); - if let Some(storage) = module.storage { - let storage = convert(storage)?; - let prefix = convert(storage.prefix)?; - for entry in convert(storage.entries)?.into_iter() { - let entry_name = convert(entry.name.clone())?; - let entry_prefix = format!("{} {}", prefix, entry_name); - let entry = convert_entry(entry_prefix, entry)?; - storage_map.insert(entry_name, entry); - } - } - let mut call_map = HashMap::new(); - if let Some(calls) = module.calls { - for (index, call) in convert(calls)?.into_iter().enumerate() { - let name = convert(call.name)?; - let args = convert(call.arguments)? - .iter() - .map(|a| { - let ty = convert(a.ty.clone())?; - let name = convert(a.name.clone())?; - let arg = CallArgMetadata { - name, - ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))?, - }; - Ok(arg) - }) - .collect::, Error>>()?; - let meta = CallMetadata { - name: name.clone(), - index: index as u8, - arguments: args, - }; - call_map.insert(name, meta); - } - } +fn convert_module(index: usize, module: runtime_metadata09::ModuleMetadata) -> Result { + let mut storage_map = HashMap::new(); + if let Some(storage) = module.storage { + let storage = convert(storage)?; + let prefix = convert(storage.prefix)?; + for entry in convert(storage.entries)?.into_iter() { + let entry_name = convert(entry.name.clone())?; + let entry_prefix = format!("{} {}", prefix, entry_name); + let entry = convert_entry(entry_prefix, entry)?; + storage_map.insert(entry_name, entry); + } + } + let mut call_map = HashMap::new(); + if let Some(calls) = module.calls { + for (index, call) in convert(calls)?.into_iter().enumerate() { + let name = convert(call.name)?; + let args = convert(call.arguments)? + .iter() + .map(|a| { + let ty = convert(a.ty.clone())?; + let name = convert(a.name.clone())?; + let arg = CallArgMetadata { name, ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))? }; + Ok(arg) + }) + .collect::, Error>>()?; + let meta = CallMetadata { name: name.clone(), index: index as u8, arguments: args }; + call_map.insert(name, meta); + } + } - let mut event_map = HashMap::new(); - if let Some(events) = module.event { - for (index, event) in convert(events)?.into_iter().enumerate() { - event_map.insert(index as u8, convert_event(event)?); - } - } + let mut event_map = HashMap::new(); + if let Some(events) = module.event { + for (index, event) in convert(events)?.into_iter().enumerate() { + event_map.insert(index as u8, convert_event(event)?); + } + } - Ok(ModuleMetadata { - index: index as u8, - name: convert(module.name)?, - storage: storage_map, - calls: call_map, - events: event_map, - }) + Ok(ModuleMetadata { + index: index as u8, + name: convert(module.name)?, + storage: storage_map, + calls: call_map, + events: event_map, + }) } fn convert_event(event: runtime_metadata09::EventMetadata) -> Result { - let name = convert(event.name)?; - let mut arguments = HashSet::new(); - for arg in convert(event.arguments)? { - let arg = arg.parse::()?; - arguments.insert(arg); - } - Ok(ModuleEventMetadata { name, arguments }) + let name = convert(event.name)?; + let mut arguments = HashSet::new(); + for arg in convert(event.arguments)? { + let arg = arg.parse::()?; + arguments.insert(arg); + } + Ok(ModuleEventMetadata { name, arguments }) } -fn convert_entry( - prefix: String, - entry: runtime_metadata09::StorageEntryMetadata, -) -> Result { - let default = convert(entry.default)?; - let documentation = convert(entry.documentation)?; - Ok(StorageMetadata { - prefix, - modifier: StorageEntryModifierTemp(entry.modifier).into(), - ty: entry.ty.try_into()?, - default, - documentation: documentation - .iter() - .map(|s| s.to_string()) - .collect::>(), - }) +fn convert_entry(prefix: String, entry: runtime_metadata09::StorageEntryMetadata) -> Result { + let default = convert(entry.default)?; + let documentation = convert(entry.documentation)?; + Ok(StorageMetadata { + prefix, + modifier: StorageEntryModifierTemp(entry.modifier).into(), + ty: entry.ty.try_into()?, + default, + documentation: documentation.iter().map(|s| s.to_string()).collect::>(), + }) } /// Temporary struct for converting between `StorageEntryModifier` /// and `runtime_metadata_latest::StorageEntryModifier` struct StorageEntryModifierTemp(StorageEntryModifier); impl From for runtime_metadata_latest::StorageEntryModifier { - fn from(entry: StorageEntryModifierTemp) -> runtime_metadata_latest::StorageEntryModifier { - let entry = entry.0; - match entry { - StorageEntryModifier::Optional => { - runtime_metadata_latest::StorageEntryModifier::Optional - } - StorageEntryModifier::Default => runtime_metadata_latest::StorageEntryModifier::Default, - } - } + fn from(entry: StorageEntryModifierTemp) -> runtime_metadata_latest::StorageEntryModifier { + let entry = entry.0; + match entry { + StorageEntryModifier::Optional => runtime_metadata_latest::StorageEntryModifier::Optional, + StorageEntryModifier::Default => runtime_metadata_latest::StorageEntryModifier::Default, + } + } } /// Temprorary struct for converting between `StorageHasher` and /// `runtime_metadata_latest::StorageHasher` struct TempStorageHasher(StorageHasher); impl From for runtime_metadata_latest::StorageHasher { - fn from(hasher: TempStorageHasher) -> runtime_metadata_latest::StorageHasher { - let hasher = hasher.0; - match hasher { - StorageHasher::Blake2_128 => runtime_metadata_latest::StorageHasher::Blake2_128, - StorageHasher::Blake2_256 => runtime_metadata_latest::StorageHasher::Blake2_256, - StorageHasher::Blake2_128Concat => { - runtime_metadata_latest::StorageHasher::Blake2_128Concat - } - StorageHasher::Twox128 => runtime_metadata_latest::StorageHasher::Twox128, - StorageHasher::Twox256 => runtime_metadata_latest::StorageHasher::Twox256, - StorageHasher::Twox64Concat => runtime_metadata_latest::StorageHasher::Twox64Concat, - } - } + fn from(hasher: TempStorageHasher) -> runtime_metadata_latest::StorageHasher { + let hasher = hasher.0; + match hasher { + StorageHasher::Blake2_128 => runtime_metadata_latest::StorageHasher::Blake2_128, + StorageHasher::Blake2_256 => runtime_metadata_latest::StorageHasher::Blake2_256, + StorageHasher::Blake2_128Concat => runtime_metadata_latest::StorageHasher::Blake2_128Concat, + StorageHasher::Twox128 => runtime_metadata_latest::StorageHasher::Twox128, + StorageHasher::Twox256 => runtime_metadata_latest::StorageHasher::Twox256, + StorageHasher::Twox64Concat => runtime_metadata_latest::StorageHasher::Twox64Concat, + } + } } /// Temporary struct for converting between `DecodeDifferentStr` and /// `DecodeDifferentStrLatest` struct TempDecodeDifferentStr(DecodeDifferentStr); impl From for LatestDecodeDifferentStr { - fn from(decode_str: TempDecodeDifferentStr) -> LatestDecodeDifferentStr { - let decode_str = decode_str.0; - match decode_str { - DecodeDifferent::Encode(b) => runtime_metadata_latest::DecodeDifferent::Encode(b), - DecodeDifferent::Decoded(o) => runtime_metadata_latest::DecodeDifferent::Decoded(o), - } - } + fn from(decode_str: TempDecodeDifferentStr) -> LatestDecodeDifferentStr { + let decode_str = decode_str.0; + match decode_str { + DecodeDifferent::Encode(b) => runtime_metadata_latest::DecodeDifferent::Encode(b), + DecodeDifferent::Decoded(o) => runtime_metadata_latest::DecodeDifferent::Decoded(o), + } + } } impl TryFrom for StorageType { - type Error = Error; - fn try_from(entry: StorageEntryType) -> Result { - let entry = match entry { - StorageEntryType::Plain(v) => { - let ty = convert(v)?; - StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) - } - StorageEntryType::Map { - hasher, - key, - value, - is_linked, - } => { - let key = convert(key)?; - let value = convert(value)?; - StorageType::Map { - hasher: TempStorageHasher(hasher).into(), - key: regex::parse(&key).ok_or(Error::InvalidType(key))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - unused: is_linked, - } - } - StorageEntryType::DoubleMap { - hasher, - key1, - key2, - value, - key2_hasher, - } => { - let key1 = convert(key1)?; - let key2 = convert(key2)?; - let value = convert(value)?; - StorageType::DoubleMap { - hasher: TempStorageHasher(hasher).into(), - key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, - key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - key2_hasher: TempStorageHasher(key2_hasher).into(), - } - } - }; - Ok(entry) - } + type Error = Error; + fn try_from(entry: StorageEntryType) -> Result { + let entry = match entry { + StorageEntryType::Plain(v) => { + let ty = convert(v)?; + StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) + } + StorageEntryType::Map { hasher, key, value, is_linked } => { + let key = convert(key)?; + let value = convert(value)?; + StorageType::Map { + hasher: TempStorageHasher(hasher).into(), + key: regex::parse(&key).ok_or(Error::InvalidType(key))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + unused: is_linked, + } + } + StorageEntryType::DoubleMap { hasher, key1, key2, value, key2_hasher } => { + let key1 = convert(key1)?; + let key2 = convert(key2)?; + let value = convert(value)?; + StorageType::DoubleMap { + hasher: TempStorageHasher(hasher).into(), + key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, + key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + key2_hasher: TempStorageHasher(key2_hasher).into(), + } + } + }; + Ok(entry) + } } diff --git a/core/src/decoder/metadata/version_10.rs b/core/src/decoder/metadata/version_10.rs index 7a358b4f..522aad9b 100644 --- a/core/src/decoder/metadata/version_10.rs +++ b/core/src/decoder/metadata/version_10.rs @@ -15,237 +15,202 @@ // along with substrate-desub. If not, see . use super::{ - CallArgMetadata, CallMetadata, Error, EventArg, Metadata, ModuleEventMetadata, ModuleMetadata, - StorageMetadata, StorageType, + CallArgMetadata, CallMetadata, Error, EventArg, Metadata, ModuleEventMetadata, ModuleMetadata, StorageMetadata, + StorageType, }; use crate::regex; use runtime_metadata10::{ - DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryModifier, - StorageEntryType, StorageHasher, META_RESERVED, + DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryModifier, StorageEntryType, StorageHasher, + META_RESERVED, }; use std::{ - collections::{HashMap, HashSet}, - convert::{TryFrom, TryInto}, + collections::{HashMap, HashSet}, + convert::{TryFrom, TryInto}, }; type DecodeDifferentStr = DecodeDifferent<&'static str, String>; type LatestDecodeDifferentStr = runtime_metadata_latest::DecodeDifferent<&'static str, String>; impl TryFrom for Metadata { - type Error = Error; + type Error = Error; - fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { - if metadata.0 != META_RESERVED { - // 'meta' warn endiannes - return Err(Error::InvalidPrefix); - } - let meta = match metadata.1 { - RuntimeMetadata::V10(meta) => meta, - _ => return Err(Error::InvalidVersion), - }; - let mut modules = HashMap::new(); - let (mut modules_by_event_index, mut modules_by_call_index) = - (HashMap::new(), HashMap::new()); - let (mut event_index, mut call_index) = (0, 0); - for (i, module) in convert(meta.modules)?.into_iter().enumerate() { - let module_name = convert(module.name.clone())?; - if module.calls.is_some() { - modules_by_call_index.insert(call_index, module_name.clone()); - call_index += 1; - } - if module.event.is_none() { - modules_by_event_index.insert(event_index, module_name.clone()); - event_index += 1; - } - let module_metadata = convert_module(i, module)?; - modules.insert(module_name, std::sync::Arc::new(module_metadata)); - } - Ok(Metadata { - modules, - modules_by_event_index, - modules_by_call_index, - extrinsics: None, - }) - } + fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { + if metadata.0 != META_RESERVED { + // 'meta' warn endiannes + return Err(Error::InvalidPrefix); + } + let meta = match metadata.1 { + RuntimeMetadata::V10(meta) => meta, + _ => return Err(Error::InvalidVersion), + }; + let mut modules = HashMap::new(); + let (mut modules_by_event_index, mut modules_by_call_index) = (HashMap::new(), HashMap::new()); + let (mut event_index, mut call_index) = (0, 0); + for (i, module) in convert(meta.modules)?.into_iter().enumerate() { + let module_name = convert(module.name.clone())?; + if module.calls.is_some() { + modules_by_call_index.insert(call_index, module_name.clone()); + call_index += 1; + } + if module.event.is_none() { + modules_by_event_index.insert(event_index, module_name.clone()); + event_index += 1; + } + let module_metadata = convert_module(i, module)?; + modules.insert(module_name, std::sync::Arc::new(module_metadata)); + } + Ok(Metadata { modules, modules_by_event_index, modules_by_call_index, extrinsics: None }) + } } fn convert(dd: DecodeDifferent) -> Result { - match dd { - DecodeDifferent::Decoded(value) => Ok(value), - _ => Err(Error::ExpectedDecoded), - } + match dd { + DecodeDifferent::Decoded(value) => Ok(value), + _ => Err(Error::ExpectedDecoded), + } } -fn convert_module( - index: usize, - module: runtime_metadata10::ModuleMetadata, -) -> Result { - let mut storage_map = HashMap::new(); - if let Some(storage) = module.storage { - let storage = convert(storage)?; - let prefix = convert(storage.prefix)?; - for entry in convert(storage.entries)?.into_iter() { - let entry_name = convert(entry.name.clone())?; - let entry_prefix = format!("{} {}", prefix, entry_name); - let entry = convert_entry(entry_prefix, entry)?; - storage_map.insert(entry_name, entry); - } - } - let mut call_map = HashMap::new(); - if let Some(calls) = module.calls { - for (index, call) in convert(calls)?.into_iter().enumerate() { - let name = convert(call.name)?; - let args = convert(call.arguments)? - .iter() - .map(|a| { - let ty = convert(a.ty.clone())?; - let name = convert(a.name.clone())?; - let arg = CallArgMetadata { - name, - ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))?, - }; - Ok(arg) - }) - .collect::, Error>>()?; - let meta = CallMetadata { - name: name.clone(), - index: index as u8, - arguments: args, - }; - call_map.insert(name, meta); - } - } - let mut event_map = HashMap::new(); - if let Some(events) = module.event { - for (index, event) in convert(events)?.into_iter().enumerate() { - event_map.insert(index as u8, convert_event(event)?); - } - } +fn convert_module(index: usize, module: runtime_metadata10::ModuleMetadata) -> Result { + let mut storage_map = HashMap::new(); + if let Some(storage) = module.storage { + let storage = convert(storage)?; + let prefix = convert(storage.prefix)?; + for entry in convert(storage.entries)?.into_iter() { + let entry_name = convert(entry.name.clone())?; + let entry_prefix = format!("{} {}", prefix, entry_name); + let entry = convert_entry(entry_prefix, entry)?; + storage_map.insert(entry_name, entry); + } + } + let mut call_map = HashMap::new(); + if let Some(calls) = module.calls { + for (index, call) in convert(calls)?.into_iter().enumerate() { + let name = convert(call.name)?; + let args = convert(call.arguments)? + .iter() + .map(|a| { + let ty = convert(a.ty.clone())?; + let name = convert(a.name.clone())?; + let arg = CallArgMetadata { name, ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))? }; + Ok(arg) + }) + .collect::, Error>>()?; + let meta = CallMetadata { name: name.clone(), index: index as u8, arguments: args }; + call_map.insert(name, meta); + } + } + let mut event_map = HashMap::new(); + if let Some(events) = module.event { + for (index, event) in convert(events)?.into_iter().enumerate() { + event_map.insert(index as u8, convert_event(event)?); + } + } - Ok(ModuleMetadata { - index: index as u8, - name: convert(module.name)?, - storage: storage_map, - calls: call_map, - events: event_map, - }) + Ok(ModuleMetadata { + index: index as u8, + name: convert(module.name)?, + storage: storage_map, + calls: call_map, + events: event_map, + }) } fn convert_event(event: runtime_metadata10::EventMetadata) -> Result { - let name = convert(event.name)?; - let mut arguments = HashSet::new(); - for arg in convert(event.arguments)? { - let arg = arg.parse::()?; - arguments.insert(arg); - } - Ok(ModuleEventMetadata { name, arguments }) + let name = convert(event.name)?; + let mut arguments = HashSet::new(); + for arg in convert(event.arguments)? { + let arg = arg.parse::()?; + arguments.insert(arg); + } + Ok(ModuleEventMetadata { name, arguments }) } -fn convert_entry( - prefix: String, - entry: runtime_metadata10::StorageEntryMetadata, -) -> Result { - let default = convert(entry.default)?; - let documentation = convert(entry.documentation)?; - Ok(StorageMetadata { - prefix, - modifier: StorageEntryModifierTemp(entry.modifier).into(), - ty: entry.ty.try_into()?, - default, - documentation: documentation - .iter() - .map(|s| s.to_string()) - .collect::>(), - }) +fn convert_entry(prefix: String, entry: runtime_metadata10::StorageEntryMetadata) -> Result { + let default = convert(entry.default)?; + let documentation = convert(entry.documentation)?; + Ok(StorageMetadata { + prefix, + modifier: StorageEntryModifierTemp(entry.modifier).into(), + ty: entry.ty.try_into()?, + default, + documentation: documentation.iter().map(|s| s.to_string()).collect::>(), + }) } /// Temporary struct for converting between `StorageEntryModifier` /// and `runtime_metadata_latest::StorageEntryModifier` struct StorageEntryModifierTemp(StorageEntryModifier); impl From for runtime_metadata_latest::StorageEntryModifier { - fn from(entry: StorageEntryModifierTemp) -> runtime_metadata_latest::StorageEntryModifier { - let entry = entry.0; - match entry { - StorageEntryModifier::Optional => { - runtime_metadata_latest::StorageEntryModifier::Optional - } - StorageEntryModifier::Default => runtime_metadata_latest::StorageEntryModifier::Default, - } - } + fn from(entry: StorageEntryModifierTemp) -> runtime_metadata_latest::StorageEntryModifier { + let entry = entry.0; + match entry { + StorageEntryModifier::Optional => runtime_metadata_latest::StorageEntryModifier::Optional, + StorageEntryModifier::Default => runtime_metadata_latest::StorageEntryModifier::Default, + } + } } /// Temprorary struct for converting between `StorageHasher` and /// `runtime_metadata_latest::StorageHasher` struct TempStorageHasher(StorageHasher); impl From for runtime_metadata_latest::StorageHasher { - fn from(hasher: TempStorageHasher) -> runtime_metadata_latest::StorageHasher { - let hasher = hasher.0; - match hasher { - StorageHasher::Blake2_128 => runtime_metadata_latest::StorageHasher::Blake2_128, - StorageHasher::Blake2_128Concat => runtime_metadata_latest::StorageHasher::Blake2_128, - StorageHasher::Blake2_256 => runtime_metadata_latest::StorageHasher::Blake2_256, - StorageHasher::Twox128 => runtime_metadata_latest::StorageHasher::Twox128, - StorageHasher::Twox256 => runtime_metadata_latest::StorageHasher::Twox256, - StorageHasher::Twox64Concat => runtime_metadata_latest::StorageHasher::Twox64Concat, - } - } + fn from(hasher: TempStorageHasher) -> runtime_metadata_latest::StorageHasher { + let hasher = hasher.0; + match hasher { + StorageHasher::Blake2_128 => runtime_metadata_latest::StorageHasher::Blake2_128, + StorageHasher::Blake2_128Concat => runtime_metadata_latest::StorageHasher::Blake2_128, + StorageHasher::Blake2_256 => runtime_metadata_latest::StorageHasher::Blake2_256, + StorageHasher::Twox128 => runtime_metadata_latest::StorageHasher::Twox128, + StorageHasher::Twox256 => runtime_metadata_latest::StorageHasher::Twox256, + StorageHasher::Twox64Concat => runtime_metadata_latest::StorageHasher::Twox64Concat, + } + } } /// Temporary struct for converting between `DecodeDifferentStr` and /// `DecodeDifferentStrLatest` struct TempDecodeDifferentStr(DecodeDifferentStr); impl From for LatestDecodeDifferentStr { - fn from(decode_str: TempDecodeDifferentStr) -> LatestDecodeDifferentStr { - let decode_str = decode_str.0; - match decode_str { - DecodeDifferent::Encode(b) => runtime_metadata_latest::DecodeDifferent::Encode(b), - DecodeDifferent::Decoded(o) => runtime_metadata_latest::DecodeDifferent::Decoded(o), - } - } + fn from(decode_str: TempDecodeDifferentStr) -> LatestDecodeDifferentStr { + let decode_str = decode_str.0; + match decode_str { + DecodeDifferent::Encode(b) => runtime_metadata_latest::DecodeDifferent::Encode(b), + DecodeDifferent::Decoded(o) => runtime_metadata_latest::DecodeDifferent::Decoded(o), + } + } } impl TryFrom for StorageType { - type Error = Error; - fn try_from(entry: StorageEntryType) -> Result { - let entry = match entry { - StorageEntryType::Plain(v) => { - let ty = convert(v)?; - StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) - } - StorageEntryType::Map { - hasher, - key, - value, - is_linked, - } => { - let key = convert(key)?; - let value = convert(value)?; - StorageType::Map { - hasher: TempStorageHasher(hasher).into(), - key: regex::parse(&key).ok_or(Error::InvalidType(key))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - unused: is_linked, - } - } - StorageEntryType::DoubleMap { - hasher, - key1, - key2, - value, - key2_hasher, - } => { - let key1 = convert(key1)?; - let key2 = convert(key2)?; - let value = convert(value)?; - StorageType::DoubleMap { - hasher: TempStorageHasher(hasher).into(), - key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, - key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - key2_hasher: TempStorageHasher(key2_hasher).into(), - } - } - }; - Ok(entry) - } + type Error = Error; + fn try_from(entry: StorageEntryType) -> Result { + let entry = match entry { + StorageEntryType::Plain(v) => { + let ty = convert(v)?; + StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) + } + StorageEntryType::Map { hasher, key, value, is_linked } => { + let key = convert(key)?; + let value = convert(value)?; + StorageType::Map { + hasher: TempStorageHasher(hasher).into(), + key: regex::parse(&key).ok_or(Error::InvalidType(key))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + unused: is_linked, + } + } + StorageEntryType::DoubleMap { hasher, key1, key2, value, key2_hasher } => { + let key1 = convert(key1)?; + let key2 = convert(key2)?; + let value = convert(value)?; + StorageType::DoubleMap { + hasher: TempStorageHasher(hasher).into(), + key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, + key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + key2_hasher: TempStorageHasher(key2_hasher).into(), + } + } + }; + Ok(entry) + } } diff --git a/core/src/decoder/metadata/version_11.rs b/core/src/decoder/metadata/version_11.rs index 90474415..4085a917 100644 --- a/core/src/decoder/metadata/version_11.rs +++ b/core/src/decoder/metadata/version_11.rs @@ -30,233 +30,198 @@ // along with substrate-desub. If not, see . use super::{ - CallArgMetadata, CallMetadata, Error, EventArg, ExtrinsicMetadata, Metadata, - ModuleEventMetadata, ModuleMetadata, StorageMetadata, StorageType, + CallArgMetadata, CallMetadata, Error, EventArg, ExtrinsicMetadata, Metadata, ModuleEventMetadata, ModuleMetadata, + StorageMetadata, StorageType, }; use crate::{regex, RustTypeMarker}; use runtime_metadata11::{ - DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryModifier, - StorageEntryType, StorageHasher, META_RESERVED, + DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryModifier, StorageEntryType, StorageHasher, + META_RESERVED, }; use std::{ - collections::{HashMap, HashSet}, - convert::{TryFrom, TryInto}, + collections::{HashMap, HashSet}, + convert::{TryFrom, TryInto}, }; impl TryFrom for Metadata { - type Error = Error; + type Error = Error; - fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { - if metadata.0 != META_RESERVED { - // 'meta' warn endiannes - return Err(Error::InvalidPrefix); - } - let meta = match metadata.1 { - RuntimeMetadata::V11(meta) => meta, - _ => return Err(Error::InvalidVersion), - }; - let mut modules = HashMap::new(); - let (mut modules_by_event_index, mut modules_by_call_index) = - (HashMap::new(), HashMap::new()); - let (mut event_index, mut call_index) = (0, 0); - for (i, module) in convert(meta.modules)?.into_iter().enumerate() { - let module_name = convert(module.name.clone())?; - if module.calls.is_some() { - modules_by_call_index.insert(call_index, module_name.clone()); - call_index += 1; - } - if module.event.is_none() { - modules_by_event_index.insert(event_index, module_name.clone()); - event_index += 1; - } - let module_metadata = convert_module(i, module)?; - modules.insert(module_name, std::sync::Arc::new(module_metadata)); - } + fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { + if metadata.0 != META_RESERVED { + // 'meta' warn endiannes + return Err(Error::InvalidPrefix); + } + let meta = match metadata.1 { + RuntimeMetadata::V11(meta) => meta, + _ => return Err(Error::InvalidVersion), + }; + let mut modules = HashMap::new(); + let (mut modules_by_event_index, mut modules_by_call_index) = (HashMap::new(), HashMap::new()); + let (mut event_index, mut call_index) = (0, 0); + for (i, module) in convert(meta.modules)?.into_iter().enumerate() { + let module_name = convert(module.name.clone())?; + if module.calls.is_some() { + modules_by_call_index.insert(call_index, module_name.clone()); + call_index += 1; + } + if module.event.is_none() { + modules_by_event_index.insert(event_index, module_name.clone()); + event_index += 1; + } + let module_metadata = convert_module(i, module)?; + modules.insert(module_name, std::sync::Arc::new(module_metadata)); + } - let mut extensions: Vec = Vec::new(); - for ext in meta.extrinsic.signed_extensions.iter() { - let name: String = convert(ext.clone())?; - let ty = regex::parse(&name).ok_or(Error::InvalidType(name))?; - extensions.push(ty); - } + let mut extensions: Vec = Vec::new(); + for ext in meta.extrinsic.signed_extensions.iter() { + let name: String = convert(ext.clone())?; + let ty = regex::parse(&name).ok_or(Error::InvalidType(name))?; + extensions.push(ty); + } - let extrinsics = ExtrinsicMetadata::new(meta.extrinsic.version, extensions); + let extrinsics = ExtrinsicMetadata::new(meta.extrinsic.version, extensions); - Ok(Metadata { - modules, - modules_by_event_index, - modules_by_call_index, - extrinsics: Some(extrinsics), - }) - } + Ok(Metadata { modules, modules_by_event_index, modules_by_call_index, extrinsics: Some(extrinsics) }) + } } fn convert(dd: DecodeDifferent) -> Result { - match dd { - DecodeDifferent::Decoded(value) => Ok(value), - _ => Err(Error::ExpectedDecoded), - } + match dd { + DecodeDifferent::Decoded(value) => Ok(value), + _ => Err(Error::ExpectedDecoded), + } } -fn convert_module( - index: usize, - module: runtime_metadata11::ModuleMetadata, -) -> Result { - let mut storage_map = HashMap::new(); - if let Some(storage) = module.storage { - let storage = convert(storage)?; - let prefix = convert(storage.prefix)?; - for entry in convert(storage.entries)?.into_iter() { - let entry_name = convert(entry.name.clone())?; - let entry_prefix = format!("{} {}", prefix, entry_name); - let entry = convert_entry(entry_prefix, entry)?; - storage_map.insert(entry_name, entry); - } - } - let mut call_map = HashMap::new(); - if let Some(calls) = module.calls { - for (index, call) in convert(calls)?.into_iter().enumerate() { - let name = convert(call.name)?; - let args = convert(call.arguments)? - .iter() - .map(|a| { - let ty = convert(a.ty.clone())?; - let name = convert(a.name.clone())?; - let arg = CallArgMetadata { - name, - ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))?, - }; - Ok(arg) - }) - .collect::, Error>>()?; - let meta = CallMetadata { - name: name.clone(), - index: index as u8, - arguments: args, - }; - call_map.insert(name, meta); - } - } - let mut event_map = HashMap::new(); - if let Some(events) = module.event { - for (index, event) in convert(events)?.into_iter().enumerate() { - event_map.insert(index as u8, convert_event(event)?); - } - } +fn convert_module(index: usize, module: runtime_metadata11::ModuleMetadata) -> Result { + let mut storage_map = HashMap::new(); + if let Some(storage) = module.storage { + let storage = convert(storage)?; + let prefix = convert(storage.prefix)?; + for entry in convert(storage.entries)?.into_iter() { + let entry_name = convert(entry.name.clone())?; + let entry_prefix = format!("{} {}", prefix, entry_name); + let entry = convert_entry(entry_prefix, entry)?; + storage_map.insert(entry_name, entry); + } + } + let mut call_map = HashMap::new(); + if let Some(calls) = module.calls { + for (index, call) in convert(calls)?.into_iter().enumerate() { + let name = convert(call.name)?; + let args = convert(call.arguments)? + .iter() + .map(|a| { + let ty = convert(a.ty.clone())?; + let name = convert(a.name.clone())?; + let arg = CallArgMetadata { name, ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))? }; + Ok(arg) + }) + .collect::, Error>>()?; + let meta = CallMetadata { name: name.clone(), index: index as u8, arguments: args }; + call_map.insert(name, meta); + } + } + let mut event_map = HashMap::new(); + if let Some(events) = module.event { + for (index, event) in convert(events)?.into_iter().enumerate() { + event_map.insert(index as u8, convert_event(event)?); + } + } - Ok(ModuleMetadata { - index: index as u8, - name: convert(module.name)?, - storage: storage_map, - calls: call_map, - events: event_map, - }) + Ok(ModuleMetadata { + index: index as u8, + name: convert(module.name)?, + storage: storage_map, + calls: call_map, + events: event_map, + }) } fn convert_event(event: runtime_metadata11::EventMetadata) -> Result { - let name = convert(event.name)?; - let mut arguments = HashSet::new(); - for arg in convert(event.arguments)? { - let arg = arg.parse::()?; - arguments.insert(arg); - } - Ok(ModuleEventMetadata { name, arguments }) + let name = convert(event.name)?; + let mut arguments = HashSet::new(); + for arg in convert(event.arguments)? { + let arg = arg.parse::()?; + arguments.insert(arg); + } + Ok(ModuleEventMetadata { name, arguments }) } -fn convert_entry( - prefix: String, - entry: runtime_metadata11::StorageEntryMetadata, -) -> Result { - let default = convert(entry.default)?; - let documentation = convert(entry.documentation)?; - Ok(StorageMetadata { - prefix, - modifier: StorageEntryModifierTemp(entry.modifier).into(), - ty: entry.ty.try_into()?, - default, - documentation: documentation - .iter() - .map(|s| s.to_string()) - .collect::>(), - }) +fn convert_entry(prefix: String, entry: runtime_metadata11::StorageEntryMetadata) -> Result { + let default = convert(entry.default)?; + let documentation = convert(entry.documentation)?; + Ok(StorageMetadata { + prefix, + modifier: StorageEntryModifierTemp(entry.modifier).into(), + ty: entry.ty.try_into()?, + default, + documentation: documentation.iter().map(|s| s.to_string()).collect::>(), + }) } /// Temporary struct for converting between `StorageEntryModifier` /// and `runtime_metadata11::StorageEntryModifier` struct StorageEntryModifierTemp(StorageEntryModifier); impl From for runtime_metadata_latest::StorageEntryModifier { - fn from(entry: StorageEntryModifierTemp) -> runtime_metadata_latest::StorageEntryModifier { - let entry = entry.0; - match entry { - StorageEntryModifier::Optional => { - runtime_metadata_latest::StorageEntryModifier::Optional - } - StorageEntryModifier::Default => runtime_metadata_latest::StorageEntryModifier::Default, - } - } + fn from(entry: StorageEntryModifierTemp) -> runtime_metadata_latest::StorageEntryModifier { + let entry = entry.0; + match entry { + StorageEntryModifier::Optional => runtime_metadata_latest::StorageEntryModifier::Optional, + StorageEntryModifier::Default => runtime_metadata_latest::StorageEntryModifier::Default, + } + } } /// Temprorary struct for converting between `StorageHasher` and /// `runtime_metadata_latest::StorageHasher` struct TempStorageHasher(StorageHasher); impl From for runtime_metadata_latest::StorageHasher { - fn from(hasher: TempStorageHasher) -> runtime_metadata_latest::StorageHasher { - let hasher = hasher.0; - match hasher { - StorageHasher::Blake2_128 => runtime_metadata_latest::StorageHasher::Blake2_128, - StorageHasher::Blake2_128Concat => runtime_metadata_latest::StorageHasher::Blake2_128, - StorageHasher::Blake2_256 => runtime_metadata_latest::StorageHasher::Blake2_256, - StorageHasher::Twox128 => runtime_metadata_latest::StorageHasher::Twox128, - StorageHasher::Twox256 => runtime_metadata_latest::StorageHasher::Twox256, - StorageHasher::Twox64Concat => runtime_metadata_latest::StorageHasher::Twox64Concat, - StorageHasher::Identity => runtime_metadata_latest::StorageHasher::Identity, - } - } + fn from(hasher: TempStorageHasher) -> runtime_metadata_latest::StorageHasher { + let hasher = hasher.0; + match hasher { + StorageHasher::Blake2_128 => runtime_metadata_latest::StorageHasher::Blake2_128, + StorageHasher::Blake2_128Concat => runtime_metadata_latest::StorageHasher::Blake2_128, + StorageHasher::Blake2_256 => runtime_metadata_latest::StorageHasher::Blake2_256, + StorageHasher::Twox128 => runtime_metadata_latest::StorageHasher::Twox128, + StorageHasher::Twox256 => runtime_metadata_latest::StorageHasher::Twox256, + StorageHasher::Twox64Concat => runtime_metadata_latest::StorageHasher::Twox64Concat, + StorageHasher::Identity => runtime_metadata_latest::StorageHasher::Identity, + } + } } impl TryFrom for StorageType { - type Error = Error; - fn try_from(entry: StorageEntryType) -> Result { - let entry = match entry { - StorageEntryType::Plain(v) => { - let ty = convert(v)?; - StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) - } - StorageEntryType::Map { - hasher, - key, - value, - unused, - } => { - let key = convert(key)?; - let value = convert(value)?; - StorageType::Map { - hasher: TempStorageHasher(hasher).into(), - key: regex::parse(&key).ok_or(Error::InvalidType(key))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - unused, - } - } - StorageEntryType::DoubleMap { - hasher, - key1, - key2, - value, - key2_hasher, - } => { - let key1 = convert(key1)?; - let key2 = convert(key2)?; - let value = convert(value)?; - StorageType::DoubleMap { - hasher: TempStorageHasher(hasher).into(), - key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, - key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - key2_hasher: TempStorageHasher(key2_hasher).into(), - } - } - }; - Ok(entry) - } + type Error = Error; + fn try_from(entry: StorageEntryType) -> Result { + let entry = match entry { + StorageEntryType::Plain(v) => { + let ty = convert(v)?; + StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) + } + StorageEntryType::Map { hasher, key, value, unused } => { + let key = convert(key)?; + let value = convert(value)?; + StorageType::Map { + hasher: TempStorageHasher(hasher).into(), + key: regex::parse(&key).ok_or(Error::InvalidType(key))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + unused, + } + } + StorageEntryType::DoubleMap { hasher, key1, key2, value, key2_hasher } => { + let key1 = convert(key1)?; + let key2 = convert(key2)?; + let value = convert(value)?; + StorageType::DoubleMap { + hasher: TempStorageHasher(hasher).into(), + key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, + key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + key2_hasher: TempStorageHasher(key2_hasher).into(), + } + } + }; + Ok(entry) + } } diff --git a/core/src/decoder/metadata/version_12.rs b/core/src/decoder/metadata/version_12.rs index f8837b17..ce936d38 100644 --- a/core/src/decoder/metadata/version_12.rs +++ b/core/src/decoder/metadata/version_12.rs @@ -30,201 +30,169 @@ // along with substrate-desub. If not, see . use super::{ - CallArgMetadata, CallMetadata, Error, EventArg, ExtrinsicMetadata, Metadata, - ModuleEventMetadata, ModuleMetadata, StorageMetadata, StorageType, + CallArgMetadata, CallMetadata, Error, EventArg, ExtrinsicMetadata, Metadata, ModuleEventMetadata, ModuleMetadata, + StorageMetadata, StorageType, }; use crate::{regex, RustTypeMarker}; use runtime_metadata_latest::{ - DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryType, META_RESERVED, + DecodeDifferent, RuntimeMetadata, RuntimeMetadataPrefixed, StorageEntryType, META_RESERVED, }; use std::{ - collections::{HashMap, HashSet}, - convert::{TryFrom, TryInto}, + collections::{HashMap, HashSet}, + convert::{TryFrom, TryInto}, }; impl TryFrom for Metadata { - type Error = Error; + type Error = Error; - fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { - if metadata.0 != META_RESERVED { - // 'meta' warn endiannes - return Err(Error::InvalidPrefix); - } - let meta = match metadata.1 { - RuntimeMetadata::V12(meta) => meta, - _ => return Err(Error::InvalidVersion), - }; - let mut modules = HashMap::new(); - let (mut modules_by_event_index, mut modules_by_call_index) = - (HashMap::new(), HashMap::new()); - let (mut event_index, mut call_index) = (0, 0); - for (i, module) in convert(meta.modules)?.into_iter().enumerate() { - let module_name = convert(module.name.clone())?; - if module.calls.is_some() { - modules_by_call_index.insert(call_index, module_name.clone()); - call_index += 1; - } - if module.event.is_none() { - modules_by_event_index.insert(event_index, module_name.clone()); - event_index += 1; - } - let module_metadata = convert_module(i, module)?; - modules.insert(module_name, std::sync::Arc::new(module_metadata)); - } + fn try_from(metadata: RuntimeMetadataPrefixed) -> Result { + if metadata.0 != META_RESERVED { + // 'meta' warn endiannes + return Err(Error::InvalidPrefix); + } + let meta = match metadata.1 { + RuntimeMetadata::V12(meta) => meta, + _ => return Err(Error::InvalidVersion), + }; + let mut modules = HashMap::new(); + let (mut modules_by_event_index, mut modules_by_call_index) = (HashMap::new(), HashMap::new()); + let (mut event_index, mut call_index) = (0, 0); + for (i, module) in convert(meta.modules)?.into_iter().enumerate() { + let module_name = convert(module.name.clone())?; + if module.calls.is_some() { + modules_by_call_index.insert(call_index, module_name.clone()); + call_index += 1; + } + if module.event.is_none() { + modules_by_event_index.insert(event_index, module_name.clone()); + event_index += 1; + } + let module_metadata = convert_module(i, module)?; + modules.insert(module_name, std::sync::Arc::new(module_metadata)); + } - let mut extensions: Vec = Vec::new(); - for ext in meta.extrinsic.signed_extensions.iter() { - let name: String = convert(ext.clone())?; - let ty = regex::parse(&name).ok_or(Error::InvalidType(name))?; - extensions.push(ty); - } + let mut extensions: Vec = Vec::new(); + for ext in meta.extrinsic.signed_extensions.iter() { + let name: String = convert(ext.clone())?; + let ty = regex::parse(&name).ok_or(Error::InvalidType(name))?; + extensions.push(ty); + } - let extrinsics = ExtrinsicMetadata::new(meta.extrinsic.version, extensions); + let extrinsics = ExtrinsicMetadata::new(meta.extrinsic.version, extensions); - Ok(Metadata { - modules, - modules_by_event_index, - modules_by_call_index, - extrinsics: Some(extrinsics), - }) - } + Ok(Metadata { modules, modules_by_event_index, modules_by_call_index, extrinsics: Some(extrinsics) }) + } } fn convert(dd: DecodeDifferent) -> Result { - match dd { - DecodeDifferent::Decoded(value) => Ok(value), - _ => Err(Error::ExpectedDecoded), - } + match dd { + DecodeDifferent::Decoded(value) => Ok(value), + _ => Err(Error::ExpectedDecoded), + } } -fn convert_module( - index: usize, - module: runtime_metadata_latest::ModuleMetadata, -) -> Result { - let mut storage_map = HashMap::new(); - if let Some(storage) = module.storage { - let storage = convert(storage)?; - let prefix = convert(storage.prefix)?; - for entry in convert(storage.entries)?.into_iter() { - let entry_name = convert(entry.name.clone())?; - let entry_prefix = format!("{} {}", prefix, entry_name); - let entry = convert_entry(entry_prefix, entry)?; - storage_map.insert(entry_name, entry); - } - } - let mut call_map = HashMap::new(); - if let Some(calls) = module.calls { - for (index, call) in convert(calls)?.into_iter().enumerate() { - let name = convert(call.name)?; - let args = convert(call.arguments)? - .iter() - .map(|a| { - let ty = convert(a.ty.clone())?; - let name = convert(a.name.clone())?; - let arg = CallArgMetadata { - name, - ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))?, - }; - Ok(arg) - }) - .collect::, Error>>()?; - let meta = CallMetadata { - name: name.clone(), - index: index as u8, - arguments: args, - }; - call_map.insert(name, meta); - } - } - let mut event_map = HashMap::new(); - if let Some(events) = module.event { - for (index, event) in convert(events)?.into_iter().enumerate() { - event_map.insert(index as u8, convert_event(event)?); - } - } +fn convert_module(index: usize, module: runtime_metadata_latest::ModuleMetadata) -> Result { + let mut storage_map = HashMap::new(); + if let Some(storage) = module.storage { + let storage = convert(storage)?; + let prefix = convert(storage.prefix)?; + for entry in convert(storage.entries)?.into_iter() { + let entry_name = convert(entry.name.clone())?; + let entry_prefix = format!("{} {}", prefix, entry_name); + let entry = convert_entry(entry_prefix, entry)?; + storage_map.insert(entry_name, entry); + } + } + let mut call_map = HashMap::new(); + if let Some(calls) = module.calls { + for (index, call) in convert(calls)?.into_iter().enumerate() { + let name = convert(call.name)?; + let args = convert(call.arguments)? + .iter() + .map(|a| { + let ty = convert(a.ty.clone())?; + let name = convert(a.name.clone())?; + let arg = CallArgMetadata { name, ty: regex::parse(&ty).ok_or(Error::InvalidType(ty))? }; + Ok(arg) + }) + .collect::, Error>>()?; + let meta = CallMetadata { name: name.clone(), index: index as u8, arguments: args }; + call_map.insert(name, meta); + } + } + let mut event_map = HashMap::new(); + if let Some(events) = module.event { + for (index, event) in convert(events)?.into_iter().enumerate() { + event_map.insert(index as u8, convert_event(event)?); + } + } - Ok(ModuleMetadata { - index: index as u8, - name: convert(module.name)?, - storage: storage_map, - calls: call_map, - events: event_map, - }) + Ok(ModuleMetadata { + index: index as u8, + name: convert(module.name)?, + storage: storage_map, + calls: call_map, + events: event_map, + }) } -fn convert_event( - event: runtime_metadata_latest::EventMetadata, -) -> Result { - let name = convert(event.name)?; - let mut arguments = HashSet::new(); - for arg in convert(event.arguments)? { - let arg = arg.parse::()?; - arguments.insert(arg); - } - Ok(ModuleEventMetadata { name, arguments }) +fn convert_event(event: runtime_metadata_latest::EventMetadata) -> Result { + let name = convert(event.name)?; + let mut arguments = HashSet::new(); + for arg in convert(event.arguments)? { + let arg = arg.parse::()?; + arguments.insert(arg); + } + Ok(ModuleEventMetadata { name, arguments }) } fn convert_entry( - prefix: String, - entry: runtime_metadata_latest::StorageEntryMetadata, + prefix: String, + entry: runtime_metadata_latest::StorageEntryMetadata, ) -> Result { - let default = convert(entry.default)?; - let documentation = convert(entry.documentation)?; - Ok(StorageMetadata { - prefix, - modifier: entry.modifier, - ty: entry.ty.try_into()?, - default, - documentation: documentation - .iter() - .map(|s| s.to_string()) - .collect::>(), - }) + let default = convert(entry.default)?; + let documentation = convert(entry.documentation)?; + Ok(StorageMetadata { + prefix, + modifier: entry.modifier, + ty: entry.ty.try_into()?, + default, + documentation: documentation.iter().map(|s| s.to_string()).collect::>(), + }) } impl TryFrom for StorageType { - type Error = Error; - fn try_from(entry: StorageEntryType) -> Result { - let entry = match entry { - StorageEntryType::Plain(v) => { - let ty = convert(v)?; - StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) - } - StorageEntryType::Map { - hasher, - key, - value, - unused, - } => { - let key = convert(key)?; - let value = convert(value)?; - StorageType::Map { - hasher, - key: regex::parse(&key).ok_or(Error::InvalidType(key))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - unused, - } - } - StorageEntryType::DoubleMap { - hasher, - key1, - key2, - value, - key2_hasher, - } => { - let key1 = convert(key1)?; - let key2 = convert(key2)?; - let value = convert(value)?; - StorageType::DoubleMap { - hasher, - key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, - key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, - value: regex::parse(&value).ok_or(Error::InvalidType(value))?, - key2_hasher, - } - } - }; - Ok(entry) - } + type Error = Error; + fn try_from(entry: StorageEntryType) -> Result { + let entry = match entry { + StorageEntryType::Plain(v) => { + let ty = convert(v)?; + StorageType::Plain(regex::parse(&ty).ok_or(Error::InvalidType(ty))?) + } + StorageEntryType::Map { hasher, key, value, unused } => { + let key = convert(key)?; + let value = convert(value)?; + StorageType::Map { + hasher, + key: regex::parse(&key).ok_or(Error::InvalidType(key))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + unused, + } + } + StorageEntryType::DoubleMap { hasher, key1, key2, value, key2_hasher } => { + let key1 = convert(key1)?; + let key2 = convert(key2)?; + let value = convert(value)?; + StorageType::DoubleMap { + hasher, + key1: regex::parse(&key1).ok_or(Error::InvalidType(key1))?, + key2: regex::parse(&key2).ok_or(Error::InvalidType(key2))?, + value: regex::parse(&value).ok_or(Error::InvalidType(value))?, + key2_hasher, + } + } + }; + Ok(entry) + } } diff --git a/core/src/decoder/storage.rs b/core/src/decoder/storage.rs index a07bdbf2..a3b8d818 100644 --- a/core/src/decoder/storage.rs +++ b/core/src/decoder/storage.rs @@ -25,102 +25,102 @@ use crate::substrate_types::SubstrateType; #[derive(Debug, Clone, PartialEq)] pub struct StorageInfo { - pub meta: StorageMetadata, - pub module: Arc, + pub meta: StorageMetadata, + pub module: Arc, } impl StorageInfo { - pub fn new(meta: StorageMetadata, module: Arc) -> Self { - Self { meta, module } - } + pub fn new(meta: StorageMetadata, module: Arc) -> Self { + Self { meta, module } + } } #[derive(Debug, Clone, PartialEq)] pub struct StorageLookupTable { - table: HashMap, StorageInfo>, + table: HashMap, StorageInfo>, } impl StorageLookupTable { - pub fn new(map: HashMap, StorageInfo>) -> Self { - Self { - table: map, - // module: module.clone() - } - } - - /// Returns the StorageMetadata given the `prefix` of a StorageKey. - pub fn lookup(&self, prefix: &[u8]) -> Option<&StorageInfo> { - self.table.get(prefix) - } - - pub fn meta_for_key(&self, key: &[u8]) -> Option<&StorageInfo> { - let key = self.table.keys().find(|&k| &key[..k.len()] == k.as_slice()); - key.map(|k| self.lookup(k)).flatten() - } - - pub fn extra_key_data<'a>(&self, key: &'a [u8]) -> Option<&'a [u8]> { - let k = self.table.keys().find(|k| &key[..k.len()] == k.as_slice()); - - k.map(|k| &key[k.len()..]) - } + pub fn new(map: HashMap, StorageInfo>) -> Self { + Self { + table: map, + // module: module.clone() + } + } + + /// Returns the StorageMetadata given the `prefix` of a StorageKey. + pub fn lookup(&self, prefix: &[u8]) -> Option<&StorageInfo> { + self.table.get(prefix) + } + + pub fn meta_for_key(&self, key: &[u8]) -> Option<&StorageInfo> { + let key = self.table.keys().find(|&k| &key[..k.len()] == k.as_slice()); + key.map(|k| self.lookup(k)).flatten() + } + + pub fn extra_key_data<'a>(&self, key: &'a [u8]) -> Option<&'a [u8]> { + let k = self.table.keys().find(|k| &key[..k.len()] == k.as_slice()); + + k.map(|k| &key[k.len()..]) + } } #[derive(Debug, Clone, PartialEq, Serialize)] pub enum StorageKeyData { - Map { - hasher: StorageHasher, - /// hashed and scale-encoded key - key: Vec, - key_type: RustTypeMarker, - }, - DoubleMap { - hasher: StorageHasher, - /// hashed and scale-encoded key - key1: Vec, - key1_type: RustTypeMarker, - /// hashed and scale-encoded key - key2: Vec, - key2_type: RustTypeMarker, - key2_hasher: StorageHasher, - }, + Map { + hasher: StorageHasher, + /// hashed and scale-encoded key + key: Vec, + key_type: RustTypeMarker, + }, + DoubleMap { + hasher: StorageHasher, + /// hashed and scale-encoded key + key1: Vec, + key1_type: RustTypeMarker, + /// hashed and scale-encoded key + key2: Vec, + key2_type: RustTypeMarker, + key2_hasher: StorageHasher, + }, } #[derive(Debug, Clone, PartialEq, Serialize)] pub struct StorageKey { - pub module: String, - pub prefix: String, - pub extra: Option, + pub module: String, + pub prefix: String, + pub extra: Option, } #[derive(Debug, Clone, PartialEq, Serialize)] pub struct StorageValue(SubstrateType); impl StorageValue { - pub fn new(val: SubstrateType) -> Self { - Self(val) - } + pub fn new(val: SubstrateType) -> Self { + Self(val) + } - pub fn ty(&self) -> &SubstrateType { - &self.0 - } + pub fn ty(&self) -> &SubstrateType { + &self.0 + } } #[derive(Debug, Clone, PartialEq, Serialize)] pub struct GenericStorage { - key: StorageKey, - value: Option, + key: StorageKey, + value: Option, } impl GenericStorage { - pub fn new(key: StorageKey, value: Option) -> Self { - Self { key, value } - } + pub fn new(key: StorageKey, value: Option) -> Self { + Self { key, value } + } - pub fn key(&self) -> &StorageKey { - &self.key - } + pub fn key(&self) -> &StorageKey { + &self.key + } - pub fn value(&self) -> Option<&StorageValue> { - self.value.as_ref() - } + pub fn value(&self) -> Option<&StorageValue> { + self.value.as_ref() + } } diff --git a/core/src/error.rs b/core/src/error.rs index 360127b2..02c05815 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -4,30 +4,30 @@ use thiserror::Error; #[derive(Error, Debug)] pub enum Error { - #[error("Codec {0}")] - Codec(#[from] CodecError), - #[error("{0}")] - Metadata(#[from] MetadataError), - #[error("Failed to get metadata item because of `{0}`, where cursor is {1} and data is {2}")] - DetailedMetaFail(MetadataError, usize, String), - #[error("decoding failed")] - DecodeFail, - #[error("error: {0}")] - Fail(String), - #[error("parse error {0}")] - Regex(#[from] onig::Error), - #[error("Conversion from {0} to {1} not possible")] - Conversion(String, String), + #[error("Codec {0}")] + Codec(#[from] CodecError), + #[error("{0}")] + Metadata(#[from] MetadataError), + #[error("Failed to get metadata item because of `{0}`, where cursor is {1} and data is {2}")] + DetailedMetaFail(MetadataError, usize, String), + #[error("decoding failed")] + DecodeFail, + #[error("error: {0}")] + Fail(String), + #[error("parse error {0}")] + Regex(#[from] onig::Error), + #[error("Conversion from {0} to {1} not possible")] + Conversion(String, String), } impl From<&str> for Error { - fn from(e: &str) -> Error { - Error::Fail(e.to_string()) - } + fn from(e: &str) -> Error { + Error::Fail(e.to_string()) + } } impl From for Error { - fn from(e: String) -> Error { - Error::Fail(e) - } + fn from(e: String) -> Error { + Error::Fail(e) + } } diff --git a/core/src/lib.rs b/core/src/lib.rs index faaaf5d0..e0277aac 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with substrate-desub. If not, see . -#![feature(backtrace)] - #[forbid(unsafe_code)] pub mod decoder; mod error; @@ -32,99 +30,96 @@ use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; pub trait TypeDetective: fmt::Debug + dyn_clone::DynClone + Send + Sync { - /// Get a 'RustTypeMarker' - fn get(&self, chain: &str, spec: u32, module: &str, ty: &str) -> Option<&RustTypeMarker>; + /// Get a 'RustTypeMarker' + fn get(&self, chain: &str, spec: u32, module: &str, ty: &str) -> Option<&RustTypeMarker>; - /// get a type specific to decoding extrinsics - fn get_extrinsic_ty(&self, chain: &str, spec: u32, ty: &str) -> Option<&RustTypeMarker>; + /// get a type specific to decoding extrinsics + fn get_extrinsic_ty(&self, chain: &str, spec: u32, ty: &str) -> Option<&RustTypeMarker>; } /// A field with an associated name #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct StructField { - pub name: String, - pub ty: RustTypeMarker, + pub name: String, + pub ty: RustTypeMarker, } impl Display for StructField { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "struct_field({}: {})", self.name, self.ty) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "struct_field({}: {})", self.name, self.ty) + } } impl StructField { - pub fn new>(name: S, ty: RustTypeMarker) -> Self { - let name = name.into(); - Self { name, ty } - } + pub fn new>(name: S, ty: RustTypeMarker) -> Self { + let name = name.into(); + Self { name, ty } + } } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct SetField { - pub name: String, - pub num: u8, + pub name: String, + pub num: u8, } impl Display for SetField { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "set_field({} {})", self.name, self.num) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "set_field({} {})", self.name, self.num) + } } impl SetField { - pub fn new>(name: S, num: u8) -> Self { - let (name, num) = (name.into(), num); - Self { name, num } - } + pub fn new>(name: S, num: u8) -> Self { + let (name, num) = (name.into(), num); + Self { name, num } + } } /// TODO: Allow mixed struct-unit types #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct EnumField { - /// name of the Variant - /// if the variant is a Unit enum, it will not have a name - pub variant_name: Option, - pub ty: StructUnitOrTuple, + /// name of the Variant + /// if the variant is a Unit enum, it will not have a name + pub variant_name: Option, + pub ty: StructUnitOrTuple, } impl EnumField { - pub fn new(variant_name: Option, ty: StructUnitOrTuple) -> Self { - EnumField { variant_name, ty } - } + pub fn new(variant_name: Option, ty: StructUnitOrTuple) -> Self { + EnumField { variant_name, ty } + } } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub enum StructUnitOrTuple { - Struct(Vec), - Unit(String), - Tuple(RustTypeMarker), + Struct(Vec), + Unit(String), + Tuple(RustTypeMarker), } impl From for EnumField { - fn from(s: String) -> EnumField { - EnumField { - variant_name: None, - ty: StructUnitOrTuple::Unit(s), - } - } + fn from(s: String) -> EnumField { + EnumField { variant_name: None, ty: StructUnitOrTuple::Unit(s) } + } } impl Display for EnumField { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut _enum = String::from("enum"); - match &self.ty { - StructUnitOrTuple::Struct(s) => { - for s in s.iter() { - _enum.push_str(&format!("{}, ", s)); - } - } - StructUnitOrTuple::Unit(u) => { - _enum.push_str(&format!("{}, ", u)); - } - StructUnitOrTuple::Tuple(v) => _enum.push_str(&format!("{} ", v)), - }; - write!(f, "{}", _enum) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut _enum = String::from("enum"); + match &self.ty { + StructUnitOrTuple::Struct(s) => { + for s in s.iter() { + _enum.push_str(&format!("{}, ", s)); + } + } + StructUnitOrTuple::Unit(u) => { + _enum.push_str(&format!("{}, ", u)); + } + StructUnitOrTuple::Tuple(v) => _enum.push_str(&format!("{} ", v)), + }; + write!(f, "{}", _enum) + } } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] @@ -133,194 +128,190 @@ impl Display for EnumField { /// Definitions for Vec/Option/Compact /// Boxed because self-referential otherwise pub enum CommonTypes { - /// Rust std Vec type - Vec(Box), - /// Rust std Option type - Option(Box), - /// Rust Result type - Result(Box, Box), - /// parity-scale-codec Compact type - Compact(Box), + /// Rust std Vec type + Vec(Box), + /// Rust std Option type + Option(Box), + /// Rust Result type + Result(Box, Box), + /// parity-scale-codec Compact type + Compact(Box), } impl Display for CommonTypes { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut common_types = String::from(""); - match self { - CommonTypes::Vec(t) => { - common_types.push_str(&format!("Vec<{}>", t)); - } - CommonTypes::Option(t) => { - common_types.push_str(&format!("Option<{}>", t)); - } - CommonTypes::Result(r, e) => { - common_types.push_str(&format!("Result<{},{}>", r, e)); - } - CommonTypes::Compact(t) => { - common_types.push_str(&format!("Compact<{}>", t)); - } - } - write!(f, "{}", common_types) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut common_types = String::from(""); + match self { + CommonTypes::Vec(t) => { + common_types.push_str(&format!("Vec<{}>", t)); + } + CommonTypes::Option(t) => { + common_types.push_str(&format!("Option<{}>", t)); + } + CommonTypes::Result(r, e) => { + common_types.push_str(&format!("Result<{},{}>", r, e)); + } + CommonTypes::Compact(t) => { + common_types.push_str(&format!("Compact<{}>", t)); + } + } + write!(f, "{}", common_types) + } } impl CommonTypes { - /// returns the inner types of Common Rust Constructs - /// types with more than one generic (E.G Result) - /// are indexes in a Vector - /// Types with only one generic (E.G Option) have only - /// one vector element - pub fn get_inner_type(&self) -> Vec<&RustTypeMarker> { - match self { - CommonTypes::Vec(ref v_inner) => vec![v_inner], - CommonTypes::Option(ref o_inner) => vec![o_inner], - CommonTypes::Result(ref r_inner1, ref r_inner2) => vec![r_inner1, r_inner2], - CommonTypes::Compact(ref c_inner) => vec![c_inner], - } - } + /// returns the inner types of Common Rust Constructs + /// types with more than one generic (E.G Result) + /// are indexes in a Vector + /// Types with only one generic (E.G Option) have only + /// one vector element + pub fn get_inner_type(&self) -> Vec<&RustTypeMarker> { + match self { + CommonTypes::Vec(ref v_inner) => vec![v_inner], + CommonTypes::Option(ref o_inner) => vec![o_inner], + CommonTypes::Result(ref r_inner1, ref r_inner2) => vec![r_inner1, r_inner2], + CommonTypes::Compact(ref c_inner) => vec![c_inner], + } + } } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub enum RustTypeMarker { - /// name of a type that exists elsewhere in type declarations - TypePointer(String), - - /// Some Struct - /// Field Name -> Field Type - Struct(Vec), - - /// A C-Like Enum - Set(Vec), - - /// A tuple type (max size 32) - Tuple(Vec), - - /// Some Enum - /// A Rust Enum that contains mixed "Struct" and Unit fields - /// will have unit fields as struct but with the type as "Null" - Enum(Vec), - - /// A sized array - Array { - /// size of the array - size: usize, - /// type of array - ty: Box, - }, - - /// Definitions for common patterns seen in substrate/polkadot - /// type definitions - Std(CommonTypes), - - /// A Generic Type, EX: HeartBeat - /// Tuple of (OuterType, InnerType) - Generic((Box, Box)), - /// primitive unsigned 8 bit integer - U8, - /// primtiive unsigned 16 bit integer - U16, - /// primitive unsigned 32 bit integer - U32, - /// primitive unsigned 64 bit integer - U64, - /// primitive unsigned 128 bit integer - U128, - /// primitive unsigned word-sized integer - USize, - - /// primitive signed 8 bit integer - I8, - /// primitive signed 16 bit integer - I16, - /// primitive signed 32 bit integer - I32, - /// primitive signed 64 bit integer - I64, - /// primitive signed 128 bit integer - I128, - /// primitive signed word-sized integer - ISize, - - /// primitive IEEE-spec 32-bit floating-point number - F32, - /// primitive IEEE-spec 64-bit floating-point number - F64, - - /// Boolean true/false type - Bool, - - /// String type - String, - - /// Used for fields that don't exist (ex Unit variant in an enum with both - /// units/structs) - Null, + /// name of a type that exists elsewhere in type declarations + TypePointer(String), + + /// Some Struct + /// Field Name -> Field Type + Struct(Vec), + + /// A C-Like Enum + Set(Vec), + + /// A tuple type (max size 32) + Tuple(Vec), + + /// Some Enum + /// A Rust Enum that contains mixed "Struct" and Unit fields + /// will have unit fields as struct but with the type as "Null" + Enum(Vec), + + /// A sized array + Array { + /// size of the array + size: usize, + /// type of array + ty: Box, + }, + + /// Definitions for common patterns seen in substrate/polkadot + /// type definitions + Std(CommonTypes), + + /// A Generic Type, EX: HeartBeat + /// Tuple of (OuterType, InnerType) + Generic((Box, Box)), + /// primitive unsigned 8 bit integer + U8, + /// primtiive unsigned 16 bit integer + U16, + /// primitive unsigned 32 bit integer + U32, + /// primitive unsigned 64 bit integer + U64, + /// primitive unsigned 128 bit integer + U128, + /// primitive unsigned word-sized integer + USize, + + /// primitive signed 8 bit integer + I8, + /// primitive signed 16 bit integer + I16, + /// primitive signed 32 bit integer + I32, + /// primitive signed 64 bit integer + I64, + /// primitive signed 128 bit integer + I128, + /// primitive signed word-sized integer + ISize, + + /// primitive IEEE-spec 32-bit floating-point number + F32, + /// primitive IEEE-spec 64-bit floating-point number + F64, + + /// Boolean true/false type + Bool, + + /// String type + String, + + /// Used for fields that don't exist (ex Unit variant in an enum with both + /// units/structs) + Null, } fn display_types(fields: &[RustTypeMarker]) -> String { - let mut s = String::new(); - - s.push('('); - for substring in fields.iter() { - s.push_str(&format!("{}, ", substring)) - } - s.push(')'); - s + let mut s = String::new(); + + s.push('('); + for substring in fields.iter() { + s.push_str(&format!("{}, ", substring)) + } + s.push(')'); + s } impl Display for RustTypeMarker { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut type_marker = String::from(""); - match self { - RustTypeMarker::TypePointer(t) => type_marker.push_str(t), - RustTypeMarker::Struct(t) => { - for substring in t.iter() { - type_marker.push_str(&format!("{}, ", substring)) - } - } - RustTypeMarker::Set(t) => { - for substring in t.iter() { - type_marker.push_str(&format!("{}, ", substring)) - } - } - RustTypeMarker::Tuple(t) => type_marker.push_str(&display_types(&t)), - RustTypeMarker::Enum(t) => { - type_marker.push_str("{ "); - for field in t.iter() { - type_marker.push_str(&format!("{} ,", &field.to_string())); - } - type_marker.push_str(" }") - } - RustTypeMarker::Array { size, ty } => { - type_marker.push_str(&format!("[{};{}], ", ty, size)) - } - RustTypeMarker::Std(t) => type_marker.push_str(&t.to_string()), - RustTypeMarker::Generic((outer, inner)) => { - type_marker.push_str(&format!("{}<{}>", outer, inner)) - } - RustTypeMarker::U8 => type_marker.push_str("u8"), - RustTypeMarker::U16 => type_marker.push_str("u16"), - RustTypeMarker::U32 => type_marker.push_str("u32"), - RustTypeMarker::U64 => type_marker.push_str("u64"), - RustTypeMarker::U128 => type_marker.push_str("u128"), - RustTypeMarker::USize => type_marker.push_str("usize"), - - RustTypeMarker::I8 => type_marker.push_str("i8"), - RustTypeMarker::I16 => type_marker.push_str("i16"), - RustTypeMarker::I32 => type_marker.push_str("i32"), - RustTypeMarker::I64 => type_marker.push_str("i64"), - RustTypeMarker::I128 => type_marker.push_str("i128"), - RustTypeMarker::ISize => type_marker.push_str("isize"), - - RustTypeMarker::F32 => type_marker.push_str("f32"), - RustTypeMarker::F64 => type_marker.push_str("f64"), - - RustTypeMarker::Bool => type_marker.push_str("bool"), - - RustTypeMarker::String => type_marker.push_str("string"), - - RustTypeMarker::Null => type_marker.push_str("null"), - } - write!(f, "{}", type_marker) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut type_marker = String::from(""); + match self { + RustTypeMarker::TypePointer(t) => type_marker.push_str(t), + RustTypeMarker::Struct(t) => { + for substring in t.iter() { + type_marker.push_str(&format!("{}, ", substring)) + } + } + RustTypeMarker::Set(t) => { + for substring in t.iter() { + type_marker.push_str(&format!("{}, ", substring)) + } + } + RustTypeMarker::Tuple(t) => type_marker.push_str(&display_types(&t)), + RustTypeMarker::Enum(t) => { + type_marker.push_str("{ "); + for field in t.iter() { + type_marker.push_str(&format!("{} ,", &field.to_string())); + } + type_marker.push_str(" }") + } + RustTypeMarker::Array { size, ty } => type_marker.push_str(&format!("[{};{}], ", ty, size)), + RustTypeMarker::Std(t) => type_marker.push_str(&t.to_string()), + RustTypeMarker::Generic((outer, inner)) => type_marker.push_str(&format!("{}<{}>", outer, inner)), + RustTypeMarker::U8 => type_marker.push_str("u8"), + RustTypeMarker::U16 => type_marker.push_str("u16"), + RustTypeMarker::U32 => type_marker.push_str("u32"), + RustTypeMarker::U64 => type_marker.push_str("u64"), + RustTypeMarker::U128 => type_marker.push_str("u128"), + RustTypeMarker::USize => type_marker.push_str("usize"), + + RustTypeMarker::I8 => type_marker.push_str("i8"), + RustTypeMarker::I16 => type_marker.push_str("i16"), + RustTypeMarker::I32 => type_marker.push_str("i32"), + RustTypeMarker::I64 => type_marker.push_str("i64"), + RustTypeMarker::I128 => type_marker.push_str("i128"), + RustTypeMarker::ISize => type_marker.push_str("isize"), + + RustTypeMarker::F32 => type_marker.push_str("f32"), + RustTypeMarker::F64 => type_marker.push_str("f64"), + + RustTypeMarker::Bool => type_marker.push_str("bool"), + + RustTypeMarker::String => type_marker.push_str("string"), + + RustTypeMarker::Null => type_marker.push_str("null"), + } + write!(f, "{}", type_marker) + } } diff --git a/core/src/regex.rs b/core/src/regex.rs index 3580fb4e..0d74c812 100644 --- a/core/src/regex.rs +++ b/core/src/regex.rs @@ -20,120 +20,119 @@ use onig::{Regex, Region, SearchOptions}; #[derive(Debug, Clone, PartialEq, Eq)] enum RegexSet { - ArrayPrimitive, - ArrayStruct, - Vec, - Option, - Result, - Compact, - Box, - Tuple, - Generic, + ArrayPrimitive, + ArrayStruct, + Vec, + Option, + Result, + Compact, + Box, + Tuple, + Generic, } impl RegexSet { - /// Checks if string matches any of the patterns defined - /// Returns none if it does not match - fn get_type(s: &str) -> Option { - if rust_array_decl_prim().is_match(s) { - Some(RegexSet::ArrayPrimitive) - } else if rust_array_decl_struct().is_match(s) { - Some(RegexSet::ArrayStruct) - } else if rust_vec_decl().is_match(s) { - Some(RegexSet::Vec) - } else if rust_option_decl().is_match(s) { - Some(RegexSet::Option) - } else if rust_result_decl().is_match(s) { - Some(RegexSet::Result) - } else if rust_compact_decl().is_match(s) { - Some(RegexSet::Compact) - } else if rust_box_decl().is_match(s) { - Some(RegexSet::Box) - } else if rust_tuple_decl().is_match(s) { - Some(RegexSet::Tuple) - } else if rust_generic_decl().is_match(s) { - Some(RegexSet::Generic) - } else { - None - } - } - - fn parse_type(&self, s: &str) -> Option { - match self { - RegexSet::ArrayPrimitive => parse_primitive_array(s), - RegexSet::ArrayStruct => parse_struct_array(s), - RegexSet::Vec => parse_vec(s), - RegexSet::Option => parse_option(s), - RegexSet::Result => parse_result(s), - RegexSet::Compact => parse_compact(s), - RegexSet::Box => parse_box(s), - RegexSet::Tuple => parse_tuple(s), - RegexSet::Generic => parse_generic(s), - } - } + /// Checks if string matches any of the patterns defined + /// Returns none if it does not match + fn get_type(s: &str) -> Option { + if rust_array_decl_prim().is_match(s) { + Some(RegexSet::ArrayPrimitive) + } else if rust_array_decl_struct().is_match(s) { + Some(RegexSet::ArrayStruct) + } else if rust_vec_decl().is_match(s) { + Some(RegexSet::Vec) + } else if rust_option_decl().is_match(s) { + Some(RegexSet::Option) + } else if rust_result_decl().is_match(s) { + Some(RegexSet::Result) + } else if rust_compact_decl().is_match(s) { + Some(RegexSet::Compact) + } else if rust_box_decl().is_match(s) { + Some(RegexSet::Box) + } else if rust_tuple_decl().is_match(s) { + Some(RegexSet::Tuple) + } else if rust_generic_decl().is_match(s) { + Some(RegexSet::Generic) + } else { + None + } + } + + fn parse_type(&self, s: &str) -> Option { + match self { + RegexSet::ArrayPrimitive => parse_primitive_array(s), + RegexSet::ArrayStruct => parse_struct_array(s), + RegexSet::Vec => parse_vec(s), + RegexSet::Option => parse_option(s), + RegexSet::Result => parse_result(s), + RegexSet::Compact => parse_compact(s), + RegexSet::Box => parse_box(s), + RegexSet::Tuple => parse_tuple(s), + RegexSet::Generic => parse_generic(s), + } + } } // primitive array declaration with named capture groups, ie [u8; 99] // width of number and unsigned/signed are all in their own capture group // size of array is in the last capture group fn rust_array_decl_prim() -> Regex { - Regex::new(r"^\[ *?(?[uif]{1})(?8)?(?16)?(?32)?(?64)?(?128)?;\s*?(?[\d]*) *?]") - .expect("Primitive Regex expression invalid") + Regex::new( + r"^\[ *?(?[uif]{1})(?8)?(?16)?(?32)?(?64)?(?128)?;\s*?(?[\d]*) *?]", + ) + .expect("Primitive Regex expression invalid") } // matches arrays with struct arguments, IE: [Vec; 10] // First capture group is Type // Second Capture group is size fn rust_array_decl_struct() -> Regex { - Regex::new(r"^\[ *?([\w><]+) *?; *?(\d+) *?\]").expect("Primitive Regex expression invalid") + Regex::new(r"^\[ *?([\w><]+) *?; *?(\d+) *?\]").expect("Primitive Regex expression invalid") } /// Match a rust vector /// allowed to be nested within, or have other (ie Option<>) nested within pub fn rust_vec_decl() -> Regex { - Regex::new(r"^Vec<(?[\w><,():\;\[\] ]+)>") - .expect("Regex expression should be infallible; qed") + Regex::new(r"^Vec<(?[\w><,():\;\[\] ]+)>").expect("Regex expression should be infallible; qed") } /// Match a Rust Option /// Allowed to be nested within another type, or have other (ie Vec<>) nested pub fn rust_option_decl() -> Regex { - Regex::new(r"^Option<(?[\w><,(): ]+)>") - .expect("Regex expression should be infallible; qed") + Regex::new(r"^Option<(?[\w><,(): ]+)>").expect("Regex expression should be infallible; qed") } /// Match a rust result pub fn rust_result_decl() -> Regex { - Regex::new(r"^Result<(?\(?[\w><,: ]*\)?), *(?\(?[\w><, ]*\)?)>") - .expect("Regex experession should be infallible; qed") + Regex::new(r"^Result<(?\(?[\w><,: ]*\)?), *(?\(?[\w><, ]*\)?)>") + .expect("Regex experession should be infallible; qed") } /// Match a parity-scale-codec Compact type pub fn rust_compact_decl() -> Regex { - Regex::new(r"^Compact<(?[\w><,(): ]+)>") - .expect("Regex expression should be infallible; qed") + Regex::new(r"^Compact<(?[\w><,(): ]+)>").expect("Regex expression should be infallible; qed") } /// Match a rust Boxed type pub fn rust_box_decl() -> Regex { - Regex::new(r"^Box<(?[\w><,(): ]+)>").expect("Regex expression should be infallible; qed") + Regex::new(r"^Box<(?[\w><,(): ]+)>").expect("Regex expression should be infallible; qed") } /// Match a Rust Generic Type Declaration /// Excudes types Vec/Option/Compact/Box from matches pub fn rust_generic_decl() -> Regex { - Regex::new(r"\b(?!(?:Vec|Option|Compact|Box)\b)(?\w+)<(?[\w<>,: ]+)>") - .expect("Regex expressions should be infallible; qed") + Regex::new(r"\b(?!(?:Vec|Option|Compact|Box)\b)(?\w+)<(?[\w<>,: ]+)>") + .expect("Regex expressions should be infallible; qed") } /// Transforms a prefixed generic type (EX: T::Moment) /// into a non-prefixed type (T::Moment -> Moment) pub fn remove_prefix<'a, S: Into<&'a str>>(s: S) -> Option { - let s: &str = s.into(); + let s: &str = s.into(); - let re = Regex::new(r"[\w><]::([\w><]+)").expect("Regex expressions should be infallible; qed"); - let caps = re.captures(s)?; - caps.iter().nth(1)?.map(|s| s.to_string()) + let re = Regex::new(r"[\w><]::([\w><]+)").expect("Regex expressions should be infallible; qed"); + let caps = re.captures(s)?; + caps.iter().nth(1)?.map(|s| s.to_string()) } /// Only captures text within the tuples, @@ -145,44 +144,37 @@ pub fn remove_prefix<'a, S: Into<&'a str>>(s: S) -> Option { /// captures may be indexed like a tuple, via Captures<'a>::at(pos: usize) /// except starting at 1, since 0 is always the entire match pub fn rust_tuple_decl() -> Regex { - Regex::new( - [ - r#"^\(([\w\d><:;\[\]()\n ]+)"#, - r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, - r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, - r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, - r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, - r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, - r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, - r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, - r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, - r#",? *([\w\d><:;\[\]()\n ]+)*\)$"#, - ] - .join("") - .as_str(), - ) - .expect("Regex Expressions should be infallible; qed") + Regex::new( + [ + r#"^\(([\w\d><:;\[\]()\n ]+)"#, + r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, + r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, + r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, + r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, + r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, + r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, + r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, + r#",? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*,? *([\w\d><:;\[\]()\n ]+)*"#, + r#",? *([\w\d><:;\[\]()\n ]+)*\)$"#, + ] + .join("") + .as_str(), + ) + .expect("Regex Expressions should be infallible; qed") } pub fn parse_struct_array(s: &str) -> Option { - let re = rust_array_decl_struct(); - if !re.is_match(s) { - return None; - } - - let ty = re.captures(s)?.at(1)?; - let ty = parse(ty).expect("Will always be some type; qed"); - - let size = re - .captures(s)? - .at(2)? - .parse::() - .expect("size of array must be a number"); - - Some(RustTypeMarker::Array { - size, - ty: Box::new(ty), - }) + let re = rust_array_decl_struct(); + if !re.is_match(s) { + return None; + } + + let ty = re.captures(s)?.at(1)?; + let ty = parse(ty).expect("Will always be some type; qed"); + + let size = re.captures(s)?.at(2)?.parse::().expect("size of array must be a number"); + + Some(RustTypeMarker::Array { size, ty: Box::new(ty) }) } /// Parse a known match to the array regular expression @@ -191,137 +183,129 @@ pub fn parse_struct_array(s: &str) -> Option { /// /// TODO: Use errors instead of returning option pub fn parse_primitive_array(s: &str) -> Option { - let re = rust_array_decl_prim(); - if !re.is_match(s) { - return None; - } - - let mut region = Region::new(); - - let (mut t, mut size, mut ty) = (None, None, None); - if let Some(_position) = re.search_with_options( - s, - 0, - s.len(), - SearchOptions::SEARCH_OPTION_NONE, - Some(&mut region), - ) { - re.foreach_name(|name, groups| { - for group in groups { - // capture groups that don't represent type - // ie if type is 'u8', 'u32' capture group - // will be None - if let Some(pos) = region.pos(*group as usize) { - match name { - "type" => { - // first thing matched - t = Some(&s[pos.0..pos.1]) - } - "size" => { - // last thing matched - size = Some(&s[pos.0..pos.1]) - } - "bit8" => ty = Some(8), - "bit16" => ty = Some(16), - "bit32" => ty = Some(32), - "bit64" => ty = Some(64), - "bit128" => ty = Some(128), - _ => panic!("Unhandled capture group"), - } - } else { - continue; - } - } - true - }); - }; - let t = t?; - let size = size?; - let ty = ty?; - - let ty = match ty { - 8 => match t { - "u" => RustTypeMarker::U8, - "i" => RustTypeMarker::I8, - "f" => panic!("type does not exist 'f8'"), - _ => panic!("impossible match encountered"), - }, - 16 => match t { - "u" => RustTypeMarker::U16, - "i" => RustTypeMarker::I16, - "f" => panic!("type does not exist 'f16'"), - _ => panic!("impossible match encountered"), - }, - 32 => match t { - "u" => RustTypeMarker::U32, - "i" => RustTypeMarker::I32, - "f" => RustTypeMarker::F32, - _ => panic!("impossible match encountered"), - }, - 64 => match t { - "u" => RustTypeMarker::U64, - "i" => RustTypeMarker::I64, - "f" => RustTypeMarker::F64, - _ => panic!("impossible match encountered"), - }, - 128 => match t { - "u" => RustTypeMarker::U128, - "i" => RustTypeMarker::I128, - "f" => panic!("type does not exist: 'f128'"), - _ => panic!("impossible match encountered"), - }, - _ => panic!("Couldn't determine bit-width of types in array"), - }; - let ty = Box::new(ty); - let size = size.parse::().expect("Should always be number"); - Some(RustTypeMarker::Array { size, ty }) + let re = rust_array_decl_prim(); + if !re.is_match(s) { + return None; + } + + let mut region = Region::new(); + + let (mut t, mut size, mut ty) = (None, None, None); + if let Some(_position) = re.search_with_options(s, 0, s.len(), SearchOptions::SEARCH_OPTION_NONE, Some(&mut region)) + { + re.foreach_name(|name, groups| { + for group in groups { + // capture groups that don't represent type + // ie if type is 'u8', 'u32' capture group + // will be None + if let Some(pos) = region.pos(*group as usize) { + match name { + "type" => { + // first thing matched + t = Some(&s[pos.0..pos.1]) + } + "size" => { + // last thing matched + size = Some(&s[pos.0..pos.1]) + } + "bit8" => ty = Some(8), + "bit16" => ty = Some(16), + "bit32" => ty = Some(32), + "bit64" => ty = Some(64), + "bit128" => ty = Some(128), + _ => panic!("Unhandled capture group"), + } + } else { + continue; + } + } + true + }); + }; + let t = t?; + let size = size?; + let ty = ty?; + + let ty = match ty { + 8 => match t { + "u" => RustTypeMarker::U8, + "i" => RustTypeMarker::I8, + "f" => panic!("type does not exist 'f8'"), + _ => panic!("impossible match encountered"), + }, + 16 => match t { + "u" => RustTypeMarker::U16, + "i" => RustTypeMarker::I16, + "f" => panic!("type does not exist 'f16'"), + _ => panic!("impossible match encountered"), + }, + 32 => match t { + "u" => RustTypeMarker::U32, + "i" => RustTypeMarker::I32, + "f" => RustTypeMarker::F32, + _ => panic!("impossible match encountered"), + }, + 64 => match t { + "u" => RustTypeMarker::U64, + "i" => RustTypeMarker::I64, + "f" => RustTypeMarker::F64, + _ => panic!("impossible match encountered"), + }, + 128 => match t { + "u" => RustTypeMarker::U128, + "i" => RustTypeMarker::I128, + "f" => panic!("type does not exist: 'f128'"), + _ => panic!("impossible match encountered"), + }, + _ => panic!("Couldn't determine bit-width of types in array"), + }; + let ty = Box::new(ty); + let size = size.parse::().expect("Should always be number"); + Some(RustTypeMarker::Array { size, ty }) } fn parse_vec(s: &str) -> Option { - let re = rust_vec_decl(); + let re = rust_vec_decl(); - if !re.is_match(s) { - return None; - } + if !re.is_match(s) { + return None; + } - let ty = re.captures(s)?.at(1)?; - let ty = parse(ty).expect("Should always be some type; qed"); - Some(RustTypeMarker::Std(CommonTypes::Vec(Box::new(ty)))) + let ty = re.captures(s)?.at(1)?; + let ty = parse(ty).expect("Should always be some type; qed"); + Some(RustTypeMarker::Std(CommonTypes::Vec(Box::new(ty)))) } fn parse_option(s: &str) -> Option { - let re = rust_option_decl(); - if !re.is_match(s) { - return None; - } - let ty = re.captures(s)?.at(1)?; - let ty = parse(ty).expect("Should always be some type; qed"); - Some(RustTypeMarker::Std(CommonTypes::Option(Box::new(ty)))) + let re = rust_option_decl(); + if !re.is_match(s) { + return None; + } + let ty = re.captures(s)?.at(1)?; + let ty = parse(ty).expect("Should always be some type; qed"); + Some(RustTypeMarker::Std(CommonTypes::Option(Box::new(ty)))) } fn parse_result(s: &str) -> Option { - let re = rust_result_decl(); - if !re.is_match(s) { - return None; - } - - let ty = parse(re.captures(s)?.at(1)?).expect("Should always be some type; qed"); - let err = parse(re.captures(s)?.at(2)?).expect("Should always be some type; qed"); - Some(RustTypeMarker::Std(CommonTypes::Result( - Box::new(ty), - Box::new(err), - ))) + let re = rust_result_decl(); + if !re.is_match(s) { + return None; + } + + let ty = parse(re.captures(s)?.at(1)?).expect("Should always be some type; qed"); + let err = parse(re.captures(s)?.at(2)?).expect("Should always be some type; qed"); + Some(RustTypeMarker::Std(CommonTypes::Result(Box::new(ty), Box::new(err)))) } fn parse_compact(s: &str) -> Option { - let re = rust_compact_decl(); - if !re.is_match(s) { - return None; - } - let ty = re.captures(s)?.at(1)?; - - let ty = parse(ty).expect("Should always be some type; qed"); - Some(RustTypeMarker::Std(CommonTypes::Compact(Box::new(ty)))) + let re = rust_compact_decl(); + if !re.is_match(s) { + return None; + } + let ty = re.captures(s)?.at(1)?; + + let ty = parse(ty).expect("Should always be some type; qed"); + Some(RustTypeMarker::Std(CommonTypes::Compact(Box::new(ty)))) } /// Parse a Box @@ -329,728 +313,520 @@ fn parse_compact(s: &str) -> Option { /// We only care about the underlying data structure. /// So we do not preserve the fact that this type is 'boxed'. fn parse_box(s: &str) -> Option { - let re = rust_box_decl(); - if !re.is_match(s) { - return None; - } - let ty = re.captures(s)?.at(1)?; + let re = rust_box_decl(); + if !re.is_match(s) { + return None; + } + let ty = re.captures(s)?.at(1)?; - Some(parse(ty).expect("Should always be some type; qed")) + Some(parse(ty).expect("Should always be some type; qed")) } fn parse_tuple(s: &str) -> Option { - let re = rust_tuple_decl(); - if !re.is_match(s) { - return None; - } - - // skip the first element (entire match) - let ty = re - .captures(s)? - .iter() - .skip(1) - .filter_map(|c| { - if let Some(c) = c { - Some(parse(c).expect("Must be a type; qed")) - } else { - None - } - }) - .collect::>(); - - Some(RustTypeMarker::Tuple(ty)) + let re = rust_tuple_decl(); + if !re.is_match(s) { + return None; + } + + // skip the first element (entire match) + let ty = re + .captures(s)? + .iter() + .skip(1) + .filter_map(|c| if let Some(c) = c { Some(parse(c).expect("Must be a type; qed")) } else { None }) + .collect::>(); + + Some(RustTypeMarker::Tuple(ty)) } fn parse_generic(s: &str) -> Option { - let re = rust_generic_decl(); - if !re.is_match(s) { - return None; - } - let ty_outer = re.captures(s)?.at(1)?; - let ty_inner = re.captures(s)?.at(2)?; - let ty_outer = parse(ty_outer).expect("Must be a type; qed"); - // NOTE: - // ty_inner may be a throwaway type in some cases where the inner type are part of - // the already-defined definitions in the JSON - // for example, the "HeartBeat" definition in Polkadot JSON definitions already takes into - // account that a HeartBeat type in Polkadot is HeartBeat - let ty_inner = parse(ty_inner).expect("Must be a type; qed"); - - Some(RustTypeMarker::Generic(( - Box::new(ty_outer), - Box::new(ty_inner), - ))) + let re = rust_generic_decl(); + if !re.is_match(s) { + return None; + } + let ty_outer = re.captures(s)?.at(1)?; + let ty_inner = re.captures(s)?.at(2)?; + let ty_outer = parse(ty_outer).expect("Must be a type; qed"); + // NOTE: + // ty_inner may be a throwaway type in some cases where the inner type are part of + // the already-defined definitions in the JSON + // for example, the "HeartBeat" definition in Polkadot JSON definitions already takes into + // account that a HeartBeat type in Polkadot is HeartBeat + let ty_inner = parse(ty_inner).expect("Must be a type; qed"); + + Some(RustTypeMarker::Generic((Box::new(ty_outer), Box::new(ty_inner)))) } /// recursively parses a regex set /// returning a RustTypeMarker with all matched types pub fn parse(s: &str) -> Option { - match s { - // match primitive types first - "u8" => Some(RustTypeMarker::U8), - "u16" => Some(RustTypeMarker::U16), - "u32" => Some(RustTypeMarker::U32), - "u64" => Some(RustTypeMarker::U64), - "u128" => Some(RustTypeMarker::U128), - "usize" => Some(RustTypeMarker::USize), - - "i8" => Some(RustTypeMarker::I8), - "i16" => Some(RustTypeMarker::I16), - "i32" => Some(RustTypeMarker::I32), - "i64" => Some(RustTypeMarker::I64), - "i128" => Some(RustTypeMarker::I128), - "isize" => Some(RustTypeMarker::ISize), - - "f32" => Some(RustTypeMarker::F32), - "f64" => Some(RustTypeMarker::F64), - - "bool" => Some(RustTypeMarker::Bool), - "Null" => Some(RustTypeMarker::Null), - - _ => { - // check if nested type - if let Some(m) = RegexSet::get_type(s) { - m.parse_type(s) - } else { - // if not a primitive, then a type pointer - Some(RustTypeMarker::TypePointer(s.to_string())) - } - } - } + match s { + // match primitive types first + "u8" => Some(RustTypeMarker::U8), + "u16" => Some(RustTypeMarker::U16), + "u32" => Some(RustTypeMarker::U32), + "u64" => Some(RustTypeMarker::U64), + "u128" => Some(RustTypeMarker::U128), + "usize" => Some(RustTypeMarker::USize), + + "i8" => Some(RustTypeMarker::I8), + "i16" => Some(RustTypeMarker::I16), + "i32" => Some(RustTypeMarker::I32), + "i64" => Some(RustTypeMarker::I64), + "i128" => Some(RustTypeMarker::I128), + "isize" => Some(RustTypeMarker::ISize), + + "f32" => Some(RustTypeMarker::F32), + "f64" => Some(RustTypeMarker::F64), + + "bool" => Some(RustTypeMarker::Bool), + "Null" => Some(RustTypeMarker::Null), + + _ => { + // check if nested type + if let Some(m) = RegexSet::get_type(s) { + m.parse_type(s) + } else { + // if not a primitive, then a type pointer + Some(RustTypeMarker::TypePointer(s.to_string())) + } + } + } } #[cfg(test)] mod tests { - use super::*; - - #[test] - fn should_match_array_decl() { - let re = rust_array_decl_prim(); - assert!(re.is_match("[u8; 16]")); - assert!(re.is_match("[u16; 16]")); - assert!(re.is_match("[u32; 16]")); - assert!(re.is_match("[u64; 16]")); - assert!(re.is_match("[u128; 16]")); - assert!(re.is_match("[i8; 16]")); - assert!(re.is_match("[i16; 16]")); - assert!(re.is_match("[i32; 16]")); - assert!(re.is_match("[i64; 16]")); - assert!(re.is_match("[i128; 16]")); - assert!(re.is_match("[u16; 128]")); - assert!(re.is_match("[u32; 64]")); - assert!(re.is_match("[u64; 99999]")); - assert!(re.is_match("[u128; 23]")); - } - - #[test] - fn should_seperate_args_in_capture_groups() { - let re = rust_array_decl_prim(); - - let caps = re.captures("[u8; 16]").unwrap(); - assert_eq!( - vec![ - Some("[u8; 16]"), - Some("u"), - Some("8"), - None, - None, - None, - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[i8; 16]").unwrap(); - assert_eq!( - vec![ - Some("[i8; 16]"), - Some("i"), - Some("8"), - None, - None, - None, - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[u16; 16]").unwrap(); - assert_eq!( - vec![ - Some("[u16; 16]"), - Some("u"), - None, - Some("16"), - None, - None, - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[i16; 16]").unwrap(); - assert_eq!( - vec![ - Some("[i16; 16]"), - Some("i"), - None, - Some("16"), - None, - None, - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[u32; 16]").unwrap(); - assert_eq!( - vec![ - Some("[u32; 16]"), - Some("u"), - None, - None, - Some("32"), - None, - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[i32; 16]").unwrap(); - assert_eq!( - vec![ - Some("[i32; 16]"), - Some("i"), - None, - None, - Some("32"), - None, - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[u64; 16]").unwrap(); - assert_eq!( - vec![ - Some("[u64; 16]"), - Some("u"), - None, - None, - None, - Some("64"), - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[i64; 16]").unwrap(); - assert_eq!( - vec![ - Some("[i64; 16]"), - Some("i"), - None, - None, - None, - Some("64"), - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[u128; 16]").unwrap(); - assert_eq!( - vec![ - Some("[u128; 16]"), - Some("u"), - None, - None, - None, - None, - Some("128"), - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[i128; 16]").unwrap(); - assert_eq!( - vec![ - Some("[i128; 16]"), - Some("i"), - None, - None, - None, - None, - Some("128"), - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[f32; 16]").unwrap(); - assert_eq!( - vec![ - Some("[f32; 16]"), - Some("f"), - None, - None, - Some("32"), - None, - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[f64; 16]").unwrap(); - assert_eq!( - vec![ - Some("[f64; 16]"), - Some("f"), - None, - None, - None, - Some("64"), - None, - Some("16") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[i128; 9999]").unwrap(); - assert_eq!( - vec![ - Some("[i128; 9999]"), - Some("i"), - None, - None, - None, - None, - Some("128"), - Some("9999") - ], - caps.iter().collect::>>() - ); - - let caps = re.captures("[u128; 9999]").unwrap(); - assert_eq!( - vec![ - Some("[u128; 9999]"), - Some("u"), - None, - None, - None, - None, - Some("128"), - Some("9999") - ], - caps.iter().collect::>>() - ); - } - - #[test] - #[should_panic] - fn should_not_parse_on_nonexistant_type() { - parse_primitive_array("[f16; 32]"); - } - - #[test] - fn should_match_regex_array() { - assert_eq!( - parse_primitive_array("[u8; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::U8) - } - ); - assert_eq!( - parse_primitive_array("[u16; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::U16) - } - ); - assert_eq!( - parse_primitive_array("[u32; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::U32) - } - ); - assert_eq!( - parse_primitive_array("[u64; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::U64) - } - ); - assert_eq!( - parse_primitive_array("[u128; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::U128) - } - ); - assert_eq!( - parse_primitive_array("[i8; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::I8) - } - ); - assert_eq!( - parse_primitive_array("[i16; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::I16) - } - ); - assert_eq!( - parse_primitive_array("[i32; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::I32) - } - ); - assert_eq!( - parse_primitive_array("[i64; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::I64) - } - ); - assert_eq!( - parse_primitive_array("[i128; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::I128) - } - ); - assert_eq!( - parse_primitive_array("[f32; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::F32) - } - ); - assert_eq!( - parse_primitive_array("[f64; 32]").unwrap(), - RustTypeMarker::Array { - size: 32, - ty: Box::new(RustTypeMarker::F64) - } - ); - assert_eq!( - parse_primitive_array("[i128; 999999]").unwrap(), - RustTypeMarker::Array { - size: 999_999, - ty: Box::new(RustTypeMarker::I128) - } - ); - } - - #[test] - fn should_match_struct_array() { - let re = rust_array_decl_struct(); - assert_eq!(true, re.is_match("[Foo; 10]")) - } - - #[test] - fn should_parse_struct_array() { - let ty = parse_struct_array("[Foo; 99]").unwrap(); - assert_eq!( - ty, - RustTypeMarker::Array { - size: 99, - ty: Box::new(RustTypeMarker::TypePointer("Foo".to_string())) - } - ); - } - - #[test] - fn should_match_vecs() { - let re = rust_vec_decl(); - assert!(re.is_match("Vec")); - assert!(re.is_match("Vec")); - assert!(re.is_match("Vec")); - } - - #[test] - fn should_get_type_of_vec() { - let re = rust_vec_decl(); - let caps = re.captures("Vec").unwrap(); - // first capture group is always entire expression - assert!(caps.at(1) == Some("RuntimeVersionApi")); - } - - #[test] - fn should_match_compact() { - let re = rust_compact_decl(); - assert!(re.is_match("Compact")); - assert!(re.is_match("Compact")); - assert!(re.is_match("Compact")); - } - - #[test] - fn should_get_type_of_compact() { - let re = rust_compact_decl(); - let caps = re.captures("Compact").unwrap(); - assert!(caps.at(1) == Some("RuntimeVersionApi")); - } - - #[test] - fn should_match_options() { - let re = rust_option_decl(); - assert!(re.is_match("Option")); - assert!(re.is_match("Option")); - assert!(re.is_match("Option")); - assert!(re.is_match("Option>")); - } - - #[test] - fn should_get_type_of_option() { - let re = rust_option_decl(); - let caps = re.captures("Option").unwrap(); - // first capture group is always entire expression - assert!(caps.at(1) == Some("RuntimeVersionApi")); - - let re = rust_option_decl(); - let caps = re.captures("Option>").unwrap(); - assert!(caps.at(1) == Some("Vec")); - } - - #[test] - fn should_match_results() { - let re = rust_result_decl(); - assert!(re.is_match("Result")); - assert!(re.is_match("Result<(), FooError>")); - assert!(re.is_match("Result")); - assert!(re.is_match("Result, FooError>")); - assert!(re.is_match("Result<(Vec, Weird), (FooError, WeirdErrorFormat)>")); - } - - #[test] - fn should_get_type_of_result() { - let re = rust_result_decl(); - let caps = re.captures("Result").unwrap(); - - assert!(caps.at(1) == Some("Foo")); - assert!(caps.at(2) == Some("Bar")); - - let caps = re.captures("Result<(Foo, Zoo), (Bar, Car)>").unwrap(); - dbg!(&caps.at(1)); - assert!(caps.at(1) == Some("(Foo, Zoo)")); - assert!(caps.at(2) == Some("(Bar, Car)")); - } - - #[test] - fn should_match_arbitrary_types() { - let re = rust_generic_decl(); - assert!(re.is_match("GenericOuterType")); - assert!(re.is_match("GenericOutT>")); - assert!(!re.is_match("Vec")); - assert!(!re.is_match("Option")); - assert!(!re.is_match("Compact")); - } - - #[test] - fn should_get_arbitrary_type() { - let re = rust_generic_decl(); - let caps = re.captures("GenericOuterType").unwrap(); - assert_eq!( - vec![ - Some("GenericOuterType"), - Some("GenericOuterType"), - Some("GenericInnerType") - ], - caps.iter().collect::>>() - ); - } - - #[test] - fn should_match_tuples() { - let re = rust_tuple_decl(); - assert!(re.is_match("(StorageKey, Option)")); - assert!(re.is_match("(ApiKey, u32)")); - assert!(re.is_match("(u32,ApiKey,AnotherType)")); - // assert the upper match limit - assert!(re.is_match(["(StorageKey, Option, Foo, Bar, Aoo, Raw, Car, Dar, Eoo, Foo, Goo, Foo, Foo, Foo, Foo, Foo,", + use super::*; + + #[test] + fn should_match_array_decl() { + let re = rust_array_decl_prim(); + assert!(re.is_match("[u8; 16]")); + assert!(re.is_match("[u16; 16]")); + assert!(re.is_match("[u32; 16]")); + assert!(re.is_match("[u64; 16]")); + assert!(re.is_match("[u128; 16]")); + assert!(re.is_match("[i8; 16]")); + assert!(re.is_match("[i16; 16]")); + assert!(re.is_match("[i32; 16]")); + assert!(re.is_match("[i64; 16]")); + assert!(re.is_match("[i128; 16]")); + assert!(re.is_match("[u16; 128]")); + assert!(re.is_match("[u32; 64]")); + assert!(re.is_match("[u64; 99999]")); + assert!(re.is_match("[u128; 23]")); + } + + #[test] + fn should_seperate_args_in_capture_groups() { + let re = rust_array_decl_prim(); + + let caps = re.captures("[u8; 16]").unwrap(); + assert_eq!( + vec![Some("[u8; 16]"), Some("u"), Some("8"), None, None, None, None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[i8; 16]").unwrap(); + assert_eq!( + vec![Some("[i8; 16]"), Some("i"), Some("8"), None, None, None, None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[u16; 16]").unwrap(); + assert_eq!( + vec![Some("[u16; 16]"), Some("u"), None, Some("16"), None, None, None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[i16; 16]").unwrap(); + assert_eq!( + vec![Some("[i16; 16]"), Some("i"), None, Some("16"), None, None, None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[u32; 16]").unwrap(); + assert_eq!( + vec![Some("[u32; 16]"), Some("u"), None, None, Some("32"), None, None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[i32; 16]").unwrap(); + assert_eq!( + vec![Some("[i32; 16]"), Some("i"), None, None, Some("32"), None, None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[u64; 16]").unwrap(); + assert_eq!( + vec![Some("[u64; 16]"), Some("u"), None, None, None, Some("64"), None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[i64; 16]").unwrap(); + assert_eq!( + vec![Some("[i64; 16]"), Some("i"), None, None, None, Some("64"), None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[u128; 16]").unwrap(); + assert_eq!( + vec![Some("[u128; 16]"), Some("u"), None, None, None, None, Some("128"), Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[i128; 16]").unwrap(); + assert_eq!( + vec![Some("[i128; 16]"), Some("i"), None, None, None, None, Some("128"), Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[f32; 16]").unwrap(); + assert_eq!( + vec![Some("[f32; 16]"), Some("f"), None, None, Some("32"), None, None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[f64; 16]").unwrap(); + assert_eq!( + vec![Some("[f64; 16]"), Some("f"), None, None, None, Some("64"), None, Some("16")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[i128; 9999]").unwrap(); + assert_eq!( + vec![Some("[i128; 9999]"), Some("i"), None, None, None, None, Some("128"), Some("9999")], + caps.iter().collect::>>() + ); + + let caps = re.captures("[u128; 9999]").unwrap(); + assert_eq!( + vec![Some("[u128; 9999]"), Some("u"), None, None, None, None, Some("128"), Some("9999")], + caps.iter().collect::>>() + ); + } + + #[test] + #[should_panic] + fn should_not_parse_on_nonexistant_type() { + parse_primitive_array("[f16; 32]"); + } + + #[test] + fn should_match_regex_array() { + assert_eq!( + parse_primitive_array("[u8; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::U8) } + ); + assert_eq!( + parse_primitive_array("[u16; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::U16) } + ); + assert_eq!( + parse_primitive_array("[u32; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::U32) } + ); + assert_eq!( + parse_primitive_array("[u64; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::U64) } + ); + assert_eq!( + parse_primitive_array("[u128; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::U128) } + ); + assert_eq!( + parse_primitive_array("[i8; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::I8) } + ); + assert_eq!( + parse_primitive_array("[i16; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::I16) } + ); + assert_eq!( + parse_primitive_array("[i32; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::I32) } + ); + assert_eq!( + parse_primitive_array("[i64; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::I64) } + ); + assert_eq!( + parse_primitive_array("[i128; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::I128) } + ); + assert_eq!( + parse_primitive_array("[f32; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::F32) } + ); + assert_eq!( + parse_primitive_array("[f64; 32]").unwrap(), + RustTypeMarker::Array { size: 32, ty: Box::new(RustTypeMarker::F64) } + ); + assert_eq!( + parse_primitive_array("[i128; 999999]").unwrap(), + RustTypeMarker::Array { size: 999_999, ty: Box::new(RustTypeMarker::I128) } + ); + } + + #[test] + fn should_match_struct_array() { + let re = rust_array_decl_struct(); + assert_eq!(true, re.is_match("[Foo; 10]")) + } + + #[test] + fn should_parse_struct_array() { + let ty = parse_struct_array("[Foo; 99]").unwrap(); + assert_eq!( + ty, + RustTypeMarker::Array { size: 99, ty: Box::new(RustTypeMarker::TypePointer("Foo".to_string())) } + ); + } + + #[test] + fn should_match_vecs() { + let re = rust_vec_decl(); + assert!(re.is_match("Vec")); + assert!(re.is_match("Vec")); + assert!(re.is_match("Vec")); + } + + #[test] + fn should_get_type_of_vec() { + let re = rust_vec_decl(); + let caps = re.captures("Vec").unwrap(); + // first capture group is always entire expression + assert!(caps.at(1) == Some("RuntimeVersionApi")); + } + + #[test] + fn should_match_compact() { + let re = rust_compact_decl(); + assert!(re.is_match("Compact")); + assert!(re.is_match("Compact")); + assert!(re.is_match("Compact")); + } + + #[test] + fn should_get_type_of_compact() { + let re = rust_compact_decl(); + let caps = re.captures("Compact").unwrap(); + assert!(caps.at(1) == Some("RuntimeVersionApi")); + } + + #[test] + fn should_match_options() { + let re = rust_option_decl(); + assert!(re.is_match("Option")); + assert!(re.is_match("Option")); + assert!(re.is_match("Option")); + assert!(re.is_match("Option>")); + } + + #[test] + fn should_get_type_of_option() { + let re = rust_option_decl(); + let caps = re.captures("Option").unwrap(); + // first capture group is always entire expression + assert!(caps.at(1) == Some("RuntimeVersionApi")); + + let re = rust_option_decl(); + let caps = re.captures("Option>").unwrap(); + assert!(caps.at(1) == Some("Vec")); + } + + #[test] + fn should_match_results() { + let re = rust_result_decl(); + assert!(re.is_match("Result")); + assert!(re.is_match("Result<(), FooError>")); + assert!(re.is_match("Result")); + assert!(re.is_match("Result, FooError>")); + assert!(re.is_match("Result<(Vec, Weird), (FooError, WeirdErrorFormat)>")); + } + + #[test] + fn should_get_type_of_result() { + let re = rust_result_decl(); + let caps = re.captures("Result").unwrap(); + + assert!(caps.at(1) == Some("Foo")); + assert!(caps.at(2) == Some("Bar")); + + let caps = re.captures("Result<(Foo, Zoo), (Bar, Car)>").unwrap(); + dbg!(&caps.at(1)); + assert!(caps.at(1) == Some("(Foo, Zoo)")); + assert!(caps.at(2) == Some("(Bar, Car)")); + } + + #[test] + fn should_match_arbitrary_types() { + let re = rust_generic_decl(); + assert!(re.is_match("GenericOuterType")); + assert!(re.is_match("GenericOutT>")); + assert!(!re.is_match("Vec")); + assert!(!re.is_match("Option")); + assert!(!re.is_match("Compact")); + } + + #[test] + fn should_get_arbitrary_type() { + let re = rust_generic_decl(); + let caps = re.captures("GenericOuterType").unwrap(); + assert_eq!( + vec![Some("GenericOuterType"), Some("GenericOuterType"), Some("GenericInnerType")], + caps.iter().collect::>>() + ); + } + + #[test] + fn should_match_tuples() { + let re = rust_tuple_decl(); + assert!(re.is_match("(StorageKey, Option)")); + assert!(re.is_match("(ApiKey, u32)")); + assert!(re.is_match("(u32,ApiKey,AnotherType)")); + // assert the upper match limit + assert!(re.is_match(["(StorageKey, Option, Foo, Bar, Aoo, Raw, Car, Dar, Eoo, Foo, Goo, Foo, Foo, Foo, Foo, Foo,", "Hoo, Ioo, Joo, Koo, Loo, Moo, Noo, Ooo, Poo, Qoo, Roo, Soo, Too, Uoo, Xoo)" ].join("").as_str())); - assert!(re.is_match( - ["(StorageKey, Option, Foo, + assert!(re.is_match( + ["(StorageKey, Option, Foo, Bar, Aoo)"] - .join("") - .as_str() - )); - } - - #[test] - fn should_not_overflow_retry_limit() { - let re = rust_tuple_decl(); - let tuple = "(ParaId, Option<(CollatorId, Retriable)>)"; - assert!(re.is_match(tuple)) - } - - #[test] - fn should_get_types_in_tuple() { - let re = rust_tuple_decl(); - let match_str = "(StorageKey, Option)"; - let caps = re.captures(match_str).unwrap(); - assert_eq!( - vec![ - Some("(StorageKey, Option)"), - Some("StorageKey"), - Some("Option"), - ], - caps.iter() - .filter(|c| c.is_some()) - .collect::>>() - ); - } - - #[test] - fn should_correctly_indicate_type() { - assert_eq!( - RegexSet::get_type("[ u8; 32 ]"), - Some(RegexSet::ArrayPrimitive) - ); - assert_eq!(RegexSet::get_type("Vec"), Some(RegexSet::Vec)); - assert_eq!(RegexSet::get_type("Option"), Some(RegexSet::Option)); - assert_eq!(RegexSet::get_type("Compact"), Some(RegexSet::Compact)); - assert_eq!( - RegexSet::get_type("(StorageKey, Foo)"), - Some(RegexSet::Tuple) - ); - - assert_eq!(RegexSet::get_type("Vec>"), Some(RegexSet::Vec)); - assert_eq!( - RegexSet::get_type("Option>"), - Some(RegexSet::Option) - ); - } - - #[test] - fn should_parse_type() { - assert_eq!(parse("u8").unwrap(), RustTypeMarker::U8); - assert_eq!(parse("u16").unwrap(), RustTypeMarker::U16); - assert_eq!(parse("u32").unwrap(), RustTypeMarker::U32); - assert_eq!(parse("u64").unwrap(), RustTypeMarker::U64); - assert_eq!(parse("u128").unwrap(), RustTypeMarker::U128); - assert_eq!(parse("usize").unwrap(), RustTypeMarker::USize); - - assert_eq!(parse("i8").unwrap(), RustTypeMarker::I8); - assert_eq!(parse("i16").unwrap(), RustTypeMarker::I16); - assert_eq!(parse("i32").unwrap(), RustTypeMarker::I32); - assert_eq!(parse("i64").unwrap(), RustTypeMarker::I64); - assert_eq!(parse("i128").unwrap(), RustTypeMarker::I128); - assert_eq!(parse("isize").unwrap(), RustTypeMarker::ISize); - - assert_eq!(parse("f32").unwrap(), RustTypeMarker::F32); - assert_eq!(parse("f64").unwrap(), RustTypeMarker::F64); - - assert_eq!(parse("bool").unwrap(), RustTypeMarker::Bool); - assert_eq!(parse("Null").unwrap(), RustTypeMarker::Null); - - assert_eq!( - parse("Option").unwrap(), - RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::TypePointer( - "Foo".to_string() - )))) - ); - assert_eq!( - parse("Compact>>").unwrap(), - RustTypeMarker::Std(CommonTypes::Compact(Box::new(RustTypeMarker::Std( - CommonTypes::Vec(Box::new(RustTypeMarker::Std(CommonTypes::Option( - Box::new(RustTypeMarker::TypePointer("Foo".to_string())) - )))) - )))) - ); - - assert_eq!( - parse("Compact>").unwrap(), - RustTypeMarker::Std(CommonTypes::Compact(Box::new(RustTypeMarker::Std( - CommonTypes::Vec(Box::new(RustTypeMarker::Tuple(vec![ - RustTypeMarker::TypePointer("Foo".to_string()), - RustTypeMarker::TypePointer("Bar".to_string()), - RustTypeMarker::U8, - ]))) - )))) - ); - - assert_eq!( - parse("Option>").unwrap(), - RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::Std( - CommonTypes::Vec(Box::new(RustTypeMarker::Tuple(vec![ - RustTypeMarker::TypePointer("Foo".to_string()), - RustTypeMarker::TypePointer("Bar".to_string()), - RustTypeMarker::U8, - ]))) - )))) - ); - - assert_eq!( - parse("Vec>").unwrap(), - RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::Std( - CommonTypes::Vec(Box::new(RustTypeMarker::Tuple(vec![ - RustTypeMarker::TypePointer("Foo".to_string()), - RustTypeMarker::TypePointer("Bar".to_string()), - RustTypeMarker::TypePointer("T::SystemMarker".to_string()), - ]))) - )))) - ); - - assert_eq!( - parse("[Vec; 10]").unwrap(), - RustTypeMarker::Array { - size: 10, - ty: Box::new(RustTypeMarker::Std(CommonTypes::Vec(Box::new( - RustTypeMarker::U8 - )))) - } - ); - } - - #[test] - fn should_remove_prefix() { - assert_eq!(remove_prefix("T::Moment").unwrap(), "Moment"); - assert_eq!( - remove_prefix("T::Generic").unwrap(), - "Generic" - ); - } - - #[test] - fn should_parse_box() { - assert_eq!( - parse("Box").unwrap(), - RustTypeMarker::TypePointer("T::Proposal".to_string()) - ) - } - - #[test] - fn should_parse_vec_of_tuples() { - pretty_env_logger::try_init(); - let ty = "Vec<(NominatorIndexCompact, CompactScoreCompact, ValidatorIndexCompact)>"; - assert_eq!( - parse_vec(ty).unwrap(), - RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::Tuple(vec![ - RustTypeMarker::TypePointer("NominatorIndexCompact".into()), - RustTypeMarker::TypePointer("CompactScoreCompact".into()), - RustTypeMarker::TypePointer("ValidatorIndexCompact".into()) - ])))) - ); - let ty = "Vec<(NominatorIndexCompact, [CompactScoreCompact; 2], ValidatorIndexCompact)>"; - let res = parse_vec(ty).unwrap(); - log::debug!("{:?}", res); - } + .join("") + .as_str() + )); + } + + #[test] + fn should_not_overflow_retry_limit() { + let re = rust_tuple_decl(); + let tuple = "(ParaId, Option<(CollatorId, Retriable)>)"; + assert!(re.is_match(tuple)) + } + + #[test] + fn should_get_types_in_tuple() { + let re = rust_tuple_decl(); + let match_str = "(StorageKey, Option)"; + let caps = re.captures(match_str).unwrap(); + assert_eq!( + vec![Some("(StorageKey, Option)"), Some("StorageKey"), Some("Option"),], + caps.iter().filter(|c| c.is_some()).collect::>>() + ); + } + + #[test] + fn should_correctly_indicate_type() { + assert_eq!(RegexSet::get_type("[ u8; 32 ]"), Some(RegexSet::ArrayPrimitive)); + assert_eq!(RegexSet::get_type("Vec"), Some(RegexSet::Vec)); + assert_eq!(RegexSet::get_type("Option"), Some(RegexSet::Option)); + assert_eq!(RegexSet::get_type("Compact"), Some(RegexSet::Compact)); + assert_eq!(RegexSet::get_type("(StorageKey, Foo)"), Some(RegexSet::Tuple)); + + assert_eq!(RegexSet::get_type("Vec>"), Some(RegexSet::Vec)); + assert_eq!(RegexSet::get_type("Option>"), Some(RegexSet::Option)); + } + + #[test] + fn should_parse_type() { + assert_eq!(parse("u8").unwrap(), RustTypeMarker::U8); + assert_eq!(parse("u16").unwrap(), RustTypeMarker::U16); + assert_eq!(parse("u32").unwrap(), RustTypeMarker::U32); + assert_eq!(parse("u64").unwrap(), RustTypeMarker::U64); + assert_eq!(parse("u128").unwrap(), RustTypeMarker::U128); + assert_eq!(parse("usize").unwrap(), RustTypeMarker::USize); + + assert_eq!(parse("i8").unwrap(), RustTypeMarker::I8); + assert_eq!(parse("i16").unwrap(), RustTypeMarker::I16); + assert_eq!(parse("i32").unwrap(), RustTypeMarker::I32); + assert_eq!(parse("i64").unwrap(), RustTypeMarker::I64); + assert_eq!(parse("i128").unwrap(), RustTypeMarker::I128); + assert_eq!(parse("isize").unwrap(), RustTypeMarker::ISize); + + assert_eq!(parse("f32").unwrap(), RustTypeMarker::F32); + assert_eq!(parse("f64").unwrap(), RustTypeMarker::F64); + + assert_eq!(parse("bool").unwrap(), RustTypeMarker::Bool); + assert_eq!(parse("Null").unwrap(), RustTypeMarker::Null); + + assert_eq!( + parse("Option").unwrap(), + RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::TypePointer("Foo".to_string())))) + ); + assert_eq!( + parse("Compact>>").unwrap(), + RustTypeMarker::Std(CommonTypes::Compact(Box::new(RustTypeMarker::Std(CommonTypes::Vec(Box::new( + RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::TypePointer("Foo".to_string())))) + )))))) + ); + + assert_eq!( + parse("Compact>").unwrap(), + RustTypeMarker::Std(CommonTypes::Compact(Box::new(RustTypeMarker::Std(CommonTypes::Vec(Box::new( + RustTypeMarker::Tuple(vec![ + RustTypeMarker::TypePointer("Foo".to_string()), + RustTypeMarker::TypePointer("Bar".to_string()), + RustTypeMarker::U8, + ]) + )))))) + ); + + assert_eq!( + parse("Option>").unwrap(), + RustTypeMarker::Std(CommonTypes::Option(Box::new(RustTypeMarker::Std(CommonTypes::Vec(Box::new( + RustTypeMarker::Tuple(vec![ + RustTypeMarker::TypePointer("Foo".to_string()), + RustTypeMarker::TypePointer("Bar".to_string()), + RustTypeMarker::U8, + ]) + )))))) + ); + + assert_eq!( + parse("Vec>").unwrap(), + RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::Std(CommonTypes::Vec(Box::new( + RustTypeMarker::Tuple(vec![ + RustTypeMarker::TypePointer("Foo".to_string()), + RustTypeMarker::TypePointer("Bar".to_string()), + RustTypeMarker::TypePointer("T::SystemMarker".to_string()), + ]) + )))))) + ); + + assert_eq!( + parse("[Vec; 10]").unwrap(), + RustTypeMarker::Array { + size: 10, + ty: Box::new(RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::U8)))) + } + ); + } + + #[test] + fn should_remove_prefix() { + assert_eq!(remove_prefix("T::Moment").unwrap(), "Moment"); + assert_eq!(remove_prefix("T::Generic").unwrap(), "Generic"); + } + + #[test] + fn should_parse_box() { + assert_eq!(parse("Box").unwrap(), RustTypeMarker::TypePointer("T::Proposal".to_string())) + } + + #[test] + fn should_parse_vec_of_tuples() { + pretty_env_logger::try_init(); + let ty = "Vec<(NominatorIndexCompact, CompactScoreCompact, ValidatorIndexCompact)>"; + assert_eq!( + parse_vec(ty).unwrap(), + RustTypeMarker::Std(CommonTypes::Vec(Box::new(RustTypeMarker::Tuple(vec![ + RustTypeMarker::TypePointer("NominatorIndexCompact".into()), + RustTypeMarker::TypePointer("CompactScoreCompact".into()), + RustTypeMarker::TypePointer("ValidatorIndexCompact".into()) + ])))) + ); + let ty = "Vec<(NominatorIndexCompact, [CompactScoreCompact; 2], ValidatorIndexCompact)>"; + let res = parse_vec(ty).unwrap(); + log::debug!("{:?}", res); + } } diff --git a/core/src/substrate_types.rs b/core/src/substrate_types.rs index 39962b36..b172a1f5 100644 --- a/core/src/substrate_types.rs +++ b/core/src/substrate_types.rs @@ -39,207 +39,200 @@ pub type Data = pallet_identity::Data; #[derive(Debug, PartialEq, Clone, Serialize)] #[serde(untagged)] pub enum SubstrateType { - /// 512-bit hash type - H512(primitives::H512), - /// 256-bit hash type - H256(primitives::H256), - - /// Recursive Call Type - Call(Vec<(String, SubstrateType)>), - /// Era - Era(runtime_primitives::generic::Era), - - /// Vote - #[serde(with = "RemoteVote")] - GenericVote(pallet_democracy::Vote), - - /// Substrate Indices Address Type - // TODO: this is not generic for any chain that doesn't use a - // u32 and [u8; 32] for its index/id - #[serde(with = "RemoteAddress")] - Address(Address), - - #[serde(with = "RemoteData")] - Data(Data), - - /// SignedExtension Type - SignedExtra(String), - - /// vectors, arrays, and tuples - #[serde(serialize_with = "crate::util::as_hex")] - Composite(Vec), - - /// C-Like Enum Type - Set(SetField), - /// Enum - Enum(StructUnitOrTuple), - /// Struct Type - Struct(Vec), - /// Option Type - Option(Box>), - /// Result Type - Result(Box>), - - // Std - /// The unsigned 8-bit type - U8(u8), - /// unsigned 16-bit type - U16(u16), - /// unsigned 32-bit type - U32(u32), - /// unsigned 64-bit type - U64(u64), - /// unsigned 128-bit type - U128(u128), - /// unsigned cpu word-size type - USize(usize), - /// signed 8-bit type - I8(i8), - /// signed 16-bit type - I16(i16), - /// signed 32-bit type - I32(i32), - /// signed 64-bit type - I64(i64), - /// signed 128-bit type - I128(i128), - /// signed word-sized type - ISize(isize), - /// floating-point 32-bit type (not supported by SCALE) - F32(f32), - /// floating-point 64-bit type (not supported by SCALE) - F64(f64), - - /// boolean type - Bool(bool), - // not sure what to do with this yet - // may get rid of it - Null, + /// 512-bit hash type + H512(primitives::H512), + /// 256-bit hash type + H256(primitives::H256), + + /// Recursive Call Type + Call(Vec<(String, SubstrateType)>), + /// Era + Era(runtime_primitives::generic::Era), + + /// Vote + #[serde(with = "RemoteVote")] + GenericVote(pallet_democracy::Vote), + + /// Substrate Indices Address Type + // TODO: this is not generic for any chain that doesn't use a + // u32 and [u8; 32] for its index/id + #[serde(with = "RemoteAddress")] + Address(Address), + + #[serde(with = "RemoteData")] + Data(Data), + + /// SignedExtension Type + SignedExtra(String), + + /// vectors, arrays, and tuples + #[serde(serialize_with = "crate::util::as_hex")] + Composite(Vec), + + /// C-Like Enum Type + Set(SetField), + /// Enum + Enum(StructUnitOrTuple), + /// Struct Type + Struct(Vec), + /// Option Type + Option(Box>), + /// Result Type + Result(Box>), + + // Std + /// The unsigned 8-bit type + U8(u8), + /// unsigned 16-bit type + U16(u16), + /// unsigned 32-bit type + U32(u32), + /// unsigned 64-bit type + U64(u64), + /// unsigned 128-bit type + U128(u128), + /// unsigned cpu word-size type + USize(usize), + /// signed 8-bit type + I8(i8), + /// signed 16-bit type + I16(i16), + /// signed 32-bit type + I32(i32), + /// signed 64-bit type + I64(i64), + /// signed 128-bit type + I128(i128), + /// signed word-sized type + ISize(isize), + /// floating-point 32-bit type (not supported by SCALE) + F32(f32), + /// floating-point 64-bit type (not supported by SCALE) + F64(f64), + + /// boolean type + Bool(bool), + // not sure what to do with this yet + // may get rid of it + Null, } impl fmt::Display for SubstrateType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - SubstrateType::H512(v) => write!(f, "{}", v), - SubstrateType::H256(v) => write!(f, "{}", v), - SubstrateType::Call(c) => { - write!(f, "CALL")?; - for arg in c.iter() { - write!(f, "{}: {}", arg.0, arg.1)?; - } - Ok(()) - } - SubstrateType::Era(v) => match v { - runtime_primitives::generic::Era::Mortal(s, e) => write!(f, " Era {}..{}", s, e), - runtime_primitives::generic::Era::Immortal => write!(f, " Immortal Era"), - }, - SubstrateType::GenericVote(v) => write!( - f, - "Aye={}, Conviction={}", - v.aye, - v.conviction.lock_periods() - ), - SubstrateType::Address(v) => match v { - pallet_indices::address::Address::Id(ref i) => write!( - f, - "Account::Id({})", - i.to_ss58check_with_version(Ss58AddressFormat::SubstrateAccount) - ), - pallet_indices::address::Address::Index(i) => write!(f, "Index: {:?}", i), - }, - SubstrateType::Data(d) => write!(f, "{:?}", d), - SubstrateType::SignedExtra(v) => write!(f, "{}", v), - SubstrateType::Composite(v) => { - let mut s = String::from(""); - for v in v.iter() { - s.push_str(&format!("{}", v)) - } - write!(f, "{}", s) - } - SubstrateType::Set(v) => write!(f, "{}", v), - SubstrateType::Enum(v) => write!(f, "{}", v), - SubstrateType::Struct(v) => { - let mut s = String::from(""); - for val in v.iter() { - s.push_str(&format!("{}", val)) - } - write!(f, "{}", s) - } - SubstrateType::Option(v) => write!(f, "{:?}", v), - SubstrateType::Result(v) => write!(f, "{:?}", v), - SubstrateType::U8(v) => { - write!(f, "{:X}", v) // u8's print in hex format - } - SubstrateType::U16(v) => write!(f, "{}", v), - SubstrateType::U32(v) => write!(f, "{}", v), - SubstrateType::U64(v) => write!(f, "{}", v), - SubstrateType::U128(v) => write!(f, "{}", v), - SubstrateType::USize(v) => write!(f, "{}", v), - SubstrateType::I8(v) => write!(f, "{}", v), - SubstrateType::I16(v) => write!(f, "{}", v), - SubstrateType::I32(v) => write!(f, "{}", v), - SubstrateType::I64(v) => write!(f, "{}", v), - SubstrateType::I128(v) => write!(f, "{}", v), - SubstrateType::ISize(v) => write!(f, "{}", v), - SubstrateType::F32(v) => write!(f, "{}", v), - SubstrateType::F64(v) => write!(f, "{}", v), - SubstrateType::Bool(v) => write!(f, "{}", v), - SubstrateType::Null => write!(f, "Null"), - } - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SubstrateType::H512(v) => write!(f, "{}", v), + SubstrateType::H256(v) => write!(f, "{}", v), + SubstrateType::Call(c) => { + write!(f, "CALL")?; + for arg in c.iter() { + write!(f, "{}: {}", arg.0, arg.1)?; + } + Ok(()) + } + SubstrateType::Era(v) => match v { + runtime_primitives::generic::Era::Mortal(s, e) => write!(f, " Era {}..{}", s, e), + runtime_primitives::generic::Era::Immortal => write!(f, " Immortal Era"), + }, + SubstrateType::GenericVote(v) => write!(f, "Aye={}, Conviction={}", v.aye, v.conviction.lock_periods()), + SubstrateType::Address(v) => match v { + pallet_indices::address::Address::Id(ref i) => { + write!(f, "Account::Id({})", i.to_ss58check_with_version(Ss58AddressFormat::SubstrateAccount)) + } + pallet_indices::address::Address::Index(i) => write!(f, "Index: {:?}", i), + }, + SubstrateType::Data(d) => write!(f, "{:?}", d), + SubstrateType::SignedExtra(v) => write!(f, "{}", v), + SubstrateType::Composite(v) => { + let mut s = String::from(""); + for v in v.iter() { + s.push_str(&format!("{}", v)) + } + write!(f, "{}", s) + } + SubstrateType::Set(v) => write!(f, "{}", v), + SubstrateType::Enum(v) => write!(f, "{}", v), + SubstrateType::Struct(v) => { + let mut s = String::from(""); + for val in v.iter() { + s.push_str(&format!("{}", val)) + } + write!(f, "{}", s) + } + SubstrateType::Option(v) => write!(f, "{:?}", v), + SubstrateType::Result(v) => write!(f, "{:?}", v), + SubstrateType::U8(v) => { + write!(f, "{:X}", v) // u8's print in hex format + } + SubstrateType::U16(v) => write!(f, "{}", v), + SubstrateType::U32(v) => write!(f, "{}", v), + SubstrateType::U64(v) => write!(f, "{}", v), + SubstrateType::U128(v) => write!(f, "{}", v), + SubstrateType::USize(v) => write!(f, "{}", v), + SubstrateType::I8(v) => write!(f, "{}", v), + SubstrateType::I16(v) => write!(f, "{}", v), + SubstrateType::I32(v) => write!(f, "{}", v), + SubstrateType::I64(v) => write!(f, "{}", v), + SubstrateType::I128(v) => write!(f, "{}", v), + SubstrateType::ISize(v) => write!(f, "{}", v), + SubstrateType::F32(v) => write!(f, "{}", v), + SubstrateType::F64(v) => write!(f, "{}", v), + SubstrateType::Bool(v) => write!(f, "{}", v), + SubstrateType::Null => write!(f, "Null"), + } + } } #[derive(Debug, PartialEq, Clone, Serialize)] #[serde(untagged)] pub enum StructUnitOrTuple { - Struct(Vec), - Unit(String), - /// vector of variant name -> type - Tuple { - name: String, - ty: Box, - }, + Struct(Vec), + Unit(String), + /// vector of variant name -> type + Tuple { + name: String, + ty: Box, + }, } impl fmt::Display for StructUnitOrTuple { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut _enum = String::from(" tuple[ "); - match self { - Self::Struct(v) => { - for val in v.iter() { - _enum.push_str(&format!("{}, ", val)) - } - } - Self::Unit(v) => _enum.push_str(&format!("{}, ", v)), - Self::Tuple { name, ty } => _enum.push_str(&format!(" {}:{} ", name, ty.to_string())), - } - _enum.push_str(" ]"); - write!(f, "{}", _enum) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut _enum = String::from(" tuple[ "); + match self { + Self::Struct(v) => { + for val in v.iter() { + _enum.push_str(&format!("{}, ", val)) + } + } + Self::Unit(v) => _enum.push_str(&format!("{}, ", v)), + Self::Tuple { name, ty } => _enum.push_str(&format!(" {}:{} ", name, ty.to_string())), + } + _enum.push_str(" ]"); + write!(f, "{}", _enum) + } } /// Type with an associated name #[derive(Debug, PartialEq, Clone, Serialize)] pub struct StructField { - /// name of a field, if any - /// this is an option, because IE a Tuple-enum Variant - /// will not have named fields - pub name: Option, - /// Type of field - pub ty: SubstrateType, + /// name of a field, if any + /// this is an option, because IE a Tuple-enum Variant + /// will not have named fields + pub name: Option, + /// Type of field + pub ty: SubstrateType, } impl StructField { - pub fn new>(name: Option, ty: SubstrateType) -> Self { - let name: Option = name.map(|s| s.into()); - Self { name, ty } - } + pub fn new>(name: Option, ty: SubstrateType) -> Self { + let name: Option = name.map(|s| s.into()); + Self { name, ty } + } } impl fmt::Display for StructField { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "struct_field( {:?}: {} )", self.name, self.ty) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "struct_field( {:?}: {} )", self.name, self.ty) + } } // ============================================ @@ -247,116 +240,113 @@ impl fmt::Display for StructField { // ============================================ impl TryFrom<&SubstrateType> for Vec { - type Error = Error; - fn try_from(ty: &SubstrateType) -> Result, Error> { - match ty { - SubstrateType::Composite(elements) => { - if elements - .iter() - .any(|ty| !matches!(ty, SubstrateType::U8(_))) - { - Err(Error::Conversion(format!("{:?}", ty), "u8".to_string())) - } else { - Ok(elements - .iter() - .map(|v| match v { - SubstrateType::U8(byte) => *byte, - _ => unreachable!(), - }) - .collect::>()) - } - } - _ => Err(Error::Conversion(format!("{}", ty), "Vec".to_string())), - } - } + type Error = Error; + fn try_from(ty: &SubstrateType) -> Result, Error> { + match ty { + SubstrateType::Composite(elements) => { + if elements.iter().any(|ty| !matches!(ty, SubstrateType::U8(_))) { + Err(Error::Conversion(format!("{:?}", ty), "u8".to_string())) + } else { + Ok(elements + .iter() + .map(|v| match v { + SubstrateType::U8(byte) => *byte, + _ => unreachable!(), + }) + .collect::>()) + } + } + _ => Err(Error::Conversion(format!("{}", ty), "Vec".to_string())), + } + } } impl From for SubstrateType { - fn from(num: u8) -> SubstrateType { - SubstrateType::U8(num) - } + fn from(num: u8) -> SubstrateType { + SubstrateType::U8(num) + } } impl From for SubstrateType { - fn from(num: u16) -> SubstrateType { - SubstrateType::U16(num) - } + fn from(num: u16) -> SubstrateType { + SubstrateType::U16(num) + } } impl From for SubstrateType { - fn from(num: u32) -> SubstrateType { - SubstrateType::U32(num) - } + fn from(num: u32) -> SubstrateType { + SubstrateType::U32(num) + } } impl From for SubstrateType { - fn from(num: u64) -> SubstrateType { - SubstrateType::U64(num) - } + fn from(num: u64) -> SubstrateType { + SubstrateType::U64(num) + } } impl From for SubstrateType { - fn from(num: u128) -> SubstrateType { - SubstrateType::U128(num) - } + fn from(num: u128) -> SubstrateType { + SubstrateType::U128(num) + } } impl From for SubstrateType { - fn from(num: usize) -> SubstrateType { - SubstrateType::USize(num) - } + fn from(num: usize) -> SubstrateType { + SubstrateType::USize(num) + } } impl From for SubstrateType { - fn from(num: i8) -> SubstrateType { - SubstrateType::I8(num) - } + fn from(num: i8) -> SubstrateType { + SubstrateType::I8(num) + } } impl From for SubstrateType { - fn from(num: i16) -> SubstrateType { - SubstrateType::I16(num) - } + fn from(num: i16) -> SubstrateType { + SubstrateType::I16(num) + } } impl From for SubstrateType { - fn from(num: i32) -> SubstrateType { - SubstrateType::I32(num) - } + fn from(num: i32) -> SubstrateType { + SubstrateType::I32(num) + } } impl From for SubstrateType { - fn from(num: i64) -> SubstrateType { - SubstrateType::I64(num) - } + fn from(num: i64) -> SubstrateType { + SubstrateType::I64(num) + } } impl From for SubstrateType { - fn from(num: i128) -> SubstrateType { - SubstrateType::I128(num) - } + fn from(num: i128) -> SubstrateType { + SubstrateType::I128(num) + } } impl From for SubstrateType { - fn from(num: isize) -> SubstrateType { - SubstrateType::ISize(num) - } + fn from(num: isize) -> SubstrateType { + SubstrateType::ISize(num) + } } impl From for SubstrateType { - fn from(num: f32) -> SubstrateType { - SubstrateType::F32(num) - } + fn from(num: f32) -> SubstrateType { + SubstrateType::F32(num) + } } impl From for SubstrateType { - fn from(num: f64) -> SubstrateType { - SubstrateType::F64(num) - } + fn from(num: f64) -> SubstrateType { + SubstrateType::F64(num) + } } impl From for SubstrateType { - fn from(val: bool) -> SubstrateType { - SubstrateType::Bool(val) - } + fn from(val: bool) -> SubstrateType { + SubstrateType::Bool(val) + } } diff --git a/core/src/substrate_types/remote.rs b/core/src/substrate_types/remote.rs index 307f9bc6..6583e3d0 100644 --- a/core/src/substrate_types/remote.rs +++ b/core/src/substrate_types/remote.rs @@ -22,16 +22,16 @@ use super::{Address, Conviction, Data, Vote}; #[derive(Serialize, Deserialize)] #[serde(remote = "Address")] pub enum RemoteAddress { - Id(AccountId32), - Index(u32), + Id(AccountId32), + Index(u32), } #[derive(Serialize, Deserialize)] #[serde(remote = "Vote")] pub struct RemoteVote { - pub aye: bool, - #[serde(with = "RemoteConviction")] - pub conviction: Conviction, + pub aye: bool, + #[serde(with = "RemoteConviction")] + pub conviction: Conviction, } /// Either underlying data blob if it is at most 32 bytes, or a hash of it. If the data is greater @@ -41,39 +41,39 @@ pub struct RemoteVote { #[derive(Serialize, Deserialize)] #[serde(remote = "Data")] pub enum RemoteData { - /// No data here. - None, - /// The data is stored directly. - Raw(Vec), - /// Only the Blake2 hash of the data is stored. The preimage of the hash may be retrieved - /// through some hash-lookup service. - BlakeTwo256([u8; 32]), - /// Only the SHA2-256 hash of the data is stored. The preimage of the hash may be retrieved - /// through some hash-lookup service. - Sha256([u8; 32]), - /// Only the Keccak-256 hash of the data is stored. The preimage of the hash may be retrieved - /// through some hash-lookup service. - Keccak256([u8; 32]), - /// Only the SHA3-256 hash of the data is stored. The preimage of the hash may be retrieved - /// through some hash-lookup service. - ShaThree256([u8; 32]), + /// No data here. + None, + /// The data is stored directly. + Raw(Vec), + /// Only the Blake2 hash of the data is stored. The preimage of the hash may be retrieved + /// through some hash-lookup service. + BlakeTwo256([u8; 32]), + /// Only the SHA2-256 hash of the data is stored. The preimage of the hash may be retrieved + /// through some hash-lookup service. + Sha256([u8; 32]), + /// Only the Keccak-256 hash of the data is stored. The preimage of the hash may be retrieved + /// through some hash-lookup service. + Keccak256([u8; 32]), + /// Only the SHA3-256 hash of the data is stored. The preimage of the hash may be retrieved + /// through some hash-lookup service. + ShaThree256([u8; 32]), } #[derive(Serialize, Deserialize)] #[serde(remote = "Conviction")] pub enum RemoteConviction { - /// 0.1x votes, unlocked. - None, - /// 1x votes, locked for an enactment period following a successful vote. - Locked1x, - /// 2x votes, locked for 2x enactment periods following a successful vote. - Locked2x, - /// 3x votes, locked for 4x... - Locked3x, - /// 4x votes, locked for 8x... - Locked4x, - /// 5x votes, locked for 16x... - Locked5x, - /// 6x votes, locked for 32x... - Locked6x, + /// 0.1x votes, unlocked. + None, + /// 1x votes, locked for an enactment period following a successful vote. + Locked1x, + /// 2x votes, locked for 2x enactment periods following a successful vote. + Locked2x, + /// 3x votes, locked for 4x... + Locked3x, + /// 4x votes, locked for 8x... + Locked4x, + /// 5x votes, locked for 16x... + Locked5x, + /// 6x votes, locked for 32x... + Locked6x, } diff --git a/core/src/test_suite.rs b/core/src/test_suite.rs index c911ea05..7bf2fea3 100644 --- a/core/src/test_suite.rs +++ b/core/src/test_suite.rs @@ -18,13 +18,13 @@ use runtime_version::RuntimeVersion; use std::borrow::Cow; pub fn mock_runtime(num: u32) -> RuntimeVersion { - RuntimeVersion { - spec_name: "test-runtime".into(), - impl_name: "test-runtime-impl".into(), - authoring_version: num, - spec_version: num, - impl_version: num, - apis: Cow::from(Vec::new()), - transaction_version: 4, - } + RuntimeVersion { + spec_name: "test-runtime".into(), + impl_name: "test-runtime-impl".into(), + authoring_version: num, + spec_version: num, + impl_version: num, + apis: Cow::from(Vec::new()), + transaction_version: 4, + } } diff --git a/core/src/util.rs b/core/src/util.rs index 2beadff3..32e4e48f 100644 --- a/core/src/util.rs +++ b/core/src/util.rs @@ -16,74 +16,59 @@ use crate::{Error, SubstrateType}; use primitives::crypto::{Ss58AddressFormat, Ss58Codec}; use serde::{ - ser::{self, SerializeSeq}, - Serializer, + ser::{self, SerializeSeq}, + Serializer, }; use std::convert::TryFrom; // Utility function to serialize from slice/vec to hex // If the SubstrateType is a collection of u8s, will serialize as hex -pub fn as_hex( - elements: &[SubstrateType], - serializer: S, -) -> Result { - if elements - .iter() - .any(|ty| !matches!(ty, SubstrateType::U8(_))) - { - let mut seq = serializer.serialize_seq(Some(elements.len()))?; - for e in elements.iter() { - seq.serialize_element(&e)?; - } - seq.end() - } else { - let bytes = elements - .iter() - .map(|v| match v { - SubstrateType::U8(byte) => *byte, - _ => unreachable!(), - }) - .collect::>(); - let mut hex_str = String::from("0x"); - hex_str.push_str(&hex::encode(bytes.as_slice())); - serializer.serialize_str(&hex_str) - } +pub fn as_hex(elements: &[SubstrateType], serializer: S) -> Result { + if elements.iter().any(|ty| !matches!(ty, SubstrateType::U8(_))) { + let mut seq = serializer.serialize_seq(Some(elements.len()))?; + for e in elements.iter() { + seq.serialize_element(&e)?; + } + seq.end() + } else { + let bytes = elements + .iter() + .map(|v| match v { + SubstrateType::U8(byte) => *byte, + _ => unreachable!(), + }) + .collect::>(); + let mut hex_str = String::from("0x"); + hex_str.push_str(&hex::encode(bytes.as_slice())); + serializer.serialize_str(&hex_str) + } } /// Serialize a Substrate Type as a ss58 Address /// # Panics /// Panics if a SubstrateType can not be serialized into an ss58 address type -pub fn as_substrate_address( - ty: &SubstrateType, - serializer: S, -) -> Result { - match ty { - SubstrateType::Composite(_) => { - let bytes: Vec = TryFrom::try_from(ty) - .map_err(|err: Error| ser::Error::custom(err.to_string()))?; - if bytes.len() != 32 { - return Err(ser::Error::custom("address length is incorrect".to_string())); - } - let mut addr: [u8; 32] = Default::default(); - for (i, b) in bytes.into_iter().enumerate() { - addr[i] = b; - } - let addr = primitives::crypto::AccountId32::from(addr) - .to_ss58check_with_version(Ss58AddressFormat::SubstrateAccount); - serializer.serialize_str(&addr) - } - SubstrateType::Address(v) => match v { - pallet_indices::address::Address::Id(ref i) => { - let addr = i.to_ss58check_with_version(Ss58AddressFormat::SubstrateAccount); - serializer.serialize_str(&addr) - } - pallet_indices::address::Address::Index(i) => { - serializer.serialize_str(&format!("{}", i)) - } - }, - _ => Err(ser::Error::custom(format!( - "Could not format {:?} as Ss58 Address", - ty - ))), - } +pub fn as_substrate_address(ty: &SubstrateType, serializer: S) -> Result { + match ty { + SubstrateType::Composite(_) => { + let bytes: Vec = TryFrom::try_from(ty).map_err(|err: Error| ser::Error::custom(err.to_string()))?; + if bytes.len() != 32 { + return Err(ser::Error::custom("address length is incorrect".to_string())); + } + let mut addr: [u8; 32] = Default::default(); + for (i, b) in bytes.into_iter().enumerate() { + addr[i] = b; + } + let addr = primitives::crypto::AccountId32::from(addr) + .to_ss58check_with_version(Ss58AddressFormat::SubstrateAccount); + serializer.serialize_str(&addr) + } + SubstrateType::Address(v) => match v { + pallet_indices::address::Address::Id(ref i) => { + let addr = i.to_ss58check_with_version(Ss58AddressFormat::SubstrateAccount); + serializer.serialize_str(&addr) + } + pallet_indices::address::Address::Index(i) => serializer.serialize_str(&format!("{}", i)), + }, + _ => Err(ser::Error::custom(format!("Could not format {:?} as Ss58 Address", ty))), + } } diff --git a/extras/src/error.rs b/extras/src/error.rs index 8441108f..eec71c15 100644 --- a/extras/src/error.rs +++ b/extras/src/error.rs @@ -20,8 +20,8 @@ pub type Result = std::result::Result; #[derive(Debug, Error)] pub enum Error { - #[error("Decode {0}")] - Decode(#[from] serde_json::Error), - #[error("{0} Not Found")] - NotFound(String), + #[error("Decode {0}")] + Decode(#[from] serde_json::Error), + #[error("{0} Not Found")] + NotFound(String), } diff --git a/extras/src/extrinsics.rs b/extras/src/extrinsics.rs index 5a27da38..52673f45 100644 --- a/extras/src/extrinsics.rs +++ b/extras/src/extrinsics.rs @@ -19,41 +19,33 @@ use std::collections::HashMap; #[derive(Debug, Serialize, Deserialize, Default, Eq, PartialEq, Clone)] pub struct Extrinsics { - default: ModuleTypes, - #[serde(flatten)] - overrides: HashMap>, + default: ModuleTypes, + #[serde(flatten)] + overrides: HashMap>, } impl Extrinsics { - pub fn new(raw_json: &str) -> Result { - serde_json::from_str(raw_json).map_err(Into::into) - } + pub fn new(raw_json: &str) -> Result { + serde_json::from_str(raw_json).map_err(Into::into) + } - pub fn get_chain_types(&self, chain: &str, spec: u32) -> Option<&ModuleTypes> { - self.overrides - .get(chain)? - .iter() - .find(|f| crate::is_in_range(spec, f)) - .map(|o| &o.types) - } + pub fn get_chain_types(&self, chain: &str, spec: u32) -> Option<&ModuleTypes> { + self.overrides.get(chain)?.iter().find(|f| crate::is_in_range(spec, f)).map(|o| &o.types) + } - pub fn get(&self, ty: &str, spec: u32, chain: &str) -> Option<&core::RustTypeMarker> { - if let Some(ty) = self - .get_chain_types(chain, spec) - .map(|c| c.get(ty)) - .flatten() - { - Some(ty) - } else { - self.default.get(ty) - } - } + pub fn get(&self, ty: &str, spec: u32, chain: &str) -> Option<&core::RustTypeMarker> { + if let Some(ty) = self.get_chain_types(chain, spec).map(|c| c.get(ty)).flatten() { + Some(ty) + } else { + self.default.get(ty) + } + } } #[cfg(test)] mod tests { - use super::*; - const TEST_STR: &str = r#" + use super::*; + const TEST_STR: &str = r#" { "default": { "Foo": "H256" @@ -72,8 +64,8 @@ mod tests { } "#; - #[test] - fn should_deserialize_extrinsics() { - let extrinsics: Extrinsics = Extrinsics::new(TEST_STR).unwrap(); - } + #[test] + fn should_deserialize_extrinsics() { + let extrinsics: Extrinsics = Extrinsics::new(TEST_STR).unwrap(); + } } diff --git a/extras/src/lib.rs b/extras/src/lib.rs index 2c813624..74c07fbf 100644 --- a/extras/src/lib.rs +++ b/extras/src/lib.rs @@ -17,22 +17,22 @@ use serde::{Deserialize, Serialize}; /// An overrides for a range of runtime versions #[derive(Debug, Serialize, Deserialize, Default, Eq, PartialEq, Clone)] pub struct TypeRange { - /// the spec these overrides are relevant for - #[serde(rename = "minmax")] - min_max: [Option; 2], - /// types that are being overriden - /// points to the types that should be used instead in definitions.json - types: ModuleTypes, + /// the spec these overrides are relevant for + #[serde(rename = "minmax")] + min_max: [Option; 2], + /// types that are being overriden + /// points to the types that should be used instead in definitions.json + types: ModuleTypes, } /// Check if a type is in the range of `TypeRange` fn is_in_range(spec: u32, over_ride: &TypeRange) -> bool { - match over_ride.min_max { - [Some(min), Some(max)] => (min..=max).contains(&(spec as usize)), - [Some(min), None] => (spec as usize) > min, - [None, Some(max)] => (spec as usize) < max, - // presumably, this would be for null -> null, - // so for every spec - [None, None] => true, - } + match over_ride.min_max { + [Some(min), Some(max)] => (min..=max).contains(&(spec as usize)), + [Some(min), None] => (spec as usize) > min, + [None, Some(max)] => (spec as usize) < max, + // presumably, this would be for null -> null, + // so for every spec + [None, None] => true, + } } diff --git a/extras/src/modules.rs b/extras/src/modules.rs index 78f518a8..2c0d5464 100644 --- a/extras/src/modules.rs +++ b/extras/src/modules.rs @@ -15,181 +15,168 @@ use crate::error::Error; use core::{regex, EnumField, RustTypeMarker, SetField, StructField, StructUnitOrTuple}; use serde::{ - de::{Deserializer, MapAccess, Visitor}, - Deserialize, Serialize, + de::{Deserializer, MapAccess, Visitor}, + Deserialize, Serialize, }; use std::{collections::HashMap, fmt}; /// Types for each substrate Module #[derive(Serialize, Default, Debug, PartialEq, Eq, Clone)] pub struct Modules { - /// module name -> Type Map of module - modules: HashMap, + /// module name -> Type Map of module + modules: HashMap, } impl Modules { - /// Construct this struct from JSON - pub fn new(raw_json: &str) -> Result { - let modules: Modules = serde_json::from_str(raw_json)?; - Ok(modules) - } + /// Construct this struct from JSON + pub fn new(raw_json: &str) -> Result { + let modules: Modules = serde_json::from_str(raw_json)?; + Ok(modules) + } - pub fn get(&self, ty: &str) -> Option<&ModuleTypes> { - self.modules.get(ty) - } + pub fn get(&self, ty: &str) -> Option<&ModuleTypes> { + self.modules.get(ty) + } - pub fn get_type(&self, module: &str, ty: &str) -> Option<&RustTypeMarker> { - self.modules.get(module)?.types.get(ty) - } + pub fn get_type(&self, module: &str, ty: &str) -> Option<&RustTypeMarker> { + self.modules.get(module)?.types.get(ty) + } - /// Iterate over all the types in each module - pub fn iter_types(&self) -> impl Iterator { - self.modules.values().map(|v| v.types.iter()).flatten() - } + /// Iterate over all the types in each module + pub fn iter_types(&self) -> impl Iterator { + self.modules.values().map(|v| v.types.iter()).flatten() + } } /// Map of types to their Type Markers #[derive(Serialize, Debug, Default, PartialEq, Eq, Clone)] pub struct ModuleTypes { - /// Type Name -> Type - types: HashMap, + /// Type Name -> Type + types: HashMap, } impl ModuleTypes { - pub fn get(&self, ty: &str) -> Option<&RustTypeMarker> { - self.types.get(ty) - } + pub fn get(&self, ty: &str) -> Option<&RustTypeMarker> { + self.types.get(ty) + } - /// Merges a ModuleTypes struct with another, to create a new HashMap - /// The `other` struct takes priority if there are type conflicts - pub fn merge(&self, other: &ModuleTypes) -> ModuleTypes { - let mut types = self.types.clone(); - let other = other.clone(); - types.extend(other.types.into_iter()); + /// Merges a ModuleTypes struct with another, to create a new HashMap + /// The `other` struct takes priority if there are type conflicts + pub fn merge(&self, other: &ModuleTypes) -> ModuleTypes { + let mut types = self.types.clone(); + let other = other.clone(); + types.extend(other.types.into_iter()); - ModuleTypes { types } - } + ModuleTypes { types } + } } impl<'de> Deserialize<'de> for Modules { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct ModulesVisitor; + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ModulesVisitor; - impl<'de> Visitor<'de> for ModulesVisitor { - type Value = Modules; + impl<'de> Visitor<'de> for ModulesVisitor { + type Value = Modules; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("map types") - } + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("map types") + } - fn visit_map(self, mut map: V) -> Result - where - V: MapAccess<'de>, - { - let mut modules: HashMap = HashMap::new(); - while let Some(key) = map.next_key::<&str>()? { - let val: ModuleTypes = map.next_value()?; - modules.insert(key.to_string(), val); - } - Ok(Modules { modules }) - } - } - deserializer.deserialize_map(ModulesVisitor) - } + fn visit_map(self, mut map: V) -> Result + where + V: MapAccess<'de>, + { + let mut modules: HashMap = HashMap::new(); + while let Some(key) = map.next_key::<&str>()? { + let val: ModuleTypes = map.next_value()?; + modules.insert(key.to_string(), val); + } + Ok(Modules { modules }) + } + } + deserializer.deserialize_map(ModulesVisitor) + } } impl<'de> Deserialize<'de> for ModuleTypes { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_map(ModuleTypeVisitor) - } + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_map(ModuleTypeVisitor) + } } struct ModuleTypeVisitor; impl<'de> Visitor<'de> for ModuleTypeVisitor { - type Value = ModuleTypes; + type Value = ModuleTypes; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("Map or string") - } + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Map or string") + } - fn visit_map(self, mut map: V) -> Result - where - V: MapAccess<'de>, - { - let mut module_types: HashMap = HashMap::new(); + fn visit_map(self, mut map: V) -> Result + where + V: MapAccess<'de>, + { + let mut module_types: HashMap = HashMap::new(); - while let Some(key) = map.next_key::<&str>()? { - match key { - // skip over "types" key, this encapsulates the types we actually care - // about - "types" => { - let val: serde_json::Value = map.next_value()?; - let val = val.as_object().expect("Types must refer to an object"); - for (key, val) in val.iter() { - parse_mod_types(&mut module_types, key, val); - } - } - m => { - let val: serde_json::Value = map.next_value()?; - //let val = val.as_object().expect("Types must refer to an object"); - parse_mod_types(&mut module_types, m, &val); - } - } - } - Ok(ModuleTypes { - types: module_types, - }) - } + while let Some(key) = map.next_key::<&str>()? { + match key { + // skip over "types" key, this encapsulates the types we actually care + // about + "types" => { + let val: serde_json::Value = map.next_value()?; + let val = val.as_object().expect("Types must refer to an object"); + for (key, val) in val.iter() { + parse_mod_types(&mut module_types, key, val); + } + } + m => { + let val: serde_json::Value = map.next_value()?; + //let val = val.as_object().expect("Types must refer to an object"); + parse_mod_types(&mut module_types, m, &val); + } + } + } + Ok(ModuleTypes { types: module_types }) + } } -fn parse_mod_types( - module_types: &mut HashMap, - key: &str, - val: &serde_json::Value, -) { - if val.is_string() { - module_types.insert( - key.to_string(), - regex::parse(val.as_str().expect("Checked; qed")).expect("not a type"), - ); - } else if val.is_object() { - let obj = val - .as_object() - .expect("checked for object before unwrap; qed"); - if obj.contains_key("_enum") { - module_types.insert(key.to_string(), parse_enum(&obj["_enum"])); - } else if obj.contains_key("_set") { - let obj = obj["_set"].as_object().expect("_set is a map"); - module_types.insert(key.to_string(), parse_set(obj)); - } else if obj.contains_key("_alias") { - let mut fields = Vec::new(); - for (key, val) in obj.iter() { - if key == "_alias" { - continue; - } else { - let field = - StructField::new(key, regex::parse(&val_to_str(val)).expect("Not a type")); - fields.push(field); - } - } - module_types.insert(key.to_string(), RustTypeMarker::Struct(fields)); - } else { - let mut fields = Vec::new(); - for (key, val) in obj.iter() { - let field = - StructField::new(key, regex::parse(&val_to_str(val)).expect("Not a type")); - fields.push(field); - } - module_types.insert(key.to_string(), RustTypeMarker::Struct(fields)); - } - } +fn parse_mod_types(module_types: &mut HashMap, key: &str, val: &serde_json::Value) { + if val.is_string() { + module_types.insert(key.to_string(), regex::parse(val.as_str().expect("Checked; qed")).expect("not a type")); + } else if val.is_object() { + let obj = val.as_object().expect("checked for object before unwrap; qed"); + if obj.contains_key("_enum") { + module_types.insert(key.to_string(), parse_enum(&obj["_enum"])); + } else if obj.contains_key("_set") { + let obj = obj["_set"].as_object().expect("_set is a map"); + module_types.insert(key.to_string(), parse_set(obj)); + } else if obj.contains_key("_alias") { + let mut fields = Vec::new(); + for (key, val) in obj.iter() { + if key == "_alias" { + continue; + } else { + let field = StructField::new(key, regex::parse(&val_to_str(val)).expect("Not a type")); + fields.push(field); + } + } + module_types.insert(key.to_string(), RustTypeMarker::Struct(fields)); + } else { + let mut fields = Vec::new(); + for (key, val) in obj.iter() { + let field = StructField::new(key, regex::parse(&val_to_str(val)).expect("Not a type")); + fields.push(field); + } + module_types.insert(key.to_string(), RustTypeMarker::Struct(fields)); + } + } } /// internal api to convert a serde value to str @@ -197,71 +184,58 @@ fn parse_mod_types( /// # Panics /// panics if the value is not a string fn val_to_str(v: &serde_json::Value) -> String { - v.as_str().expect("will be string").to_string() + v.as_str().expect("will be string").to_string() } fn parse_set(obj: &serde_json::map::Map) -> RustTypeMarker { - let mut set_vec = Vec::new(); - for (key, value) in obj.iter() { - let num: u8 = serde_json::from_value(value.clone()).expect("Must be u8"); - let set_field = SetField::new(key, num); - set_vec.push(set_field) - } - RustTypeMarker::Set(set_vec) + let mut set_vec = Vec::new(); + for (key, value) in obj.iter() { + let num: u8 = serde_json::from_value(value.clone()).expect("Must be u8"); + let set_field = SetField::new(key, num); + set_vec.push(set_field) + } + RustTypeMarker::Set(set_vec) } /// internal api to convert a serde value to str /// /// # Panics fn parse_enum(obj: &serde_json::Value) -> RustTypeMarker { - if obj.is_array() { - let arr = obj.as_array().expect("checked before cast; qed"); - let mut rust_enum = Vec::new(); - for unit in arr.iter() { - // if an enum is an array, it's a unit enum (stateless) - rust_enum.push( - unit.as_str() - .expect("Will be string according to polkadot-js defs") - .to_string(), - ) - } - let rust_enum = rust_enum - .into_iter() - .map(|f| f.into()) - .collect::>(); - RustTypeMarker::Enum(rust_enum) - // all enum 'objects' in polkadot.js definitions are tuple-enums - } else if obj.is_object() { - let obj = obj.as_object().expect("Checked before casting; qed"); - let mut rust_enum = Vec::new(); - for (key, value) in obj.iter() { - let value = if value.is_null() { - "null" - } else { - value.as_str().expect("will be str; qed") - }; - let field = EnumField::new( - Some(key.into()), - StructUnitOrTuple::Tuple(regex::parse(value).expect("Not a type")), - ); - rust_enum.push(field); - } - RustTypeMarker::Enum(rust_enum) - // so far, polkadot.js does not define any struct-like enums - } else { - panic!("Unnaccounted type") - } + if obj.is_array() { + let arr = obj.as_array().expect("checked before cast; qed"); + let mut rust_enum = Vec::new(); + for unit in arr.iter() { + // if an enum is an array, it's a unit enum (stateless) + rust_enum.push(unit.as_str().expect("Will be string according to polkadot-js defs").to_string()) + } + let rust_enum = rust_enum.into_iter().map(|f| f.into()).collect::>(); + RustTypeMarker::Enum(rust_enum) + // all enum 'objects' in polkadot.js definitions are tuple-enums + } else if obj.is_object() { + let obj = obj.as_object().expect("Checked before casting; qed"); + let mut rust_enum = Vec::new(); + for (key, value) in obj.iter() { + let value = if value.is_null() { "null" } else { value.as_str().expect("will be str; qed") }; + let field = + EnumField::new(Some(key.into()), StructUnitOrTuple::Tuple(regex::parse(value).expect("Not a type"))); + rust_enum.push(field); + } + RustTypeMarker::Enum(rust_enum) + // so far, polkadot.js does not define any struct-like enums + } else { + panic!("Unnaccounted type") + } } #[cfg(test)] mod tests { - use super::Modules; - use super::*; - use crate::error::Error; - use crate::ModuleTypes; - use core::{EnumField, RustTypeMarker, SetField, StructField, StructUnitOrTuple}; - use std::collections::HashMap; - const RAW_JSON: &'static str = r#" + use super::Modules; + use super::*; + use crate::error::Error; + use crate::ModuleTypes; + use core::{EnumField, RustTypeMarker, SetField, StructField, StructUnitOrTuple}; + use std::collections::HashMap; + const RAW_JSON: &'static str = r#" { "runtime": { "types": { @@ -305,124 +279,73 @@ mod tests { } "#; - #[test] - fn should_deserialize_correctly() -> Result<(), Error> { - let deser_dot_types = Modules::new(RAW_JSON)?; - let mut modules = HashMap::new(); - let mut types = HashMap::new(); - types.insert( - "Extrinsic".to_string(), - RustTypeMarker::TypePointer("GenericExtrinsic".to_string()), - ); - types.insert( - "hash".to_string(), - RustTypeMarker::TypePointer("H512".to_string()), - ); - types.insert("BlockNumber".to_string(), RustTypeMarker::U64); - types.insert( - "ChangesTrieConfiguration".to_string(), - RustTypeMarker::Struct(vec![ - StructField { - name: "digestInterval".to_string(), - ty: RustTypeMarker::U32, - }, - StructField { - name: "digestLevels".to_string(), - ty: RustTypeMarker::U32, - }, - ]), - ); - types.insert( - "DispatchInfo".to_string(), - RustTypeMarker::Struct(vec![ - StructField { - name: "weight".to_string(), - ty: RustTypeMarker::TypePointer("Weight".to_string()), - }, - StructField { - name: "class".to_string(), - ty: RustTypeMarker::TypePointer("DispatchClass".to_string()), - }, - StructField { - name: "paysFee".to_string(), - ty: RustTypeMarker::Bool, - }, - ]), - ); - types.insert( - "MultiSignature".to_string(), - RustTypeMarker::Enum(vec![ - EnumField { - variant_name: Some("Ed25519".to_string()), - ty: StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer( - "Ed25519Signature".to_string(), - )), - }, - EnumField { - variant_name: Some("Sr25519".to_string()), - ty: StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer( - "Sr25519Signature".to_string(), - )), - }, - EnumField { - variant_name: Some("Ecdsa".to_string()), - ty: StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer( - "EcdsaSignature".to_string(), - )), - }, - ]), - ); - types.insert( - "Reasons".to_string(), - RustTypeMarker::Enum(vec![ - EnumField { - variant_name: None, - ty: StructUnitOrTuple::Unit("Fee".to_string()), - }, - EnumField { - variant_name: None, - ty: StructUnitOrTuple::Unit("Misc".to_string()), - }, - EnumField { - variant_name: None, - ty: StructUnitOrTuple::Unit("All".to_string()), - }, - ]), - ); - types.insert( - "WithdrawReasons".to_string(), - RustTypeMarker::Set(vec![ - SetField { - name: "TransactionPayment".to_string(), - num: 1, - }, - SetField { - name: "Transfer".to_string(), - num: 2, - }, - SetField { - name: "Reserve".to_string(), - num: 4, - }, - SetField { - name: "Fee".to_string(), - num: 8, - }, - SetField { - name: "Tip".to_string(), - num: 16, - }, - ]), - ); + #[test] + fn should_deserialize_correctly() -> Result<(), Error> { + let deser_dot_types = Modules::new(RAW_JSON)?; + let mut modules = HashMap::new(); + let mut types = HashMap::new(); + types.insert("Extrinsic".to_string(), RustTypeMarker::TypePointer("GenericExtrinsic".to_string())); + types.insert("hash".to_string(), RustTypeMarker::TypePointer("H512".to_string())); + types.insert("BlockNumber".to_string(), RustTypeMarker::U64); + types.insert( + "ChangesTrieConfiguration".to_string(), + RustTypeMarker::Struct(vec![ + StructField { name: "digestInterval".to_string(), ty: RustTypeMarker::U32 }, + StructField { name: "digestLevels".to_string(), ty: RustTypeMarker::U32 }, + ]), + ); + types.insert( + "DispatchInfo".to_string(), + RustTypeMarker::Struct(vec![ + StructField { name: "weight".to_string(), ty: RustTypeMarker::TypePointer("Weight".to_string()) }, + StructField { name: "class".to_string(), ty: RustTypeMarker::TypePointer("DispatchClass".to_string()) }, + StructField { name: "paysFee".to_string(), ty: RustTypeMarker::Bool }, + ]), + ); + types.insert( + "MultiSignature".to_string(), + RustTypeMarker::Enum(vec![ + EnumField { + variant_name: Some("Ed25519".to_string()), + ty: StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer("Ed25519Signature".to_string())), + }, + EnumField { + variant_name: Some("Sr25519".to_string()), + ty: StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer("Sr25519Signature".to_string())), + }, + EnumField { + variant_name: Some("Ecdsa".to_string()), + ty: StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer("EcdsaSignature".to_string())), + }, + ]), + ); + types.insert( + "Reasons".to_string(), + RustTypeMarker::Enum(vec![ + EnumField { variant_name: None, ty: StructUnitOrTuple::Unit("Fee".to_string()) }, + EnumField { variant_name: None, ty: StructUnitOrTuple::Unit("Misc".to_string()) }, + EnumField { variant_name: None, ty: StructUnitOrTuple::Unit("All".to_string()) }, + ]), + ); + types.insert( + "WithdrawReasons".to_string(), + RustTypeMarker::Set(vec![ + SetField { name: "TransactionPayment".to_string(), num: 1 }, + SetField { name: "Transfer".to_string(), num: 2 }, + SetField { name: "Reserve".to_string(), num: 4 }, + SetField { name: "Fee".to_string(), num: 8 }, + SetField { name: "Tip".to_string(), num: 16 }, + ]), + ); - for (key, val) in types.iter() { - assert_eq!(val, &deser_dot_types.modules["runtime"].types[key]); - } + for (key, val) in types.iter() { + assert_eq!(val, &deser_dot_types.modules["runtime"].types[key]); + } - let mod_types = ModuleTypes { types }; - modules.insert("runtime".to_string(), mod_types); - let dot_types = Modules { modules }; - assert_eq!(dot_types, deser_dot_types); - Ok(()) - } + let mod_types = ModuleTypes { types }; + modules.insert("runtime".to_string(), mod_types); + let dot_types = Modules { modules }; + assert_eq!(dot_types, deser_dot_types); + Ok(()) + } } diff --git a/extras/src/overrides.rs b/extras/src/overrides.rs index 465afeb2..7b58f1cb 100644 --- a/extras/src/overrides.rs +++ b/extras/src/overrides.rs @@ -19,51 +19,47 @@ use std::collections::HashMap; /// Types that are given priority over those defined in [Modules](struct.Modules.html) #[derive(Debug, Serialize, Deserialize, Default, Eq, PartialEq, Clone)] pub struct Overrides { - /// Type Overrides for modules (where duplication between modules exist) - #[serde(rename = "TYPES_MODULES")] - types_modules: HashMap, - /// Overrides based on metadata versions - /// this is for support of old testnets (Alexander) - // this can be safely ignored for the most part - #[serde(rename = "TYPES_META")] - types_meta: Vec, - /// these are override types for Polkadot & Kusama chains - /// NOTE The SessionKeys definition for Polkadot and Substrate (OpaqueKeys - /// implementation) are different. Detect Polkadot and inject the `Keys` - /// definition as applicable. (4 keys in substrate vs 5 in Polkadot/CC3). - #[serde(rename = "TYPES_SPEC")] - // chain(e.g kusama/polkadot) -> Vector of overrides - types_spec: HashMap>, + /// Type Overrides for modules (where duplication between modules exist) + #[serde(rename = "TYPES_MODULES")] + types_modules: HashMap, + /// Overrides based on metadata versions + /// this is for support of old testnets (Alexander) + // this can be safely ignored for the most part + #[serde(rename = "TYPES_META")] + types_meta: Vec, + /// these are override types for Polkadot & Kusama chains + /// NOTE The SessionKeys definition for Polkadot and Substrate (OpaqueKeys + /// implementation) are different. Detect Polkadot and inject the `Keys` + /// definition as applicable. (4 keys in substrate vs 5 in Polkadot/CC3). + #[serde(rename = "TYPES_SPEC")] + // chain(e.g kusama/polkadot) -> Vector of overrides + types_spec: HashMap>, } impl Overrides { - /// Construct overrides from JSON - pub fn new(raw_json: &str) -> Result { - serde_json::from_str(raw_json).map_err(Into::into) - } + /// Construct overrides from JSON + pub fn new(raw_json: &str) -> Result { + serde_json::from_str(raw_json).map_err(Into::into) + } - /// get a module types based upon spec - pub fn get_chain_types(&self, chain: &str, spec: u32) -> Option<&ModuleTypes> { - self.types_spec - .get(chain)? - .iter() - .find(|f| crate::is_in_range(spec, f)) - .map(|o| &o.types) - } + /// get a module types based upon spec + pub fn get_chain_types(&self, chain: &str, spec: u32) -> Option<&ModuleTypes> { + self.types_spec.get(chain)?.iter().find(|f| crate::is_in_range(spec, f)).map(|o| &o.types) + } - /// get types for a substrate module - pub fn get_module_types(&self, module: &str) -> Option<&ModuleTypes> { - self.types_modules.get(module) - } + /// get types for a substrate module + pub fn get_module_types(&self, module: &str) -> Option<&ModuleTypes> { + self.types_modules.get(module) + } } #[cfg(test)] mod tests { - use super::*; + use super::*; - #[test] - fn should_deserialize_into_single_override() { - let json = r#" + #[test] + fn should_deserialize_into_single_override() { + let json = r#" { "minmax": [ 1020, @@ -78,13 +74,13 @@ mod tests { } "#; - let single_override: TypeRange = serde_json::from_str(json).unwrap(); - dbg!(single_override); - } + let single_override: TypeRange = serde_json::from_str(json).unwrap(); + dbg!(single_override); + } - #[test] - fn should_deserialize_into_spec() { - let json = r#" + #[test] + fn should_deserialize_into_spec() { + let json = r#" { "kusama": [ { @@ -135,13 +131,13 @@ mod tests { } "#; - let types_spec: HashMap> = serde_json::from_str(json).unwrap(); - dbg!(types_spec); - } + let types_spec: HashMap> = serde_json::from_str(json).unwrap(); + dbg!(types_spec); + } - #[test] - fn should_deserialize_types_meta() { - let json = r#" + #[test] + fn should_deserialize_types_meta() { + let json = r#" [ { "minmax": [ 0, @@ -156,7 +152,7 @@ mod tests { } ] "#; - let types_meta: Vec = serde_json::from_str(json).unwrap(); - dbg!(types_meta); - } + let types_meta: Vec = serde_json::from_str(json).unwrap(); + dbg!(types_meta); + } } diff --git a/extras/src/resolver.rs b/extras/src/resolver.rs index 90404588..69fcee2b 100644 --- a/extras/src/resolver.rs +++ b/extras/src/resolver.rs @@ -19,390 +19,293 @@ use core::{regex, RustTypeMarker, TypeDetective}; #[cfg(feature = "default_definitions")] mod default { - pub const DEFINITIONS: &str = include_str!("./definitions/definitions.json"); - pub const OVERRIDES: &str = include_str!("./definitions/overrides.json"); - pub const EXTRINSICS: &str = include_str!("./definitions/extrinsics.json"); + pub const DEFINITIONS: &str = include_str!("./definitions/definitions.json"); + pub const OVERRIDES: &str = include_str!("./definitions/overrides.json"); + pub const EXTRINSICS: &str = include_str!("./definitions/extrinsics.json"); } pub struct Builder { - mods: Modules, - overrides: Overrides, - extrinsics: Extrinsics, + mods: Modules, + overrides: Overrides, + extrinsics: Extrinsics, } impl Builder { - pub fn modules(mut self, modules: Modules) -> Self { - self.mods = modules; - self - } - - pub fn modules_from_json(mut self, modules: &str) -> Result { - self.mods = Modules::new(modules)?; - Ok(self) - } - - pub fn overrides(mut self, overrides: Overrides) -> Self { - self.overrides = overrides; - self - } - - pub fn overrides_from_json(mut self, json: &str) -> Result { - self.overrides = Overrides::new(json)?; - Ok(self) - } - - pub fn extrinsics(mut self, extrinsics: Extrinsics) -> Self { - self.extrinsics = extrinsics; - self - } - - pub fn extrinsics_from_json(mut self, json: &str) -> Result { - self.extrinsics = Extrinsics::new(json)?; - Ok(self) - } - - pub fn build(self) -> TypeResolver { - TypeResolver { - mods: self.mods, - overrides: self.overrides, - extrinsics: self.extrinsics, - } - } + pub fn modules(mut self, modules: Modules) -> Self { + self.mods = modules; + self + } + + pub fn modules_from_json(mut self, modules: &str) -> Result { + self.mods = Modules::new(modules)?; + Ok(self) + } + + pub fn overrides(mut self, overrides: Overrides) -> Self { + self.overrides = overrides; + self + } + + pub fn overrides_from_json(mut self, json: &str) -> Result { + self.overrides = Overrides::new(json)?; + Ok(self) + } + + pub fn extrinsics(mut self, extrinsics: Extrinsics) -> Self { + self.extrinsics = extrinsics; + self + } + + pub fn extrinsics_from_json(mut self, json: &str) -> Result { + self.extrinsics = Extrinsics::new(json)?; + Ok(self) + } + + pub fn build(self) -> TypeResolver { + TypeResolver { mods: self.mods, overrides: self.overrides, extrinsics: self.extrinsics } + } } // we need a way to construct the builder when // not using default features #[cfg(not(feature = "default_definitions"))] impl Builder { - fn new(modules: Modules, extrinsics: Extrinsics, overrides: Overrides) -> Self { - Self { - mods, - overrides, - extrinsics, - } - } + fn new(modules: Modules, extrinsics: Extrinsics, overrides: Overrides) -> Self { + Self { mods, overrides, extrinsics } + } } #[cfg(feature = "default_definitions")] impl Default for Builder { - fn default() -> Self { - Self { - mods: Modules::new(default::DEFINITIONS) - .expect("Included definitions should not panic"), - overrides: Overrides::new(default::OVERRIDES) - .expect("Included overrides should not panic"), - extrinsics: Extrinsics::new(default::EXTRINSICS) - .expect("Included extrinsics should not panic"), - } - } + fn default() -> Self { + Self { + mods: Modules::new(default::DEFINITIONS).expect("Included definitions should not panic"), + overrides: Overrides::new(default::OVERRIDES).expect("Included overrides should not panic"), + extrinsics: Extrinsics::new(default::EXTRINSICS).expect("Included extrinsics should not panic"), + } + } } #[cfg(feature = "default_definitions")] impl Default for TypeResolver { - fn default() -> Self { - Builder::default().build() - } + fn default() -> Self { + Builder::default().build() + } } #[derive(Debug, Clone)] pub struct TypeResolver { - mods: Modules, - overrides: Overrides, - extrinsics: Extrinsics, + mods: Modules, + overrides: Overrides, + extrinsics: Extrinsics, } impl TypeResolver { - /// Build the builder for `TypeResolver` - pub fn builder() -> Builder { - Builder::default() - } - - /// Construct the TypeResolver from its parts - pub fn new(modules: Modules, extrinsics: Extrinsics, overrides: Overrides) -> Self { - Self { - mods: modules, - extrinsics, - overrides, - } - } - - /// Try to resolve a type - /// First, tries to resolve from the overrides (overrides.json), - /// then checks if extrinsics includes the type (extrinsics.json). - /// If none of the above contains the type that we are looking for, - /// we check if the modules includes it (definitions.json) - /// - /// # Return - /// returns None if the type cannot be resolved - pub fn get(&self, chain: &str, spec: u32, module: &str, ty: &str) -> Option<&RustTypeMarker> { - let (module, ty, chain) = sanitize_types(module, ty, chain); - log::trace!("Getting Type: {}, module: {}, spec: {}", ty, module, spec); - - if let Some(t) = self.check_overrides(&module, ty.as_str(), spec, &chain) { - log::trace!("Resolving to Override"); - Some(&t) - } else if let Some(t) = self.extrinsics.get(ty.as_str(), spec, &chain) { - log::trace!("Resolving to Extrinsic Type"); - Some(&t) - } else { - log::trace!("Resolving to Type Pointer"); - self.resolve_helper(&module, &ty) - } - } - - pub fn get_ext_ty(&self, chain: &str, spec: u32, ty: &str) -> Option<&RustTypeMarker> { - if let Some(t) = self.extrinsics.get(ty, spec, chain) { - match t { - RustTypeMarker::TypePointer(t) => self.resolve_helper("runtime", t), - t => Some(t), - } - } else { - None - } - } - - /// Try to resolve a type pointer from the default definitions (definitions.json) - fn resolve_helper(&self, module: &str, ty_pointer: &str) -> Option<&RustTypeMarker> { - log::trace!("Helper resolving {}, {}", module, ty_pointer); - - if let Some(t) = self.mods.get_type(module, ty_pointer) { - log::trace!("Type {} found in module {}", ty_pointer, module); - Some(t) - } else if let Some(t) = self.mods.get_type("runtime", ty_pointer) { - log::trace!( - "Type not found in {}, trying `runtime` for type {}", - module, - ty_pointer - ); - Some(t) - } else if let Some(t) = self.check_other_modules(ty_pointer) { - log::trace!("trying other modules"); - Some(t) - } else { - None - } - } - - /// check if an override exists for a given type - /// - /// if it does, return the types/type pointer - fn check_overrides( - &self, - module: &str, - ty: &str, - spec: u32, - chain: &str, - ) -> Option<&RustTypeMarker> { - // check if the type is a module override first - if let Some(m) = self.overrides.get_module_types(module) { - if let Some(ty) = m.get(ty) { - return Some(ty); - } - } - - // if it isn't in modules, chain types is next - self.overrides.get_chain_types(chain, spec)?.get(ty) - } - - /// Checks all modules for the types - fn check_other_modules(&self, ty_pointer: &str) -> Option<&RustTypeMarker> { - self.mods - .iter_types() - .find(|(n, _)| n.as_str() == ty_pointer) - .map(|(_, t)| t) - } + /// Build the builder for `TypeResolver` + pub fn builder() -> Builder { + Builder::default() + } + + /// Construct the TypeResolver from its parts + pub fn new(modules: Modules, extrinsics: Extrinsics, overrides: Overrides) -> Self { + Self { mods: modules, extrinsics, overrides } + } + + /// Try to resolve a type + /// First, tries to resolve from the overrides (overrides.json), + /// then checks if extrinsics includes the type (extrinsics.json). + /// If none of the above contains the type that we are looking for, + /// we check if the modules includes it (definitions.json) + /// + /// # Return + /// returns None if the type cannot be resolved + pub fn get(&self, chain: &str, spec: u32, module: &str, ty: &str) -> Option<&RustTypeMarker> { + let (module, ty, chain) = sanitize_types(module, ty, chain); + log::trace!("Getting Type: {}, module: {}, spec: {}", ty, module, spec); + + if let Some(t) = self.check_overrides(&module, ty.as_str(), spec, &chain) { + log::trace!("Resolving to Override"); + Some(&t) + } else if let Some(t) = self.extrinsics.get(ty.as_str(), spec, &chain) { + log::trace!("Resolving to Extrinsic Type"); + Some(&t) + } else { + log::trace!("Resolving to Type Pointer"); + self.resolve_helper(&module, &ty) + } + } + + pub fn get_ext_ty(&self, chain: &str, spec: u32, ty: &str) -> Option<&RustTypeMarker> { + if let Some(t) = self.extrinsics.get(ty, spec, chain) { + match t { + RustTypeMarker::TypePointer(t) => self.resolve_helper("runtime", t), + t => Some(t), + } + } else { + None + } + } + + /// Try to resolve a type pointer from the default definitions (definitions.json) + fn resolve_helper(&self, module: &str, ty_pointer: &str) -> Option<&RustTypeMarker> { + log::trace!("Helper resolving {}, {}", module, ty_pointer); + + if let Some(t) = self.mods.get_type(module, ty_pointer) { + log::trace!("Type {} found in module {}", ty_pointer, module); + Some(t) + } else if let Some(t) = self.mods.get_type("runtime", ty_pointer) { + log::trace!("Type not found in {}, trying `runtime` for type {}", module, ty_pointer); + Some(t) + } else if let Some(t) = self.check_other_modules(ty_pointer) { + log::trace!("trying other modules"); + Some(t) + } else { + None + } + } + + /// check if an override exists for a given type + /// + /// if it does, return the types/type pointer + fn check_overrides(&self, module: &str, ty: &str, spec: u32, chain: &str) -> Option<&RustTypeMarker> { + // check if the type is a module override first + if let Some(m) = self.overrides.get_module_types(module) { + if let Some(ty) = m.get(ty) { + return Some(ty); + } + } + + // if it isn't in modules, chain types is next + self.overrides.get_chain_types(chain, spec)?.get(ty) + } + + /// Checks all modules for the types + fn check_other_modules(&self, ty_pointer: &str) -> Option<&RustTypeMarker> { + self.mods.iter_types().find(|(n, _)| n.as_str() == ty_pointer).map(|(_, t)| t) + } } fn sanitize_types(module: &str, ty: &str, chain: &str) -> (String, String, String) { - let module = module.to_ascii_lowercase(); - let chain = chain.to_ascii_lowercase(); - let ty = if let Some(un_prefixed) = regex::remove_prefix(ty) { - un_prefixed - } else { - ty.to_string() - }; - - log::trace!("Possibly de-prefixed type: {}", ty); - (module, ty, chain) + let module = module.to_ascii_lowercase(); + let chain = chain.to_ascii_lowercase(); + let ty = if let Some(un_prefixed) = regex::remove_prefix(ty) { un_prefixed } else { ty.to_string() }; + + log::trace!("Possibly de-prefixed type: {}", ty); + (module, ty, chain) } impl TypeDetective for TypeResolver { - fn get(&self, chain: &str, spec: u32, module: &str, ty: &str) -> Option<&RustTypeMarker> { - TypeResolver::get(self, chain, spec, module, ty) - } + fn get(&self, chain: &str, spec: u32, module: &str, ty: &str) -> Option<&RustTypeMarker> { + TypeResolver::get(self, chain, spec, module, ty) + } - fn get_extrinsic_ty(&self, chain: &str, spec: u32, ty: &str) -> Option<&RustTypeMarker> { - TypeResolver::get_ext_ty(self, chain, spec, ty) - } + fn get_extrinsic_ty(&self, chain: &str, spec: u32, ty: &str) -> Option<&RustTypeMarker> { + TypeResolver::get_ext_ty(self, chain, spec, ty) + } } #[cfg(test)] mod tests { - use super::default::*; - use super::*; - use core::{EnumField, StructField, StructUnitOrTuple}; - - #[test] - fn should_get_type_from_module() -> Result<()> { - let post_1031_dispatch_error = RustTypeMarker::Enum(vec![ - EnumField::new( - Some("Other".into()), - StructUnitOrTuple::Tuple(RustTypeMarker::Null), - ), - EnumField::new( - Some("CannotLookup".into()), - StructUnitOrTuple::Tuple(RustTypeMarker::Null), - ), - EnumField::new( - Some("BadOrigin".into()), - StructUnitOrTuple::Tuple(RustTypeMarker::Null), - ), - EnumField::new( - Some("Module".into()), - StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer( - "DispatchErrorModule".to_string(), - )), - ), - ]); - let types = TypeResolver::default(); - let t = types - .get("kusama", 1040, "system", "DispatchError") - .unwrap(); - assert_eq!(t, &post_1031_dispatch_error); - Ok(()) - } - - #[test] - fn should_resolve_a_type() -> Result<()> { - let correct = RustTypeMarker::Struct(vec![ - StructField { - name: "id".to_string(), - ty: RustTypeMarker::TypePointer("LockIdentifier".to_string()), - }, - StructField { - name: "amount".to_string(), - ty: RustTypeMarker::TypePointer("Balance".to_string()), - }, - StructField { - name: "until".to_string(), - ty: RustTypeMarker::TypePointer("BlockNumber".to_string()), - }, - StructField { - name: "reasons".to_string(), - ty: RustTypeMarker::TypePointer("WithdrawReasons".to_string()), - }, - ]); - let types = TypeResolver::default(); - let resolved = types - .get("kusama", 1040, "balances", "BalanceLockTo212") - .unwrap(); - assert_eq!(&correct, resolved); - Ok(()) - } - - #[test] - fn should_get_duplicated_types() -> Result<()> { - let types = TypeResolver::default(); - let t = types - .get("kusama", 1040, "contracts", "StorageKey") - .unwrap(); - assert_eq!( - t, - &RustTypeMarker::TypePointer("ContractStorageKey".to_string()) - ); - Ok(()) - } - - #[test] - fn should_adhere_to_spec() -> Result<()> { - let pre_1019_balance_lock = RustTypeMarker::Struct(vec![ - StructField { - name: "id".to_string(), - ty: RustTypeMarker::TypePointer("LockIdentifier".to_string()), - }, - StructField { - name: "amount".to_string(), - ty: RustTypeMarker::TypePointer("Balance".to_string()), - }, - StructField { - name: "reasons".to_string(), - ty: RustTypeMarker::TypePointer("Reasons".to_string()), - }, - ]); - let types = TypeResolver::default(); - let t = types - .get("kusama", 1000, "balances", "BalanceLock") - .unwrap(); - assert_eq!(t, &pre_1019_balance_lock); - let t = types - .get("kusama", 1018, "balances", "BalanceLock") - .unwrap(); - assert_eq!(t, &pre_1019_balance_lock); - let t = types - .get("kusama", 1031, "balances", "BalanceLock") - .unwrap(); - assert_eq!( - t, - &RustTypeMarker::TypePointer("BalanceLockTo212".to_string()) - ); - let t = types - .get("kusama", 1019, "balances", "BalanceLock") - .unwrap(); - assert_eq!( - t, - &RustTypeMarker::TypePointer("BalanceLockTo212".to_string()) - ); - let t = types - .get("kusama", 1032, "balances", "BalanceLock") - .unwrap(); - assert_eq!( - t, - &RustTypeMarker::TypePointer("BalanceLockTo212".to_string()) - ); - let t = types - .get("kusama", 1042, "balances", "BalanceLock") - .unwrap(); - assert_eq!( - t, - &RustTypeMarker::TypePointer("BalanceLockTo212".to_string()) - ); - Ok(()) - } - - #[test] - fn should_differentiate_chains() { - let types = TypeResolver::default(); - let dot_t = types.get("polkadot", 5, "runtime", "LookupSource").unwrap(); - let ksm_t = types.get("kusama", 5, "runtime", "LookupSource").unwrap(); - assert_eq!(dot_t, &RustTypeMarker::TypePointer("AccountId".to_string())); - assert_ne!(dot_t, ksm_t); - } - - #[test] - fn should_deserialize_overrides() { - let overrides = Overrides::new(OVERRIDES).unwrap(); - dbg!(overrides); - } - - #[test] - fn should_deserialize_ext_definitions() { - let extrinsics = Extrinsics::new(EXTRINSICS).unwrap(); - dbg!(extrinsics); - } - - #[test] - fn should_get_types_from_json() { - let extrinsics = Extrinsics::new(EXTRINSICS).unwrap(); - extrinsics.get_chain_types("kusama", 1031); - extrinsics.get_chain_types("kusama", 1007); - extrinsics.get_chain_types("kusama", 1006); - let tys = extrinsics.get_chain_types("kusama", 1003); - dbg!(tys); - } - - #[test] - fn should_deserialize_definitions() -> Result<()> { - let types = Modules::new(DEFINITIONS)?; - dbg!(&types); - Ok(()) - } + use super::default::*; + use super::*; + use core::{EnumField, StructField, StructUnitOrTuple}; + + #[test] + fn should_get_type_from_module() -> Result<()> { + let post_1031_dispatch_error = RustTypeMarker::Enum(vec![ + EnumField::new(Some("Other".into()), StructUnitOrTuple::Tuple(RustTypeMarker::Null)), + EnumField::new(Some("CannotLookup".into()), StructUnitOrTuple::Tuple(RustTypeMarker::Null)), + EnumField::new(Some("BadOrigin".into()), StructUnitOrTuple::Tuple(RustTypeMarker::Null)), + EnumField::new( + Some("Module".into()), + StructUnitOrTuple::Tuple(RustTypeMarker::TypePointer("DispatchErrorModule".to_string())), + ), + ]); + let types = TypeResolver::default(); + let t = types.get("kusama", 1040, "system", "DispatchError").unwrap(); + assert_eq!(t, &post_1031_dispatch_error); + Ok(()) + } + + #[test] + fn should_resolve_a_type() -> Result<()> { + let correct = RustTypeMarker::Struct(vec![ + StructField { name: "id".to_string(), ty: RustTypeMarker::TypePointer("LockIdentifier".to_string()) }, + StructField { name: "amount".to_string(), ty: RustTypeMarker::TypePointer("Balance".to_string()) }, + StructField { name: "until".to_string(), ty: RustTypeMarker::TypePointer("BlockNumber".to_string()) }, + StructField { name: "reasons".to_string(), ty: RustTypeMarker::TypePointer("WithdrawReasons".to_string()) }, + ]); + let types = TypeResolver::default(); + let resolved = types.get("kusama", 1040, "balances", "BalanceLockTo212").unwrap(); + assert_eq!(&correct, resolved); + Ok(()) + } + + #[test] + fn should_get_duplicated_types() -> Result<()> { + let types = TypeResolver::default(); + let t = types.get("kusama", 1040, "contracts", "StorageKey").unwrap(); + assert_eq!(t, &RustTypeMarker::TypePointer("ContractStorageKey".to_string())); + Ok(()) + } + + #[test] + fn should_adhere_to_spec() -> Result<()> { + let pre_1019_balance_lock = RustTypeMarker::Struct(vec![ + StructField { name: "id".to_string(), ty: RustTypeMarker::TypePointer("LockIdentifier".to_string()) }, + StructField { name: "amount".to_string(), ty: RustTypeMarker::TypePointer("Balance".to_string()) }, + StructField { name: "reasons".to_string(), ty: RustTypeMarker::TypePointer("Reasons".to_string()) }, + ]); + let types = TypeResolver::default(); + let t = types.get("kusama", 1000, "balances", "BalanceLock").unwrap(); + assert_eq!(t, &pre_1019_balance_lock); + let t = types.get("kusama", 1018, "balances", "BalanceLock").unwrap(); + assert_eq!(t, &pre_1019_balance_lock); + let t = types.get("kusama", 1031, "balances", "BalanceLock").unwrap(); + assert_eq!(t, &RustTypeMarker::TypePointer("BalanceLockTo212".to_string())); + let t = types.get("kusama", 1019, "balances", "BalanceLock").unwrap(); + assert_eq!(t, &RustTypeMarker::TypePointer("BalanceLockTo212".to_string())); + let t = types.get("kusama", 1032, "balances", "BalanceLock").unwrap(); + assert_eq!(t, &RustTypeMarker::TypePointer("BalanceLockTo212".to_string())); + let t = types.get("kusama", 1042, "balances", "BalanceLock").unwrap(); + assert_eq!(t, &RustTypeMarker::TypePointer("BalanceLockTo212".to_string())); + Ok(()) + } + + #[test] + fn should_differentiate_chains() { + let types = TypeResolver::default(); + let dot_t = types.get("polkadot", 5, "runtime", "LookupSource").unwrap(); + let ksm_t = types.get("kusama", 5, "runtime", "LookupSource").unwrap(); + assert_eq!(dot_t, &RustTypeMarker::TypePointer("AccountId".to_string())); + assert_ne!(dot_t, ksm_t); + } + + #[test] + fn should_deserialize_overrides() { + let overrides = Overrides::new(OVERRIDES).unwrap(); + dbg!(overrides); + } + + #[test] + fn should_deserialize_ext_definitions() { + let extrinsics = Extrinsics::new(EXTRINSICS).unwrap(); + dbg!(extrinsics); + } + + #[test] + fn should_get_types_from_json() { + let extrinsics = Extrinsics::new(EXTRINSICS).unwrap(); + extrinsics.get_chain_types("kusama", 1031); + extrinsics.get_chain_types("kusama", 1007); + extrinsics.get_chain_types("kusama", 1006); + let tys = extrinsics.get_chain_types("kusama", 1003); + dbg!(tys); + } + + #[test] + fn should_deserialize_definitions() -> Result<()> { + let types = Modules::new(DEFINITIONS)?; + dbg!(&types); + Ok(()) + } } diff --git a/integration_tests/tests/extrinsics.rs b/integration_tests/tests/extrinsics.rs index 58b5f346..0c3ecbb0 100644 --- a/integration_tests/tests/extrinsics.rs +++ b/integration_tests/tests/extrinsics.rs @@ -5,458 +5,418 @@ extern crate extras; use crate::test_suite; use codec::{Decode, Encode}; use desub_core::{ - decoder::{Chain, Decoder, GenericStorage, Metadata, StorageHasher, StorageKey, StorageValue}, - SubstrateType, + decoder::{Chain, Decoder, GenericStorage, Metadata, StorageHasher, StorageKey, StorageValue}, + SubstrateType, }; use primitives::twox_128; pub fn init() { - pretty_env_logger::try_init(); + pretty_env_logger::try_init(); } #[test] pub fn should_decode_ext342962() { - init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block342962(); - let meta = Metadata::new(meta.as_slice()); - - // block 6 of KSM CC3 is spec 1020 - decoder.register_version(1031, &meta); - for e in ext.iter() { - println!("{:?}", e); - let decoded = decoder - .decode_extrinsic(1031, e.as_slice()) - .expect("should decode"); - println!("{:?}", decoded); - println!("{}", decoded); - } - - // assert_eq!(vec![("now".to_string(), SubstrateType::U64(1577070096000))], decoded); - // 1577070096000 is the UNIX timestamp in milliseconds of - // Monday, December 23, 2019 3:01:36 AM - // when block 342,962 was processed + init(); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block342962(); + let meta = Metadata::new(meta.as_slice()); + + // block 6 of KSM CC3 is spec 1020 + decoder.register_version(1031, &meta); + for e in ext.iter() { + println!("{:?}", e); + let decoded = decoder.decode_extrinsic(1031, e.as_slice()).expect("should decode"); + println!("{:?}", decoded); + println!("{}", decoded); + } + + // assert_eq!(vec![("now".to_string(), SubstrateType::U64(1577070096000))], decoded); + // 1577070096000 is the UNIX timestamp in milliseconds of + // Monday, December 23, 2019 3:01:36 AM + // when block 342,962 was processed } #[test] pub fn should_decode_ext422871() { - init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block422871(); - let meta = Metadata::new(meta.as_slice()); - decoder.register_version(1031, &meta); - - println!("{}", ext.len()); - for e in ext.iter() { - println!("{:?}", e); - let decoded = decoder - .decode_extrinsic(1031, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - } + init(); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block422871(); + let meta = Metadata::new(meta.as_slice()); + decoder.register_version(1031, &meta); + + println!("{}", ext.len()); + for e in ext.iter() { + println!("{:?}", e); + let decoded = decoder.decode_extrinsic(1031, e.as_slice()).expect("should decode"); + println!("{}", decoded); + } } #[test] pub fn should_decode_ext50970() { - init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block50970(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1031, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1031, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - } + init(); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block50970(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1031, &meta); + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1031, e.as_slice()).expect("should decode"); + println!("{}", decoded); + } } #[test] pub fn should_decode_ext_106284() { - init(); - - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block106284(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1042, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1042, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + init(); + + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block106284(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1042, &meta); + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1042, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] pub fn should_decode_ext_1674683() { - init(); - - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block1674683(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1055, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1055, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + init(); + + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block1674683(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1055, &meta); + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1055, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] pub fn should_decode_ext_1677621() { - init(); + init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); - let (meta, ext) = test_suite::extrinsics_block1677621(); - let meta = Metadata::new(meta.as_slice()); + let (meta, ext) = test_suite::extrinsics_block1677621(); + let meta = Metadata::new(meta.as_slice()); - decoder.register_version(1055, &meta); + decoder.register_version(1055, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1055, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1055, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_1702023() { - init(); + init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); - let (meta, ext) = test_suite::extrinsics_block1702023(); - let meta = Metadata::new(meta.as_slice()); + let (meta, ext) = test_suite::extrinsics_block1702023(); + let meta = Metadata::new(meta.as_slice()); - decoder.register_version(1055, &meta); + decoder.register_version(1055, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1055, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1055, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_1714495() { - init(); + init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); - let (meta, ext) = test_suite::extrinsics_block1714495(); - let meta = Metadata::new(meta.as_slice()); + let (meta, ext) = test_suite::extrinsics_block1714495(); + let meta = Metadata::new(meta.as_slice()); - decoder.register_version(1055, &meta); + decoder.register_version(1055, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1055, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1055, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_1717926() { - init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block1717926(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1055, &meta); - - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1055, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + init(); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block1717926(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1055, &meta); + + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1055, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_1718223() { - init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block1718223(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1055, &meta); - - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1055, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + init(); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block1718223(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1055, &meta); + + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1055, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_1732321() { - init(); + init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); - let (meta, ext) = test_suite::extrinsics_block1732321(); - let meta = Metadata::new(meta.as_slice()); + let (meta, ext) = test_suite::extrinsics_block1732321(); + let meta = Metadata::new(meta.as_slice()); - decoder.register_version(1055, &meta); + decoder.register_version(1055, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1055, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1055, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_1731904() { - init(); + init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); - let (meta, ext) = test_suite::extrinsics_block1731904(); - let meta = Metadata::new(meta.as_slice()); + let (meta, ext) = test_suite::extrinsics_block1731904(); + let meta = Metadata::new(meta.as_slice()); - decoder.register_version(1055, &meta); + decoder.register_version(1055, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1055, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1055, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_1768321() { - init(); + init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); - let (meta, ext) = test_suite::extrinsics_block1768321(); - let meta = Metadata::new(meta.as_slice()); + let (meta, ext) = test_suite::extrinsics_block1768321(); + let meta = Metadata::new(meta.as_slice()); - decoder.register_version(1055, &meta); + decoder.register_version(1055, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1055, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1055, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_6144() { - init(); - - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block6144(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1020, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1020, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + init(); + + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block6144(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1020, &meta); + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1020, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_779410_ksm() { - init(); - - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block779410(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1042, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1042, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + init(); + + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block779410(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1042, &meta); + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1042, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_899638_ksm() { - init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block899638(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1042, &meta); - for e in ext.iter() { - println!("{:?}", e); - println!("{:X?}", e); - let decoded = decoder - .decode_extrinsic(1042, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + init(); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block899638(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1042, &meta); + for e in ext.iter() { + println!("{:?}", e); + println!("{:X?}", e); + let decoded = decoder.decode_extrinsic(1042, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_233816_ksm() { - init(); - - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block233816(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1030, &meta); - for e in ext.iter() { - println!("DECODING --------------------- \n {:X?} \n ------", e); - let decoded = decoder - .decode_extrinsic(1030, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + init(); + + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block233816(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1030, &meta); + for e in ext.iter() { + println!("DECODING --------------------- \n {:X?} \n ------", e); + let decoded = decoder.decode_extrinsic(1030, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_607421_ksm() { - init(); - - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); - - let (meta, ext) = test_suite::extrinsics_block607421(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(1039, &meta); - for e in ext.iter() { - println!("DECODING: \n ------ \n {:X?} \n ------", e); - let decoded = decoder - .decode_extrinsic(1039, e.as_slice()) - .expect("should decode"); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - } + init(); + + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); + + let (meta, ext) = test_suite::extrinsics_block607421(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(1039, &meta); + for e in ext.iter() { + println!("DECODING: \n ------ \n {:X?} \n ------", e); + let decoded = decoder.decode_extrinsic(1039, e.as_slice()).expect("should decode"); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + } } #[test] fn should_decode_ext_892_dot() { - init(); - - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Polkadot); - - let (meta, ext) = test_suite::extrinsics_block892_dot(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(0, &meta); - for e in ext.iter() { - println!("-----------------------------------------------------------------"); - println!("DECODING: \n ------ \n {:X?} \n ------", e); - let decoded = decoder - .decode_extrinsic(0, e.as_slice()) - .expect("should decode"); - println!("{:?}", decoded); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - println!("-----------------------------------------------------------------"); - } + init(); + + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Polkadot); + + let (meta, ext) = test_suite::extrinsics_block892_dot(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(0, &meta); + for e in ext.iter() { + println!("-----------------------------------------------------------------"); + println!("DECODING: \n ------ \n {:X?} \n ------", e); + let decoded = decoder.decode_extrinsic(0, e.as_slice()).expect("should decode"); + println!("{:?}", decoded); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + println!("-----------------------------------------------------------------"); + } } #[test] fn should_decode_ext_1191_wnd() { - init(); - - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Polkadot); - - let (meta, ext) = test_suite::extrinsics_block1191_wnd(); - let meta = Metadata::new(meta.as_slice()); - - decoder.register_version(0, &meta); - for e in ext.iter() { - println!("-----------------------------------------------------------------"); - println!("DECODING: \n ------ \n {:X?} \n ------", e); - let decoded = decoder - .decode_extrinsic(0, e.as_slice()) - .expect("should decode"); - println!("{:?}", decoded); - println!("{}", decoded); - println!("{}", serde_json::to_string(&decoded).unwrap()); - println!("-----------------------------------------------------------------"); - } + init(); + + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Polkadot); + + let (meta, ext) = test_suite::extrinsics_block1191_wnd(); + let meta = Metadata::new(meta.as_slice()); + + decoder.register_version(0, &meta); + for e in ext.iter() { + println!("-----------------------------------------------------------------"); + println!("DECODING: \n ------ \n {:X?} \n ------", e); + let decoded = decoder.decode_extrinsic(0, e.as_slice()).expect("should decode"); + println!("{:?}", decoded); + println!("{}", decoded); + println!("{}", serde_json::to_string(&decoded).unwrap()); + println!("-----------------------------------------------------------------"); + } } diff --git a/integration_tests/tests/metadata.rs b/integration_tests/tests/metadata.rs index 253786a4..6bd22bfc 100644 --- a/integration_tests/tests/metadata.rs +++ b/integration_tests/tests/metadata.rs @@ -4,44 +4,44 @@ use primitives::twox_128; #[test] fn should_create_metadata_v9() { - let meta = test_suite::runtime_v9(); - let meta: Metadata = Metadata::new(meta.as_slice()); - println!("{}", meta.pretty()); - let meta = test_suite::runtime_v9_block6(); - let _meta: Metadata = Metadata::new(meta.as_slice()); + let meta = test_suite::runtime_v9(); + let meta: Metadata = Metadata::new(meta.as_slice()); + println!("{}", meta.pretty()); + let meta = test_suite::runtime_v9_block6(); + let _meta: Metadata = Metadata::new(meta.as_slice()); } #[test] fn should_create_metadata_v10() { - let meta = test_suite::runtime_v10(); - let meta: Metadata = Metadata::new(meta.as_slice()); - println!("{}", meta.pretty()); + let meta = test_suite::runtime_v10(); + let meta: Metadata = Metadata::new(meta.as_slice()); + println!("{}", meta.pretty()); } #[test] fn should_create_metadata_v9_block500000() { - pretty_env_logger::try_init(); - let meta = test_suite::runtime_v9_block500k(); - let meta: Metadata = Metadata::new(meta.as_slice()); - println!("{}", meta.pretty()); + pretty_env_logger::try_init(); + let meta = test_suite::runtime_v9_block500k(); + let meta: Metadata = Metadata::new(meta.as_slice()); + println!("{}", meta.pretty()); } #[test] fn should_create_metadata_v12_block_4643974() { - pretty_env_logger::try_init(); - let meta = test_suite::runtime_v12_block_4643974(); - let meta: Metadata = Metadata::new(meta.as_slice()); - println!("{}", meta.pretty()); + pretty_env_logger::try_init(); + let meta = test_suite::runtime_v12_block_4643974(); + let meta: Metadata = Metadata::new(meta.as_slice()); + println!("{}", meta.pretty()); } #[test] fn should_get_correct_lookup_table() { - let meta = test_suite::runtime_v11(); - let meta: Metadata = Metadata::new(meta.as_slice()); - let lookup_table = meta.storage_lookup_table(); - let mut key = twox_128("System".as_bytes()).to_vec(); - key.extend(twox_128("Account".as_bytes()).iter()); - let storage_entry = lookup_table.lookup(&key); - println!("{:?}", storage_entry); - assert_eq!(storage_entry.unwrap().meta.prefix(), "System Account"); + let meta = test_suite::runtime_v11(); + let meta: Metadata = Metadata::new(meta.as_slice()); + let lookup_table = meta.storage_lookup_table(); + let mut key = twox_128("System".as_bytes()).to_vec(); + key.extend(twox_128("Account".as_bytes()).iter()); + let storage_entry = lookup_table.lookup(&key); + println!("{:?}", storage_entry); + assert_eq!(storage_entry.unwrap().meta.prefix(), "System Account"); } diff --git a/integration_tests/tests/storage.rs b/integration_tests/tests/storage.rs index 28d49b4d..c7d77a82 100644 --- a/integration_tests/tests/storage.rs +++ b/integration_tests/tests/storage.rs @@ -1,8 +1,8 @@ use crate::test_suite; use codec::{Decode, Encode}; use desub_core::{ - decoder::{Chain, Decoder, Metadata}, - SubstrateType, + decoder::{Chain, Decoder, Metadata}, + SubstrateType, }; use frame_system::AccountInfo; use pallet_balances::AccountData; @@ -10,79 +10,68 @@ use primitives::twox_128; // hex(encoded): 010000000864000000000000000000000000000000c80000000000000000000000000000002c01000000000000000000000000000090010000000000000000000000000000 fn mock_account_info() -> AccountInfo> { - let mock_account_data: AccountData = AccountData { - free: 100, - reserved: 200, - misc_frozen: 300, - fee_frozen: 400, - }; - let mock_account_info: AccountInfo> = AccountInfo { - nonce: 1, - refcount: 8, - data: mock_account_data, - }; - mock_account_info + let mock_account_data: AccountData = + AccountData { free: 100, reserved: 200, misc_frozen: 300, fee_frozen: 400 }; + let mock_account_info: AccountInfo> = + AccountInfo { nonce: 1, refcount: 8, data: mock_account_data }; + mock_account_info } /// T::BlockNumber in meta V11 Block 1768321 fn get_plain_value() -> (Vec, Option>) { - let mut key = twox_128("System".as_bytes()).to_vec(); - key.extend(twox_128("Number".as_bytes()).iter()); - let value = 1768321u32.encode(); - (key, Some(value)) + let mut key = twox_128("System".as_bytes()).to_vec(); + key.extend(twox_128("Number".as_bytes()).iter()); + let value = 1768321u32.encode(); + (key, Some(value)) } #[test] fn should_decode_plain() { - pretty_env_logger::try_init(); + pretty_env_logger::try_init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); - let meta = test_suite::runtime_v11(); - let meta = Metadata::new(meta.as_slice()); - decoder.register_version(2023, &meta); + let meta = test_suite::runtime_v11(); + let meta = Metadata::new(meta.as_slice()); + decoder.register_version(2023, &meta); - let res = decoder.decode_storage(2023, get_plain_value()).unwrap(); - assert_eq!(&SubstrateType::U32(1768321), res.value().unwrap().ty()); + let res = decoder.decode_storage(2023, get_plain_value()).unwrap(); + assert_eq!(&SubstrateType::U32(1768321), res.value().unwrap().ty()); } #[test] fn should_decode_map() { - pretty_env_logger::try_init(); + pretty_env_logger::try_init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); - let meta = test_suite::runtime_v11(); - let meta = Metadata::new(meta.as_slice()); - decoder.register_version(2023, &meta); + let meta = test_suite::runtime_v11(); + let meta = Metadata::new(meta.as_slice()); + decoder.register_version(2023, &meta); - let account = mock_account_info(); - let encoded_account = account.encode(); - let storage_key = hex::decode("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da932a5935f6edc617ae178fef9eb1e211fbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f").unwrap(); + let account = mock_account_info(); + let encoded_account = account.encode(); + let storage_key = hex::decode("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da932a5935f6edc617ae178fef9eb1e211fbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f").unwrap(); - let res = decoder - .decode_storage(2023, (storage_key, Some(encoded_account))) - .unwrap(); - println!("{:?}", res); + let res = decoder.decode_storage(2023, (storage_key, Some(encoded_account))).unwrap(); + println!("{:?}", res); } #[test] fn should_decode_double_map() { - pretty_env_logger::try_init(); - let types = extras::TypeResolver::default(); - let mut decoder = Decoder::new(types, Chain::Kusama); + pretty_env_logger::try_init(); + let types = extras::TypeResolver::default(); + let mut decoder = Decoder::new(types, Chain::Kusama); - let meta = test_suite::runtime_v11(); - let meta = Metadata::new(meta.as_slice()); - decoder.register_version(2023, &meta); - // THIS STORAGE KEY IS WRONG for "ImOnline AuthoredBlocks" type - let storage_key = hex::decode("2b06af9719ac64d755623cda8ddd9b94b1c371ded9e9c565e89ba783c4d5f5f9b4def25cfda6ef3a00000000e535263148daaf49be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f").unwrap(); - let authored_blocks: u32 = 250; + let meta = test_suite::runtime_v11(); + let meta = Metadata::new(meta.as_slice()); + decoder.register_version(2023, &meta); + // THIS STORAGE KEY IS WRONG for "ImOnline AuthoredBlocks" type + let storage_key = hex::decode("2b06af9719ac64d755623cda8ddd9b94b1c371ded9e9c565e89ba783c4d5f5f9b4def25cfda6ef3a00000000e535263148daaf49be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f").unwrap(); + let authored_blocks: u32 = 250; - let res = decoder - .decode_storage(2023, (storage_key, Some(authored_blocks.encode()))) - .unwrap(); - println!("{:?}", res); + let res = decoder.decode_storage(2023, (storage_key, Some(authored_blocks.encode()))).unwrap(); + println!("{:?}", res); } diff --git a/integration_tests/tests/test_suite.rs b/integration_tests/tests/test_suite.rs index d191abf2..a0d4078c 100644 --- a/integration_tests/tests/test_suite.rs +++ b/integration_tests/tests/test_suite.rs @@ -4,137 +4,122 @@ use std::{fs::File, io::prelude::*}; // TODO: Can make `extrinsic test` into a macro -fn extrinsic_test>( - spec: S, - chain: Chain, - block: S, - num: usize, -) -> (Vec, Vec>) { - let spec: String = spec.into(); - let block: String = block.into(); - let mut exts: Vec> = Vec::new(); - let chain = chain.to_string(); - if std::path::Path::new("./integration_tests").exists() { - std::env::set_current_dir("./integration_tests").unwrap(); - } - let path = format!("{}{}/", EXT_PATH, chain); - let path = &format!("{}spec{}_block{}/", path, spec, block); - println!( - "{}/{}", - path, - std::env::current_dir().unwrap().to_str().unwrap() - ); - for i in 0..num { - let ext_path = &format!( - "{}EXTRINSIC_spec_{}_block_{}_index_{}.bin", - &path, spec, block, i - ); - let mut f = File::open(ext_path).expect("Opening extrinsic failed"); - let mut ext = Vec::new(); - f.read_to_end(&mut ext).expect("Reading file failed"); - exts.push(ext) - } - - let mut f = File::open(&format!( - "{}spec_{}_block_{}_METADATA.bin", - &path, spec, block - )) - .expect("Opening Metadata file failed"); - let mut meta = Vec::new(); - f.read_to_end(&mut meta).expect("Reading file failed"); - - (meta, exts) +fn extrinsic_test>(spec: S, chain: Chain, block: S, num: usize) -> (Vec, Vec>) { + let spec: String = spec.into(); + let block: String = block.into(); + let mut exts: Vec> = Vec::new(); + let chain = chain.to_string(); + if std::path::Path::new("./integration_tests").exists() { + std::env::set_current_dir("./integration_tests").unwrap(); + } + let path = format!("{}{}/", EXT_PATH, chain); + let path = &format!("{}spec{}_block{}/", path, spec, block); + println!("{}/{}", path, std::env::current_dir().unwrap().to_str().unwrap()); + for i in 0..num { + let ext_path = &format!("{}EXTRINSIC_spec_{}_block_{}_index_{}.bin", &path, spec, block, i); + let mut f = File::open(ext_path).expect("Opening extrinsic failed"); + let mut ext = Vec::new(); + f.read_to_end(&mut ext).expect("Reading file failed"); + exts.push(ext) + } + + let mut f = File::open(&format!("{}spec_{}_block_{}_METADATA.bin", &path, spec, block)) + .expect("Opening Metadata file failed"); + let mut meta = Vec::new(); + f.read_to_end(&mut meta).expect("Reading file failed"); + + (meta, exts) } /// returns raw metadata bytes and a vector of raw extrinsic bytes /// from block 342962 with spec 1031 pub fn extrinsics_block342962() -> (Vec, Vec>) { - extrinsic_test("1031", Chain::Kusama, "342962", 2) + extrinsic_test("1031", Chain::Kusama, "342962", 2) } /// returns raw metadata bytes and a vector of raw extrinsic bytes /// from block 422871 with spec 1031 /// there are three extrinsics: FinalityTracker, Parachains and Timestmap pub fn extrinsics_block422871() -> (Vec, Vec>) { - extrinsic_test("1031", Chain::Kusama, "422871", 3) + extrinsic_test("1031", Chain::Kusama, "422871", 3) } /// returns raw metadata bytes and a vector of raw extrinsic bytes /// from block 422871 with spec 1031 /// there are three extrinsics: FinalityTracker, Parachains and Timestmap pub fn extrinsics_block50970() -> (Vec, Vec>) { - extrinsic_test("1031", Chain::Kusama, "50970", 4) + extrinsic_test("1031", Chain::Kusama, "50970", 4) } /// returns raw metadata bytes and a vector of raw extrinsic bytes /// from block 422871 with spec 1031 /// there are three extrinsics: FinalityTracker, Parachains and Timestmap pub fn extrinsics_block106284() -> (Vec, Vec>) { - extrinsic_test("1042", Chain::Kusama, "106284", 4) + extrinsic_test("1042", Chain::Kusama, "106284", 4) } pub fn extrinsics_block1674683() -> (Vec, Vec>) { - extrinsic_test("1055", Chain::Kusama, "1674683", 3) + extrinsic_test("1055", Chain::Kusama, "1674683", 3) } pub fn extrinsics_block1677621() -> (Vec, Vec>) { - extrinsic_test("1055", Chain::Kusama, "1677621", 4) + extrinsic_test("1055", Chain::Kusama, "1677621", 4) } pub fn extrinsics_block1702023() -> (Vec, Vec>) { - extrinsic_test("1055", Chain::Kusama, "1702023", 17) + extrinsic_test("1055", Chain::Kusama, "1702023", 17) } pub fn extrinsics_block1714495() -> (Vec, Vec>) { - extrinsic_test("1055", Chain::Kusama, "1714495", 4) + extrinsic_test("1055", Chain::Kusama, "1714495", 4) } pub fn extrinsics_block1717926() -> (Vec, Vec>) { - extrinsic_test("1055", Chain::Kusama, "1717926", 4) + extrinsic_test("1055", Chain::Kusama, "1717926", 4) } pub fn extrinsics_block1718223() -> (Vec, Vec>) { - extrinsic_test("1055", Chain::Kusama, "1718223", 4) + extrinsic_test("1055", Chain::Kusama, "1718223", 4) } pub fn extrinsics_block1732321() -> (Vec, Vec>) { - extrinsic_test("1055", Chain::Kusama, "1732321", 4) + extrinsic_test("1055", Chain::Kusama, "1732321", 4) } pub fn extrinsics_block1731904() -> (Vec, Vec>) { - extrinsic_test("1055", Chain::Kusama, "1731904", 4) + extrinsic_test("1055", Chain::Kusama, "1731904", 4) } pub fn extrinsics_block1768321() -> (Vec, Vec>) { - extrinsic_test("1055", Chain::Kusama, "1768321", 3) + extrinsic_test("1055", Chain::Kusama, "1768321", 3) } pub fn extrinsics_block6144() -> (Vec, Vec>) { - extrinsic_test("1020", Chain::Kusama, "6144", 3) + extrinsic_test("1020", Chain::Kusama, "6144", 3) } pub fn extrinsics_block779410() -> (Vec, Vec>) { - extrinsic_test("1042", Chain::Kusama, "779410", 4) + extrinsic_test("1042", Chain::Kusama, "779410", 4) } pub fn extrinsics_block899638() -> (Vec, Vec>) { - extrinsic_test("1042", Chain::Kusama, "899638", 4) + extrinsic_test("1042", Chain::Kusama, "899638", 4) } pub fn extrinsics_block233816() -> (Vec, Vec>) { - extrinsic_test("1030", Chain::Kusama, "233816", 4) + extrinsic_test("1030", Chain::Kusama, "233816", 4) } pub fn extrinsics_block607421() -> (Vec, Vec>) { - extrinsic_test("1039", Chain::Kusama, "607421", 4) + extrinsic_test("1039", Chain::Kusama, "607421", 4) } pub fn extrinsics_block892_dot() -> (Vec, Vec>) { - extrinsic_test("0", Chain::Polkadot, "892", 4) + extrinsic_test("0", Chain::Polkadot, "892", 4) } pub fn extrinsics_block1191_wnd() -> (Vec, Vec>) { - extrinsic_test("1", Chain::Westend, "1191", 4) + extrinsic_test("1", Chain::Westend, "1191", 4) } /// Get the runtime metadata from KusamaCC3 from block 3,901,874 @@ -143,10 +128,10 @@ pub fn extrinsics_block1191_wnd() -> (Vec, Vec>) { /// # Panics /// Panics on std::io::Error pub fn runtime_v11() -> Vec { - let mut f = File::open("./data/metadata_v11.bin").expect("Opening file failed"); - let mut buffer = Vec::new(); - f.read_to_end(&mut buffer).expect("Reading file failed"); - buffer + let mut f = File::open("./data/metadata_v11.bin").expect("Opening file failed"); + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer).expect("Reading file failed"); + buffer } /// Get the runtime metadata from KusamaCC3 around block 361,0000 @@ -156,10 +141,10 @@ pub fn runtime_v11() -> Vec { /// # Panics /// Panics on std::io::Error pub fn runtime_v9() -> Vec { - let mut f = File::open("./data/metadata_v9.bin").expect("Opening file failed"); - let mut buffer = Vec::new(); - f.read_to_end(&mut buffer).expect("Reading file failed"); - buffer + let mut f = File::open("./data/metadata_v9.bin").expect("Opening file failed"); + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer).expect("Reading file failed"); + buffer } /// Get the runtime metadata from KusamaCC3 around block 361,0000 @@ -170,10 +155,10 @@ pub fn runtime_v9() -> Vec { /// # Panics /// Panics on std::io::Error pub fn runtime_v9_block500k() -> Vec { - let mut f = File::open("./data/metadata_v9_block500000.bin").expect("Opening file failed"); - let mut buffer = Vec::new(); - f.read_to_end(&mut buffer).expect("Reading file failed"); - buffer + let mut f = File::open("./data/metadata_v9_block500000.bin").expect("Opening file failed"); + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer).expect("Reading file failed"); + buffer } /// Get the runtime metadata from KusamaCC3 for metadata version 10 @@ -183,17 +168,17 @@ pub fn runtime_v9_block500k() -> Vec { /// # Panics /// Panics on std::io::Error pub fn runtime_v10() -> Vec { - let mut f = File::open("./data/metadata_v10.bin").expect("Opening file failed"); - let mut buffer = Vec::new(); - f.read_to_end(&mut buffer).expect("Reading file failed"); - buffer + let mut f = File::open("./data/metadata_v10.bin").expect("Opening file failed"); + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer).expect("Reading file failed"); + buffer } pub fn runtime_v12_block_4643974() -> Vec { - let mut f = File::open("./data/metadata_v12_block4643974.bin").expect("Opening file failed"); - let mut buffer = Vec::new(); - f.read_to_end(&mut buffer).expect("Reading file failed"); - buffer + let mut f = File::open("./data/metadata_v12_block4643974.bin").expect("Opening file failed"); + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer).expect("Reading file failed"); + buffer } /// Get some runtime metadata from KusamaCC3 at block 6 @@ -203,8 +188,8 @@ pub fn runtime_v12_block_4643974() -> Vec { /// # Panics /// Panics on std::io::Error pub fn runtime_v9_block6() -> Vec { - let mut f = File::open("./data/metadata_v9_block6.bin").expect("Opening file failed"); - let mut buffer = Vec::new(); - f.read_to_end(&mut buffer).expect("Reading file failed"); - buffer + let mut f = File::open("./data/metadata_v9_block6.bin").expect("Opening file failed"); + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer).expect("Reading file failed"); + buffer } diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index c83a407b..00000000 --- a/rustfmt.toml +++ /dev/null @@ -1,5 +0,0 @@ -edition = "2018" -# fn_args_layout = "compressed" -# spaces_around_ranges = true -max_width = 100 -# wrap_comments = true