1use massa_models::{
2 address::{Address, AddressDeserializer, AddressSerializer},
3 amount::{Amount, AmountDeserializer, AmountSerializer},
4 serialization::{StringDeserializer, StringSerializer, VecU8Deserializer, VecU8Serializer},
5 slot::{Slot, SlotDeserializer, SlotSerializer},
6};
7use massa_proto_rs::massa::api::v1 as grpc_api;
8use massa_serialization::{
9 BoolDeserializer, BoolSerializer, Deserializer, SerializeError, Serializer,
10 U16VarIntDeserializer, U16VarIntSerializer, U64VarIntDeserializer, U64VarIntSerializer,
11};
12use nom::{
13 error::{context, ContextError, ParseError},
14 sequence::tuple,
15 IResult, Parser,
16};
17use serde::{Deserialize, Serialize};
18use std::ops::Bound;
19
20use crate::config::DeferredCallsConfig;
21
22#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
24pub struct DeferredCall {
25 pub sender_address: Address,
27 pub target_slot: Slot,
29 pub target_address: Address,
31 pub target_function: String,
33 pub parameters: Vec<u8>,
35 pub coins: Amount,
37 pub max_gas: u64,
40 pub fee: Amount,
42 pub cancelled: bool,
44}
45
46impl DeferredCall {
47 #[allow(clippy::too_many_arguments)]
48 pub fn new(
49 sender_address: Address,
50 target_slot: Slot,
51 target_address: Address,
52 target_function: String,
53 parameters: Vec<u8>,
54 coins: Amount,
55 max_gas: u64,
56 fee: Amount,
57 cancelled: bool,
58 ) -> Self {
59 DeferredCall {
60 sender_address,
61 target_slot,
62 target_address,
63 target_function,
64 parameters,
65 coins,
66 max_gas,
67 fee,
68 cancelled,
69 }
70 }
71
72 pub fn get_effective_gas(&self, alloc_gas_cost: u64) -> u64 {
75 self.max_gas.saturating_add(alloc_gas_cost)
76 }
77
78 pub fn get_storage_cost(
80 cost_per_byte: Amount,
81 params_size: u64,
82 max_function_name_length: u16,
83 ) -> Amount {
84 let total_size = params_size
86 .saturating_add(max_function_name_length as u64)
87 .saturating_add(111); cost_per_byte.saturating_mul_u64(total_size)
89 }
90}
91
92impl From<DeferredCall> for grpc_api::DeferredCallInfoEntry {
93 fn from(call: DeferredCall) -> Self {
94 grpc_api::DeferredCallInfoEntry {
95 sender_address: call.sender_address.to_string(),
96 target_slot: Some(call.target_slot.into()),
97 target_address: call.target_address.to_string(),
98 target_function: call.target_function,
99 parameters: call.parameters,
100 coins: Some(call.coins.into()),
101 max_gas: call.max_gas,
102 fee: Some(call.fee.into()),
103 cancelled: call.cancelled,
104 }
105 }
106}
107
108#[derive(Clone)]
110pub struct DeferredCallSerializer {
111 pub(crate) slot_serializer: SlotSerializer,
112 pub(crate) address_serializer: AddressSerializer,
113 pub(crate) string_serializer: StringSerializer<U16VarIntSerializer, u16>,
114 pub(crate) vec_u8_serializer: VecU8Serializer,
115 pub(crate) amount_serializer: AmountSerializer,
116 pub(crate) u64_var_int_serializer: U64VarIntSerializer,
117 pub(crate) bool_serializer: BoolSerializer,
118}
119
120impl DeferredCallSerializer {
121 pub fn new() -> Self {
123 Self {
124 slot_serializer: SlotSerializer::new(),
125 address_serializer: AddressSerializer::new(),
126 string_serializer: StringSerializer::new(U16VarIntSerializer::new()),
127 vec_u8_serializer: VecU8Serializer::new(),
128 amount_serializer: AmountSerializer::new(),
129 u64_var_int_serializer: U64VarIntSerializer::new(),
130 bool_serializer: BoolSerializer::new(),
131 }
132 }
133}
134
135impl Serializer<DeferredCall> for DeferredCallSerializer {
136 fn serialize(&self, value: &DeferredCall, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
137 self.address_serializer
138 .serialize(&value.sender_address, buffer)?;
139 self.slot_serializer.serialize(&value.target_slot, buffer)?;
140 self.address_serializer
141 .serialize(&value.target_address, buffer)?;
142 self.string_serializer
143 .serialize(&value.target_function, buffer)?;
144 self.vec_u8_serializer
145 .serialize(&value.parameters, buffer)?;
146 self.amount_serializer.serialize(&value.coins, buffer)?;
147 self.u64_var_int_serializer
148 .serialize(&value.max_gas, buffer)?;
149 self.amount_serializer.serialize(&value.fee, buffer)?;
150 self.bool_serializer.serialize(&value.cancelled, buffer)?;
151 Ok(())
152 }
153}
154
155#[derive(Clone)]
157pub struct DeferredCallDeserializer {
158 slot_deserializer: SlotDeserializer,
159 pub(crate) address_deserializer: AddressDeserializer,
160 pub(crate) string_deserializer: StringDeserializer<U16VarIntDeserializer, u16>,
161 pub(crate) vec_u8_deserializer: VecU8Deserializer,
162 pub(crate) amount_deserializer: AmountDeserializer,
163 pub(crate) u64_var_int_deserializer: U64VarIntDeserializer,
164 pub(crate) bool_deserializer: BoolDeserializer,
165}
166
167impl DeferredCallDeserializer {
168 pub fn new(config: DeferredCallsConfig) -> Self {
170 Self {
171 slot_deserializer: SlotDeserializer::new(
172 (Bound::Included(0), Bound::Included(u64::MAX)),
173 (Bound::Included(0), Bound::Excluded(config.thread_count)),
174 ),
175 address_deserializer: AddressDeserializer::new(),
176 string_deserializer: StringDeserializer::new(U16VarIntDeserializer::new(
177 Bound::Included(0),
178 Bound::Included(config.max_function_name_length),
179 )),
180 vec_u8_deserializer: VecU8Deserializer::new(
181 std::ops::Bound::Included(0),
182 std::ops::Bound::Included(config.max_parameter_size as u64),
183 ),
184 amount_deserializer: AmountDeserializer::new(
185 Bound::Included(Amount::MIN),
186 Bound::Included(Amount::MAX),
187 ),
188 u64_var_int_deserializer: U64VarIntDeserializer::new(
189 Bound::Included(0),
190 Bound::Included(u64::MAX),
191 ),
192 bool_deserializer: BoolDeserializer::new(),
193 }
194 }
195}
196
197impl Deserializer<DeferredCall> for DeferredCallDeserializer {
198 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
199 &self,
200 buffer: &'a [u8],
201 ) -> IResult<&'a [u8], DeferredCall, E> {
202 context(
203 "Failed AsyncCall deserialization",
204 tuple((
205 context("Failed sender_address deserialization", |input| {
206 self.address_deserializer.deserialize(input)
207 }),
208 context("Failed target_slot deserialization", |input| {
209 self.slot_deserializer.deserialize(input)
210 }),
211 context("Failed target_address deserialization", |input| {
212 self.address_deserializer.deserialize(input)
213 }),
214 context("Failed target_function deserialization", |input| {
215 self.string_deserializer.deserialize(input)
216 }),
217 context("Failed parameters deserialization", |input| {
218 self.vec_u8_deserializer.deserialize(input)
219 }),
220 context("Failed coins deserialization", |input| {
221 self.amount_deserializer.deserialize(input)
222 }),
223 context("Failed max_gas deserialization", |input| {
224 self.u64_var_int_deserializer.deserialize(input)
225 }),
226 context("Failed fee deserialization", |input| {
227 self.amount_deserializer.deserialize(input)
228 }),
229 context("Failed cancelled deserialization", |input| {
230 self.bool_deserializer.deserialize(input)
231 }),
232 )),
233 )
234 .map(
235 |(
236 sender_address,
237 target_slot,
238 target_address,
239 target_function,
240 parameters,
241 coins,
242 max_gas,
243 fee,
244 cancelled,
245 )| {
246 DeferredCall::new(
247 sender_address,
248 target_slot,
249 target_address,
250 target_function,
251 parameters,
252 coins,
253 max_gas,
254 fee,
255 cancelled,
256 )
257 },
258 )
259 .parse(buffer)
260 }
261}
262
263#[cfg(test)]
264mod tests {
265 use std::str::FromStr;
266
267 use massa_serialization::DeserializeError;
268
269 use super::*;
270
271 #[test]
272 fn test_serialization_deserialization() {
273 let call = DeferredCall::new(
274 Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
275 Slot::new(42, 0),
276 Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
277 "function".to_string(),
278 vec![0, 1, 2, 3],
279 Amount::from_raw(100),
280 500000,
281 Amount::from_raw(25),
282 false,
283 );
284 let serializer = DeferredCallSerializer::new();
285
286 let deserializer = DeferredCallDeserializer::new(DeferredCallsConfig::default());
287 let mut buffer = Vec::new();
288 serializer.serialize(&call, &mut buffer).unwrap();
289 let (rest, deserialized_call) = deserializer
290 .deserialize::<DeserializeError>(&buffer)
291 .unwrap();
292 assert_eq!(call, deserialized_call);
293 assert!(rest.is_empty());
294 }
295}