Skip to content

Commit

Permalink
support metadata v15 (#587)
Browse files Browse the repository at this point in the history
* parameterized test for testing different metadata versions (internally still uses v14 for both cases)

* failing test for supporting metadata v14 and v15

* compatibility with metadata v14 and v15. v14 is always converted to v15

file from_v14_to_v15.rs contains a function copied from subxt: https://github.com/paritytech/subxt/blob/b9f5419095b31b64421fef1edea6facea607c915/metadata/src/from_into/v14.rs

* cargo fmt

* add license information
  • Loading branch information
masapr authored Jun 16, 2023
1 parent f11729e commit 5325827
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 46 deletions.
61 changes: 61 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ members = [
async-trait = "0.1.68"
codec = { package = "parity-scale-codec", version = "3.2.1", default-features = false, features = ['derive'] }
derive_more = { version = "0.99.5" }
frame-metadata = { version = "15.1", default-features = false, features = ["v14", "serde_full", "decode"] }
frame-metadata = { version = "15.1", default-features = false, features = ["v14", "v15-unstable", "serde_full", "decode"] }
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
log = { version = "0.4.14", default-features = false }
maybe-async = { version = "0.2.7" }
Expand Down Expand Up @@ -63,6 +63,7 @@ ac-primitives = { path = "primitives", default-features = false }
ac-node-api = { path = "node-api", features = ["mocks"] }
kitchensink-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
scale-info = { version = "2.1.1", features = ["derive"] }
test-case = "3.1.0"

[features]
default = ["std", "jsonrpsee-client", "sync-api"]
Expand Down
5 changes: 4 additions & 1 deletion node-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] }
codec = { package = "parity-scale-codec", version = "3.2.1", features = ["derive", "bit-vec"], default-features = false }
derive_more = { version = "0.99.17" }
either = { version = "1.6.1", default-features = false }
frame-metadata = { version = "15.1", default-features = false, features = ["v14", "serde_full", "decode"] }
frame-metadata = { version = "15.1", default-features = false, features = ["v14", "v15-unstable", "serde_full", "decode"] }
hex = { version = "0.4.3", default-features = false }
log = { version = "0.4.14", default-features = false }
scale-info = { version = "2.0.1", features = ["derive", "decode", "bitvec"], default-features = false }
Expand All @@ -30,6 +30,9 @@ sp-storage = { default-features = false, features = ["serde"], git = "https://gi
sp-application-crypto = { default-features = false, git = "https://github.com/paritytech/substrate.git", features = ["full_crypto"], branch = "master" }
sp-runtime-interface = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "master" }

[dev-dependencies]
test-case = "3.1.0"

[features]
default = ["std"]
# To support `no_std` builds in non-32 bit environments.
Expand Down
47 changes: 28 additions & 19 deletions node-api/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,13 @@ mod tests {
use super::*;
use crate::{
decoder::Value,
test_utils::{event_record, events, events_raw, metadata},
test_utils::{
event_record, events, events_raw, metadata_with_version, SupportedMetadataVersions,
},
};
use codec::Encode;
use scale_info::TypeInfo;
use test_case::test_case;

/// [`RawEventDetails`] can be annoying to test, because it contains
/// type info in the decoded field Values. Strip that here so that
Expand Down Expand Up @@ -387,15 +390,16 @@ mod tests {
assert_eq!(actual_fields_no_context, expected.fields);
}

#[test]
fn dynamically_decode_single_event() {
#[test_case(SupportedMetadataVersions::V14)]
#[test_case(SupportedMetadataVersions::V15)]
fn dynamically_decode_single_event(metadata_version: SupportedMetadataVersions) {
#[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
enum Event {
A(u8, bool, Vec<String>),
}

// Create fake metadata that knows about our single event, above:
let metadata = metadata::<Event>();
let metadata = metadata_with_version::<Event>(metadata_version);

// Encode our events in the format we expect back from a node, and
// construst an Events object to iterate them:
Expand Down Expand Up @@ -426,16 +430,17 @@ mod tests {
assert!(event_details.next().is_none());
}

#[test]
fn dynamically_decode_multiple_events() {
#[test_case(SupportedMetadataVersions::V14)]
#[test_case(SupportedMetadataVersions::V15)]
fn dynamically_decode_multiple_events(metadata_version: SupportedMetadataVersions) {
#[derive(Clone, Copy, Debug, PartialEq, Decode, Encode, TypeInfo)]
enum Event {
A(u8),
B(bool),
}

// Create fake metadata that knows about our single event, above:
let metadata = metadata::<Event>();
let metadata = metadata_with_version::<Event>(metadata_version);

// Encode our events in the format we expect back from a node, and
// construst an Events object to iterate them:
Expand Down Expand Up @@ -496,16 +501,17 @@ mod tests {
assert!(event_details.next().is_none());
}

#[test]
fn dynamically_decode_multiple_events_until_error() {
#[test_case(SupportedMetadataVersions::V14)]
#[test_case(SupportedMetadataVersions::V15)]
fn dynamically_decode_multiple_events_until_error(metadata_version: SupportedMetadataVersions) {
#[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
enum Event {
A(u8),
B(bool),
}

// Create fake metadata that knows about our single event, above:
let metadata = metadata::<Event>();
let metadata = metadata_with_version::<Event>(metadata_version);

// Encode 2 events:
let mut event_bytes = vec![];
Expand Down Expand Up @@ -558,15 +564,16 @@ mod tests {
assert!(events_iter.next().is_none());
}

#[test]
fn compact_event_field() {
#[test_case(SupportedMetadataVersions::V14)]
#[test_case(SupportedMetadataVersions::V15)]
fn compact_event_field(metadata_version: SupportedMetadataVersions) {
#[derive(Clone, Debug, PartialEq, Encode, Decode, TypeInfo)]
enum Event {
A(#[codec(compact)] u32),
}

// Create fake metadata that knows about our single event, above:
let metadata = metadata::<Event>();
let metadata = metadata_with_version::<Event>(metadata_version);

// Encode our events in the format we expect back from a node, and
// construst an Events object to iterate them:
Expand All @@ -591,8 +598,9 @@ mod tests {
assert!(event_details.next().is_none());
}

#[test]
fn compact_wrapper_struct_field() {
#[test_case(SupportedMetadataVersions::V14)]
#[test_case(SupportedMetadataVersions::V15)]
fn compact_wrapper_struct_field(metadata_version: SupportedMetadataVersions) {
#[derive(Clone, Decode, Debug, PartialEq, Encode, TypeInfo)]
enum Event {
A(#[codec(compact)] CompactWrapper),
Expand All @@ -602,7 +610,7 @@ mod tests {
struct CompactWrapper(u64);

// Create fake metadata that knows about our single event, above:
let metadata = metadata::<Event>();
let metadata = metadata_with_version::<Event>(metadata_version);

// Encode our events in the format we expect back from a node, and
// construct an Events object to iterate them:
Expand All @@ -629,8 +637,9 @@ mod tests {
assert!(event_details.next().is_none());
}

#[test]
fn event_containing_explicit_index() {
#[test_case(SupportedMetadataVersions::V14)]
#[test_case(SupportedMetadataVersions::V15)]
fn event_containing_explicit_index(metadata_version: SupportedMetadataVersions) {
#[derive(Clone, Debug, PartialEq, Eq, Decode, Encode, TypeInfo)]
#[repr(u8)]
#[allow(trivial_numeric_casts, clippy::unnecessary_cast)] // required because the Encode derive produces a warning otherwise
Expand All @@ -644,7 +653,7 @@ mod tests {
}

// Create fake metadata that knows about our single event, above:
let metadata = metadata::<Event>();
let metadata = metadata_with_version::<Event>(metadata_version);

// Encode our events in the format we expect back from a node, and
// construct an Events object to iterate them:
Expand Down
96 changes: 96 additions & 0 deletions node-api/src/from_v14_to_v15.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// This file was taken from subxt (Parity Technologies (UK))
// https://github.com/paritytech/subxt/
// And was adapted by Supercomputing Systems AG.
//
// Copyright 2019-2023 Parity Technologies (UK) Ltd and Supercomputing Systems AG.
// This file is licensed as Apache-2.0
// see LICENSE for license details.

use frame_metadata::{v14, v15};

pub fn v14_to_v15(metadata: v14::RuntimeMetadataV14) -> v15::RuntimeMetadataV15 {
v15::RuntimeMetadataV15 {
types: metadata.types,
pallets: metadata
.pallets
.into_iter()
.map(|pallet| frame_metadata::v15::PalletMetadata {
name: pallet.name,
storage: pallet
.storage
.map(|storage| frame_metadata::v15::PalletStorageMetadata {
prefix: storage.prefix,
entries: storage
.entries
.into_iter()
.map(|entry| {
let modifier = match entry.modifier {
frame_metadata::v14::StorageEntryModifier::Optional => {
frame_metadata::v15::StorageEntryModifier::Optional
}
frame_metadata::v14::StorageEntryModifier::Default => {
frame_metadata::v15::StorageEntryModifier::Default
}
};

let ty = match entry.ty {
frame_metadata::v14::StorageEntryType::Plain(ty) => {
frame_metadata::v15::StorageEntryType::Plain(ty)
},
frame_metadata::v14::StorageEntryType::Map {
hashers,
key,
value,
} => frame_metadata::v15::StorageEntryType::Map {
hashers: hashers.into_iter().map(|hasher| match hasher {
frame_metadata::v14::StorageHasher::Blake2_128 => frame_metadata::v15::StorageHasher::Blake2_128,
frame_metadata::v14::StorageHasher::Blake2_256 => frame_metadata::v15::StorageHasher::Blake2_256,
frame_metadata::v14::StorageHasher::Blake2_128Concat => frame_metadata::v15::StorageHasher::Blake2_128Concat ,
frame_metadata::v14::StorageHasher::Twox128 => frame_metadata::v15::StorageHasher::Twox128,
frame_metadata::v14::StorageHasher::Twox256 => frame_metadata::v15::StorageHasher::Twox256,
frame_metadata::v14::StorageHasher::Twox64Concat => frame_metadata::v15::StorageHasher::Twox64Concat,
frame_metadata::v14::StorageHasher::Identity=> frame_metadata::v15::StorageHasher::Identity,
}).collect(),
key,
value,
},
};

frame_metadata::v15::StorageEntryMetadata {
name: entry.name,
modifier,
ty,
default: entry.default,
docs: entry.docs,
}
})
.collect(),
}),
calls: pallet.calls.map(|calls| frame_metadata::v15::PalletCallMetadata { ty: calls.ty } ),
event: pallet.event.map(|event| frame_metadata::v15::PalletEventMetadata { ty: event.ty } ),
constants: pallet.constants.into_iter().map(|constant| frame_metadata::v15::PalletConstantMetadata {
name: constant.name,
ty: constant.ty,
value: constant.value,
docs: constant.docs,
} ).collect(),
error: pallet.error.map(|error| frame_metadata::v15::PalletErrorMetadata { ty: error.ty } ),
index: pallet.index,
docs: Default::default(),
})
.collect(),
extrinsic: frame_metadata::v15::ExtrinsicMetadata {
ty: metadata.extrinsic.ty,
version: metadata.extrinsic.version,
signed_extensions: metadata.extrinsic.signed_extensions.into_iter().map(|ext| {
frame_metadata::v15::SignedExtensionMetadata {
identifier: ext.identifier,
ty: ext.ty,
additional_signed: ext.additional_signed,
}
}).collect()
},
ty: metadata.ty,
apis: Default::default(),
}
}
1 change: 1 addition & 0 deletions node-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub use metadata::{Metadata, MetadataError};
pub mod decoder;
pub mod error;
pub mod events;
pub mod from_v14_to_v15;
pub mod metadata;
pub mod storage;

Expand Down
11 changes: 7 additions & 4 deletions node-api/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
//!
//! This file is mostly subxt.

use crate::{alloc::borrow::ToOwned, storage::GetStorageTypes, Encoded};
use crate::{
alloc::borrow::ToOwned, from_v14_to_v15::v14_to_v15, storage::GetStorageTypes, Encoded,
};
use codec::{Decode, Encode, Error as CodecError};
use frame_metadata::{
PalletConstantMetadata, RuntimeMetadata, RuntimeMetadataLastVersion, RuntimeMetadataPrefixed,
StorageEntryMetadata, META_RESERVED,
v15::{PalletConstantMetadata, RuntimeMetadataLastVersion, StorageEntryMetadata},
RuntimeMetadata, RuntimeMetadataPrefixed, META_RESERVED,
};
use scale_info::{form::PortableForm, PortableRegistry, Type};
use sp_storage::StorageKey;
Expand Down Expand Up @@ -334,7 +336,8 @@ impl TryFrom<RuntimeMetadataPrefixed> for Metadata {
return Err(InvalidMetadataError::InvalidPrefix)
}
let metadata = match metadata.1 {
RuntimeMetadata::V14(meta) => meta,
RuntimeMetadata::V14(meta) => v14_to_v15(meta),
RuntimeMetadata::V15(meta) => meta,
_ => return Err(InvalidMetadataError::InvalidVersion),
};

Expand Down
Loading

0 comments on commit 5325827

Please sign in to comment.