-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Perbill and other should be decode only valid instance. #5462
Comments
If we look at the size of the compact encoding of perthings here is the result: Percent: PerU16: Permill: Perbill: Perquinntill: Considering these result I think the compact representation for perthing doesn't really make sense. My opinion is to remove it. |
How does compact encoding exactly work, for example can you elaborate more on this comment:
Also bringing this issue generally up as it seem to have been forgotten but it is important to resolve. |
ah I wrote bit but it is byte.
the general doc is https://substrate.dev/docs/en/knowledgebase/advanced/codec The issue needs a new major version from parity-scale-codec, though we thought would be good to include paritytech/parity-scale-codec#208 |
at the same time we could remove compact encoding of perthings for substrate 2.0 ? |
Okay now it is clear. But as far as I can see if just create a percent and encode it, you will use the fixe-width encoding. Only if you wrap it inside a compact struct etc. we will use the compact encoding. I think this is perfectly fine. The user should be aware of this and make sure they use compact only it makes sense. Another note is: #6720 Here we manually wrapped u32 and u16 values in compact. But based on your info, for u16 it is most often not really worth being encoded as compact. The PR overall did improve the size of the solution struct, but that was probably most often because of u32 being optimised. |
indeed the only worry for me is when used in dispatchable like this: decl_module! {
....
fn transfert_some(origin, #[compact] p: Perbill) { ... }
} Here such code allow the caller to give a Perbill which is more than 1. |
Yes I think the best and only thing to do is to document this in Perbill and all the others that they may bot be worth being used with #[compact]. Not much more that we can do about it. |
The decode can still fail and make the transaction invalid. |
with current parity scale codec it doesn't seems doable. Another idea could be to just convert to max when decoding a compact encoding of a value beyond the maximum allowed. impl CompactAs for Perbill {
type As = u64;
fn encode_as(&self) -> &u64{
self.deconstruct()
}
fn decode_from(x: u64) -> Perbill {
Perbill { x.max(BILLION) }
}
}
impl From<Compact<Perbill>> for Perbill {
fn from(x: Compact<Perbill>) -> Perbill {
Perbill(x.deconstruct().max(BILLION))
}
} There is still an issue if user do (If user still want to use this specific encoding, then we can implement Encode/Decode on a new struct CompactPerbill and implement From/Into.) |
I thought this issue is just about the efficiency of compact usage, I forgot the initial point that decoding can be corrupt. I am sure that we don't Will you work on this yourself? else I can probably have a go later this week. |
ah I wrote:
But its wrong, if we implement the CompactAs manually then Decode implementation is: impl<T> Decode for Compact<T>
where
T: CompactAs,
Compact<T::As>: Decode,
{
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
Compact::<T::As>::decode(input)
.map(|x| Compact(<T as CompactAs>::decode_from(x.0)))
}
} So Then I think manually implementation CompactAs is a good solution, I can do, it should be quick |
Currenctly decoding a 2 billion value doesn't return error
I think as the doc state
We must actually return error if value is more than one billion.
(and same for other perthings)
cc @kianenigma
The text was updated successfully, but these errors were encountered: