// Copyright 2019-2023 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see .
use clap::Parser as ClapParser;
use codec::Encode;
use color_eyre::eyre;
use std::{env, path::PathBuf};
use subxt_codegen::{
generate_runtime_api_from_bytes, generate_runtime_api_from_url, utils::Uri, CratePath,
DerivesRegistry, TypeSubstitutes,
};
use wasm_testbed::WasmTestBed;
/// Command for generating indirect runtimes code.
#[derive(Debug, ClapParser)]
struct Command {
#[clap(name = "from-node-url", long, value_parser)]
node_url: Option,
#[clap(name = "from-wasm-file", long, value_parser)]
wasm_file: Option,
}
enum RuntimeMetadataSource {
NodeUrl(Uri),
WasmFile(wasm_loader::Source),
}
impl RuntimeMetadataSource {
fn from_command(cmd: Command) -> color_eyre::Result {
match (cmd.node_url, cmd.wasm_file) {
(Some(_), Some(_)) => Err(eyre::eyre!(
"Please specify one of `--from-node-url` or `--from-wasm-file` but not both"
)),
(None, None) =>
Err(eyre::eyre!("Please specify one of `--from-node-url` or `--from-wasm-file`")),
(Some(node_url), None) => Ok(Self::NodeUrl(node_url)),
(None, Some(source)) =>
Ok(Self::WasmFile(wasm_loader::Source::File(PathBuf::from(source)))),
}
}
}
struct TypeSubstitute {
subxt_type: syn::Path,
substitute: syn::Path,
}
impl TypeSubstitute {
fn simple(subxt_type: &str) -> Self {
Self {
subxt_type: syn::parse_str::(subxt_type).unwrap(),
substitute: syn::parse_str::(&format!("::{}", subxt_type)).unwrap(),
}
}
fn custom(subxt_type: &str, substitute: &str) -> Self {
Self {
subxt_type: syn::parse_str::(subxt_type).unwrap(),
substitute: syn::parse_str::(substitute).unwrap(),
}
}
}
fn print_runtime(runtime_api: proc_macro2::TokenStream) {
println!(
"// Copyright 2019-2023 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see .
//! Autogenerated runtime API
//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen
//! EXECUTED COMMAND: {}
{}
",
env::args().collect::>().join(" "),
runtime_api
);
}
fn main() -> color_eyre::Result<()> {
let args: Command = Command::parse();
let metadata_source = RuntimeMetadataSource::from_command(args)?;
// Module under which the API is generated.
let item_mod = syn::parse_quote!(
pub mod api {}
);
// Default module derivatives.
let mut derives = DerivesRegistry::new(&CratePath::default());
derives.extend_for_all(vec![syn::parse_quote!(Clone)]);
// Type substitutes
let mut type_substitutes = TypeSubstitutes::new(&CratePath::default());
type_substitutes.extend(
vec![
TypeSubstitute::simple("sp_core::crypto::AccountId32"),
TypeSubstitute::custom("bp_millau::millau_hash::MillauHash", "::bp_millau::MillauHash"),
TypeSubstitute::simple("bp_millau::BlakeTwoAndKeccak256"),
TypeSubstitute::custom(
"sp_runtime::generic::digest::Digest",
"::sp_runtime::generic::Digest",
),
TypeSubstitute::custom("sp_runtime::generic::era::Era", "::sp_runtime::generic::Era"),
TypeSubstitute::custom(
"sp_runtime::generic::header::Header",
"::sp_runtime::generic::Header",
),
TypeSubstitute::simple("bp_header_chain::justification::GrandpaJustification"),
TypeSubstitute::simple("bp_header_chain::InitializationData"),
TypeSubstitute::simple(
"bridge_runtime_common::messages::target::FromBridgedChainMessagesProof",
),
TypeSubstitute::custom("sp_weights::weight_v2::Weight", "::sp_weights::Weight"),
TypeSubstitute::simple(
"bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof",
),
TypeSubstitute::simple("bp_messages::UnrewardedRelayersState"),
]
.drain(..)
.map(|substitute| (substitute.subxt_type, substitute.substitute.try_into().unwrap())),
);
// Generate the Runtime API.
let runtime_api = match metadata_source {
RuntimeMetadataSource::NodeUrl(node_url) => generate_runtime_api_from_url(
item_mod,
&node_url,
derives,
type_substitutes,
CratePath::default(),
),
RuntimeMetadataSource::WasmFile(source) => {
let testbed = WasmTestBed::new(&source)
.map_err(|e| eyre::eyre!("Error creating WasmTestBed: {:?}", e))?;
generate_runtime_api_from_bytes(
item_mod,
&testbed.runtime_metadata_prefixed().encode(),
derives,
type_substitutes,
CratePath::default(),
)
},
};
print_runtime(runtime_api);
Ok(())
}