diff --git a/Cargo.toml b/Cargo.toml index 6988c13252..8856789b40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ pallet-indices = { git = "https://github.com/paritytech/substrate/", package = " substrate-rpc-api = { git = "https://github.com/paritytech/substrate/", package = "sc-rpc-api" } substrate-rpc-primitives = { git = "https://github.com/paritytech/substrate/", package = "substrate-rpc-primitives" } substrate-primitives = { git = "https://github.com/paritytech/substrate/", package = "substrate-primitives" } -txpool = { git = "https://github.com/paritytech/substrate/", package = "sc-transaction-graph" } +txpool-api = { git = "https://github.com/paritytech/substrate/", package = "sp-transaction-pool-api" } [dev-dependencies] env_logger = "0.7" diff --git a/src/events.rs b/src/events.rs index 419889cedc..984f0a27d5 100644 --- a/src/events.rs +++ b/src/events.rs @@ -157,7 +157,7 @@ impl EventsDecoder { let mut missing = HashSet::new(); let mut ignore_set = HashSet::new(); ignore_set.extend(ignore); - for module in self.metadata.modules() { + for module in self.metadata.modules_with_events() { for event in module.events() { for arg in event.arguments() { for primitive in arg.primitives() { @@ -220,15 +220,14 @@ impl EventsDecoder { let phase = Phase::decode(input)?; let module_variant = input.read_byte()? as u8; - let module_name = self.metadata.module_name(module_variant)?; - let event = if module_name == "System" { + let module = self.metadata.module_with_events(module_variant)?; + let event = if module.name() == "System" { let system_event = SystemEvent::decode(input)?; RuntimeEvent::System(system_event) } else { let event_variant = input.read_byte()? as u8; - let module = self.metadata.module(&module_name)?; let event_metadata = module.event(event_variant)?; - log::debug!("decoding event '{}::{}'", module_name, event_metadata.name); + log::debug!("decoding event '{}::{}'", module.name(), event_metadata.name); let mut event_data = Vec::::new(); self.decode_raw_bytes( @@ -237,7 +236,7 @@ impl EventsDecoder { &mut event_data, )?; RuntimeEvent::Raw(RawEvent { - module: module_name.clone(), + module: module.name().to_string(), variant: event_metadata.name.clone(), data: event_data, }) diff --git a/src/lib.rs b/src/lib.rs index 1417d5a1f2..7a8d58c6c8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -339,7 +339,7 @@ where let genesis_hash = self.genesis_hash; let call = self .metadata() - .module(&call.module) + .module_with_calls(&call.module) .and_then(|module| module.call(&call.function, call.args))?; log::info!( @@ -527,7 +527,7 @@ mod tests { fn test_chain_read_metadata() { let (_, client) = test_setup(); - let balances = client.metadata().module("Balances").unwrap(); + let balances = client.metadata().module_with_calls("Balances").unwrap(); let dest = substrate_keyring::AccountKeyring::Bob.to_account_id(); let address: Address = dest.clone().into(); let amount: Balance = 10_000; @@ -541,7 +541,10 @@ mod tests { let free_balance = >::hashed_key_for(&dest); let free_balance_key = StorageKey(free_balance); - let free_balance_key2 = balances + let free_balance_key2 = client + .metadata() + .module("Balances") + .unwrap() .storage("FreeBalance") .unwrap() .get_map::() diff --git a/src/metadata.rs b/src/metadata.rs index 61e6e2a63a..52a2c981fb 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -43,6 +43,8 @@ use crate::codec::Encoded; pub enum MetadataError { #[error("Module not found")] ModuleNotFound(String), + #[error("Module with events not found")] + ModuleWithEventsNotFound(u8), #[error("Call not found")] CallNotFound(&'static str), #[error("Event not found")] @@ -58,14 +60,11 @@ pub enum MetadataError { #[derive(Clone, Debug)] pub struct Metadata { modules: HashMap, - modules_by_event_index: HashMap, + modules_with_calls: HashMap, + modules_with_events: HashMap, } impl Metadata { - pub fn modules(&self) -> impl Iterator { - self.modules.values() - } - pub fn module(&self, name: S) -> Result<&ModuleMetadata, MetadataError> where S: ToString, @@ -76,11 +75,28 @@ impl Metadata { .ok_or(MetadataError::ModuleNotFound(name)) } - pub fn module_name(&self, module_index: u8) -> Result { - self.modules_by_event_index - .get(&module_index) - .cloned() - .ok_or(MetadataError::EventNotFound(module_index)) + pub fn module_with_calls(&self, name: S) -> Result<&ModuleWithCalls, MetadataError> + where + S: ToString, + { + let name = name.to_string(); + self.modules_with_calls + .get(&name) + .ok_or(MetadataError::ModuleNotFound(name)) + } + + pub fn modules_with_events(&self) -> impl Iterator { + self.modules_with_events.values() + } + + pub fn module_with_events( + &self, + module_index: u8, + ) -> Result<&ModuleWithEvents, MetadataError> { + self.modules_with_events + .values() + .find(|&module| module.index == module_index) + .ok_or(MetadataError::ModuleWithEventsNotFound(module_index)) } pub fn pretty(&self) -> String { @@ -93,15 +109,19 @@ impl Metadata { string.push_str(storage.as_str()); string.push('\n'); } - for call in module.calls.keys() { - string.push_str(" c "); - string.push_str(call.as_str()); - string.push('\n'); + if let Some(module) = self.modules_with_calls.get(name) { + 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'); + if let Some(module) = self.modules_with_events.get(name) { + for event in module.events.values() { + string.push_str(" e "); + string.push_str(event.name.as_str()); + string.push('\n'); + } } } string @@ -110,38 +130,51 @@ impl Metadata { #[derive(Clone, Debug)] pub struct ModuleMetadata { - index: u8, name: String, storage: HashMap, - calls: HashMap>, - events: HashMap, // constants } impl ModuleMetadata { - pub fn name(&self) -> &str { - &self.name + pub fn storage(&self, key: &'static str) -> Result<&StorageMetadata, MetadataError> { + self.storage + .get(key) + .ok_or(MetadataError::StorageNotFound(key)) } +} +#[derive(Clone, Debug)] +pub struct ModuleWithCalls { + index: u8, + calls: HashMap, +} + +impl ModuleWithCalls { pub fn call( &self, function: &'static str, params: T, ) -> Result { - let fn_bytes = self + let fn_index = self .calls .get(function) .ok_or(MetadataError::CallNotFound(function))?; - let mut bytes = vec![self.index]; - bytes.extend(fn_bytes); + let mut bytes = vec![self.index, *fn_index]; bytes.extend(params.encode()); Ok(Encoded(bytes)) } +} - pub fn storage(&self, key: &'static str) -> Result<&StorageMetadata, MetadataError> { - self.storage - .get(key) - .ok_or(MetadataError::StorageNotFound(key)) +#[derive(Clone, Debug)] +pub struct ModuleWithEvents { + index: u8, + name: String, + events: HashMap, +} + +impl ModuleWithEvents { + pub fn name(&self) -> &str { + &self.name } pub fn events(&self) -> impl Iterator { @@ -157,7 +190,8 @@ impl ModuleMetadata { #[derive(Clone, Debug)] pub struct StorageMetadata { - prefix: String, + module_prefix: String, + storage_prefix: String, modifier: StorageEntryModifier, ty: StorageEntryType, default: Vec, @@ -169,13 +203,15 @@ impl StorageMetadata { ) -> Result, MetadataError> { match &self.ty { StorageEntryType::Map { hasher, .. } => { - let prefix = self.prefix.as_bytes().to_vec(); + let module_prefix = self.module_prefix.as_bytes().to_vec(); + let storage_prefix = self.storage_prefix.as_bytes().to_vec(); let hasher = hasher.to_owned(); let default = Decode::decode(&mut &self.default[..]) .map_err(|_| MetadataError::MapValueTypeError)?; Ok(StorageMap { _marker: PhantomData, - prefix, + module_prefix, + storage_prefix, hasher, default, }) @@ -188,27 +224,30 @@ impl StorageMetadata { #[derive(Clone, Debug)] pub struct StorageMap { _marker: PhantomData, - prefix: Vec, + module_prefix: Vec, + storage_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 mut bytes = substrate_primitives::twox_128(&self.module_prefix).to_vec(); + bytes.extend(&substrate_primitives::twox_128(&self.storage_prefix)[..]); + let encoded_key = key.encode(); let hash = match self.hasher { StorageHasher::Blake2_128 => { - substrate_primitives::blake2_128(&bytes).to_vec() + substrate_primitives::blake2_128(&encoded_key).to_vec() } StorageHasher::Blake2_256 => { - substrate_primitives::blake2_256(&bytes).to_vec() + substrate_primitives::blake2_256(&encoded_key).to_vec() } - StorageHasher::Twox128 => substrate_primitives::twox_128(&bytes).to_vec(), - StorageHasher::Twox256 => substrate_primitives::twox_256(&bytes).to_vec(), - StorageHasher::Twox64Concat => substrate_primitives::twox_64(&bytes).to_vec(), + StorageHasher::Twox128 => substrate_primitives::twox_128(&encoded_key).to_vec(), + StorageHasher::Twox256 => substrate_primitives::twox_256(&encoded_key).to_vec(), + StorageHasher::Twox64Concat => substrate_primitives::twox_64(&encoded_key).to_vec(), }; - StorageKey(hash) + bytes.extend(hash); + StorageKey(bytes) } pub fn default(&self) -> V { @@ -306,25 +345,66 @@ impl TryFrom for Metadata { return Err(Error::InvalidPrefix) } let meta = match metadata.1 { - RuntimeMetadata::V8(meta) => meta, + RuntimeMetadata::V9(meta) => meta, _ => return Err(Error::InvalidVersion), }; let mut modules = HashMap::new(); - let mut modules_by_event_index = HashMap::new(); - let mut event_index = 0; - for (i, module) in convert(meta.modules)?.into_iter().enumerate() { + let mut modules_with_calls = HashMap::new(); + let mut modules_with_events = HashMap::new(); + for module in convert(meta.modules)?.into_iter() { let module_name = convert(module.name.clone())?; - let module_metadata = convert_module(i, module)?; - // modules with no events have no corresponding definition in the top level enum - if !module_metadata.events.is_empty() { - modules_by_event_index.insert(event_index, module_name.clone()); - event_index += 1; + + let mut storage_map = HashMap::new(); + if let Some(storage) = module.storage { + let storage = convert(storage)?; + let module_prefix = convert(storage.prefix)?; + for entry in convert(storage.entries)?.into_iter() { + let storage_prefix = convert(entry.name.clone())?; + let entry = convert_entry(module_prefix.clone(), storage_prefix.clone(), entry)?; + storage_map.insert(storage_prefix, entry); + } + } + modules.insert( + module_name.clone(), + ModuleMetadata { + name: module_name.clone(), + storage: storage_map, + }, + ); + + if let Some(calls) = module.calls { + let mut call_map = HashMap::new(); + for (index, call) in convert(calls)?.into_iter().enumerate() { + let name = convert(call.name)?; + call_map.insert(name, index as u8); + } + modules_with_calls.insert( + module_name.clone(), + ModuleWithCalls { + index: modules_with_calls.len() as u8, + calls: call_map, + }, + ); + } + if let Some(events) = module.event { + let mut event_map = HashMap::new(); + for (index, event) in convert(events)?.into_iter().enumerate() { + event_map.insert(index as u8, convert_event(event)?); + } + modules_with_events.insert( + module_name.clone(), + ModuleWithEvents { + index: modules_with_events.len() as u8, + name: module_name.clone(), + events: event_map, + }, + ); } - modules.insert(module_name, module_metadata); } Ok(Metadata { modules, - modules_by_event_index, + modules_with_calls, + modules_with_events, }) } } @@ -336,43 +416,6 @@ fn convert(dd: DecodeDifferent) -> Result 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)?; - call_map.insert(name, vec![index as u8]); - } - } - 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, - }) -} - fn convert_event( event: runtime_metadata::EventMetadata, ) -> Result { @@ -386,12 +429,14 @@ fn convert_event( } fn convert_entry( - prefix: String, + module_prefix: String, + storage_prefix: String, entry: runtime_metadata::StorageEntryMetadata, ) -> Result { let default = convert(entry.default)?; Ok(StorageMetadata { - prefix, + module_prefix, + storage_prefix, modifier: entry.modifier, ty: entry.ty, default, diff --git a/src/rpc.rs b/src/rpc.rs index fbbfdd456e..89ca279476 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -65,7 +65,7 @@ use substrate_rpc_primitives::{ list::ListOrValue, number::NumberOrHex, }; -use txpool::watcher::Status; +use txpool_api::TransactionStatus; use crate::{ error::Error, @@ -194,8 +194,8 @@ impl Rpc { &self, ) -> impl Future::Hash>>, Error = Error> { - let events_key = b"System Events"; - let storage_key = twox_128(events_key); + let mut storage_key = twox_128(b"System").to_vec(); + storage_key.extend(twox_128(b"Events").to_vec()); log::debug!("Events storage key {:?}", storage_key); let closure: MapClosure::Hash>> = @@ -204,7 +204,7 @@ impl Rpc { event }); self.state - .subscribe_storage(Some(vec![StorageKey(storage_key.to_vec())])) + .subscribe_storage(Some(vec![StorageKey(storage_key)])) .map(|stream: TypedSubscriptionStream<_>| stream.map(closure)) .map_err(Into::into) } @@ -274,15 +274,15 @@ impl Rpc { log::info!("received status {:?}", status); match status { // ignore in progress extrinsic for now - Status::Future | Status::Ready | Status::Broadcast(_) => { + TransactionStatus::Future | TransactionStatus::Ready | TransactionStatus::Broadcast(_) => { None } - Status::Finalized(block_hash) => Some(Ok(block_hash)), - Status::Usurped(_) => { + TransactionStatus::Finalized(block_hash) => Some(Ok(block_hash)), + TransactionStatus::Usurped(_) => { Some(Err("Extrinsic Usurped".into())) } - Status::Dropped => Some(Err("Extrinsic Dropped".into())), - Status::Invalid => Some(Err("Extrinsic Invalid".into())), + TransactionStatus::Dropped => Some(Err("Extrinsic Dropped".into())), + TransactionStatus::Invalid => Some(Err("Extrinsic Invalid".into())), } }) .into_future()