Add metadata V15 with Runtime API support (#48)

* v15: Add everything from v14

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Add feature to make the V15 the default version

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Add trait metadata

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Add method metadata

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Add param metadata

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Constructor for the metadata

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v14: Keep backwards compatibility with v14 re-exports

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Add trait and method documentation

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Make trait version optional

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Do not reexport v14 types

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Expose metadata as unstable

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Exclude trait versioning from metadata

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Add pallet documentation

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Rename runtime API structs

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* v15: Rename `ParamMetadata` to RuntimeApiMethodParamMetadata

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Update frame-metadata/src/v15.rs

Co-authored-by: Bastian Köcher <git@kchr.de>

* v15: Reanme `runtime` -> `apis` and use global META_RESERVED

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* lib: Force CI by better docs

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Copyright: Align copyright with substrate

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

---------

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
Alexandru Vasile
2023-03-30 15:32:53 +03:00
committed by GitHub
parent 040a53c63a
commit a09bd49175
10 changed files with 539 additions and 24 deletions
+1 -3
View File
@@ -1,6 +1,4 @@
// This file is part of Substrate.
// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
+15 -3
View File
@@ -1,6 +1,4 @@
// This file is part of Substrate.
// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -89,12 +87,19 @@ pub mod v13;
#[cfg(feature = "v14")]
pub mod v14;
/// Metadata v15
#[cfg(feature = "v15-unstable")]
pub mod v15;
// Reexport all the types from the latest version.
//
// When a new version becomes available, update this.
#[cfg(feature = "v14")]
pub use self::v14::*;
/// Metadata prefix.
pub const META_RESERVED: u32 = 0x6174656d; // 'meta' warning for endianness.
/// Metadata prefixed by a u32 for reserved usage
#[derive(Eq, Encode, PartialEq, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
@@ -172,6 +177,12 @@ pub enum RuntimeMetadata {
/// Version 14 for runtime metadata, as raw encoded bytes.
#[cfg(not(feature = "v14"))]
V14(OpaqueMetadata),
/// Version 15 for runtime metadata.
#[cfg(feature = "v15-unstable")]
V15(v15::RuntimeMetadataV15),
/// Version 15 for runtime metadata, as raw encoded bytes.
#[cfg(not(feature = "v15-unstable"))]
V15(OpaqueMetadata),
}
impl RuntimeMetadata {
@@ -193,6 +204,7 @@ impl RuntimeMetadata {
RuntimeMetadata::V12(_) => 12,
RuntimeMetadata::V13(_) => 13,
RuntimeMetadata::V14(_) => 14,
RuntimeMetadata::V15(_) => 15,
}
}
}
+1 -3
View File
@@ -1,6 +1,4 @@
// This file is part of Substrate.
// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
+1 -3
View File
@@ -1,6 +1,4 @@
// This file is part of Substrate.
// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
+1 -3
View File
@@ -1,6 +1,4 @@
// This file is part of Substrate.
// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
+1 -3
View File
@@ -1,6 +1,4 @@
// This file is part of Substrate.
// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
+516
View File
@@ -0,0 +1,516 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[cfg(feature = "decode")]
use codec::Decode;
#[cfg(feature = "serde_full")]
use serde::Serialize;
use super::{RuntimeMetadataPrefixed, META_RESERVED};
use codec::Encode;
use scale_info::prelude::vec::Vec;
use scale_info::{
form::{Form, MetaForm, PortableForm},
IntoPortable, MetaType, PortableRegistry, Registry,
};
/// Latest runtime metadata
pub type RuntimeMetadataLastVersion = RuntimeMetadataV15;
impl From<RuntimeMetadataLastVersion> for super::RuntimeMetadataPrefixed {
fn from(metadata: RuntimeMetadataLastVersion) -> RuntimeMetadataPrefixed {
RuntimeMetadataPrefixed(META_RESERVED, super::RuntimeMetadata::V15(metadata))
}
}
/// The metadata of a runtime.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
pub struct RuntimeMetadataV15 {
/// Type registry containing all types used in the metadata.
pub types: PortableRegistry,
/// Metadata of all the pallets.
pub pallets: Vec<PalletMetadata<PortableForm>>,
/// Metadata of the extrinsic.
pub extrinsic: ExtrinsicMetadata<PortableForm>,
/// The type of the `Runtime`.
pub ty: <PortableForm as Form>::Type,
/// Metadata of the Runtime API.
pub apis: Vec<RuntimeApiMetadata<PortableForm>>,
}
impl RuntimeMetadataV15 {
/// Create a new instance of [`RuntimeMetadataV15`].
pub fn new(
pallets: Vec<PalletMetadata>,
extrinsic: ExtrinsicMetadata,
runtime_type: MetaType,
apis: Vec<RuntimeApiMetadata>,
) -> Self {
let mut registry = Registry::new();
let pallets = registry.map_into_portable(pallets);
let extrinsic = extrinsic.into_portable(&mut registry);
let ty = registry.register_type(&runtime_type);
let apis = registry.map_into_portable(apis);
Self {
types: registry.into(),
pallets,
extrinsic,
ty,
apis,
}
}
}
/// Metadata of a runtime trait.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct RuntimeApiMetadata<T: Form = MetaForm> {
/// Trait name.
pub name: T::String,
/// Trait methods.
pub methods: Vec<RuntimeApiMethodMetadata<T>>,
/// Trait documentation.
pub docs: Vec<T::String>,
}
impl IntoPortable for RuntimeApiMetadata {
type Output = RuntimeApiMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
RuntimeApiMetadata {
name: self.name.into_portable(registry),
methods: registry.map_into_portable(self.methods),
docs: registry.map_into_portable(self.docs),
}
}
}
/// Metadata of a runtime method.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct RuntimeApiMethodMetadata<T: Form = MetaForm> {
/// Method name.
pub name: T::String,
/// Method parameters.
pub inputs: Vec<RuntimeApiMethodParamMetadata<T>>,
/// Method output.
pub output: T::Type,
/// Method documentation.
pub docs: Vec<T::String>,
}
impl IntoPortable for RuntimeApiMethodMetadata {
type Output = RuntimeApiMethodMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
RuntimeApiMethodMetadata {
name: self.name.into_portable(registry),
inputs: registry.map_into_portable(self.inputs),
output: registry.register_type(&self.output),
docs: registry.map_into_portable(self.docs),
}
}
}
/// Metadata of a runtime method parameter.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct RuntimeApiMethodParamMetadata<T: Form = MetaForm> {
/// Parameter name.
pub name: T::String,
/// Parameter type.
pub ty: T::Type,
}
impl IntoPortable for RuntimeApiMethodParamMetadata {
type Output = RuntimeApiMethodParamMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
RuntimeApiMethodParamMetadata {
name: self.name.into_portable(registry),
ty: registry.register_type(&self.ty),
}
}
}
/// Metadata of the extrinsic used by the runtime.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct ExtrinsicMetadata<T: Form = MetaForm> {
/// The type of the extrinsic.
pub ty: T::Type,
/// Extrinsic version.
pub version: u8,
/// The signed extensions in the order they appear in the extrinsic.
pub signed_extensions: Vec<SignedExtensionMetadata<T>>,
}
impl IntoPortable for ExtrinsicMetadata {
type Output = ExtrinsicMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
ExtrinsicMetadata {
ty: registry.register_type(&self.ty),
version: self.version,
signed_extensions: registry.map_into_portable(self.signed_extensions),
}
}
}
/// Metadata of an extrinsic's signed extension.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct SignedExtensionMetadata<T: Form = MetaForm> {
/// The unique signed extension identifier, which may be different from the type name.
pub identifier: T::String,
/// The type of the signed extension, with the data to be included in the extrinsic.
pub ty: T::Type,
/// The type of the additional signed data, with the data to be included in the signed payload
pub additional_signed: T::Type,
}
impl IntoPortable for SignedExtensionMetadata {
type Output = SignedExtensionMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
SignedExtensionMetadata {
identifier: self.identifier.into_portable(registry),
ty: registry.register_type(&self.ty),
additional_signed: registry.register_type(&self.additional_signed),
}
}
}
/// All metadata about an runtime pallet.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct PalletMetadata<T: Form = MetaForm> {
/// Pallet name.
pub name: T::String,
/// Pallet storage metadata.
pub storage: Option<PalletStorageMetadata<T>>,
/// Pallet calls metadata.
pub calls: Option<PalletCallMetadata<T>>,
/// Pallet event metadata.
pub event: Option<PalletEventMetadata<T>>,
/// Pallet constants metadata.
pub constants: Vec<PalletConstantMetadata<T>>,
/// Pallet error metadata.
pub error: Option<PalletErrorMetadata<T>>,
/// Define the index of the pallet, this index will be used for the encoding of pallet event,
/// call and origin variants.
pub index: u8,
/// Pallet documentation.
pub docs: Vec<T::String>,
}
impl IntoPortable for PalletMetadata {
type Output = PalletMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
PalletMetadata {
name: self.name.into_portable(registry),
storage: self.storage.map(|storage| storage.into_portable(registry)),
calls: self.calls.map(|calls| calls.into_portable(registry)),
event: self.event.map(|event| event.into_portable(registry)),
constants: registry.map_into_portable(self.constants),
error: self.error.map(|error| error.into_portable(registry)),
index: self.index,
docs: registry.map_into_portable(self.docs),
}
}
}
/// All metadata of the pallet's storage.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct PalletStorageMetadata<T: Form = MetaForm> {
/// The common prefix used by all storage entries.
pub prefix: T::String,
/// Metadata for all storage entries.
pub entries: Vec<StorageEntryMetadata<T>>,
}
impl IntoPortable for PalletStorageMetadata {
type Output = PalletStorageMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
PalletStorageMetadata {
prefix: self.prefix.into_portable(registry),
entries: registry.map_into_portable(self.entries),
}
}
}
/// Metadata about one storage entry.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct StorageEntryMetadata<T: Form = MetaForm> {
/// Variable name of the storage entry.
pub name: T::String,
/// An `Option` modifier of that storage entry.
pub modifier: StorageEntryModifier,
/// Type of the value stored in the entry.
pub ty: StorageEntryType<T>,
/// Default value (SCALE encoded).
pub default: Vec<u8>,
/// Storage entry documentation.
pub docs: Vec<T::String>,
}
impl IntoPortable for StorageEntryMetadata {
type Output = StorageEntryMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
StorageEntryMetadata {
name: self.name.into_portable(registry),
modifier: self.modifier,
ty: self.ty.into_portable(registry),
default: self.default,
docs: registry.map_into_portable(self.docs),
}
}
}
/// A storage entry modifier indicates how a storage entry is returned when fetched and what the value will be if the key is not present.
/// Specifically this refers to the "return type" when fetching a storage entry, and what the value will be if the key is not present.
///
/// `Optional` means you should expect an `Option<T>`, with `None` returned if the key is not present.
/// `Default` means you should expect a `T` with the default value of default if the key is not present.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
pub enum StorageEntryModifier {
/// The storage entry returns an `Option<T>`, with `None` if the key is not present.
Optional,
/// The storage entry returns `T::Default` if the key is not present.
Default,
}
/// Hasher used by storage maps
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
pub enum StorageHasher {
/// 128-bit Blake2 hash.
Blake2_128,
/// 256-bit Blake2 hash.
Blake2_256,
/// Multiple 128-bit Blake2 hashes concatenated.
Blake2_128Concat,
/// 128-bit XX hash.
Twox128,
/// 256-bit XX hash.
Twox256,
/// Multiple 64-bit XX hashes concatenated.
Twox64Concat,
/// Identity hashing (no hashing).
Identity,
}
/// A type of storage value.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub enum StorageEntryType<T: Form = MetaForm> {
/// Plain storage entry (just the value).
Plain(T::Type),
/// A storage map.
Map {
/// One or more hashers, should be one hasher per key element.
hashers: Vec<StorageHasher>,
/// The type of the key, can be a tuple with elements for each of the hashers.
key: T::Type,
/// The type of the value.
value: T::Type,
},
}
impl IntoPortable for StorageEntryType {
type Output = StorageEntryType<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
match self {
Self::Plain(plain) => StorageEntryType::Plain(registry.register_type(&plain)),
Self::Map {
hashers,
key,
value,
} => StorageEntryType::Map {
hashers,
key: registry.register_type(&key),
value: registry.register_type(&value),
},
}
}
}
/// Metadata for all calls in a pallet
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct PalletCallMetadata<T: Form = MetaForm> {
/// The corresponding enum type for the pallet call.
pub ty: T::Type,
}
impl IntoPortable for PalletCallMetadata {
type Output = PalletCallMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
PalletCallMetadata {
ty: registry.register_type(&self.ty),
}
}
}
impl From<MetaType> for PalletCallMetadata {
fn from(ty: MetaType) -> Self {
Self { ty }
}
}
/// Metadata about the pallet Event type.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
pub struct PalletEventMetadata<T: Form = MetaForm> {
/// The Event type.
pub ty: T::Type,
}
impl IntoPortable for PalletEventMetadata {
type Output = PalletEventMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
PalletEventMetadata {
ty: registry.register_type(&self.ty),
}
}
}
impl From<MetaType> for PalletEventMetadata {
fn from(ty: MetaType) -> Self {
Self { ty }
}
}
/// Metadata about one pallet constant.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(
feature = "serde_full",
serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct PalletConstantMetadata<T: Form = MetaForm> {
/// Name of the pallet constant.
pub name: T::String,
/// Type of the pallet constant.
pub ty: T::Type,
/// Value stored in the constant (SCALE encoded).
pub value: Vec<u8>,
/// Documentation of the constant.
pub docs: Vec<T::String>,
}
impl IntoPortable for PalletConstantMetadata {
type Output = PalletConstantMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
PalletConstantMetadata {
name: self.name.into_portable(registry),
ty: registry.register_type(&self.ty),
value: self.value,
docs: registry.map_into_portable(self.docs),
}
}
}
/// Metadata about a pallet error.
#[derive(Clone, PartialEq, Eq, Encode, Debug)]
#[cfg_attr(feature = "decode", derive(Decode))]
#[cfg_attr(feature = "serde_full", derive(Serialize))]
#[cfg_attr(feature = "serde_full", serde(bound(serialize = "T::Type: Serialize")))]
pub struct PalletErrorMetadata<T: Form = MetaForm> {
/// The error type information.
pub ty: T::Type,
}
impl IntoPortable for PalletErrorMetadata {
type Output = PalletErrorMetadata<PortableForm>;
fn into_portable(self, registry: &mut Registry) -> Self::Output {
PalletErrorMetadata {
ty: registry.register_type(&self.ty),
}
}
}
impl From<MetaType> for PalletErrorMetadata {
fn from(ty: MetaType) -> Self {
Self { ty }
}
}
+1 -3
View File
@@ -1,6 +1,4 @@
// This file is part of Substrate.
// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
+1 -3
View File
@@ -1,6 +1,4 @@
// This file is part of Substrate.
// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");