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

support metadata v15 #587

Merged
merged 5 commits into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! ❤️

#[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};
masapr marked this conversation as resolved.
Show resolved Hide resolved

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