Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static Metadata Validation #478

Merged
merged 173 commits into from
Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
173 commits
Select commit Hold shift + click to select a range
12313d7
metadata: Implement MetadataHashable for deterministic hashing
lexnv Mar 14, 2022
707a5e5
metadata: Hash `scale_info::Field`
lexnv Mar 14, 2022
3353583
metadata: Hash `scale_info::Variant`
lexnv Mar 14, 2022
ebc588a
metadata: Hash `scale_info::TypeDef`
lexnv Mar 14, 2022
dc727fc
metadata: Hash pallet metadata
lexnv Mar 14, 2022
4690ac0
metadata: Avoid data representation collision via unique identifiers
lexnv Mar 14, 2022
8178351
metadata: Finalize hashing on recursive types
lexnv Mar 14, 2022
b60ebdf
metadata: Cache recursive calls
lexnv Mar 14, 2022
a9b1447
metadata: Move `MetadataHashable` to codegen to avoid cyclic dependency
lexnv Mar 16, 2022
3ece9e3
codegen: Add pallet unique hash
lexnv Mar 16, 2022
c64cc60
metadata: Wrap metadata as owned
lexnv Mar 16, 2022
a24da9a
subxt: Use MetadataHashable wrapper for clients
lexnv Mar 16, 2022
05f1bc8
subxt: Generate runtime pallet uid from metadata
lexnv Mar 16, 2022
b98a93c
Validate metadata compatibility at the pallet level
lexnv Mar 16, 2022
73befba
Update polkadot.rs
lexnv Mar 16, 2022
e576ab2
Modify examples and tests for the new API
lexnv Mar 16, 2022
76f2c9c
codegen: Implement metadata uid
lexnv Mar 17, 2022
58f743c
Update polkadot with TryFrom implementation
lexnv Mar 17, 2022
ea9e233
client: Change `to_runtime_api` to reflect TryFrom changes
lexnv Mar 17, 2022
f9d9956
client: Skip full metadata validation option
lexnv Mar 17, 2022
0ed1f43
codegen: Add option to skip pallet validation for TransactionApi
lexnv Mar 17, 2022
f5665f7
codegen: Add option to skip pallet validation for StorageApi
lexnv Mar 17, 2022
b36555f
Update polkadot.rs with ability to skip pallet validation
lexnv Mar 17, 2022
e8e8792
codegen: Change `MetadataHashable` to per function implementation
lexnv Mar 17, 2022
86b1c7e
codegen: Use metadata hashes functions
lexnv Mar 17, 2022
c0ecf32
subxt: Use metadata hashes functions
lexnv Mar 17, 2022
4431c22
codegen: Make `get_type_uid` private
lexnv Mar 17, 2022
1fa9db4
codegen, subxt: Rename metadata functions `*_uid` to `*_hash`
lexnv Mar 17, 2022
2d6e906
codegen: Update `get_field_hash` to use `codec::Encode`
lexnv Mar 17, 2022
4da2e0e
subxt: Update polkadot.rs
lexnv Mar 17, 2022
ce7a6d7
codegen, subxt: Move metadata check from client to subxt::Metadata
lexnv Mar 18, 2022
7033233
codegen, subxt: Rename metadata check functions to follow `*_hash` na…
lexnv Mar 18, 2022
ed51cd8
codegen: Update polkadot.rs to reflect naming changes
lexnv Mar 18, 2022
0d500eb
codegen: Use `encode_to` for metadata generation
lexnv Mar 18, 2022
1c2f986
codegen: Update polkadot.rs to reflect `encode_to` changes
lexnv Mar 18, 2022
02bb231
codegen: Specific name for visited set
lexnv Mar 18, 2022
13e6112
metadata: Provide cache to hashing functions
lexnv Mar 18, 2022
d388598
metadata: Compute metadata hash by sorted pallets
lexnv Mar 21, 2022
5e6a21d
metadata: Get extrinsic hash
lexnv Mar 21, 2022
45c6453
metadata: Extend metadata hash with extrinsic and metadata type
lexnv Mar 21, 2022
5eb41c9
metadata: Add cache as metadata parameter
lexnv Mar 21, 2022
e33f33a
codegen, subxt: Update metadata hash to use cache
lexnv Mar 21, 2022
c5d89a3
metadata: Implement Default trait for MetadataHasherCache
lexnv Mar 21, 2022
e7af28f
metadata: Add cache for pallets
lexnv Mar 21, 2022
e0779bd
metadata: Move functionality to metadata crate
lexnv Mar 21, 2022
953c031
codegen, subxt: Use subxt-metadata crate
lexnv Mar 21, 2022
b865f18
codegen: Remove metdata hashing functionality
lexnv Mar 21, 2022
26216fa
metadata: Add documentation
lexnv Mar 21, 2022
aad7d2d
metadata: Fix vector capacity to include extrinisc and type hash
lexnv Mar 21, 2022
5de8e83
metadata: Add empty CLI
lexnv Mar 22, 2022
3877505
metadata-cli: Fetch metadata from substrate nodes
lexnv Mar 22, 2022
1809cc7
metadata-cli: Log metadata hashes of provided nodes
lexnv Mar 22, 2022
1957e56
metadata-cli: Group compatible nodes by metadata
lexnv Mar 22, 2022
9e32361
metadata-cli: Simplify hash map insertion
lexnv Mar 22, 2022
70aa7c1
metadata-cli: Move full metadata check to function
lexnv Mar 22, 2022
bfa9c8f
metadata-cli: Group metadata validation at the pallet level
lexnv Mar 22, 2022
c7a1e27
subxt: Persist metadata cache
lexnv Mar 23, 2022
ca8c22c
metadata: Move compatibility cli from subxt-metadata to subxt-cli
lexnv Mar 23, 2022
776250e
metadata: Remove cli from subxt-metadata
lexnv Mar 23, 2022
1c600ee
cli: Fix clippy
lexnv Mar 23, 2022
95a6134
Merge remote-tracking branch 'origin/master' into 398_static_md_check
lexnv Mar 23, 2022
beee3f1
metadata: Fix compatible metadata when pallets are registered in diff…
lexnv Mar 23, 2022
84e049e
tests: Handle result of pallet hashing
lexnv Mar 24, 2022
6635423
metadata: Remove type cache for deterministic hashing
lexnv Mar 24, 2022
1fe787d
metadata: Add test assets from `substrate-node-template` tag `polkado…
lexnv Mar 24, 2022
20055e5
metadata-tests: Check cache hashing for Balances pallet
lexnv Mar 24, 2022
7a9b8e5
metadata: Fix `get_type_hash` clippy issue
lexnv Mar 24, 2022
931fcdb
metadata-tests: Compare one time cache with persistent cache
lexnv Mar 24, 2022
c9ed131
metadata-test: Check metadata hash populates cache for pallets
lexnv Mar 24, 2022
43ae4db
metadata-tests: Simplify `cache_deterministic_hash` test
lexnv Mar 24, 2022
f9ca06d
metadata-tests: Check deterministic metadata for different order pallets
lexnv Mar 24, 2022
09e74d2
metadata: Fix clippy
lexnv Mar 24, 2022
57771e8
codegen: Implement TransactionApiUnchecked for skipping pallet valida…
lexnv Mar 24, 2022
f3f4d72
codegen: Implement StorageApiUnchecked for skipping pallet validation
lexnv Mar 25, 2022
9e4c62c
codegen: Remove skip_pallet_validation boolean
lexnv Mar 25, 2022
f92383c
subxt: Implement ClientUnchecked for skipping metadata validation
lexnv Mar 25, 2022
07cf5f2
Update polkadot.rs
lexnv Mar 25, 2022
6baa8e8
Update examples of rpc_call to skip metadata
lexnv Mar 25, 2022
8378086
subxt: Remove heck dependency
lexnv Mar 28, 2022
5fa5df8
codegen: Add pallet name as an identifier for pallet hashing
lexnv Mar 28, 2022
8da1497
metadata: Implement MetadataHashDetails
lexnv Mar 28, 2022
62a7eec
metadata: Adjust testing to `MetadataHashDetails` interface
lexnv Mar 28, 2022
f026078
codegen: Remove extra `pallet_name`
lexnv Mar 28, 2022
31c016c
subxt: Update polkadot.rs
lexnv Mar 28, 2022
8fcf824
subxt: Fix clippy issue
lexnv Mar 28, 2022
816e916
codegen: Change StorageApi to support `_unchecked` methods
lexnv Mar 29, 2022
58fd3e3
codegen: Change TransactionApi to support `_unchecked` methods
lexnv Mar 29, 2022
e0ef532
subxt: Switch back from `TryFrom` to `From` for `subxt::Client`
lexnv Mar 29, 2022
b0061e4
codegen, subxt: Remove `ClientUnchecked`
lexnv Mar 29, 2022
5ecf7b7
codegen: Expose `validate_metadata` as validation of compatibility me…
lexnv Mar 29, 2022
392da6d
examples: Update to the new interface
lexnv Mar 30, 2022
f2e8dfc
subxt: Update test integration to latest interface
lexnv Mar 30, 2022
f8df12a
subxt: Update polkadot.rs
lexnv Mar 30, 2022
467d707
metadata/tests: Check different pallet index order
lexnv Mar 31, 2022
d20bcd0
metadata/tests: Check recursive type hashing
lexnv Mar 31, 2022
e042c05
metadata/tests: Check recursive types registered in different order
lexnv Mar 31, 2022
b3c4029
metadata/tests: Fix recursive types warning
lexnv Mar 31, 2022
1900091
metadata/tests: Remove test assets
lexnv Mar 31, 2022
252c4d1
metadata/tests: Extend tests to verify cached pallet values
lexnv Mar 31, 2022
964f92c
Merge remote-tracking branch 'origin/master' into 398_static_md_check
lexnv Mar 31, 2022
9278811
Merge remote-tracking branch 'origin/master' into 398_static_md_check
lexnv Apr 4, 2022
551c595
Merge remote-tracking branch 'origin/master' into 398_static_md_check
lexnv Apr 4, 2022
db8fdfb
examples: Add metadata compatiblity example
lexnv Apr 4, 2022
d25c912
examples: Revert balance_transfer to initial form
lexnv Apr 4, 2022
5fb0cdd
codegen: Add ConstantsApi metadata check
lexnv Apr 4, 2022
7293531
tests: Modify tests to accomodate ConstantsApi changes
lexnv Apr 4, 2022
a5415b8
examples: Modify verified version
lexnv Apr 4, 2022
ce05435
subxt: Generate polkadot.rs from `0.9.18-4542a603cc-aarch64-macos`
lexnv Apr 4, 2022
ba95ac8
examples: Update polkadot_metadata.scale from `0.9.18-4542a603cc-aarc…
lexnv Apr 4, 2022
1efd776
metadata: Update documentation
lexnv Apr 4, 2022
dc3b106
tests: Modify default pallet usage
lexnv Apr 4, 2022
bb0b838
metadata/tests: Remove hex dependency
lexnv Apr 4, 2022
3a2d695
metadata/tests: Add MetadataTestType to capture complex types
lexnv Apr 4, 2022
853ba6f
metadata/tests: Update tests to use complex types
lexnv Apr 4, 2022
f0a2b75
metadata/tests: Check metadata correctness via extending pallets
lexnv Apr 4, 2022
545dfd0
metadata/tests: Extend pallet hash with Events
lexnv Apr 4, 2022
63b32bc
metadata/tests: Extend pallet hash with constants
lexnv Apr 4, 2022
7d55527
metadata/tests: Extend pallet hash with error
lexnv Apr 4, 2022
4e30b52
examples: Extend metadata compatibiliy with StorageApi and ConstantsApi
lexnv Apr 4, 2022
dab2beb
Modify comments and documentation
lexnv Apr 5, 2022
a152c6b
Merge remote-tracking branch 'origin/master' into 398_static_md_check
lexnv Apr 6, 2022
4af15fe
metadata: Benchmarks for full validation and pallet validation
lexnv Apr 6, 2022
74d3bc8
Merge remote-tracking branch 'origin/master' into 398_static_md_check
lexnv Apr 6, 2022
58cbc3f
metadata/benches: Fix clippy
lexnv Apr 7, 2022
efa5df1
metadata: Hash metadata just by inspecting the provided pallets
lexnv Apr 7, 2022
414dee6
metadata: Make pallets generic over T for `AsRef<str>`
lexnv Apr 7, 2022
7396595
codegen: Expose the name of the pallets composing the metadata
lexnv Apr 7, 2022
7d1adc3
subxt/tests: Update polkadot.rs with pallets name
lexnv Apr 7, 2022
1f5c5f4
codegen: Obtain metadata hash only by inspecting pallets
lexnv Apr 7, 2022
cbc3727
codegen,subxt: Extend the metadata hash to utilize just pallets
lexnv Apr 7, 2022
a82fad2
subxt/tests: Update polkadot.rs with client metadata has per pallet
lexnv Apr 7, 2022
c96606a
metadata/tests: Test `get_metadata_per_pallet_hash` correctness
lexnv Apr 7, 2022
c558df4
metadata: Fix clippy
lexnv Apr 7, 2022
a6f5650
metadata/benches: Fix decode of metadata
lexnv Apr 7, 2022
8f57e20
metadata: Fix clippy
lexnv Apr 7, 2022
23b382f
[static metadata] validate storage, calls and constants per call (#507)
jsdw Apr 8, 2022
9a08a84
Fix clippy
lexnv Apr 8, 2022
6cbebc9
bench the per-call metadata functions
jsdw Apr 8, 2022
fd4d425
metadata: Add test for `node_template_runtime_variant`
lexnv Apr 8, 2022
640b052
ensure criteron cli opts work
jsdw Apr 8, 2022
1323696
group benchmarks and avoid unwrap issues
jsdw Apr 8, 2022
9a7bbbc
metadata: Check template runtime for handling the pallet swap order case
lexnv Apr 8, 2022
5548b5a
Merge remote-tracking branch 'origin/398_static_md_check' into 398_st…
lexnv Apr 8, 2022
fd00319
metadata: Remove debug logs
lexnv Apr 8, 2022
a0e3b6c
metadata: Optimise by removing field's name and type_name and type's …
lexnv Apr 8, 2022
0ce19bb
metadata: Refactor `get_type_hash` to break recursion earlier
lexnv Apr 8, 2022
eb051a9
subxt: Add tests for `hash_cache`
lexnv Apr 8, 2022
cb2de4a
subxt: Add tests for checking Metadata Inner cache
lexnv Apr 8, 2022
e4e2866
metadata: Check semantic changes inside enum and struct fields
lexnv Apr 11, 2022
f65dabc
metadata: Add enums named differently with compatible semantic meaning
lexnv Apr 11, 2022
6c776eb
metadata: Guard testing of release versions for `node_template_runtime`
lexnv Apr 11, 2022
9c46526
Improve documentation
lexnv Apr 11, 2022
b713993
Update polkadot.rs
lexnv Apr 11, 2022
2d55752
metadata/tests: Manually construct type of `node_template_runtimeL::C…
lexnv Apr 11, 2022
79ea3fe
no more special Call handling, avoid a little cloning, and actually s…
jsdw Apr 13, 2022
a1f9038
remove unused deps and fmt
jsdw Apr 13, 2022
9691f51
RuntimeMetadataLastVersion => RuntimeMetadataV14
jsdw Apr 13, 2022
fd7aa62
remove a bunch of allocations in the metadata hashing, speed up from …
jsdw Apr 13, 2022
a658d6f
update release docs to release metadata crate too
jsdw Apr 13, 2022
06241f4
Merge remote-tracking branch 'origin/master' into 398_static_md_check
lexnv Apr 26, 2022
8c4aca6
subxt: Remove codegen dependency
lexnv Apr 26, 2022
0f7a770
subxt: Replace std RwLock with parking_lot
lexnv Apr 26, 2022
e355ec6
subxt/tests: Add ws address to `TestNodeProcess`
lexnv Apr 26, 2022
73be46c
subxt/tests: Add metadata validation integration test
lexnv Apr 26, 2022
b4c0185
subxt: Allow setting metadata on the ClientBuilder
lexnv Apr 26, 2022
2a625a9
subxt/tests: Check incompatible metadatas
lexnv Apr 26, 2022
633c3f0
metadata: Fix constant hashing for deterministic output
lexnv Apr 26, 2022
542dec6
subxt/tests: Check metadata validation for constants
lexnv Apr 26, 2022
74be005
subxt/tests: Test validation for calls
lexnv Apr 27, 2022
83f0ba4
subxt/tests: Test validation for storage
lexnv Apr 27, 2022
1abd3ca
Merge remote-tracking branch 'origin/master' into 398_static_md_check
lexnv Apr 27, 2022
b0e8b4c
subxt: Expose `set_metadata` for testing only
lexnv Apr 27, 2022
460c18c
subxt: Guard metadata tests under integration-tests
lexnv Apr 28, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"codegen",
"examples",
"macro",
"metadata",
"subxt",
"test-runtime"
]
3 changes: 2 additions & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ We also assume that ongoing work done is being merged directly to the `master` b
a little time in between each to let crates.io catch up with what we've published).

```
(cd codegen && cargo publish) && \
(cd metadata && cargo publish) && \
(cd codegen && cargo publish) && \
sleep 10 && \
(cd macro && cargo publish) && \
sleep 10 && \
Expand Down
4 changes: 4 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ path = "src/main.rs"
[dependencies]
# perform subxt codegen
subxt-codegen = { version = "0.20.0", path = "../codegen" }
# perform node compatibility
subxt-metadata = { version = "0.20.0", path = "../metadata" }
# information of portable registry
scale-info = "2.0.0"
# parse command line args
structopt = "0.3.25"
# make the request to a substrate node to get the metadata
Expand Down
127 changes: 126 additions & 1 deletion cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@ use color_eyre::eyre::{
self,
WrapErr,
};
use frame_metadata::RuntimeMetadataPrefixed;
use frame_metadata::{
RuntimeMetadata,
RuntimeMetadataPrefixed,
RuntimeMetadataV14,
META_RESERVED,
};
use scale::{
Decode,
Input,
};
use serde::{
Deserialize,
Serialize,
};
use std::{
collections::HashMap,
fs,
io::{
self,
Expand All @@ -34,6 +44,10 @@ use std::{
};
use structopt::StructOpt;
use subxt_codegen::GeneratedTypeDerives;
use subxt_metadata::{
get_metadata_hash,
get_pallet_hash,
};

/// Utilities for working with substrate metadata for subxt.
#[derive(Debug, StructOpt)]
Expand Down Expand Up @@ -75,6 +89,18 @@ enum Command {
#[structopt(long = "derive")]
derives: Vec<String>,
},
/// Verify metadata compatibility between substrate nodes.
Compatibility {
/// Urls of the substrate nodes to verify for metadata compatibility.
#[structopt(name = "nodes", long, use_delimiter = true, parse(try_from_str))]
nodes: Vec<url::Url>,
/// Check the compatibility of metadata for a particular pallet.
///
/// ### Note
/// The validation will omit the full metadata check and focus instead on the pallet.
#[structopt(long, parse(try_from_str))]
pallet: Option<String>,
},
}

fn main() -> color_eyre::Result<()> {
Expand Down Expand Up @@ -126,6 +152,105 @@ fn main() -> color_eyre::Result<()> {
codegen(&mut &bytes[..], derives)?;
Ok(())
}
Command::Compatibility { nodes, pallet } => {
match pallet {
Some(pallet) => handle_pallet_metadata(nodes.as_slice(), pallet.as_str()),
None => handle_full_metadata(nodes.as_slice()),
}
}
}
}

fn handle_pallet_metadata(nodes: &[url::Url], name: &str) -> color_eyre::Result<()> {
#[derive(Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
struct CompatibilityPallet {
pallet_present: HashMap<String, Vec<String>>,
pallet_not_found: Vec<String>,
}

let mut compatibility: CompatibilityPallet = Default::default();
for node in nodes.iter() {
let metadata = fetch_runtime_metadata(node)?;

match metadata.pallets.iter().find(|pallet| pallet.name == name) {
Some(pallet_metadata) => {
let hash = get_pallet_hash(&metadata.types, pallet_metadata);
let hex_hash = hex::encode(hash);
println!(
"Node {:?} has pallet metadata hash {:?}",
node.as_str(),
hex_hash
);

compatibility
.pallet_present
.entry(hex_hash)
.or_insert_with(Vec::new)
.push(node.as_str().to_string());
}
None => {
compatibility
.pallet_not_found
.push(node.as_str().to_string());
}
}
}

println!(
"\nCompatible nodes by pallet\n{}",
serde_json::to_string_pretty(&compatibility)
.context("Failed to parse compatibility map")?
);

Ok(())
}

fn handle_full_metadata(nodes: &[url::Url]) -> color_eyre::Result<()> {
let mut compatibility_map: HashMap<String, Vec<String>> = HashMap::new();
for node in nodes.iter() {
let metadata = fetch_runtime_metadata(node)?;
let hash = get_metadata_hash(&metadata);
let hex_hash = hex::encode(hash);
println!("Node {:?} has metadata hash {:?}", node.as_str(), hex_hash,);

compatibility_map
.entry(hex_hash)
.or_insert_with(Vec::new)
.push(node.as_str().to_string());
}

println!(
"\nCompatible nodes\n{}",
serde_json::to_string_pretty(&compatibility_map)
.context("Failed to parse compatibility map")?
);

Ok(())
}

fn fetch_runtime_metadata(url: &url::Url) -> color_eyre::Result<RuntimeMetadataV14> {
let (_, bytes) = fetch_metadata(url)?;

let metadata = <RuntimeMetadataPrefixed as Decode>::decode(&mut &bytes[..])?;
if metadata.0 != META_RESERVED {
return Err(eyre::eyre!(
"Node {:?} has invalid metadata prefix: {:?} expected prefix: {:?}",
url.as_str(),
metadata.0,
META_RESERVED
))
}

match metadata.1 {
RuntimeMetadata::V14(v14) => Ok(v14),
_ => {
Err(eyre::eyre!(
"Node {:?} with unsupported metadata version: {:?}",
url.as_str(),
metadata.1
))
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ proc-macro-error = "1.0.4"
quote = "1.0.8"
syn = "1.0.58"
scale-info = { version = "2.0.0", features = ["bit-vec"] }
sp-core = { version = "6.0.0" }
subxt-metadata = { version = "0.20.0", path = "../metadata" }

[dev-dependencies]
bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] }
Expand Down
26 changes: 17 additions & 9 deletions codegen/src/api/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::types::{
TypeGenerator,
};
use frame_metadata::{
v14::RuntimeMetadataV14,
PalletCallMetadata,
PalletMetadata,
};
Expand All @@ -35,6 +36,7 @@ use quote::{
use scale_info::form::PortableForm;

pub fn generate_calls(
metadata: &RuntimeMetadataV14,
type_gen: &TypeGenerator,
pallet: &PalletMetadata<PortableForm>,
call: &PalletCallMetadata<PortableForm>,
Expand All @@ -48,7 +50,7 @@ pub fn generate_calls(
);
let (call_structs, call_fns): (Vec<_>, Vec<_>) = struct_defs
.iter_mut()
.map(|struct_def| {
.map(|(variant_name, struct_def)| {
let (call_fn_args, call_args): (Vec<_>, Vec<_>) =
match struct_def.fields {
CompositeDefFields::Named(ref named_fields) => {
Expand All @@ -74,30 +76,36 @@ pub fn generate_calls(
};

let pallet_name = &pallet.name;
let call_struct_name = &struct_def.name;
let function_name = struct_def.name.to_string().to_snake_case();
let fn_name = format_ident!("{}", function_name);
let call_name = &variant_name;
let struct_name = &struct_def.name;
let call_hash = subxt_metadata::get_call_hash(metadata, pallet_name, call_name)
.unwrap_or_else(|_| abort_call_site!("Metadata information for the call {}_{} could not be found", pallet_name, call_name));

let fn_name = format_ident!("{}", variant_name.to_snake_case());
// Propagate the documentation just to `TransactionApi` methods, while
// draining the documentation of inner call structures.
let docs = struct_def.docs.take();
// The call structure's documentation was stripped above.
let call_struct = quote! {
#struct_def

impl ::subxt::Call for #call_struct_name {
impl ::subxt::Call for #struct_name {
const PALLET: &'static str = #pallet_name;
const FUNCTION: &'static str = #function_name;
const FUNCTION: &'static str = #call_name;
}
};
let client_fn = quote! {
#docs
pub fn #fn_name(
&self,
#( #call_fn_args, )*
) -> ::subxt::SubmittableExtrinsic<'a, T, X, #call_struct_name, DispatchError, root_mod::Event> {
let call = #call_struct_name { #( #call_args, )* };
::subxt::SubmittableExtrinsic::new(self.client, call)
) -> Result<::subxt::SubmittableExtrinsic<'a, T, X, #struct_name, DispatchError, root_mod::Event>, ::subxt::BasicError> {
if self.client.metadata().call_hash::<#struct_name>()? == [#(#call_hash,)*] {
let call = #struct_name { #( #call_args, )* };
Ok(::subxt::SubmittableExtrinsic::new(self.client, call))
} else {
Err(::subxt::MetadataError::IncompatibleMetadata.into())
lexnv marked this conversation as resolved.
Show resolved Hide resolved
}
}
};
(call_struct, client_fn)
Expand Down
18 changes: 14 additions & 4 deletions codegen/src/api/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@

use crate::types::TypeGenerator;
use frame_metadata::{
v14::RuntimeMetadataV14,
PalletConstantMetadata,
PalletMetadata,
};
use heck::ToSnakeCase as _;
use proc_macro2::TokenStream as TokenStream2;
use proc_macro_error::abort_call_site;
use quote::{
format_ident,
quote,
};
use scale_info::form::PortableForm;

pub fn generate_constants(
metadata: &RuntimeMetadataV14,
type_gen: &TypeGenerator,
pallet: &PalletMetadata<PortableForm>,
constants: &[PalletConstantMetadata<PortableForm>],
Expand All @@ -37,16 +40,23 @@ pub fn generate_constants(
let fn_name = format_ident!("{}", constant.name.to_snake_case());
let pallet_name = &pallet.name;
let constant_name = &constant.name;
let constant_hash = subxt_metadata::get_constant_hash(metadata, pallet_name, constant_name)
.unwrap_or_else(|_| abort_call_site!("Metadata information for the constant {}_{} could not be found", pallet_name, constant_name));

let return_ty = type_gen.resolve_type_path(constant.ty.id(), &[]);
let docs = &constant.docs;

quote! {
#( #[doc = #docs ] )*
pub fn #fn_name(&self) -> ::core::result::Result<#return_ty, ::subxt::BasicError> {
let pallet = self.client.metadata().pallet(#pallet_name)?;
let constant = pallet.constant(#constant_name)?;
let value = ::subxt::codec::Decode::decode(&mut &constant.value[..])?;
Ok(value)
if self.client.metadata().constant_hash(#pallet_name, #constant_name)? == [#(#constant_hash,)*] {
let pallet = self.client.metadata().pallet(#pallet_name)?;
let constant = pallet.constant(#constant_name)?;
let value = ::subxt::codec::Decode::decode(&mut &constant.value[..])?;
Ok(value)
} else {
Err(::subxt::MetadataError::IncompatibleMetadata.into())
lexnv marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
});
Expand Down
4 changes: 2 additions & 2 deletions codegen/src/api/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ pub fn generate_events(
|name| name.into(),
"Event",
);
let event_structs = struct_defs.iter().map(|struct_def| {
let event_structs = struct_defs.iter().map(|(variant_name, struct_def)| {
let pallet_name = &pallet.name;
let event_struct = &struct_def.name;
let event_name = struct_def.name.to_string();
let event_name = variant_name;

quote! {
#struct_def
Expand Down