Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Allow nested pallet error, and encode pallet error in 2 bytes. #8081

Closed
gui1117 opened this issue Feb 9, 2021 · 11 comments · Fixed by #10242
Closed

Allow nested pallet error, and encode pallet error in 2 bytes. #8081

gui1117 opened this issue Feb 9, 2021 · 11 comments · Fixed by #10242
Assignees
Labels
J0-enhancement An additional feature request. Z2-medium Can be fixed by a coder with good Rust knowledge but little knowledge of the codebase.

Comments

@gui1117
Copy link
Contributor

gui1117 commented Feb 9, 2021

Currently pallet error is encoded in one byte, and declare in the metadata some documentation associated to each byte.

But we could encode the error on 2 bytes and allow some nested error. As long as the nested error encode in 1 byte and declare its metadata in some way.

We could implement something like this:

#[pallet::error]
enum Error<C: Config> {
    /// Some error
    Foo(Bar),
}

And require Bar to implement a trait.

trait PalletNestedError: Into<u8> {
    fn metadata() -> &[&'static str];
}

The nested error could make use of regular derive macro.

#[derive(PalletNestedError)]
pub enum Bar {
    /// Some doc
    M,
}

This require also some changes in the metadata, (and we probably want to keep the old metadata format available for off-chain libraries, but this is another issue #8083).

@gui1117 gui1117 added U3-nice_to_have Issue is worth doing eventually. Z2-medium Can be fixed by a coder with good Rust knowledge but little knowledge of the codebase. J0-enhancement An additional feature request. and removed U3-nice_to_have Issue is worth doing eventually. labels Feb 9, 2021
@gui1117
Copy link
Contributor Author

gui1117 commented May 21, 2021

once we have metadata with scale-info i think error is just a regular type with its scale-info.
So we should only make sure that the type is not too big so that it is not a footgun, but otherwise any type should easily accepted.

@stale
Copy link

stale bot commented Jul 7, 2021

Hey, is anyone still working on this? Due to the inactivity this issue has been automatically marked as stale. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the A5-stale Pull request did not receive any updates in a long time. No review needed at this stage. Close it. label Jul 7, 2021
@shawntabrizi shawntabrizi removed the A5-stale Pull request did not receive any updates in a long time. No review needed at this stage. Close it. label Jul 7, 2021
@gui1117
Copy link
Contributor Author

gui1117 commented Jul 8, 2021

still relevant to me, also with #8615 which should be able to improve it easily

@KiChjang KiChjang self-assigned this Oct 31, 2021
@KiChjang
Copy link
Contributor

KiChjang commented Nov 2, 2021

Okay, so I would ideally want to use a static assertion here to ensure that the encoded size is less than or equal to 2 bytes. Problem is, there isn't really a method to call the encoded_size() in a const context, since Rust does not support const fns in traits yet.

@KiChjang
Copy link
Contributor

KiChjang commented Nov 2, 2021

The other issue is, the pallet Error type may be parametric, so we can't know the encoded size of the type until we construct the runtime.

@gui1117
Copy link
Contributor Author

gui1117 commented Nov 2, 2021

We can still make a new trait which definition is: encoded size is at most 2 bytes. Like:

trait PalletNestedError {
    fn metadata() -> &[&'static str];
    fn encode() -> u16;
}

I mean we can create a new set of trait and derive macro to declare those errors and they would ensure the constraint we want.

We could also just have some test to ensure the max encoded size is less than some value. It might be enough I'm not sure

@xlc
Copy link
Contributor

xlc commented Nov 2, 2021

We already have assert to ensure size of Call. Similar thing can be done to ensure size of Error

@gui1117
Copy link
Contributor Author

gui1117 commented Nov 2, 2021

yes we can also assert this in the integrity test of frame_system pallet

@bkchr
Copy link
Member

bkchr commented Nov 3, 2021

Okay, so I would ideally want to use a static assertion here to ensure that the encoded size is less than or equal to 2 bytes. Problem is, there isn't really a method to call the encoded_size() in a const context, since Rust does not support const fns in traits yet.

Not sure we really need this. As I explained/tried to explain on sunday, the error will only use the "maximum" encoded size when there is actually such an error being thrown. What I mean by this, is something like this:

enum Error {
  Failure,
  SomeNestedFailure(NestedError),
}

enum NestedError {
  Failure2,
  NestFTW(NestedErrorFTW),
}

enum NestedErrorFTW {
  Yep,
}

If we are throwing Error::Failure, it would use 1 byte. Error::SomeNestedFailure(NestedError::Failure2) would use 2 bytes and Error::SomeNestedError(NestedError::NestFTW(NestedErrorFTW::Yep)) would use 3 bytes.

We probably should give people more freedom for this and document this properly so that they understand this. I would assume that 90% of the cases probably still will use only 1 byte.

@KiChjang
Copy link
Contributor

Hmm, so I'm not sure if I understand the encoding format correctly, but does SCALE not already do such an optimization for nested enums? And if it does not, then it would look like that we'll have to do some sort of custom encoding scheme to support the case where we use less bytes if the enum variant is not nested.

@gui1117
Copy link
Contributor Author

gui1117 commented Nov 10, 2021

yes SCALE does encode like this already, what we need to do is to create trait/derive macro to ensure the error type has constraint so it can be declared only similar to above, and doesn't end up being unconstrained like event which is big.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
J0-enhancement An additional feature request. Z2-medium Can be fixed by a coder with good Rust knowledge but little knowledge of the codebase.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants