5

Please see edits 2 and beyond, as they reshape the question a lot.

TLDR: I need a way to mutate an origin for all but some specific calls so that it's dispatched as RawOrigin::Signed to pass ensure_signed and also so that it goes through pallet-transaction-payment's SignedExtension to charge fees.

I have a pallet that has it's own origin (which then gets appended to the overarching Origin made by construct_runtime), this pallet dispatches calls using it's own custom origin, but I would like this origin to be compatible with ensure_signed so it works naturally with other pallets, and to do that I need to implement Into<Result<RawOrigin, Origin>> for the overarching Origin of the runtime, which is already implemented by the construct_runtime macro.

I assume it just uses the _ pattern to return Err(origin) for anything that is not already Signed(accountid), but I want to override this impl to also return Ok(Signed(accountid)) when my custom origin's enum variant matches, but since it's inside the macro I'd assume there is a specific way to do that which I can't seem to find documented.

There's also the possibility that I'm completely missing some other simpler way to have ensure_signed accept my custom origin, which I wouldn't know, again, because of the lack of documentation.

Edit: I'm going to go further into what I want to modify:

From this line in the construct_runtime macro expansion: https://github.com/paritytech/substrate/blob/master/frame/support/procedural/src/construct_runtime/expand/origin.rs#L287

impl From<RuntimeOrigin> for #scrate::sp_std::result::Result<#system_path::Origin<#runtime>, RuntimeOrigin> {
    fn from(val: RuntimeOrigin) -> Self {
        if let OriginCaller::system(l) = val.caller {
            Ok(l)
        } else {
            Err(val)
        }
    }
}

This piece of macro gets expanded inside my own runtime code, not in an external crate, so it's not just a matter of replacing it, I have no access to it simply because it's a macro that gets expanded on compile time. But here's what I want it to look like:

impl From<RuntimeOrigin> for #scrate::sp_std::result::Result<#system_path::Origin<#runtime>, RuntimeOrigin> {
    fn from(val: RuntimeOrigin) -> Self {
        match val.caller {
            OriginCaller::system(l) => Ok(l),
            OriginCaller::my_origin(c) => Ok(function_that_converts(c)),
            _ => Err(val)
        }
    }
}

Edit 2: I found an open issue in paritytech/substrate about SignedExtension (https://github.com/paritytech/substrate/issues/3419#issuecomment-587387100) that, if implemented, would allow for me to do this by simply making a SignedExtension.

The linked comment mentions that with the implementation you would be able to mutate the origin of a call in the extension, which would be perfect as I could simply write logic to convert my custom origin to Signed(account_id) in the validate function.

However, as you can see, the issue is from 2019 and is still open, so either a better and undocumented solution was introduced, or this has just been ignored ever since.

Edit 3: The issue mentioned in the previous edit really seems to be what I'd actually need, as it would also allow me to properly charge fees for those transactions by placing them before the ChargeTransactionPayment SignedExtension and making them go through it like any other Signed origin.

5
  • Can you share the source code? Oct 31, 2022 at 10:55
  • Not sure exactly what to share here, the process of making a custom origin is pretty standard. Perhaps pointing to the implementation I want to modify makes sense, here it is: github.com/paritytech/substrate/blob/master/frame/support/… Since this macro is expanded in my own runtime and not in an external crate, I expect to be able to modify the implementations generate by it.
    – Gabe
    Oct 31, 2022 at 13:13
  • Added some more info in edits.
    – Gabe
    Oct 31, 2022 at 16:41
  • It looks to me like you found the correct substrate issue.
    – apopiak
    Feb 13, 2023 at 15:40
  • Curious if you end up finding some sort of workaround for this. Mar 28, 2023 at 3:53

2 Answers 2

1

Very interesting problem but I believe you cannot modify ensure_signed as per this answer. Is it possible to define a custom origin in my pallet?

3
  • I'm not trying to modify ensure_signed, rather I'm trying to modify the Into impl generated by the construct_runtime macro which ensure_signed uses on Origin.
    – Gabe
    Oct 31, 2022 at 12:00
  • What you want to achieve i kinda understand it, You want a user to be able to dispatch call using custom origin and automatically the user will be recognized as signed origin because Into trait is implemented on your custom origins. But the issue is you cannot override this as per Shawn reply. Or maybe you really modify FRAME core. Oct 31, 2022 at 12:17
  • Shawn's reply (and also Rob's) refers to modifying the ensure_signed function and RawOrigin::Signed enum variant respectfully, this is what I want to modify: github.com/paritytech/substrate/blob/master/frame/support/… This macro is expanded inside my own runtime, so should have access to the implementation and should be able to modify it.
    – Gabe
    Oct 31, 2022 at 13:13
1

I have no access to it simply because it's a macro that gets expanded on compile time.

You can actually replace the generated code with the edits as lib.rs and it should be possible to use it.

Next why aren't you considering implementing Into<CustomOrigin> for RawOrigin at your module instead and using ensure_signed(origin.into().). I am not versed with custom origins so take this with a grain of salt, I maybe missing something.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.