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

Metadata V15: Generate Runtime APIs #918

Merged
merged 78 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
8af6a40
Update frame-metadata to v15.1.0
lexnv Apr 10, 2023
dd89dd6
Enable V15 unstable metadata in frame-metadata
lexnv Apr 10, 2023
073aea9
metadata: Move validation hashing to dedicated file
lexnv Apr 10, 2023
3c2d78a
Use sp-metadata-ir from substrate to work with metadata
lexnv Apr 11, 2023
d2d29dc
Revert using sp-metadata-ir in favor of conversion to v15
lexnv Apr 13, 2023
a795b62
metadata: Convert v14 to v15
lexnv Apr 13, 2023
98360c3
metadata: Use v15 for validation
lexnv Apr 13, 2023
04dc695
codegen: Use v15 for codegen
lexnv Apr 13, 2023
47d84bc
metadata/bench: Use v15
lexnv Apr 13, 2023
365e78d
Adjust to v15 metadata
lexnv Apr 13, 2023
9302fa2
Adjust testing
lexnv Apr 13, 2023
dd48979
Merge remote-tracking branch 'origin/master' into lexnv/metadata_v15
lexnv Apr 13, 2023
bc2cf2a
Merge remote-tracking branch 'origin/master' into lexnv/metadata_v15
lexnv Apr 14, 2023
f52b92b
Merge remote-tracking branch 'origin/master' into lexnv/metadata_v15
lexnv Apr 17, 2023
9da2bf3
Merge remote-tracking branch 'origin/master' into lexnv/metadata_v15
lexnv Apr 18, 2023
7f3931a
Improve documentation
lexnv Apr 18, 2023
4663300
force CI
lexnv Apr 18, 2023
334f7fb
rpc: Fetch metadata at version
lexnv Apr 17, 2023
15ddaaa
artifacts: Update polkadot.scale from commit 6dc9e84dde2
lexnv Apr 17, 2023
78fafe6
codegen: Fetch V15 using the new API
lexnv Apr 18, 2023
561c16d
codegen: Add runtime API interface
lexnv Apr 18, 2023
d7141ec
metadata: Hash runtime API metadata for validation
lexnv Apr 18, 2023
d7652e5
metadata: Extract runtime API metadata wrapper from subxt::Metadata
lexnv Apr 18, 2023
21741d8
subxt: Adjust hashing cache to reflect root+item keys
lexnv Apr 18, 2023
bff5b7c
rpc: Add raw state_call API method
lexnv Apr 18, 2023
2546520
runtime_api: Add payload with static and dynamic variants
lexnv Apr 18, 2023
c1c8fd4
subxt: Allow payloads to call into the runtime
lexnv Apr 18, 2023
0f8a86d
examples: Add example to make a runtime API call both static and dynamic
lexnv Apr 18, 2023
d1229e7
Update polkadot.rs
lexnv Apr 18, 2023
16474c7
Merge remote-tracking branch 'origin/master' into lexnv/add_runtime_api
lexnv Apr 20, 2023
67d63b3
codegen: Simplify client fetching
lexnv Apr 20, 2023
82548ce
Address feedback and fallback to old API if needed
lexnv Apr 20, 2023
9f7d26e
runtime_api: Make mutability conditional on input params
lexnv Apr 20, 2023
1b60e89
Regenerate polkadot.rs
lexnv Apr 21, 2023
ae35fa7
metadata: Retain only pallets without runtime API info
lexnv Apr 21, 2023
df8e3b2
codegen: Retry via `Metadata_metadata` without conversion
lexnv Apr 21, 2023
ce2d6d6
payload: Remove `Decode` and change validation fn
lexnv Apr 21, 2023
8cfdbe3
Merge branch 'master' into lexnv/add_runtime_api
lexnv Apr 25, 2023
26688d3
metadata: Retain runtime API types
lexnv Apr 25, 2023
57790d6
codegen: Runtime APIs documentation based on flag
lexnv Apr 25, 2023
a58fbdc
Update examples/examples/custom_metadata_url.rs
lexnv Apr 25, 2023
fc5a952
Merge remote-tracking branch 'origin/lexnv/add_runtime_api' into lexn…
lexnv Apr 25, 2023
e355c14
Update artifacts from polkadot-a6cfdb16e9
lexnv Apr 25, 2023
320f260
Update polkadot.rs with polkadot-a6cfdb16e9
lexnv Apr 25, 2023
5754c09
codegen: Generate input structures for runtime API
lexnv Apr 25, 2023
719a004
runtime_api: Remove the static paylaod and use single impl
lexnv Apr 25, 2023
c8b3fee
examples: Fetch account nonce
lexnv Apr 25, 2023
cd9d1e6
testing: Adjust build script to fetch latest metadata
lexnv Apr 25, 2023
df24528
testing: Check account nonce from runtime API
lexnv Apr 25, 2023
ff6efca
Update cargo.lock
lexnv Apr 25, 2023
7bd91ff
codegen: Fix doc generation for runtime types
lexnv Apr 26, 2023
b597b5d
Merge remote-tracking branch 'origin/master' into lexnv/add_runtime_api
lexnv Apr 26, 2023
ee9e679
codegen: Rename `inputs` runtime calls module to `types`
lexnv Apr 27, 2023
834e3ad
codegen: Generate Calls structs inside the types module
lexnv Apr 27, 2023
3866c6b
testing: Check Alice account nonce before submitting the tx
lexnv Apr 27, 2023
69f5322
cli: Add metadata version option flag supporting v14 and unstable
lexnv Apr 27, 2023
014b758
cli: Specify version to fetch
lexnv Apr 27, 2023
334ee4c
subxt: Fallback to fetching latest stable metadata
lexnv Apr 28, 2023
dc3433c
subxt: Add unstable-metadata feature to fetch the latest
lexnv Apr 28, 2023
f74cf75
Merge branch 'master' into lexnv/add_runtime_api
lexnv May 2, 2023
2d8e68d
RuntimeVersion with Latest and Version(u32)
lexnv May 2, 2023
4273fb7
Update polkadot.rs
lexnv May 2, 2023
ff64caa
codegen: Adjust fetch_metadata to inspect version list
lexnv May 2, 2023
b6f5f7b
Merge remote-tracking branch 'origin/master' into lexnv/add_runtime_api
lexnv May 2, 2023
9e02da4
testing: Adjust metadata to metadata_legacy
lexnv May 2, 2023
0e17af5
events: Adjust docs to use metadata_legacy
lexnv May 3, 2023
b336ff3
have a pass over fetch_metadata
jsdw May 3, 2023
4138b6a
cargo fmt
jsdw May 3, 2023
05ebbe0
Option<String> when fetch metadata via latest API
jsdw May 3, 2023
bd665d1
clippy
jsdw May 3, 2023
9c92ade
fmt
jsdw May 3, 2023
f16525d
cli: Use the MetadataVersion from codegen
lexnv May 3, 2023
e632b66
Merge remote-tracking branch 'origin/lexnv/add_runtime_api' into lexn…
lexnv May 3, 2023
9bf0f66
cli: Specify latest as default for MetadataVersion
lexnv May 3, 2023
0655df8
Merge remote-tracking branch 'origin/master' into lexnv/add_runtime_api
lexnv May 3, 2023
f29c048
cli: Remove version from metadata and use the one from file_or_url
lexnv May 3, 2023
a032374
Fix clippy
lexnv May 3, 2023
0ea32fc
codegen: Decode metadata independently for different RPC calls
lexnv May 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified artifacts/polkadot_metadata.scale
Binary file not shown.
39 changes: 31 additions & 8 deletions cli/src/commands/compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use frame_metadata::{
use jsonrpsee::client_transport::ws::Uri;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use subxt_codegen::utils::MetadataVersion;
use subxt_metadata::{get_metadata_hash, get_pallet_hash, metadata_v14_to_latest};

/// Verify metadata compatibility between substrate nodes.
Expand All @@ -25,16 +26,35 @@ pub struct Opts {
/// The validation will omit the full metadata check and focus instead on the pallet.
#[clap(long, value_parser)]
pallet: Option<String>,
/// Specify the metadata version.
///
/// - unstable:
///
/// Use the latest unstable metadata of the node.
///
/// - number
///
/// Use this specific metadata version.
///
/// Defaults to latest.
#[clap(long = "version", default_value = "latest")]
version: MetadataVersion,
}

pub async fn run(opts: Opts) -> color_eyre::Result<()> {
match opts.pallet {
Some(pallet) => handle_pallet_metadata(opts.nodes.as_slice(), pallet.as_str()).await,
None => handle_full_metadata(opts.nodes.as_slice()).await,
Some(pallet) => {
handle_pallet_metadata(opts.nodes.as_slice(), pallet.as_str(), opts.version).await
}
None => handle_full_metadata(opts.nodes.as_slice(), opts.version).await,
}
}

async fn handle_pallet_metadata(nodes: &[Uri], name: &str) -> color_eyre::Result<()> {
async fn handle_pallet_metadata(
nodes: &[Uri],
name: &str,
version: MetadataVersion,
) -> color_eyre::Result<()> {
#[derive(Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
struct CompatibilityPallet {
Expand All @@ -44,7 +64,7 @@ async fn handle_pallet_metadata(nodes: &[Uri], name: &str) -> color_eyre::Result

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

match metadata.pallets.iter().find(|pallet| pallet.name == name) {
Some(pallet_metadata) => {
Expand Down Expand Up @@ -73,10 +93,10 @@ async fn handle_pallet_metadata(nodes: &[Uri], name: &str) -> color_eyre::Result
Ok(())
}

async fn handle_full_metadata(nodes: &[Uri]) -> color_eyre::Result<()> {
async fn handle_full_metadata(nodes: &[Uri], version: MetadataVersion) -> color_eyre::Result<()> {
let mut compatibility_map: HashMap<String, Vec<String>> = HashMap::new();
for node in nodes.iter() {
let metadata = fetch_runtime_metadata(node).await?;
let metadata = fetch_runtime_metadata(node, version).await?;
let hash = get_metadata_hash(&metadata);
let hex_hash = hex::encode(hash);
println!("Node {node:?} has metadata hash {hex_hash:?}",);
Expand All @@ -96,8 +116,11 @@ async fn handle_full_metadata(nodes: &[Uri]) -> color_eyre::Result<()> {
Ok(())
}

async fn fetch_runtime_metadata(url: &Uri) -> color_eyre::Result<RuntimeMetadataV15> {
let bytes = subxt_codegen::utils::fetch_metadata_bytes(url).await?;
async fn fetch_runtime_metadata(
url: &Uri,
version: MetadataVersion,
) -> color_eyre::Result<RuntimeMetadataV15> {
let bytes = subxt_codegen::utils::fetch_metadata_bytes(url, version).await?;

let metadata = <RuntimeMetadataPrefixed as Decode>::decode(&mut &bytes[..])?;
if metadata.0 != META_RESERVED {
Expand Down
42 changes: 35 additions & 7 deletions cli/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use clap::Args;
use color_eyre::eyre;
use std::{fs, io::Read, path::PathBuf};
use subxt_codegen::utils::Uri;
use subxt_codegen::utils::{MetadataVersion, Uri};

/// The source of the metadata.
#[derive(Debug, Args)]
Expand All @@ -16,29 +16,57 @@ pub struct FileOrUrl {
/// The path to the encoded metadata file.
#[clap(long, value_parser)]
file: Option<PathBuf>,
/// Specify the metadata version.
///
/// - unstable:
///
/// Use the latest unstable metadata of the node.
///
/// - number
///
/// Use this specific metadata version.
///
/// Defaults to 14.
#[clap(long)]
version: Option<MetadataVersion>,
}

impl FileOrUrl {
/// Fetch the metadata bytes.
pub async fn fetch(&self) -> color_eyre::Result<Vec<u8>> {
match (&self.file, &self.url) {
match (&self.file, &self.url, self.version) {
// Can't provide both --file and --url
(Some(_), Some(_)) => {
(Some(_), Some(_), _) => {
eyre::bail!("specify one of `--url` or `--file` but not both")
}
// Load from --file path
(Some(path), None) => {
(Some(path), None, None) => {
let mut file = fs::File::open(path)?;
let mut bytes = Vec::new();
file.read_to_end(&mut bytes)?;
Ok(bytes)
}
// Cannot load the metadata from the file and specify a version to fetch.
(Some(_), None, Some(_)) => {
// Note: we could provide the ability to convert between metadata versions
// but that would be involved because we'd need to convert
// from each metadata to the latest one and from the
// latest one to each metadata version. For now, disable the conversion.
eyre::bail!("`--file` is incompatible with `--version`")
}
// Fetch from --url
(None, Some(uri)) => Ok(subxt_codegen::utils::fetch_metadata_bytes(uri).await?),
(None, Some(uri), version) => Ok(subxt_codegen::utils::fetch_metadata_bytes(
uri,
version.unwrap_or_default(),
)
.await?),
// Default if neither is provided; fetch from local url
(None, None) => {
(None, None, version) => {
let uri = Uri::from_static("http://localhost:9933");
Ok(subxt_codegen::utils::fetch_metadata_bytes(&uri).await?)
Ok(
subxt_codegen::utils::fetch_metadata_bytes(&uri, version.unwrap_or_default())
.await?,
)
}
}
}
Expand Down
10 changes: 7 additions & 3 deletions codegen/src/api/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ pub fn generate_calls(
pub fn #fn_name(
&self,
#( #call_fn_args, )*
) -> #crate_path::tx::Payload<#struct_name> {
) -> #crate_path::tx::Payload<types::#struct_name> {
#crate_path::tx::Payload::new_static(
#pallet_name,
#call_name,
#struct_name { #( #call_args, )* },
types::#struct_name { #( #call_args, )* },
[#(#call_hash,)*]
)
}
Expand All @@ -120,7 +120,11 @@ pub fn generate_calls(

type DispatchError = #types_mod_ident::sp_runtime::DispatchError;

#( #call_structs )*
pub mod types {
use super::#types_mod_ident;

#( #call_structs )*
}

pub struct TransactionApi;

Expand Down
23 changes: 21 additions & 2 deletions codegen/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod calls;
mod constants;
mod errors;
mod events;
mod runtime_apis;
mod storage;

use frame_metadata::v15::RuntimeMetadataV15;
Expand All @@ -18,7 +19,7 @@ use crate::error::CodegenError;
use crate::{
ir,
types::{CompositeDef, CompositeDefFields, TypeGenerator, TypeSubstitutes},
utils::{fetch_metadata_bytes_blocking, Uri},
utils::{fetch_metadata_bytes_blocking, MetadataVersion, Uri},
CratePath,
};
use codec::Decode;
Expand Down Expand Up @@ -95,7 +96,11 @@ pub fn generate_runtime_api_from_url(
should_gen_docs: bool,
runtime_types_only: bool,
) -> Result<TokenStream2, CodegenError> {
let bytes = fetch_metadata_bytes_blocking(url)?;
// Fetch latest unstable version, if that fails fall back to the latest stable.
let bytes = match fetch_metadata_bytes_blocking(url, MetadataVersion::Unstable) {
Ok(bytes) => bytes,
Err(_) => fetch_metadata_bytes_blocking(url, MetadataVersion::Latest)?,
};

generate_runtime_api_from_bytes(
item_mod,
Expand Down Expand Up @@ -434,6 +439,14 @@ impl RuntimeGenerator {

let rust_items = item_mod_ir.rust_items();

let apis_mod = runtime_apis::generate_runtime_apis(
&self.metadata,
&type_gen,
types_mod_ident,
&crate_path,
should_gen_docs,
)?;

Ok(quote! {
#( #item_mod_attrs )*
#[allow(dead_code, unused_imports, non_camel_case_types)]
Expand Down Expand Up @@ -487,6 +500,12 @@ impl RuntimeGenerator {
TransactionApi
}

pub fn apis() -> runtime_apis::RuntimeApi {
runtime_apis::RuntimeApi
}

#apis_mod

pub struct ConstantsApi;
impl ConstantsApi {
#(
Expand Down
Loading