/__w/smoldot/smoldot/repo/lib/src/json_rpc/payment_info.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Smoldot |
2 | | // Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. |
3 | | // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 |
4 | | |
5 | | // This program is free software: you can redistribute it and/or modify |
6 | | // it under the terms of the GNU General Public License as published by |
7 | | // the Free Software Foundation, either version 3 of the License, or |
8 | | // (at your option) any later version. |
9 | | |
10 | | // This program is distributed in the hope that it will be useful, |
11 | | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | // GNU General Public License for more details. |
14 | | |
15 | | // You should have received a copy of the GNU General Public License |
16 | | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | | |
18 | | use super::methods; |
19 | | |
20 | | /// Produces the input to pass to the `TransactionPaymentApi_query_info` runtime call. |
21 | 0 | pub fn payment_info_parameters( |
22 | 0 | extrinsic: &'_ [u8], |
23 | 0 | ) -> impl Iterator<Item = impl AsRef<[u8]> + '_> + Clone + '_ { |
24 | 0 | [ |
25 | 0 | either::Left(extrinsic), |
26 | 0 | either::Right(u32::try_from(extrinsic.len()).unwrap().to_le_bytes()), |
27 | 0 | ] |
28 | 0 | .into_iter() |
29 | 0 | } Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot8json_rpc12payment_info23payment_info_parameters Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot8json_rpc12payment_info23payment_info_parameters |
30 | | |
31 | | /// Name of the runtime function to call in order to obtain the payment fees. |
32 | | pub const PAYMENT_FEES_FUNCTION_NAME: &str = "TransactionPaymentApi_query_info"; |
33 | | |
34 | | /// Attempt to decode the output of the runtime call. |
35 | | /// |
36 | | /// Must be passed the version of the `TransactionPaymentApi` API, according to the runtime |
37 | | /// specification. |
38 | 0 | pub fn decode_payment_info( |
39 | 0 | scale_encoded: &'_ [u8], |
40 | 0 | api_version: u32, |
41 | 0 | ) -> Result<methods::RuntimeDispatchInfo, DecodeError> { |
42 | 0 | let is_api_v2 = match api_version { |
43 | 0 | 1 => false, |
44 | 0 | 2 => true, |
45 | 0 | _ => return Err(DecodeError::UnknownRuntimeVersion), |
46 | | }; |
47 | | |
48 | 0 | match nom::combinator::all_consuming(nom_decode_payment_info::<nom::error::Error<&'_ [u8]>>( |
49 | 0 | is_api_v2, |
50 | 0 | ))(scale_encoded) |
51 | | { |
52 | 0 | Ok((_, info)) => Ok(info), |
53 | 0 | Err(_) => Err(DecodeError::ParseError), |
54 | | } |
55 | 0 | } Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot8json_rpc12payment_info19decode_payment_info Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot8json_rpc12payment_info19decode_payment_info |
56 | | |
57 | | /// Potential error when decoding payment information runtime output. |
58 | 0 | #[derive(Debug, derive_more::Display)] Unexecuted instantiation: _RNvXs_NtNtCsN16ciHI6Qf_7smoldot8json_rpc12payment_infoNtB4_11DecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXs_NtNtCseuYC0Zibziv_7smoldot8json_rpc12payment_infoNtB4_11DecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
59 | | pub enum DecodeError { |
60 | | /// Failed to parse the return value of `TransactionPaymentApi_query_info`. |
61 | | ParseError, |
62 | | /// The `TransactionPaymentApi` API uses a version that smoldot doesn't support. |
63 | | UnknownRuntimeVersion, |
64 | | } |
65 | | |
66 | 0 | fn nom_decode_payment_info<'a, E: nom::error::ParseError<&'a [u8]>>( |
67 | 0 | is_api_v2: bool, |
68 | 0 | ) -> impl FnMut(&'a [u8]) -> nom::IResult<&'a [u8], methods::RuntimeDispatchInfo, E> { |
69 | 0 | nom::combinator::map( |
70 | 0 | nom::sequence::tuple(( |
71 | 0 | move |bytes| { |
72 | 0 | if is_api_v2 { |
73 | 0 | nom::number::streaming::le_u64(bytes) |
74 | | } else { |
75 | 0 | nom::combinator::map( |
76 | 0 | nom::sequence::tuple(( |
77 | 0 | crate::util::nom_scale_compact_u64, |
78 | 0 | crate::util::nom_scale_compact_u64, |
79 | 0 | )), |
80 | 0 | |(ref_time, _proof_size)| ref_time, Unexecuted instantiation: _RNCNCINvNtNtCsN16ciHI6Qf_7smoldot8json_rpc12payment_info23nom_decode_payment_infopE00Ba_ Unexecuted instantiation: _RNCNCINvNtNtCseuYC0Zibziv_7smoldot8json_rpc12payment_info23nom_decode_payment_infoINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEE00Ba_ |
81 | 0 | )(bytes) |
82 | | } |
83 | 0 | }, Unexecuted instantiation: _RNCINvNtNtCsN16ciHI6Qf_7smoldot8json_rpc12payment_info23nom_decode_payment_infopE0B8_ Unexecuted instantiation: _RNCINvNtNtCseuYC0Zibziv_7smoldot8json_rpc12payment_info23nom_decode_payment_infoINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEE0B8_ |
84 | 0 | nom::combinator::map_opt(nom::number::streaming::u8, |n| match n { |
85 | 0 | 0 => Some(methods::DispatchClass::Normal), |
86 | 0 | 1 => Some(methods::DispatchClass::Operational), |
87 | 0 | 2 => Some(methods::DispatchClass::Mandatory), |
88 | 0 | _ => None, |
89 | 0 | }), Unexecuted instantiation: _RNCINvNtNtCsN16ciHI6Qf_7smoldot8json_rpc12payment_info23nom_decode_payment_infopEs_0B8_ Unexecuted instantiation: _RNCINvNtNtCseuYC0Zibziv_7smoldot8json_rpc12payment_info23nom_decode_payment_infoINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEs_0B8_ |
90 | 0 | |bytes| { |
91 | 0 | // The exact format here is the SCALE encoding of the type `Balance`. |
92 | 0 | // Normally, determining the actual type of `Balance` would require parsing the |
93 | 0 | // metadata provided by the runtime. However, this is a pretty difficult to |
94 | 0 | // implement and CPU-heavy. Instead, given that there is no other field after |
95 | 0 | // the balance, we simply parse all the remaining bytes. |
96 | 0 | // Because the SCALE encoding of a number is the number in little endian format, |
97 | 0 | // we decode the bytes in little endian format in a way that works no matter the |
98 | 0 | // number of bytes. |
99 | 0 | // If a field was to be added after the balance, this code would need to be |
100 | 0 | // modified. |
101 | 0 | let mut num = 0u128; |
102 | 0 | let mut shift = 0u32; |
103 | 0 | for byte in <[u8]>::iter(bytes) { |
104 | 0 | let shifted = |
105 | 0 | u128::from(*byte) |
106 | 0 | .checked_mul(1 << shift) |
107 | 0 | .ok_or(nom::Err::Error(nom::error::make_error( |
108 | 0 | bytes, |
109 | 0 | nom::error::ErrorKind::Digit, |
110 | 0 | )))?; |
111 | | num = |
112 | 0 | num.checked_add(shifted) |
113 | 0 | .ok_or(nom::Err::Error(nom::error::make_error( |
114 | 0 | bytes, |
115 | 0 | nom::error::ErrorKind::Digit, |
116 | 0 | )))?; |
117 | | shift = |
118 | 0 | shift |
119 | 0 | .checked_add(16) |
120 | 0 | .ok_or(nom::Err::Error(nom::error::make_error( |
121 | 0 | bytes, |
122 | 0 | nom::error::ErrorKind::Digit, |
123 | 0 | )))?; |
124 | | } |
125 | | |
126 | 0 | Ok((&[][..], num)) |
127 | 0 | }, Unexecuted instantiation: _RNCINvNtNtCsN16ciHI6Qf_7smoldot8json_rpc12payment_info23nom_decode_payment_infopEs0_0B8_ Unexecuted instantiation: _RNCINvNtNtCseuYC0Zibziv_7smoldot8json_rpc12payment_info23nom_decode_payment_infoINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEs0_0B8_ |
128 | 0 | )), |
129 | 0 | |(weight, class, partial_fee)| methods::RuntimeDispatchInfo { |
130 | 0 | weight, |
131 | 0 | class, |
132 | 0 | partial_fee, |
133 | 0 | }, Unexecuted instantiation: _RNCINvNtNtCsN16ciHI6Qf_7smoldot8json_rpc12payment_info23nom_decode_payment_infopEs1_0B8_ Unexecuted instantiation: _RNCINvNtNtCseuYC0Zibziv_7smoldot8json_rpc12payment_info23nom_decode_payment_infoINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEs1_0B8_ |
134 | 0 | ) |
135 | 0 | } Unexecuted instantiation: _RINvNtNtCsN16ciHI6Qf_7smoldot8json_rpc12payment_info23nom_decode_payment_infopEB6_ Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8json_rpc12payment_info23nom_decode_payment_infoINtNtCs6ga8gEqbpRc_3nom5error5ErrorRShEEB6_ |