Metadata V15: Enrich extrinsic type info for decoding#14123
Metadata V15: Enrich extrinsic type info for decoding#14123paritytech-processbot[bot] merged 29 commits intomasterfrom
Conversation
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
kianenigma
left a comment
There was a problem hiding this comment.
Looks overall good, just one suggestion about using a type alias.
frame/system/src/offchain.rs
Outdated
| pub fn submit_transaction( | ||
| call: <T as SendTransactionTypes<LocalCall>>::OverarchingCall, | ||
| signature: Option<<T::Extrinsic as ExtrinsicT>::SignaturePayload>, | ||
| signature: Option<( |
There was a problem hiding this comment.
I don't get why we have to break down SignaturePayload? can't this have TypeInfo itself?
And if it is being broken down and not used, I rather actually delete SignaturePayload if it is not being used anymore.
| { | ||
| type Call = Call; | ||
|
|
||
| type SignaturePayload = (Address, Signature, Extra); |
There was a problem hiding this comment.
ahh, it is being done already 🙈
There was a problem hiding this comment.
In this case, a type SignaturePayloadOf<E> = (<E as Extrinsic>::X, <E as Extrinsic>::Y, <E as Extrinsic>::Z) will help prevent potential error where the order of these 3 might be mistaken.
|
Does @ascjones might be able to provide some insight into the motivation for including that type in the first place (or maybe it's been around much longer than V14?) |
| /// Usually it will contain a `Signature` and | ||
| /// may include some additional data that are specific to signed | ||
| /// extrinsics. | ||
| type SignaturePayload; |
There was a problem hiding this comment.
Instead of breaking most of the code we could just do
type SignaturePayload: SignaturePayload;
trait SignaturePayload {
type Address: TypeInfo;
type Signature: TypeInfo;
type Extra: TypeInfo;
}
There was a problem hiding this comment.
Yep, I like this approach more! Thanks for the feedback!
There was a problem hiding this comment.
@bkchr What's your opinion on having the extrinsic.ty in the metadata after this change (the message James mentioned above)?
We should have enough type info by relying on:
- address_ty
- call_ty
- signature_ty
- extra_ty
The extrinsic.ty has a manual implementation of TypeInfo that adds the above ty as generic types, but since we explicitly expose that info with this PR, I believe we should remove the extrinsic.ty.
That is unless we'll break other things
There was a problem hiding this comment.
I have no idea if someone is using this. However, frankly speaking by only having the types you listed you don't know the encoding of the Extrinsic type. While currently it may also already not being correct as it probably doesn't include the Compact<u32> length in from of the extrinsinc encoding?
There was a problem hiding this comment.
Good idea! I'll add the TypeDefCompact<u32> type to the extrinsic metadata to provide even better decoding abilities to end users. Considering this, I'll remove the extrinsic_ty from the metadata, unless encountering some edge-cases from UX teams.
The type only contained the address, call, signature and extra on its type info definition, and users should be able to obtain those details (and more) directly.
There was a problem hiding this comment.
iirc the extrinsic type was quite useless anyway before; it mostly just said "hey we want to encode the extrinsic to some vec of bytes". It doesn't provide any useful information on how those bytes need to be formed etc.
There are already a bunch of things we must just assume already about encoding extrinsics, ie the order of the signature stuff, how the not-really-scale Option for the signature is encoded (ie it has a version number &&'d to it) etc. I've always assumed this format information to be encoded in the tx version (4 atm); if a transaction has this version, it must be encoded in this way.
The metadata, in my mind, only needs to provide the information that might vary from chain to chain (eg the actual additional params etc). This tx version can encode the actual format that this stuff is turned into an extrinsic.
All of this to say, what would adding a TypeDefCompact<u32> to the metadata help with? I'd assume it to be part of the V4 extrinsic format I guess, but perhaps I'm wrong on this :)
There was a problem hiding this comment.
There are already a bunch of things we must just assume already about encoding extrinsics, ie the order of the signature stuff, how the not-really-scale Option for the signature is encoded (ie it has a version number
&&'d to it) etc. I've always assumed this format information to be encoded in the tx version (4 atm); if a transaction has this version, it must be encoded in this way.
Good point.
The metadata, in my mind, only needs to provide the information that might vary from chain to chain (eg the actual additional params etc). This tx version can encode the actual format that this stuff is turned into an extrinsic.
Just because every body is currently using our UncheckedExtrinsic doesn't mean that this will always be the case. However, it makes sense that this is a type that we can not depict in as type metadata.
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
frame/support/procedural/src/construct_runtime/expand/metadata.rs
Outdated
Show resolved
Hide resolved
Co-authored-by: Bastian Köcher <git@kchr.de>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
|
bot rebase |
|
Rebased |
jsdw
left a comment
There was a problem hiding this comment.
Looks great; well done!
Remember to release frame-metadata etc before merging :)
…ode_info Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
|
Polkadot companion is expected to fail since the latest companion conflicts, but will be solved by paritytech/polkadot#7401 (comment) |
|
bot merge |
* metadata-ir: Add extrinsic type info to decode address, call, sig Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * frame-metadata: Point to unreleased branch Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-ir: Include addrees, call, signature in V15 conversion Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-ir: Include extra ty Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * construct_runtime: Extract address,call,sig,extra ty from tx type Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * frame/tests: Check metadata populates xt types correctly Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-ir/tests: Add extra fields on ExtrinsicMetadataIR Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * primitives/traits: Expand the `Extrinsic::SignaturePayload` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * primitives: Adjust to new `Extrinsic` associated types Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * frame/metadata: Simplify metadata generation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * frame/example: Adjust to new interface Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * frame/tests: Adjust `extrinsic_metadata_ir_types` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Revert the additional Extrinsic' associated types Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * primitives: Add `SignaturePayload` marker trait Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * primitives: Implement SignaturePayload for empty tuple Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Adjust to new SignaturePayload trait Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * tests: Adjust `extrinsic_metadata_ir_types` to new interface Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * frame/support: Adjust pallet test Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * frame: Add Extrinsic length prefix to the metadata Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * primitives: Populate `ExtrinsicMetadataIR` with `len_ty` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update primitives/runtime/src/traits.rs Co-authored-by: Bastian Köcher <git@kchr.de> * Apply cargo fmt Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * v15: Remove len type of the extrinsic Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cargo: Update frame-metadata 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> Co-authored-by: parity-processbot <>
Extrinsic Metadata fields
Metadata is enriched to provide users with additional types for decoding extrinsics:
AddresstypeCalltypeSignaturetypeExtratypeAlthough already available on the extrinsic's type generic parameters, having the fields
readily available provides enough information for users to decode extrinsics without
making assumptions about the metadata shape (e.g., this eliminates the need of subxt
to parse those fields manually here, feature also requested by the linked issue).
Note: the
Extratype similar to others can be used to decode the extrinsics, as well as toskip decoding over those fields (see subxt's decoding).
Incomplete UncheckedExtrisnic type
It may be possible for certain substrate-based chains, or even substrate tests, to construct a
runtime with different types, or missing types. For those edge cases, the type reported back in
the metadata is the type of the tuple
meta_type::<()>().Depends on frame-metadata release.
Closes #12929.
Subxt Testing
// @paritytech/subxt-team @jsdw @bkchr