diff --git a/pallets/slow-clap/Cargo.toml b/pallets/slow-clap/Cargo.toml index bb7ea6f..248ee78 100644 --- a/pallets/slow-clap/Cargo.toml +++ b/pallets/slow-clap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ghost-slow-clap" -version = "0.3.32" +version = "0.3.33" description = "Applause protocol for the EVM bridge" license.workspace = true authors.workspace = true diff --git a/pallets/slow-clap/src/deserialisations.rs b/pallets/slow-clap/src/deserialisations.rs new file mode 100644 index 0000000..1597555 --- /dev/null +++ b/pallets/slow-clap/src/deserialisations.rs @@ -0,0 +1,57 @@ +use crate::{Deserialize, Deserializer, Vec, H256}; + +pub fn de_string_to_bytes<'de, D>(de: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let s: &str = Deserialize::deserialize(de)?; + Ok(Some(s.as_bytes().to_vec())) +} + +pub fn de_string_to_u64<'de, D>(de: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s: &str = Deserialize::deserialize(de)?; + let s = if s.starts_with("0x") { &s[2..] } else { &s }; + Ok(u64::from_str_radix(s, 16).ok()) +} + +pub fn de_string_to_u64_pure<'de, D>(de: D) -> Result +where + D: Deserializer<'de>, +{ + let s: &str = Deserialize::deserialize(de)?; + let s = if s.starts_with("0x") { &s[2..] } else { &s }; + Ok(u64::from_str_radix(s, 16).unwrap_or_default()) +} + +pub fn de_string_to_h256<'de, D>(de: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s: &str = Deserialize::deserialize(de)?; + let start_index = if s.starts_with("0x") { 2 } else { 0 }; + let h256: Vec<_> = (start_index..s.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("valid u8 symbol; qed")) + .collect(); + Ok(Some(H256::from_slice(&h256))) +} + +pub fn de_string_to_vec_of_bytes<'de, D>(de: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let strings: Vec<&str> = Deserialize::deserialize(de)?; + Ok(strings + .iter() + .map(|s| { + let start_index = if s.starts_with("0x") { 2 } else { 0 }; + (start_index..s.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("valid u8 symbol; qed")) + .collect::>() + }) + .collect::>>()) +} diff --git a/pallets/slow-clap/src/evm_types.rs b/pallets/slow-clap/src/evm_types.rs new file mode 100644 index 0000000..28a2104 --- /dev/null +++ b/pallets/slow-clap/src/evm_types.rs @@ -0,0 +1,49 @@ +use crate::{ + deserialisations::{ + de_string_to_bytes, de_string_to_h256, de_string_to_u64, de_string_to_u64_pure, + de_string_to_vec_of_bytes, + }, + Decode, Deserialize, Encode, RuntimeDebug, Vec, H256, +}; + +const NUMBER_OF_TOPICS: usize = 3; + +#[derive(RuntimeDebug, Clone, PartialEq, Deserialize, Encode, Decode)] +pub struct EvmResponse { + #[serde(default)] + id: Option, + #[serde(default, deserialize_with = "de_string_to_bytes")] + jsonrpc: Option>, + #[serde(default, deserialize_with = "de_string_to_bytes")] + pub error: Option>, + #[serde(default)] + pub result: Option, +} + +#[derive(RuntimeDebug, Clone, PartialEq, Deserialize, Encode, Decode)] +#[serde(untagged)] +pub enum EvmResponseType { + #[serde(deserialize_with = "de_string_to_u64_pure")] + BlockNumber(u64), + TransactionLogs(Vec), +} + +#[derive(RuntimeDebug, Clone, Eq, PartialEq, Ord, PartialOrd, Deserialize, Encode, Decode)] +#[serde(rename_all = "camelCase")] +pub struct Log { + #[serde(default, deserialize_with = "de_string_to_h256")] + pub transaction_hash: Option, + #[serde(default, deserialize_with = "de_string_to_u64")] + pub block_number: Option, + #[serde(default, deserialize_with = "de_string_to_vec_of_bytes")] + pub topics: Vec>, + pub removed: bool, +} + +impl Log { + pub fn is_sufficient(&self) -> bool { + self.transaction_hash.is_some() + && self.block_number.is_some() + && self.topics.len() == NUMBER_OF_TOPICS + } +} diff --git a/pallets/slow-clap/src/lib.rs b/pallets/slow-clap/src/lib.rs index 21572e1..2513b81 100644 --- a/pallets/slow-clap/src/lib.rs +++ b/pallets/slow-clap/src/lib.rs @@ -48,6 +48,11 @@ mod benchmarking; mod mock; mod tests; +mod deserialisations; +mod evm_types; + +use evm_types::{EvmResponse, EvmResponseType}; + pub mod sr25519 { mod app_sr25519 { use sp_application_crypto::{app_crypto, sr25519, KeyTypeId}; @@ -68,126 +73,9 @@ const DB_PREFIX: &[u8] = b"slow_clap::"; const FETCH_TIMEOUT_PERIOD: u64 = 3_000; const LOCK_BLOCK_EXPIRATION: u64 = 10; -const NUMBER_OF_TOPICS: usize = 3; pub type AuthIndex = u32; -#[derive(RuntimeDebug, Clone, PartialEq, Deserialize, Encode, Decode)] -struct EvmResponse { - #[serde(default)] - id: Option, - #[serde(default, deserialize_with = "de_string_to_bytes")] - jsonrpc: Option>, - #[serde(default, deserialize_with = "de_string_to_bytes")] - error: Option>, - #[serde(default)] - result: Option, -} - -#[derive(RuntimeDebug, Clone, PartialEq, Deserialize, Encode, Decode)] -#[serde(untagged)] -enum EvmResponseType { - #[serde(deserialize_with = "de_string_to_u64_pure")] - BlockNumber(u64), - TransactionLogs(Vec), -} - -#[derive(RuntimeDebug, Clone, Eq, PartialEq, Ord, PartialOrd, Deserialize, Encode, Decode)] -#[serde(rename_all = "camelCase")] -struct Log { - #[serde(default, deserialize_with = "de_string_to_h256")] - transaction_hash: Option, - #[serde(default, deserialize_with = "de_string_to_u64")] - block_number: Option, - #[serde(default, deserialize_with = "de_string_to_vec_of_bytes")] - topics: Vec>, - #[serde(default, deserialize_with = "de_string_to_bytes")] - address: Option>, - #[serde(default, deserialize_with = "de_string_to_btree_map")] - data: BTreeMap, - removed: bool, -} - -impl Log { - fn is_sufficient(&self) -> bool { - self.transaction_hash.is_some() - && self.block_number.is_some() - && self.topics.len() == NUMBER_OF_TOPICS - } -} - -pub fn de_string_to_bytes<'de, D>(de: D) -> Result>, D::Error> -where - D: Deserializer<'de>, -{ - let s: &str = Deserialize::deserialize(de)?; - Ok(Some(s.as_bytes().to_vec())) -} - -pub fn de_string_to_u64<'de, D>(de: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let s: &str = Deserialize::deserialize(de)?; - let s = if s.starts_with("0x") { &s[2..] } else { &s }; - Ok(u64::from_str_radix(s, 16).ok()) -} - -pub fn de_string_to_u64_pure<'de, D>(de: D) -> Result -where - D: Deserializer<'de>, -{ - let s: &str = Deserialize::deserialize(de)?; - let s = if s.starts_with("0x") { &s[2..] } else { &s }; - Ok(u64::from_str_radix(s, 16).unwrap_or_default()) -} - -pub fn de_string_to_h256<'de, D>(de: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let s: &str = Deserialize::deserialize(de)?; - let start_index = if s.starts_with("0x") { 2 } else { 0 }; - let h256: Vec<_> = (start_index..s.len()) - .step_by(2) - .map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("valid u8 symbol; qed")) - .collect(); - Ok(Some(H256::from_slice(&h256))) -} - -pub fn de_string_to_vec_of_bytes<'de, D>(de: D) -> Result>, D::Error> -where - D: Deserializer<'de>, -{ - let strings: Vec<&str> = Deserialize::deserialize(de)?; - Ok(strings - .iter() - .map(|s| { - let start_index = if s.starts_with("0x") { 2 } else { 0 }; - (start_index..s.len()) - .step_by(2) - .map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("valid u8 symbol; qed")) - .collect::>() - }) - .collect::>>()) -} - -pub fn de_string_to_btree_map<'de, D>(de: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let s: &str = Deserialize::deserialize(de)?; - let start_index = if s.starts_with("0x") { 2 } else { 0 }; - Ok(BTreeMap::from_iter((start_index..s.len()).step_by(64).map( - |i| { - ( - u128::from_str_radix(&s[i..i + 32], 16).expect("valid u8 symbol; qed"), - u128::from_str_radix(&s[i + 32..i + 64], 16).expect("valid u8 symbol; qed"), - ) - }, - ))) -} - #[derive( RuntimeDebug, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo, MaxEncodedLen, )]