Skip to content
This repository was archived by the owner on Jul 4, 2022. It is now read-only.

Commit cb0944e

Browse files
authored
Add custom decode to support RuntimeDispatchInfo when Weight=u32 (#163)
1 parent 5da1a8c commit cb0944e

File tree

1 file changed

+51
-1
lines changed
  • frame/transaction-payment/rpc/runtime-api/src

1 file changed

+51
-1
lines changed

frame/transaction-payment/rpc/runtime-api/src/lib.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
2727
use 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"))]
3333
pub 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")]
4880
fn 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! {
6799
mod 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

Comments
 (0)