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

Allow somehow validate the decoded output #280

Open
xlc opened this issue Jul 1, 2021 · 3 comments
Open

Allow somehow validate the decoded output #280

xlc opened this issue Jul 1, 2021 · 3 comments

Comments

@xlc
Copy link

xlc commented Jul 1, 2021

For example, we want a custom integer type can only old number less than 100:

#[derive(Encode, Decode)]
struct UIntLessThan100(u8);

impl UIntLessThan100 {
  pub new(val: u8) -> Option<Self> { if val < 100 { Some(Self(val)) } else { None } 
  pub add(self, other: Self) -> u8 { self.0 + other.0 } // this can never overflow because we know 100 + 100 < 255
}

But this will result an invalid struct and break the invariant and causing panics.

let bad: UIntLessThan100 = Decode::decode(&mut &[255u8]).unwrap();

BoundedVec have similar issue and the solution is write a custom decode implementation. But it is tedious for large struct.

@xlc
Copy link
Author

xlc commented Jul 2, 2021

Could be something like this serde-rs/serde#642 (comment)

@xlc
Copy link
Author

xlc commented Jul 2, 2021

From @rphmeier

You could make a PR to add a trait parity_scale_codec::Validated and then have a new #[codec(validated)] annotation which applies to a struct which is #[derive(Decode)]
Add a CodecError::ValidationFailed
Then in the autogenerated Decode impl, if the codec(validated) is present, it adds the extra check
#[codec(validate_with = "fn_path")] would avoid the need for a new trait

@rphmeier
Copy link
Contributor

rphmeier commented Jul 6, 2021

Yes, so an example of this would be

#[derive(Decode)]
#[codec(validate_with = "check_trit")]
struct Trit(u8);

// Probably some more concrete error type in practice
fn check_trit(trit: &Trit) -> Result<(), String> {
    match trit.0 {
        0 | 1 | 2 => Ok(()),
        _ => Err("byte-pattern out of range for trit".into()),
    }
}

If the "validation function" fails, that would manifest as a CodecError at a higher level.

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

No branches or pull requests

2 participants