|
19 | 19 |
|
20 | 20 | use super::*;
|
21 | 21 | use alloc::borrow::Cow;
|
22 |
| -use codec::{Decode, DecodeWithMemTracking, 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,13 +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 | 170 | #[derive(
|
123 | 171 | Clone, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo, Eq, PartialEq, Debug,
|
124 | 172 | )]
|
125 |
| -pub struct TrackInfo<Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LEN> { |
| 173 | +pub struct TrackDetails<Balance, Moment, Name> { |
126 | 174 | /// Name of this track.
|
127 |
| - pub name: [u8; N], |
| 175 | + pub name: Name, |
128 | 176 | /// A limit for the number of referenda on this track that can be being decided at once.
|
129 | 177 | /// For Root origin this should generally be just one.
|
130 | 178 | pub max_deciding: u32,
|
@@ -795,4 +843,20 @@ mod tests {
|
795 | 843 | Err("The tracks that were returned by `tracks` were not sorted by `Id`")
|
796 | 844 | );
|
797 | 845 | }
|
| 846 | + |
| 847 | + #[test] |
| 848 | + fn encoding_and_decoding_of_string_like_structure_works() { |
| 849 | + let string_like = StringLike::<13>(*b"hello, world!"); |
| 850 | + let encoded: Vec<u8> = string_like.encode(); |
| 851 | + |
| 852 | + let decoded_as_vec: Vec<u8> = |
| 853 | + Decode::decode(&mut &encoded.clone()[..]).expect("decoding as Vec<u8> should work"); |
| 854 | + assert_eq!(decoded_as_vec.len(), 13); |
| 855 | + let decoded_as_str: alloc::string::String = |
| 856 | + Decode::decode(&mut &encoded.clone()[..]).expect("decoding as str should work"); |
| 857 | + assert_eq!(decoded_as_str.len(), 13); |
| 858 | + let decoded_as_string_like: StringLike<13> = |
| 859 | + Decode::decode(&mut &encoded.clone()[..]).expect("decoding as StringLike should work"); |
| 860 | + assert_eq!(decoded_as_string_like.0.len(), 13); |
| 861 | + } |
798 | 862 | }
|
0 commit comments