mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 15:11:03 +00:00
Support constructing and submitting V5 transactions (#1931)
* TransactionExtensions basic support for V5 VerifySignature and renames * WIP: subxt-core v5 transaction support * Subxt to support V5 extrinsics * WIP tests failing with wsm trap error * Actually encode mortality to fix tx encode issue * fmt * rename to sign_with_account_and_signature * Add explicit methods for v4 and v5 ext construction * clippy * fix wasm example and no mut self where not needed * fix doc example * another doc fix * Add tests for tx encoding and fix v5 encode issue * add copyright and todo * refactor APIs to have clear v4/v5 split in core and slightly nicer split in subxt proper * rename Partial/SubmittableExtrinsic to *Transaction * Remove SignerT::address since it's not needed * doc fixes * fmt * doc fixes * Fix comment number * Clarify panic behaviour of inject_signature * fmt
This commit is contained in:
@@ -8,10 +8,11 @@ use crate::utils::variant_index::VariantIndex;
|
||||
use crate::{
|
||||
utils::ordered_map::OrderedMap, ArcStr, ConstantMetadata, ExtrinsicMetadata, Metadata,
|
||||
OuterEnumsMetadata, PalletMetadataInner, RuntimeApiMetadataInner, RuntimeApiMethodMetadata,
|
||||
RuntimeApiMethodParamMetadata, SignedExtensionMetadata, StorageEntryMetadata,
|
||||
StorageEntryModifier, StorageEntryType, StorageHasher, StorageMetadata,
|
||||
RuntimeApiMethodParamMetadata, StorageEntryMetadata, StorageEntryModifier, StorageEntryType,
|
||||
StorageHasher, StorageMetadata, TransactionExtensionMetadata,
|
||||
};
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::vec;
|
||||
use frame_metadata::v15;
|
||||
use hashbrown::HashMap;
|
||||
use scale_info::form::PortableForm;
|
||||
@@ -102,8 +103,8 @@ mod from_v15 {
|
||||
|
||||
fn from_signed_extension_metadata(
|
||||
value: v15::SignedExtensionMetadata<PortableForm>,
|
||||
) -> SignedExtensionMetadata {
|
||||
SignedExtensionMetadata {
|
||||
) -> TransactionExtensionMetadata {
|
||||
TransactionExtensionMetadata {
|
||||
identifier: value.identifier,
|
||||
extra_ty: value.ty.id,
|
||||
additional_ty: value.additional_signed.id,
|
||||
@@ -112,8 +113,8 @@ mod from_v15 {
|
||||
|
||||
fn from_extrinsic_metadata(value: v15::ExtrinsicMetadata<PortableForm>) -> ExtrinsicMetadata {
|
||||
ExtrinsicMetadata {
|
||||
version: value.version,
|
||||
signed_extensions: value
|
||||
supported_versions: vec![value.version],
|
||||
transaction_extensions: value
|
||||
.signed_extensions
|
||||
.into_iter()
|
||||
.map(from_signed_extension_metadata)
|
||||
@@ -122,6 +123,7 @@ mod from_v15 {
|
||||
call_ty: value.call_ty.id,
|
||||
signature_ty: value.signature_ty.id,
|
||||
extra_ty: value.extra_ty.id,
|
||||
transaction_extensions_version: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,9 +332,23 @@ mod into_v15 {
|
||||
|
||||
fn from_extrinsic_metadata(e: ExtrinsicMetadata) -> v15::ExtrinsicMetadata<PortableForm> {
|
||||
v15::ExtrinsicMetadata {
|
||||
version: e.version,
|
||||
// V16 and above metadata can have multiple supported extrinsic versions. We have to
|
||||
// pick just one of these if converting back to V14/V15 metadata.
|
||||
//
|
||||
// - Picking the largest may mean that older tooling won't be compatible (it may only
|
||||
// check/support older version).
|
||||
// - Picking the smallest may mean that newer tooling won't work, or newer methods won't
|
||||
// work.
|
||||
//
|
||||
// Either could make sense, but we keep the oldest to prioritize backward compat with
|
||||
// older tooling.
|
||||
version: *e
|
||||
.supported_versions
|
||||
.iter()
|
||||
.min()
|
||||
.expect("at least one extrinsic version expected"),
|
||||
signed_extensions: e
|
||||
.signed_extensions
|
||||
.transaction_extensions
|
||||
.into_iter()
|
||||
.map(from_signed_extension_metadata)
|
||||
.collect(),
|
||||
@@ -344,7 +360,7 @@ mod into_v15 {
|
||||
}
|
||||
|
||||
fn from_signed_extension_metadata(
|
||||
s: SignedExtensionMetadata,
|
||||
s: TransactionExtensionMetadata,
|
||||
) -> v15::SignedExtensionMetadata<PortableForm> {
|
||||
v15::SignedExtensionMetadata {
|
||||
identifier: s.identifier,
|
||||
|
||||
+20
-11
@@ -131,7 +131,7 @@ impl frame_decode::extrinsics::ExtrinsicTypeInfo for Metadata {
|
||||
Ok(ExtrinsicExtensionInfo {
|
||||
extension_ids: self
|
||||
.extrinsic()
|
||||
.signed_extensions()
|
||||
.transaction_extensions()
|
||||
.iter()
|
||||
.map(|f| ExtrinsicInfoArg {
|
||||
name: Cow::Borrowed(f.identifier()),
|
||||
@@ -601,10 +601,14 @@ pub struct ExtrinsicMetadata {
|
||||
signature_ty: u32,
|
||||
/// The type of the outermost Extra enum.
|
||||
extra_ty: u32,
|
||||
/// Extrinsic version.
|
||||
version: u8,
|
||||
/// Which extrinsic versions are supported by this chain.
|
||||
supported_versions: Vec<u8>,
|
||||
/// The signed extensions in the order they appear in the extrinsic.
|
||||
signed_extensions: Vec<SignedExtensionMetadata>,
|
||||
transaction_extensions: Vec<TransactionExtensionMetadata>,
|
||||
/// Version of the transaction extensions.
|
||||
// TODO [jsdw]: V16 metadata groups transaction extensions by version.
|
||||
// need to work out what to do once there is more than one version to deal with.
|
||||
transaction_extensions_version: u8,
|
||||
}
|
||||
|
||||
impl ExtrinsicMetadata {
|
||||
@@ -626,20 +630,25 @@ impl ExtrinsicMetadata {
|
||||
self.extra_ty
|
||||
}
|
||||
|
||||
/// Extrinsic version.
|
||||
pub fn version(&self) -> u8 {
|
||||
self.version
|
||||
/// Which extrinsic versions are supported.
|
||||
pub fn supported_versions(&self) -> &[u8] {
|
||||
&self.supported_versions
|
||||
}
|
||||
|
||||
/// The extra/additional information associated with the extrinsic.
|
||||
pub fn signed_extensions(&self) -> &[SignedExtensionMetadata] {
|
||||
&self.signed_extensions
|
||||
pub fn transaction_extensions(&self) -> &[TransactionExtensionMetadata] {
|
||||
&self.transaction_extensions
|
||||
}
|
||||
|
||||
/// Which version are these transaction extensions?
|
||||
pub fn transaction_extensions_version(&self) -> u8 {
|
||||
self.transaction_extensions_version
|
||||
}
|
||||
}
|
||||
|
||||
/// Metadata for the signed extensions used by extrinsics.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SignedExtensionMetadata {
|
||||
pub struct TransactionExtensionMetadata {
|
||||
/// The unique signed extension identifier, which may be different from the type name.
|
||||
identifier: String,
|
||||
/// The type of the signed extension, with the data to be included in the extrinsic.
|
||||
@@ -648,7 +657,7 @@ pub struct SignedExtensionMetadata {
|
||||
additional_ty: u32,
|
||||
}
|
||||
|
||||
impl SignedExtensionMetadata {
|
||||
impl TransactionExtensionMetadata {
|
||||
/// The unique signed extension identifier, which may be different from the type name.
|
||||
pub fn identifier(&self) -> &str {
|
||||
&self.identifier
|
||||
|
||||
@@ -95,7 +95,7 @@ impl TypeSet {
|
||||
self.insert(ty);
|
||||
}
|
||||
|
||||
for signed in &extrinsic.signed_extensions {
|
||||
for signed in &extrinsic.transaction_extensions {
|
||||
self.insert(signed.extra_ty);
|
||||
self.insert(signed.additional_ty);
|
||||
}
|
||||
@@ -294,7 +294,7 @@ fn iterate_metadata_types(metadata: &mut Metadata) -> impl Iterator<Item = &mut
|
||||
types.push(ty);
|
||||
}
|
||||
|
||||
for signed in &mut metadata.extrinsic.signed_extensions {
|
||||
for signed in &mut metadata.extrinsic.transaction_extensions {
|
||||
types.push(&mut signed.extra_ty);
|
||||
types.push(&mut signed.additional_ty);
|
||||
}
|
||||
|
||||
@@ -292,14 +292,25 @@ fn get_extrinsic_hash(
|
||||
let signature_hash = get_type_hash(registry, extrinsic.signature_ty, outer_enum_hashes);
|
||||
let extra_hash = get_type_hash(registry, extrinsic.extra_ty, outer_enum_hashes);
|
||||
|
||||
// Supported versions are just u8s and we will likely never have more than 32 of these, so put them into
|
||||
// an array of u8s and panic if more than 32.
|
||||
if extrinsic.supported_versions.len() > 32 {
|
||||
panic!("The metadata validation logic does not support more than 32 extrinsic versions.");
|
||||
}
|
||||
let supported_extrinsic_versions = {
|
||||
let mut a = [0u8; 32];
|
||||
a[0..extrinsic.supported_versions.len()].copy_from_slice(&extrinsic.supported_versions);
|
||||
a
|
||||
};
|
||||
|
||||
let mut bytes = concat_and_hash4(
|
||||
&address_hash,
|
||||
&signature_hash,
|
||||
&extra_hash,
|
||||
&[extrinsic.version; 32],
|
||||
&supported_extrinsic_versions,
|
||||
);
|
||||
|
||||
for signed_extension in extrinsic.signed_extensions.iter() {
|
||||
for signed_extension in extrinsic.transaction_extensions.iter() {
|
||||
bytes = concat_and_hash4(
|
||||
&bytes,
|
||||
&hash(signed_extension.identifier.as_bytes()),
|
||||
|
||||
Reference in New Issue
Block a user