Fix the module index used to create a encoded func (#47)

* Fix the module index used to create a encoded func

Same as Events, modules with no calls should be ignored when calculating
the module index.

* Update substrate
This commit is contained in:
Yuanchao Sun
2019-11-28 20:46:39 +08:00
committed by Andrew Jones
parent a6439500eb
commit 5108bce467
5 changed files with 158 additions and 111 deletions
+1 -1
View File
@@ -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"
+5 -6
View File
@@ -157,7 +157,7 @@ impl<T: System + Balances + 'static> EventsDecoder<T> {
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<T: System + Balances + 'static> EventsDecoder<T> {
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::<u8>::new();
self.decode_raw_bytes(
@@ -237,7 +236,7 @@ impl<T: System + Balances + 'static> EventsDecoder<T> {
&mut event_data,
)?;
RuntimeEvent::Raw(RawEvent {
module: module_name.clone(),
module: module.name().to_string(),
variant: event_metadata.name.clone(),
data: event_data,
})
+6 -3
View File
@@ -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 =
<pallet_balances::FreeBalance<node_runtime::Runtime>>::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::<AccountId, Balance>()
+137 -92
View File
@@ -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<String, ModuleMetadata>,
modules_by_event_index: HashMap<u8, String>,
modules_with_calls: HashMap<String, ModuleWithCalls>,
modules_with_events: HashMap<String, ModuleWithEvents>,
}
impl Metadata {
pub fn modules(&self) -> impl Iterator<Item = &ModuleMetadata> {
self.modules.values()
}
pub fn module<S>(&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<String, MetadataError> {
self.modules_by_event_index
.get(&module_index)
.cloned()
.ok_or(MetadataError::EventNotFound(module_index))
pub fn module_with_calls<S>(&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<Item = &ModuleWithEvents> {
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<String, StorageMetadata>,
calls: HashMap<String, Vec<u8>>,
events: HashMap<u8, ModuleEventMetadata>,
// 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<String, u8>,
}
impl ModuleWithCalls {
pub fn call<T: Encode>(
&self,
function: &'static str,
params: T,
) -> Result<Encoded, MetadataError> {
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<u8, ModuleEventMetadata>,
}
impl ModuleWithEvents {
pub fn name(&self) -> &str {
&self.name
}
pub fn events(&self) -> impl Iterator<Item = &ModuleEventMetadata> {
@@ -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<u8>,
@@ -169,13 +203,15 @@ impl StorageMetadata {
) -> Result<StorageMap<K, V>, 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<K, V> {
_marker: PhantomData<K>,
prefix: Vec<u8>,
module_prefix: Vec<u8>,
storage_prefix: Vec<u8>,
hasher: StorageHasher,
default: V,
}
impl<K: Encode, V: Decode + Clone> StorageMap<K, V> {
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<RuntimeMetadataPrefixed> 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<B: 'static, O: 'static>(dd: DecodeDifferent<B, O>) -> Result<O, Error
}
}
fn convert_module(
index: usize,
module: runtime_metadata::ModuleMetadata,
) -> Result<ModuleMetadata, Error> {
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<ModuleEventMetadata, Error> {
@@ -386,12 +429,14 @@ fn convert_event(
}
fn convert_entry(
prefix: String,
module_prefix: String,
storage_prefix: String,
entry: runtime_metadata::StorageEntryMetadata,
) -> Result<StorageMetadata, Error> {
let default = convert(entry.default)?;
Ok(StorageMetadata {
prefix,
module_prefix,
storage_prefix,
modifier: entry.modifier,
ty: entry.ty,
default,
+9 -9
View File
@@ -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<T: System + Balances + 'static> Rpc<T> {
&self,
) -> impl Future<Item = MapStream<StorageChangeSet<<T as System>::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<StorageChangeSet<<T as System>::Hash>> =
@@ -204,7 +204,7 @@ impl<T: System + Balances + 'static> Rpc<T> {
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<T: System + Balances + 'static> Rpc<T> {
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()