|
19 | 19 |
|
20 | 20 | use super::*;
|
21 | 21 | use alloc::borrow::Cow;
|
22 |
| -use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; |
| 22 | +use codec::{Compact, Decode, DecodeWithMemTracking, Encode, EncodeLike, Input, MaxEncodedLen}; |
23 | 23 | use core::fmt::Debug;
|
24 | 24 | use frame_support::{
|
25 | 25 | traits::{schedule::v3::Anon, Bounded},
|
26 | 26 | Parameter,
|
27 | 27 | };
|
28 |
| -use scale_info::TypeInfo; |
| 28 | +use scale_info::{Type, TypeInfo}; |
29 | 29 | use sp_arithmetic::{Rounding::*, SignedRounding::*};
|
30 | 30 | use sp_runtime::{FixedI64, PerThing, RuntimeDebug};
|
31 | 31 |
|
@@ -118,11 +118,61 @@ pub struct Deposit<AccountId, Balance> {
|
118 | 118 |
|
119 | 119 | pub const DEFAULT_MAX_TRACK_NAME_LEN: usize = 25;
|
120 | 120 |
|
| 121 | +/// Helper structure to treat a `[u8; N]` array as a string. |
| 122 | +/// |
| 123 | +/// This is a temporary fix (see [#7671](https://github.com/paritytech/polkadot-sdk/pull/7671)) in |
| 124 | +/// order to stop `polkadot.js` apps to fail when trying to decode the `name` field in `TrackInfo`. |
| 125 | +#[derive(Clone, Eq, DecodeWithMemTracking, PartialEq, Debug)] |
| 126 | +pub struct StringLike<const N: usize>(pub [u8; N]); |
| 127 | + |
| 128 | +impl<const N: usize> TypeInfo for StringLike<N> { |
| 129 | + type Identity = <&'static str as TypeInfo>::Identity; |
| 130 | + |
| 131 | + fn type_info() -> Type { |
| 132 | + <&str as TypeInfo>::type_info() |
| 133 | + } |
| 134 | +} |
| 135 | + |
| 136 | +impl<const N: usize> MaxEncodedLen for StringLike<N> { |
| 137 | + fn max_encoded_len() -> usize { |
| 138 | + <Compact<u32> as MaxEncodedLen>::max_encoded_len().saturating_add(N) |
| 139 | + } |
| 140 | +} |
| 141 | + |
| 142 | +impl<const N: usize> Encode for StringLike<N> { |
| 143 | + fn encode(&self) -> Vec<u8> { |
| 144 | + use codec::Compact; |
| 145 | + (Compact(N as u32), self.0).encode() |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +impl<const N: usize> Decode for StringLike<N> { |
| 150 | + fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> { |
| 151 | + let Compact(size): Compact<u32> = Decode::decode(input)?; |
| 152 | + if size != N as u32 { |
| 153 | + return Err("Invalid size".into()); |
| 154 | + } |
| 155 | + |
| 156 | + let bytes: [u8; N] = Decode::decode(input)?; |
| 157 | + Ok(Self(bytes)) |
| 158 | + } |
| 159 | +} |
| 160 | + |
| 161 | +/// Detailed information about the configuration of a referenda track. Used for internal storage. |
| 162 | +pub type TrackInfo<Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LEN> = |
| 163 | + TrackDetails<Balance, Moment, [u8; N]>; |
| 164 | + |
| 165 | +/// Detailed information about the configuration of a referenda track. Used for const querying. |
| 166 | +pub type ConstTrackInfo<Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LEN> = |
| 167 | + TrackDetails<Balance, Moment, StringLike<N>>; |
| 168 | + |
121 | 169 | /// Detailed information about the configuration of a referenda track
|
122 |
| -#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, Eq, PartialEq, Debug)] |
123 |
| -pub struct TrackInfo<Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LEN> { |
| 170 | +#[derive( |
| 171 | + Clone, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo, Eq, PartialEq, Debug, |
| 172 | +)] |
| 173 | +pub struct TrackDetails<Balance, Moment, Name> { |
124 | 174 | /// Name of this track.
|
125 |
| - pub name: [u8; N], |
| 175 | + pub name: Name, |
126 | 176 | /// A limit for the number of referenda on this track that can be being decided at once.
|
127 | 177 | /// For Root origin this should generally be just one.
|
128 | 178 | pub max_deciding: u32,
|
@@ -324,7 +374,7 @@ impl<
|
324 | 374 |
|
325 | 375 | /// Type for describing a curve over the 2-dimensional space of axes between 0-1, as represented
|
326 | 376 | /// by `(Perbill, Perbill)`.
|
327 |
| -#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo, MaxEncodedLen)] |
| 377 | +#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, TypeInfo, MaxEncodedLen)] |
328 | 378 | #[cfg_attr(not(feature = "std"), derive(RuntimeDebug))]
|
329 | 379 | pub enum Curve {
|
330 | 380 | /// Linear curve starting at `(0, ceil)`, proceeding linearly to `(length, floor)`, then
|
@@ -791,4 +841,20 @@ mod tests {
|
791 | 841 | Err("The tracks that were returned by `tracks` were not sorted by `Id`")
|
792 | 842 | );
|
793 | 843 | }
|
| 844 | + |
| 845 | + #[test] |
| 846 | + fn encoding_and_decoding_of_string_like_structure_works() { |
| 847 | + let string_like = StringLike::<13>(*b"hello, world!"); |
| 848 | + let encoded: Vec<u8> = string_like.encode(); |
| 849 | + |
| 850 | + let decoded_as_vec: Vec<u8> = |
| 851 | + Decode::decode(&mut &encoded.clone()[..]).expect("decoding as Vec<u8> should work"); |
| 852 | + assert_eq!(decoded_as_vec.len(), 13); |
| 853 | + let decoded_as_str: alloc::string::String = |
| 854 | + Decode::decode(&mut &encoded.clone()[..]).expect("decoding as str should work"); |
| 855 | + assert_eq!(decoded_as_str.len(), 13); |
| 856 | + let decoded_as_string_like: StringLike<13> = |
| 857 | + Decode::decode(&mut &encoded.clone()[..]).expect("decoding as StringLike should work"); |
| 858 | + assert_eq!(decoded_as_string_like.0.len(), 13); |
| 859 | + } |
794 | 860 | }
|
0 commit comments