Fix codegen validation when Runtime APIs are stripped (#1000)

* modify code gen

* cargo fmt

* fix return

* move the runtime_apis static

* small layout change

* tidy up metadata UI testing and test validation function too

* fix validation tests to point to metadata

* update codegen

* fix clippy and tests

* tweak a comment

* rename validate_codegen => is_codegen_valid_for

---------

Co-authored-by: James Wilson <james@jsdw.me>
This commit is contained in:
Tadeo Hepperle
2023-06-09 11:10:48 +02:00
committed by GitHub
parent e711dc1582
commit 992ec9ab9b
9 changed files with 323 additions and 212 deletions
@@ -1,5 +1,6 @@
#[allow(dead_code, unused_imports, non_camel_case_types)]
#[allow(clippy::all)]
#[allow(rustdoc::broken_intra_doc_links)]
pub mod api {
#[allow(unused_imports)]
mod root_mod {
@@ -64,6 +65,25 @@ pub mod api {
"Crowdloan",
"XcmPallet",
];
pub static RUNTIME_APIS: [&str; 17usize] = [
"Core",
"Metadata",
"BlockBuilder",
"NominationPoolsApi",
"StakingApi",
"TaggedTransactionQueue",
"OffchainWorkerApi",
"ParachainHost",
"BeefyApi",
"MmrApi",
"GrandpaApi",
"BabeApi",
"AuthorityDiscoveryApi",
"SessionKeys",
"AccountNonceApi",
"TransactionPaymentApi",
"TransactionPaymentCallApi",
];
#[doc = r" The error type returned when there is a runtime issue."]
pub type DispatchError = runtime_types::sp_runtime::DispatchError;
#[derive(
@@ -4420,26 +4440,19 @@ pub mod api {
xcm_pallet::calls::TransactionApi
}
}
#[doc = r" check whether the Client you are using is aligned with the statically generated codegen."]
pub fn validate_codegen<T: ::subxt::Config, C: ::subxt::client::OfflineClientT<T>>(
client: &C,
) -> Result<(), ::subxt::error::MetadataError> {
let runtime_metadata_hash = client
.metadata()
#[doc = r" check whether the metadata provided is aligned with this statically generated code."]
pub fn is_codegen_valid_for(metadata: &::subxt::Metadata) -> bool {
let runtime_metadata_hash = metadata
.hasher()
.only_these_pallets(&PALLETS)
.only_these_runtime_apis(&RUNTIME_APIS)
.hash();
if runtime_metadata_hash
!= [
151u8, 83u8, 251u8, 44u8, 149u8, 59u8, 20u8, 183u8, 19u8, 173u8, 234u8, 48u8,
114u8, 104u8, 69u8, 102u8, 189u8, 208u8, 10u8, 87u8, 154u8, 252u8, 54u8, 185u8,
248u8, 199u8, 45u8, 173u8, 199u8, 95u8, 189u8, 253u8,
runtime_metadata_hash
== [
48u8, 175u8, 255u8, 171u8, 180u8, 123u8, 181u8, 54u8, 125u8, 74u8, 109u8, 140u8,
192u8, 208u8, 131u8, 194u8, 195u8, 232u8, 33u8, 229u8, 178u8, 181u8, 236u8, 230u8,
37u8, 97u8, 134u8, 144u8, 187u8, 127u8, 47u8, 237u8,
]
{
Err(::subxt::error::MetadataError::IncompatibleCodegen)
} else {
Ok(())
}
}
pub mod system {
use super::root_mod;
@@ -91,19 +91,15 @@ async fn full_metadata_check() {
let api = ctx.client();
// Runtime metadata is identical to the metadata used during API generation.
assert!(node_runtime::validate_codegen(&api).is_ok());
assert!(node_runtime::is_codegen_valid_for(&api.metadata()));
// Modify the metadata.
let metadata = modified_metadata(api.metadata(), |md| {
md.pallets[0].name = "NewPallet".to_string();
});
let api = metadata_to_api(metadata, &ctx).await;
assert_eq!(
node_runtime::validate_codegen(&api)
.expect_err("Validation should fail for incompatible metadata"),
::subxt::error::MetadataError::IncompatibleCodegen
);
// It should now be invalid:
assert!(!node_runtime::is_codegen_valid_for(&metadata));
}
#[tokio::test]
@@ -134,7 +130,7 @@ async fn constant_values_are_not_validated() {
let api = metadata_to_api(metadata, &ctx).await;
assert!(node_runtime::validate_codegen(&api).is_ok());
assert!(node_runtime::is_codegen_valid_for(&api.metadata()));
assert!(api.constants().at(&deposit_addr).is_ok());
}