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

Access to Signed Extensions and Events when looking for a StaticExtrinsic #1359

Closed
tadeohepperle opened this issue Jan 12, 2024 · 1 comment · Fixed by #1376
Closed

Access to Signed Extensions and Events when looking for a StaticExtrinsic #1359

tadeohepperle opened this issue Jan 12, 2024 · 1 comment · Fixed by #1376

Comments

@tadeohepperle
Copy link
Contributor

Problem

The Extrinsics<T: Config, C: Client> struct exposes a lot of functionalities that come in handy to learn more about an extrinsic. But it lacks a statically decoded representation of a specific Extrinsic type. Right now, you do not have a nice way of e.g. finding all TransferKeepAlive extrinsics in a block together with their events and signed extensions.

Status Quo

If you have the Extrinsics of a block, you can find StaticExtrinsics with extrinsics.find<E: StaticExtrinsic>() returning an iterator over elements of the type E. But by doing this, you lose the access to the information stored in the (untyped) ExtrinsicDetails: signed extensions and events.

To get e.g. all TransferKeepAlive extrinsics in a block with their events and signed extensions, you would have to iterate over all extrinsics and then return a tuple for all the ones that are a TransferKeepAlive. This tuple would have the statically decoded transfer + the untyped ExtrinsicDetails:

extrinsics.iter().filter_map(|e| {
     if e.is_err(){
          return None;
     }
    let e = e.unwrap();
    match e.as_extrinsic::<TransferKeepAlive>(){
         Err(e) => None,
         Ok(transfer) => Some((transfer, e)) // the tuple contains all the information we need
    }
})

This is a bit cumbersome and could lead people to not use the utility functions like Extrinsics::find<E: StaticExtrinsic>();

Proposal

We could introduce a new type StaticExtrinsicDetails and use it as a return value whenever we try to find/decode static extrinsics.

struct StaticExtrinsicDetails<E: StaticExtrinsic>{
    details: ExtrinsicDetails,
    decoded: StaticExtrinsic,
}

Alternative:

We could also just extend ExtrinsicDetails by another type parameter that is () by default:

pub struct ExtrinsicDetails<T: Config, C, E = ()> {
    decoded: E // a StaticExtrinsic or () or DecodeAsType
    bytes: Arc<[u8]>,
    pallet_index: u8,
    variant_index: u8,
    ...
}

Then we could do:

impl<T: Config, C: OfflineClientT<T>> for ExtrinsicDetails<T, C, ()>  { // note: impl only for unit type 
    pub fn as_extrinsic<E: StaticExtrinsic>(&self) -> Result<Option<ExtrinsicDetails<T,C,E>>, Error> {
         // static decoding
    }

    pub fn as_root_extrinsic<E: DecodeAsType>(&self) -> Result<ExtrinsicDetails<T,C,E>>, Error> {
         // decoding
    }
}
@jsdw
Copy link
Collaborator

jsdw commented Jan 15, 2024

Good idea to make those helpers more useful :)

We could introduce a new type StaticExtrinsicDetails and use it as a return value whenever we try to find/decode static extrinsics.

That would be my preference: have find, find_first and find_last all return a simple struct with two public fields: the decoded extrinsic itself and the extrinsic details in case you want to do more! I'd probably have it look something like:

pub struct FoundExtrinsic<E> {
    pub details: ExtrinsicDetails,
    pub value: E
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants