mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 09:21:05 +00:00
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:
committed by
Andrew Jones
parent
a6439500eb
commit
5108bce467
+1
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user