Utilize Metadata V15 (#1041)

* Update frame-metadata to the latest branch

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

* metadata: Add outer enum types

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

* metadata: Extend the extrinsic with address,call,sign,extra types

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

* Codegen test Event, Error and Call for outer enums

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

* Revert "Codegen test Event, Error and Call for outer enums"

This reverts commit db542dca0369eedd257a7ec031d5b5549bc46a88.

* Update frame-metadata from the latest release

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

* Update scale-info

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

* codegen/error: Support v15 message

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

* metadata: Convert v14 to v15

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

* metadata/retain: Adjust to extrinsic type for V15

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

* metadata/validation: Adjust hashing for extrinsic types V15

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

* scripts: Fetch V15 and output codegen for full_client only

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

* subxt/blocks: Use extrinsic types directly

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

* testing: Fetch V15 for build script

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

* artifacts: Generate from latest polkadot version

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

* codegen: Fetch legacy with old API for v14 only

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

* rpc: Fetch metadata versions

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

* client: Fetch latest unstable then V15 then V14

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

* testing: Adjust testing API to latest interface

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

* Adjust clippy

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

* metadata: Generate the `RuntimeError` type for V14

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

* Remove testing files

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

* testing/staking: Remove controller account from bond

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

* metadata/validation: Use specific variants for hashing RuntimeCall

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

* XXX: Custom Substrate binary: must revert with next release

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

* XXX: To revert: CI use hardcoded substrate

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

* codegen: Use v15 outer enum types

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

* metadata: Retain outer enum types

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

* codegen: Use outer enum types instead of generating them

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

* Update artifacts

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

* Revert "XXX: Custom Substrate binary: must revert with next release"

This reverts commit e9705298661919f5769720b35030759fb8a7b01d.

Revert "XXX: To revert: CI use hardcoded substrate"

This reverts commit b18a5a0985a56ee4ad99bc9a1c0f9cd733cf4271.

* testing: Include env for dummy wat contracts

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

* Adjsut clippy

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

* ci: Use new link for fetching latest substrate binary

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

* tests: Include dummy RuntimeEvent into test metadata

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

* ci: Bump light-client timeout tests to 25min

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

* metadata/validation: Use specific pallets as provided

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

* testing: Rename metadata constant

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

* metadata: Use call_ty instead of signature_ty

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

* metadata: Rename retaining variant function

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

* metadata: Use Option<&[&str]>

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

* online_client: Fetch V15 metadata explicitely

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

* metadata/validation: Include the hash of the outer enum types

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

* metadata: Fix sign typo

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

* artifacts: Update the artifacts

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

* subxt: Remove RootError RootEvent and RootExtrinsic traits

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

* Update polkadot.rs

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

* metadata/tests: Ensure outer enum variants are retained

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

* scripts: Include multiple pallets for our decoding purposes

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

* subxt: Apply clippy

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

* artifacts: Update small metadata

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

* error: Keep raw bytes for the ModuleError representation

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

* error: Modify docs to not include links

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

* subxt/tests: Propagate `RuntimeCall` to outer enums

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

* subxt: Provide proper byte slice for decoding

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

* Update artifacts

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

* cli/tests: Adjust expected pallets message

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

* metadata: Test conversion from v14 to v15

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

* metadata: Fix typo

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

* Update subxt/src/blocks/extrinsic_types.rs

Co-authored-by: James Wilson <james@jsdw.me>

* metadata: Simplify type path for RuntimeError

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

* metadata/validation: Use visited ids per outer enum

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

* error: Remove RawModuleError

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

* Fix new clippy error from updated rust version

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

---------

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Co-authored-by: James Wilson <james@jsdw.me>
This commit is contained in:
Alexandru Vasile
2023-07-17 12:52:02 +03:00
committed by GitHub
parent 4fb051f233
commit 78a106f059
33 changed files with 3283 additions and 9056 deletions
+33 -96
View File
@@ -16,8 +16,8 @@ use crate::{
use crate::utils::strip_compact_prefix;
use codec::Decode;
use derivative::Derivative;
use scale_decode::DecodeAsFields;
use std::{collections::HashMap, sync::Arc};
use scale_decode::{DecodeAsFields, DecodeAsType};
use std::sync::Arc;
/// Trait to uniquely identify the extrinsic's identity from the runtime metadata.
///
@@ -37,23 +37,6 @@ pub trait StaticExtrinsic: DecodeAsFields {
}
}
/// This trait is implemented on the statically generated root extrinsic type, so that we're able
/// to decode it properly via a pallet that impls `DecodeAsMetadata`. This is necessary
/// because the "root extrinsic" type is generated using pallet info but doesn't actually exist in the
/// metadata types, so we have no easy way to decode things into it via type information and need a
/// little help via codegen.
#[doc(hidden)]
pub trait RootExtrinsic: Sized {
/// Given details of the pallet extrinsic we want to decode, and the name of the pallet, try to hand
/// back a "root extrinsic".
fn root_extrinsic(
pallet_bytes: &[u8],
pallet_name: &str,
pallet_extrinsic_ty: u32,
metadata: &Metadata,
) -> Result<Self, Error>;
}
/// The body of a block.
pub struct Extrinsics<T: Config, C> {
client: C,
@@ -420,22 +403,17 @@ where
}
}
/// Attempt to decode these [`ExtrinsicDetails`] into a root extrinsic type (which includes
/// Attempt to decode these [`ExtrinsicDetails`] into an outer call enum type (which includes
/// the pallet and extrinsic enum variants as well as the extrinsic fields). A compatible
/// type for this is exposed via static codegen as a root level `Call` type.
pub fn as_root_extrinsic<E: RootExtrinsic>(&self) -> Result<E, Error> {
let md = self.extrinsic_metadata()?;
let pallet_extrinsic_ty = md.pallet.call_ty_id().ok_or_else(|| {
Error::Metadata(MetadataError::CallTypeNotFoundInPallet(md.pallet.index()))
})?;
pub fn as_root_extrinsic<E: DecodeAsType>(&self) -> Result<E, Error> {
let decoded = E::decode_as_type(
&mut &self.call_bytes()[..],
self.metadata.outer_enums().call_enum_ty(),
self.metadata.types(),
)?;
// Ignore root enum index.
E::root_extrinsic(
&self.call_bytes()[1..],
md.pallet.name(),
pallet_extrinsic_ty,
&self.metadata,
)
Ok(decoded)
}
}
@@ -478,47 +456,11 @@ pub(crate) struct ExtrinsicPartTypeIds {
impl ExtrinsicPartTypeIds {
/// Extract the generic type parameters IDs from the extrinsic type.
pub(crate) fn new(metadata: &Metadata) -> Result<Self, BlockError> {
const ADDRESS: &str = "Address";
const CALL: &str = "Call";
const SIGNATURE: &str = "Signature";
const EXTRA: &str = "Extra";
let id = metadata.extrinsic().ty();
let Some(ty) = metadata.types().resolve(id) else {
return Err(BlockError::MissingType);
};
let params: HashMap<_, _> = ty
.type_params
.iter()
.map(|ty_param| {
let Some(ty) = ty_param.ty else {
return Err(BlockError::MissingType);
};
Ok((ty_param.name.as_str(), ty.id))
})
.collect::<Result<_, _>>()?;
let Some(address) = params.get(ADDRESS) else {
return Err(BlockError::MissingType);
};
let Some(call) = params.get(CALL) else {
return Err(BlockError::MissingType);
};
let Some(signature) = params.get(SIGNATURE) else {
return Err(BlockError::MissingType);
};
let Some(extra) = params.get(EXTRA) else {
return Err(BlockError::MissingType);
};
Ok(ExtrinsicPartTypeIds {
address: *address,
_call: *call,
signature: *signature,
extra: *extra,
address: metadata.extrinsic().address_ty(),
_call: metadata.extrinsic().call_ty(),
signature: metadata.extrinsic().signature_ty(),
extra: metadata.extrinsic().extra_ty(),
})
}
}
@@ -620,10 +562,10 @@ impl<T: Config> ExtrinsicEvents<T> {
#[cfg(test)]
mod tests {
use super::*;
use crate::metadata::DecodeWithMetadata;
use crate::{rpc::types::RuntimeVersion, OfflineClient, PolkadotConfig};
use assert_matches::assert_matches;
use codec::{Decode, Encode};
use frame_metadata::v15::{CustomMetadata, OuterEnums};
use frame_metadata::{
v15::{ExtrinsicMetadata, PalletCallMetadata, PalletMetadata, RuntimeMetadataV15},
RuntimeMetadataPrefixed,
@@ -660,27 +602,6 @@ mod tests {
Test(Pallet),
}
// We need this in order to be able to decode into a root extrinsic type:
impl RootExtrinsic for RuntimeCall {
fn root_extrinsic(
mut pallet_bytes: &[u8],
pallet_name: &str,
pallet_extrinsic_ty: u32,
metadata: &Metadata,
) -> Result<Self, Error> {
if pallet_name == "Test" {
return Ok(RuntimeCall::Test(Pallet::decode_with_metadata(
&mut pallet_bytes,
pallet_extrinsic_ty,
metadata,
)?));
}
panic!(
"Asked for pallet name '{pallet_name}', which isn't in our test RuntimeCall type"
)
}
}
// The calls of the pallet.
#[allow(unused)]
#[derive(
@@ -743,12 +664,28 @@ mod tests {
}];
let extrinsic = ExtrinsicMetadata {
ty: meta_type::<ExtrinsicType<(), RuntimeCall, (), ()>>(),
version: 4,
signed_extensions: vec![],
address_ty: meta_type::<()>(),
call_ty: meta_type::<RuntimeCall>(),
signature_ty: meta_type::<()>(),
extra_ty: meta_type::<()>(),
};
let meta = RuntimeMetadataV15::new(pallets, extrinsic, meta_type::<()>(), vec![]);
let meta = RuntimeMetadataV15::new(
pallets,
extrinsic,
meta_type::<()>(),
vec![],
OuterEnums {
call_enum_ty: meta_type::<RuntimeCall>(),
event_enum_ty: meta_type::<()>(),
error_enum_ty: meta_type::<()>(),
},
CustomMetadata {
map: Default::default(),
},
);
let runtime_metadata: RuntimeMetadataPrefixed = meta.into();
Metadata::new(runtime_metadata.try_into().unwrap())
+1 -3
View File
@@ -10,6 +10,4 @@ mod extrinsic_types;
pub use block_types::{Block, BlockBody};
pub use blocks_client::{subscribe_to_block_headers_filling_in_gaps, BlocksClient};
pub use extrinsic_types::{
ExtrinsicDetails, ExtrinsicEvents, Extrinsics, RootExtrinsic, StaticExtrinsic,
};
pub use extrinsic_types::{ExtrinsicDetails, ExtrinsicEvents, Extrinsics, StaticExtrinsic};