@@ -27,7 +27,7 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
2727use sp_runtime:: traits:: { MaybeDisplay , MaybeFromStr } ;
2828
2929/// Information related to a dispatchable's class, weight, and fee that can be queried from the runtime.
30- #[ derive( Eq , PartialEq , Encode , Decode , Default ) ]
30+ #[ derive( Eq , PartialEq , Encode , Default ) ]
3131#[ cfg_attr( feature = "std" , derive( Debug , Serialize , Deserialize ) ) ]
3232#[ cfg_attr( feature = "std" , serde( rename_all = "camelCase" ) ) ]
3333pub struct RuntimeDispatchInfo < Balance > {
@@ -44,6 +44,38 @@ pub struct RuntimeDispatchInfo<Balance> {
4444 pub partial_fee : Balance ,
4545}
4646
47+ // The weight type used by legacy runtimes
48+ type LegacyWeight = u32 ;
49+ // Encoding of `RuntimeDispatchInfo` is approximately (assuming `u128` balance)
50+ // old byte length (u32, u8, u128) = 168 / 8 = 21
51+ // new byte length (u64, u8, u128) = 200 / 8 = 25
52+ /// Byte length of an encoded legacy `RuntimeDispatchInfo` i.e. Weight = u32
53+ const LEGACY_RUNTIME_DISPATCH_INFO_BYTE_LENGTH : usize = 21 ;
54+
55+ impl < Balance : Decode > Decode for RuntimeDispatchInfo < Balance > {
56+ // Custom decode implementation to handle the differences between the `RuntimeDispatchInfo` type
57+ // between client version vs. runtime version
58+ // Concretely, `Weight` type changed from `u32` in some legacy runtimes to now `u64`
59+ fn decode < I : codec:: Input > ( value : & mut I ) -> Result < Self , codec:: Error > {
60+ // Check `value` len to see whether we should decode legacy or new Weight type
61+ let input_len = value. remaining_len ( ) ?. ok_or ( "empty buffer while decoding" ) ?;
62+ let weight: Weight = if input_len == LEGACY_RUNTIME_DISPATCH_INFO_BYTE_LENGTH {
63+ LegacyWeight :: decode ( value) ?. into ( )
64+ } else {
65+ Weight :: decode ( value) ?
66+ } ;
67+
68+ let class = DispatchClass :: decode ( value) ?;
69+ let partial_fee = Balance :: decode ( value) ?;
70+
71+ return Ok ( Self {
72+ weight,
73+ class,
74+ partial_fee,
75+ } )
76+ }
77+ }
78+
4779#[ cfg( feature = "std" ) ]
4880fn serialize_as_string < S : Serializer , T : std:: fmt:: Display > ( t : & T , serializer : S ) -> Result < S :: Ok , S :: Error > {
4981 serializer. serialize_str ( & t. to_string ( ) )
@@ -67,6 +99,24 @@ sp_api::decl_runtime_apis! {
6799mod tests {
68100 use super :: * ;
69101
102+ #[ test]
103+ fn it_decodes_legacy_runtime_dispatch_info ( ) {
104+ // older runtimes pre-2.0.0 use `type Weight = u32`
105+ let legacy_dispatch_info = ( 1_u32 , DispatchClass :: Normal , 1_u128 ) ;
106+ let decoded = RuntimeDispatchInfo :: < u128 > :: decode ( & mut & legacy_dispatch_info. encode ( ) [ ..] ) . expect ( "it decodes" ) ;
107+ assert_eq ! ( decoded. weight, legacy_dispatch_info. 0 as u64 ) ;
108+ assert_eq ! ( decoded. class, legacy_dispatch_info. 1 ) ;
109+ assert_eq ! ( decoded. partial_fee, legacy_dispatch_info. 2 ) ;
110+ }
111+
112+ #[ test]
113+ fn it_decodes_new_runtime_dispatch_info ( ) {
114+ // newer runtimes post-2.0.0 use `type Weight = u64`
115+ let runtime_dispatch_info = RuntimeDispatchInfo { weight : 1 , class : DispatchClass :: Normal , partial_fee : 1_u128 } ;
116+ let decoded = RuntimeDispatchInfo :: < u128 > :: decode ( & mut & runtime_dispatch_info. encode ( ) [ ..] ) . expect ( "it decodes" ) ;
117+ assert_eq ! ( decoded, runtime_dispatch_info) ;
118+ }
119+
70120 #[ test]
71121 fn should_serialize_and_deserialize_properly_with_string ( ) {
72122 let info = RuntimeDispatchInfo {
0 commit comments