Collect type ID from metadata pallet

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This commit is contained in:
Alexandru Vasile
2023-03-06 20:29:40 +02:00
parent f8399ca81f
commit 1f12320d50
11 changed files with 68665 additions and 6 deletions
+1
View File
@@ -1,4 +1,5 @@
/target /target
/**/target
**/*.rs.bk **/*.rs.bk
**/.DS_Store **/.DS_Store
cargo-timing* cargo-timing*
Generated
+4 -4
View File
@@ -3554,18 +3554,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.38" version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.38" version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
Binary file not shown.
+1 -1
View File
@@ -25,7 +25,7 @@ subxt-metadata = { version = "0.27.1", path = "../metadata" }
jsonrpsee = { version = "0.16.0", features = ["async-client", "client-ws-transport", "http-client"] } jsonrpsee = { version = "0.16.0", features = ["async-client", "client-ws-transport", "http-client"] }
hex = "0.4.3" hex = "0.4.3"
tokio = { version = "1.26", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.26", features = ["macros", "rt-multi-thread"] }
thiserror = "1.0.24" thiserror = "1.0.39"
[dev-dependencies] [dev-dependencies]
bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] }
+30
View File
@@ -0,0 +1,30 @@
// Copyright 2019-2022 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
//! To run this example, a local polkadot node should be running. Example verified against polkadot v0.9.28-9ffe6e9e3da.
//!
//! E.g.
//! ```bash
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.28/polkadot" --output /usr/local/bin/polkadot --location
//! polkadot --dev --tmp
//! ```
use sp_keyring::AccountKeyring;
use subxt::{
tx::PairSigner,
OnlineClient,
PolkadotConfig,
};
#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")]
pub mod polkadot {}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();
let metadata = Decode::
Ok(())
}
+68187
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -17,6 +17,8 @@ use scale_info::{
}; };
use std::collections::HashSet; use std::collections::HashSet;
pub mod stripped;
/// Internal byte representation for various metadata types utilized for /// Internal byte representation for various metadata types utilized for
/// generating deterministic hashes between different rust versions. /// generating deterministic hashes between different rust versions.
#[repr(u8)] #[repr(u8)]
+232
View File
@@ -0,0 +1,232 @@
// Copyright 2019-2022 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use frame_metadata::{
ExtrinsicMetadata,
PalletMetadata,
RuntimeMetadataV14,
StorageEntryMetadata,
StorageEntryType,
};
use scale_info::{
form::PortableForm,
interner::UntrackedSymbol,
Field,
PortableRegistry,
Registry,
Type,
TypeDef,
Variant,
};
use std::{
any::TypeId,
collections::{
BTreeSet,
HashSet,
},
};
/// Strip Error.
#[derive(Debug)]
pub enum StripError {
/// Pallet not present in the provided metadata.
PalletNotFound,
/// Pallet not present in the provided metadata.
TypeNotFound(u32),
}
/// Collect the type IDs from the given pallet.
fn collect_pallet_types(pallet: &PalletMetadata<PortableForm>) -> BTreeSet<u32> {
let mut type_ids = BTreeSet::new();
println!("Collect");
println!("Pallet is : {:?}", pallet);
if let Some(storage) = &pallet.storage {
println!("storage : {:?}", storage);
for entry in storage.entries.iter() {
println!("Entry : {:?}", entry);
match entry.ty {
StorageEntryType::Plain(ty) => {
type_ids.insert(ty.id());
}
StorageEntryType::Map { key, value, .. } => {
type_ids.insert(key.id());
type_ids.insert(value.id());
}
}
}
}
if let Some(calls) = &pallet.calls {
let ty = calls.ty;
type_ids.insert(ty.id());
}
if let Some(event) = &pallet.event {
let ty = event.ty;
type_ids.insert(ty.id());
}
for constant in pallet.constants.iter() {
let ty = constant.ty;
type_ids.insert(ty.id());
}
if let Some(error) = &pallet.error {
let ty = error.ty;
type_ids.insert(ty.id());
}
type_ids
}
/// Recursively add all type IDs needed to express the given type ID.
fn extend_type_id(
registry: &PortableRegistry,
id: u32,
result: &mut BTreeSet<u32>,
visited: &mut HashSet<u32>,
) -> Result<(), StripError> {
if visited.contains(&id) {
return Ok(())
}
visited.insert(id);
let ty = registry.resolve(id).ok_or(StripError::TypeNotFound(id))?;
let mut extended = Vec::new();
// Add generic type params.
for param in ty.type_params() {
if let Some(ty) = param.ty() {
extended.push(ty.id());
}
}
match ty.type_def() {
TypeDef::Composite(composite) => {
for field in composite.fields() {
extended.push(field.ty().id());
}
}
TypeDef::Variant(variant) => {
for var in variant.variants() {
for field in var.fields() {
extended.push(field.ty().id());
}
}
}
TypeDef::Sequence(sequence) => {
extended.push(sequence.type_param().id());
}
TypeDef::Array(array) => {
extended.push(array.type_param().id());
}
TypeDef::Tuple(tuple) => {
for ty in tuple.fields() {
extended.push(ty.id());
}
}
TypeDef::Primitive(_) => (),
TypeDef::Compact(compact) => {
extended.push(compact.type_param().id());
}
TypeDef::BitSequence(bit_sequence) => {
extended.push(bit_sequence.bit_store_type().id());
extended.push(bit_sequence.bit_order_type().id());
}
}
for ext in extended {
result.insert(ext);
extend_type_id(registry, ext, result, visited)?;
}
Ok(())
}
/// Keep only the pallet inside the metadata.
pub fn keep_pallet<T: AsRef<str>>(
metadata: RuntimeMetadataV14,
pallet_name: T,
) -> Result<RuntimeMetadataV14, StripError> {
let pallet = metadata
.pallets
.iter()
.find(|pallet| pallet.name == pallet_name.as_ref());
let Some(pallet) = pallet else {
return Err(StripError::PalletNotFound)
};
// Collect type ids from the pallet.
let mut type_ids = collect_pallet_types(pallet);
println!("TypeIDs {:#?}", type_ids);
// println!("TypeIDs {:#?}", type_ids);
// Extend the type IDs with their dependencies
let registry = &metadata.types;
let mut result = BTreeSet::new();
let mut visited = HashSet::new();
for id in type_ids.iter() {
extend_type_id(registry, *id, &mut result, &mut visited)?;
}
type_ids.extend(result.iter());
println!("TypeIDs Extended {:#?}", type_ids);
println!(
"Pallet [{}]\n stripped {} vs full {}\n",
pallet_name.as_ref(),
type_ids.len(),
metadata.types.types().len()
);
Ok(metadata)
}
#[cfg(test)]
mod tests {
use super::*;
use codec::Decode;
use frame_metadata::{
RuntimeMetadata,
RuntimeMetadataPrefixed,
RuntimeMetadataV14,
};
use scale_info::meta_type;
use std::{
fs,
path::Path,
};
fn load_metadata() -> RuntimeMetadataV14 {
let bytes = fs::read(Path::new("../artifacts/polkadot_metadata.scale"))
.expect("Cannot read metadata blob");
let meta: RuntimeMetadataPrefixed =
Decode::decode(&mut &*bytes).expect("Cannot decode scale metadata");
match meta.1 {
RuntimeMetadata::V14(v14) => v14,
_ => panic!("Unsupported metadata version {:?}", meta.1),
}
}
#[test]
fn strip_pallet() {
let metadata = load_metadata();
keep_pallet(metadata, "AuthorityDiscovery").unwrap();
// for pallet in metadata.pallets.iter() {
// let metadata = load_metadata();
// keep_pallet(metadata, &pallet.name).unwrap();
// }
}
}
+207
View File
@@ -0,0 +1,207 @@
running 1 test
TypeIDs {
0,
3,
4,
7,
11,
12,
13,
17,
20,
43,
80,
156,
158,
159,
161,
165,
169,
171,
172,
176,
}
TypeIDs Extended {
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122,
123,
124,
125,
126,
127,
128,
129,
130,
131,
132,
133,
134,
135,
136,
137,
138,
139,
140,
141,
142,
143,
144,
145,
146,
147,
148,
149,
150,
151,
152,
153,
154,
155,
156,
157,
158,
159,
160,
161,
162,
163,
164,
165,
166,
167,
168,
169,
170,
171,
172,
173,
174,
175,
176,
}
test stripped::tests::strip_pallet ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 6 filtered out; finished in 0.01s
+1 -1
View File
@@ -45,7 +45,7 @@ hex = "0.4.3"
jsonrpsee = { version = "0.16", optional = true, features = ["jsonrpsee-types"] } jsonrpsee = { version = "0.16", optional = true, features = ["jsonrpsee-types"] }
serde = { version = "1.0.124", features = ["derive"] } serde = { version = "1.0.124", features = ["derive"] }
serde_json = { version = "1.0.94", features = ["raw_value"] } serde_json = { version = "1.0.94", features = ["raw_value"] }
thiserror = "1.0.24" thiserror = "1.0.39"
tracing = "0.1.34" tracing = "0.1.34"
parking_lot = "0.12.0" parking_lot = "0.12.0"
frame-metadata = "15.0.0" frame-metadata = "15.0.0"