1use call::{DeferredCallDeserializer, DeferredCallSerializer};
2use config::DeferredCallsConfig;
3use macros::{
4 CALL_FIELD_CANCELED, CALL_FIELD_COINS, CALL_FIELD_FEE, CALL_FIELD_MAX_GAS,
5 CALL_FIELD_PARAMETERS, CALL_FIELD_SENDER_ADDRESS, CALL_FIELD_TARGET_ADDRESS,
6 CALL_FIELD_TARGET_FUNCTION, CALL_FIELD_TARGET_SLOT,
7};
8use massa_db_exports::{
9 DBBatch, ShareableMassaDBController, CRUD_ERROR, DEFERRED_CALLS_PREFIX,
10 DEFERRED_CALL_DESER_ERROR, DEFERRED_CALL_SER_ERROR, DEFERRED_CALL_TOTAL_GAS, KEY_DESER_ERROR,
11 STATE_CF,
12};
13use massa_models::{address::Address, slot::SlotDeserializer};
14use massa_serialization::{
15 buf_to_array_ctr, DeserializeError, Deserializer, Serializer, U128VarIntDeserializer,
16 U128VarIntSerializer,
17};
18use registry_changes::DeferredCallRegistryChanges;
19
20mod call;
23pub mod config;
24pub mod registry_changes;
25pub mod slot_changes;
26
27#[cfg(test)]
28mod tests;
29
30#[macro_use]
31mod macros;
32
33pub use call::DeferredCall;
34use massa_models::types::{SetOrDelete, SetOrKeep, SetOrKeepDeserializer, SetOrKeepSerializer};
35use massa_models::{
36 amount::Amount,
37 deferred_calls::{DeferredCallId, DeferredCallIdDeserializer, DeferredCallIdSerializer},
38 slot::Slot,
39};
40use std::collections::{BTreeMap, HashSet};
41use std::ops::Bound;
42
43pub struct DeferredCallRegistry {
45 db: ShareableMassaDBController,
46 call_serializer: DeferredCallSerializer,
47 call_id_serializer: DeferredCallIdSerializer,
48 call_deserializer: DeferredCallDeserializer,
49 call_id_deserializer: DeferredCallIdDeserializer,
50 slot_deserializer: SlotDeserializer,
51 effective_total_gas_deserializer: SetOrKeepDeserializer<u128, U128VarIntDeserializer>,
52 effective_total_gas_serializer: SetOrKeepSerializer<u128, U128VarIntSerializer>,
53 min_gas_cost: u64,
54}
55
56impl DeferredCallRegistry {
57 pub fn new(db: ShareableMassaDBController, config: DeferredCallsConfig) -> Self {
66 Self {
67 db,
68 call_serializer: DeferredCallSerializer::new(),
69 call_id_serializer: DeferredCallIdSerializer::new(),
70 call_deserializer: DeferredCallDeserializer::new(config),
71 call_id_deserializer: DeferredCallIdDeserializer::new(),
72 slot_deserializer: SlotDeserializer::new(
73 (Bound::Included(0), Bound::Included(u64::MAX)),
74 (Bound::Included(0), Bound::Excluded(config.thread_count)),
75 ),
76 effective_total_gas_deserializer: SetOrKeepDeserializer::new(
77 U128VarIntDeserializer::new(Bound::Included(u128::MIN), Bound::Included(u128::MAX)),
78 ),
79 effective_total_gas_serializer: SetOrKeepSerializer::new(U128VarIntSerializer::new()),
80 min_gas_cost: config.min_gas_cost,
81 }
82 }
83
84 pub fn get_slot_calls(&self, slot: Slot) -> DeferredSlotCalls {
86 let mut to_return = DeferredSlotCalls::new(slot);
87 let key = deferred_slot_call_prefix_key!(slot.to_bytes_key());
88
89 let mut temp = HashSet::new();
90
91 for (serialized_key, _serialized_value) in self.db.read().prefix_iterator_cf(STATE_CF, &key)
92 {
93 if !serialized_key.starts_with(&key) {
94 break;
95 }
96
97 let rest_key = &serialized_key[key.len()..];
98
99 let (_rest, call_id) = self
100 .call_id_deserializer
101 .deserialize::<DeserializeError>(rest_key)
102 .expect(KEY_DESER_ERROR);
103
104 if !temp.insert(call_id.clone()) {
105 continue;
106 }
107
108 if let Some(call) = self.get_call(&slot, &call_id) {
109 to_return.slot_calls.insert(call_id, call);
110 }
111 }
112
113 to_return.slot_base_fee = self.get_slot_base_fee(&slot);
114 to_return.effective_slot_gas = self.get_slot_gas(&slot);
115
116 to_return
117 }
118
119 pub fn get_call(&self, slot: &Slot, id: &DeferredCallId) -> Option<DeferredCall> {
121 let mut buf_id = Vec::new();
122 self.call_id_serializer
123 .serialize(id, &mut buf_id)
124 .expect(DEFERRED_CALL_SER_ERROR);
125 let key = deferred_call_prefix_key!(buf_id, slot.to_bytes_key());
126
127 let mut serialized_call: Vec<u8> = Vec::new();
128 for (serialized_key, serialized_value) in self.db.read().prefix_iterator_cf(STATE_CF, &key)
129 {
130 if !serialized_key.starts_with(&key) {
131 break;
132 }
133
134 serialized_call.extend(serialized_value.iter());
135 }
136
137 match self
138 .call_deserializer
139 .deserialize::<DeserializeError>(&serialized_call)
140 {
141 Ok((_rest, call)) => Some(call),
142 Err(_) => None,
143 }
144 }
145
146 pub fn get_slot_gas(&self, slot: &Slot) -> u64 {
148 let key = deferred_call_slot_total_gas_key!(slot.to_bytes_key());
150 match self.db.read().get_cf(STATE_CF, key) {
151 Ok(Some(v)) => {
152 let result = self
153 .call_deserializer
154 .u64_var_int_deserializer
155 .deserialize::<DeserializeError>(&v)
156 .expect(DEFERRED_CALL_DESER_ERROR)
157 .1;
158 result
159 }
160 _ => 0,
161 }
162 }
163
164 pub fn get_slot_base_fee(&self, slot: &Slot) -> Amount {
171 let key = deferred_call_slot_base_fee_key!(slot.to_bytes_key());
172 let base_fee = match self.db.read().get_cf(STATE_CF, key) {
173 Ok(Some(v)) => {
174 self.call_deserializer
175 .amount_deserializer
176 .deserialize::<DeserializeError>(&v)
177 .expect(DEFERRED_CALL_DESER_ERROR)
178 .1
179 }
180 _ => Amount::zero(),
181 };
182
183 if base_fee.is_zero() {
184 Amount::from_raw(self.min_gas_cost)
185 } else {
186 base_fee
187 }
188 }
189
190 pub fn get_total_gas(&self) -> u128 {
192 match self
193 .db
194 .read()
195 .get_cf(STATE_CF, DEFERRED_CALL_TOTAL_GAS.as_bytes().to_vec())
196 .expect(CRUD_ERROR)
197 {
198 Some(v) => {
199 let result = self
200 .effective_total_gas_deserializer
201 .deserialize::<DeserializeError>(&v)
202 .expect(DEFERRED_CALL_DESER_ERROR)
203 .1;
204
205 match result {
206 DeferredRegistryGasChange::Set(v) => v,
207 DeferredRegistryGasChange::Keep => 0,
208 }
209 }
210 None => 0,
211 }
212 }
213
214 pub fn put_entry(
215 &self,
216 slot: &Slot,
217 call_id: &DeferredCallId,
218 call: &DeferredCall,
219 batch: &mut DBBatch,
220 ) {
221 let mut buffer_id = Vec::new();
222 self.call_id_serializer
223 .serialize(call_id, &mut buffer_id)
224 .expect(DEFERRED_CALL_SER_ERROR);
225
226 let slot_bytes = slot.to_bytes_key();
227
228 let db = self.db.read();
229
230 {
231 let mut buffer = Vec::new();
233 self.call_serializer
234 .address_serializer
235 .serialize(&call.sender_address, &mut buffer)
236 .expect(DEFERRED_CALL_SER_ERROR);
237 db.put_or_update_entry_value(
238 batch,
239 sender_address_key!(buffer_id, slot_bytes),
240 &buffer,
241 );
242 }
243
244 {
245 let mut buffer = Vec::new();
247 self.call_serializer
248 .slot_serializer
249 .serialize(&call.target_slot, &mut buffer)
250 .expect(DEFERRED_CALL_SER_ERROR);
251 db.put_or_update_entry_value(batch, target_slot_key!(buffer_id, slot_bytes), &buffer);
252 }
253
254 {
255 let mut buffer = Vec::new();
257 self.call_serializer
258 .address_serializer
259 .serialize(&call.target_address, &mut buffer)
260 .expect(DEFERRED_CALL_SER_ERROR);
261 db.put_or_update_entry_value(
262 batch,
263 target_address_key!(buffer_id, slot_bytes),
264 &buffer,
265 );
266 }
267
268 {
269 let mut buffer = Vec::new();
271 self.call_serializer
272 .string_serializer
273 .serialize(&call.target_function, &mut buffer)
274 .expect(DEFERRED_CALL_SER_ERROR);
275 db.put_or_update_entry_value(
276 batch,
277 target_function_key!(buffer_id, slot_bytes),
278 &buffer,
279 );
280 }
281
282 {
283 let mut buffer = Vec::new();
285 self.call_serializer
286 .vec_u8_serializer
287 .serialize(&call.parameters, &mut buffer)
288 .expect(DEFERRED_CALL_SER_ERROR);
289 db.put_or_update_entry_value(batch, parameters_key!(buffer_id, slot_bytes), &buffer);
290 }
291
292 {
293 let mut buffer = Vec::new();
295 self.call_serializer
296 .amount_serializer
297 .serialize(&call.coins, &mut buffer)
298 .expect(DEFERRED_CALL_SER_ERROR);
299 db.put_or_update_entry_value(batch, coins_key!(buffer_id, slot_bytes), &buffer);
300 }
301
302 {
303 let mut buffer = Vec::new();
305 self.call_serializer
306 .u64_var_int_serializer
307 .serialize(&call.max_gas, &mut buffer)
308 .expect(DEFERRED_CALL_SER_ERROR);
309 db.put_or_update_entry_value(batch, max_gas_key!(buffer_id, slot_bytes), &buffer);
310 }
311
312 {
313 let mut buffer = Vec::new();
315 self.call_serializer
316 .amount_serializer
317 .serialize(&call.fee, &mut buffer)
318 .expect(DEFERRED_CALL_SER_ERROR);
319 db.put_or_update_entry_value(batch, fee_key!(buffer_id, slot_bytes), &buffer);
320 }
321
322 let mut buffer = Vec::new();
324 self.call_serializer
325 .bool_serializer
326 .serialize(&call.cancelled, &mut buffer)
327 .expect(DEFERRED_CALL_SER_ERROR);
328 db.put_or_update_entry_value(batch, cancelled_key!(buffer_id, slot_bytes), &buffer);
329 }
330
331 fn delete_entry(&self, id: &DeferredCallId, slot: &Slot, batch: &mut DBBatch) {
332 let mut buffer_id = Vec::new();
333 self.call_id_serializer
334 .serialize(id, &mut buffer_id)
335 .expect(DEFERRED_CALL_SER_ERROR);
336
337 let slot_bytes = slot.to_bytes_key();
338
339 let db = self.db.read();
340
341 db.delete_key(batch, sender_address_key!(buffer_id, slot_bytes));
342 db.delete_key(batch, target_slot_key!(buffer_id, slot_bytes));
343 db.delete_key(batch, target_address_key!(buffer_id, slot_bytes));
344 db.delete_key(batch, target_function_key!(buffer_id, slot_bytes));
345 db.delete_key(batch, parameters_key!(buffer_id, slot_bytes));
346 db.delete_key(batch, coins_key!(buffer_id, slot_bytes));
347 db.delete_key(batch, max_gas_key!(buffer_id, slot_bytes));
348 db.delete_key(batch, fee_key!(buffer_id, slot_bytes));
349 db.delete_key(batch, cancelled_key!(buffer_id, slot_bytes));
350 }
351
352 pub fn apply_changes_to_batch(
353 &self,
354 changes: DeferredCallRegistryChanges,
355 batch: &mut DBBatch,
356 ) {
357 for change in changes.slots_change.iter() {
361 let slot = change.0;
362 let slot_changes = change.1;
363 for (id, call_change) in slot_changes.calls.iter() {
364 match call_change {
365 DeferredRegistryCallChange::Set(call) => {
366 if call.cancelled {
367 massa_metrics::inc_deferred_calls_cancelled();
368 } else {
369 massa_metrics::inc_deferred_calls_registered();
370 }
371 self.put_entry(slot, id, call, batch);
372 }
373 DeferredRegistryCallChange::Delete => {
374 self.delete_entry(id, slot, batch);
375 }
376 }
377 }
378 match slot_changes.effective_slot_gas {
379 DeferredRegistryGasChange::Set(v) => {
380 let key = deferred_call_slot_total_gas_key!(slot.to_bytes_key());
381 if v.eq(&0) {
383 self.db.read().delete_key(batch, key);
384 } else {
385 let mut value_ser = Vec::new();
386 self.call_serializer
387 .u64_var_int_serializer
388 .serialize(&v, &mut value_ser)
389 .expect(DEFERRED_CALL_SER_ERROR);
390 self.db
391 .read()
392 .put_or_update_entry_value(batch, key, &value_ser);
393 }
394 }
395 DeferredRegistryGasChange::Keep => {}
396 }
397 match slot_changes.base_fee {
398 DeferredRegistryBaseFeeChange::Set(v) => {
399 let key = deferred_call_slot_base_fee_key!(slot.to_bytes_key());
400 if v.eq(&Amount::zero()) {
402 self.db.read().delete_key(batch, key);
403 } else {
404 let mut value_ser = Vec::new();
405 self.call_serializer
406 .amount_serializer
407 .serialize(&v, &mut value_ser)
408 .expect(DEFERRED_CALL_SER_ERROR);
409 self.db
410 .read()
411 .put_or_update_entry_value(batch, key, &value_ser);
412 }
413 }
414 DeferredRegistryBaseFeeChange::Keep => {}
415 }
416 }
417
418 match changes.effective_total_gas {
419 DeferredRegistryGasChange::Set(val) => {
420 massa_metrics::set_deferred_calls_total_gas(val);
421 let key = DEFERRED_CALL_TOTAL_GAS.as_bytes().to_vec();
422 let mut value_ser = Vec::new();
423 self.effective_total_gas_serializer
424 .serialize(&changes.effective_total_gas, &mut value_ser)
425 .expect(DEFERRED_CALL_SER_ERROR);
426 self.db
427 .read()
428 .put_or_update_entry_value(batch, key, &value_ser);
429 }
430 DeferredRegistryGasChange::Keep => {}
431 }
432
433 if changes.exec_stats.0 > 0 {
434 massa_metrics::inc_deferred_calls_executed_by(changes.exec_stats.0);
436 }
437 if changes.exec_stats.1 > 0 {
438 massa_metrics::inc_deferred_calls_failed_by(changes.exec_stats.1);
440 }
441 if changes.exec_stats.2 > 0 {
442 massa_metrics::dec_deferred_calls_cancelled_by(changes.exec_stats.2);
444 }
445 let total_no_more_registered = changes
446 .exec_stats
447 .0
448 .saturating_add(changes.exec_stats.1)
449 .saturating_add(changes.exec_stats.2);
450 if total_no_more_registered > 0 {
451 massa_metrics::dec_deferred_calls_registered_by(total_no_more_registered);
453 }
454 }
455
456 pub fn is_key_value_valid(&self, serialized_key: &[u8], serialized_value: &[u8]) -> bool {
457 if serialized_key.starts_with(DEFERRED_CALLS_PREFIX.as_bytes()) {
458 if let Some((_rest, slot)) = buf_to_array_ctr(
460 &serialized_key[DEFERRED_CALLS_PREFIX.len()..],
461 Slot::from_bytes_key,
462 ) {
463 if serialized_key
465 .starts_with(&deferred_call_slot_total_gas_key!(&slot.to_bytes_key()))
466 {
467 return self
468 .call_deserializer
469 .u64_var_int_deserializer
470 .deserialize::<DeserializeError>(serialized_value)
471 .is_ok();
472 } else if serialized_key
473 .starts_with(&deferred_call_slot_base_fee_key!(&slot.to_bytes_key()))
474 {
475 return self
477 .call_deserializer
478 .amount_deserializer
479 .deserialize::<DeserializeError>(serialized_value)
480 .is_ok();
481 } else {
482 let k = deferred_slot_call_prefix_key!(&slot.to_bytes_key());
486 if !serialized_key.starts_with(&k) {
488 return false;
489 }
490 let rest_key = &serialized_key[k.len()..];
491
492 if let Ok((rest, _id)) = self
493 .call_id_deserializer
494 .deserialize::<DeserializeError>(rest_key)
495 {
496 if rest.len() != 1 {
498 return false;
499 }
500 match rest[0] {
501 CALL_FIELD_SENDER_ADDRESS => {
502 let res: Result<(&[u8], Address), nom::Err<DeserializeError<'_>>> =
503 self.call_deserializer
504 .address_deserializer
505 .deserialize::<DeserializeError>(serialized_value);
506
507 return res.is_ok();
508 }
509 CALL_FIELD_TARGET_SLOT => {
510 return self
511 .slot_deserializer
512 .deserialize::<DeserializeError>(serialized_value)
513 .is_ok()
514 }
515 CALL_FIELD_TARGET_ADDRESS => {
516 let res: Result<(&[u8], Address), nom::Err<DeserializeError<'_>>> =
517 self.call_deserializer
518 .address_deserializer
519 .deserialize::<DeserializeError>(serialized_value);
520 return res.is_ok();
521 }
522 CALL_FIELD_TARGET_FUNCTION => {
523 return self
524 .call_deserializer
525 .string_deserializer
526 .deserialize::<DeserializeError>(serialized_value)
527 .is_ok()
528 }
529 CALL_FIELD_PARAMETERS => {
530 return self
531 .call_deserializer
532 .vec_u8_deserializer
533 .deserialize::<DeserializeError>(serialized_value)
534 .is_ok()
535 }
536 CALL_FIELD_MAX_GAS => {
537 return self
538 .call_deserializer
539 .u64_var_int_deserializer
540 .deserialize::<DeserializeError>(serialized_value)
541 .is_ok()
542 }
543 CALL_FIELD_FEE => {
544 return self
545 .call_deserializer
546 .amount_deserializer
547 .deserialize::<DeserializeError>(serialized_value)
548 .is_ok()
549 }
550 CALL_FIELD_CANCELED => {
551 return self
552 .call_deserializer
553 .bool_deserializer
554 .deserialize::<DeserializeError>(serialized_value)
555 .is_ok();
556 }
557 CALL_FIELD_COINS => {
558 return self
559 .call_deserializer
560 .amount_deserializer
561 .deserialize::<DeserializeError>(serialized_value)
562 .is_ok();
563 }
564 _ => {}
565 }
566 }
567 }
568 }
569 } else if serialized_key.eq(DEFERRED_CALL_TOTAL_GAS.as_bytes()) {
570 return self
571 .effective_total_gas_deserializer
572 .deserialize::<DeserializeError>(serialized_value)
573 .is_ok();
574 }
575 false
576 }
577}
578
579pub type DeferredRegistryCallChange = SetOrDelete<DeferredCall>;
580pub type DeferredRegistryGasChange<V> = SetOrKeep<V>;
581pub type DeferredRegistryBaseFeeChange = SetOrKeep<Amount>;
582
583#[derive(Debug, Clone)]
589pub struct DeferredSlotCalls {
590 pub slot: Slot,
591 pub slot_calls: BTreeMap<DeferredCallId, DeferredCall>,
592
593 pub effective_slot_gas: u64,
596
597 pub slot_base_fee: Amount,
598}
599
600impl DeferredSlotCalls {
601 pub fn new(slot: Slot) -> Self {
602 Self {
603 slot,
604 slot_calls: BTreeMap::new(),
605 effective_slot_gas: 0,
606 slot_base_fee: Amount::zero(),
607 }
608 }
609
610 pub fn apply_changes(&mut self, changes: &DeferredCallRegistryChanges) {
616 let Some(slot_changes) = changes.slots_change.get(&self.slot) else {
617 return;
618 };
619 for (id, change) in &slot_changes.calls {
620 match change {
621 DeferredRegistryCallChange::Set(call) => {
622 self.slot_calls.insert(id.clone(), call.clone());
623 }
624 DeferredRegistryCallChange::Delete => {
625 self.slot_calls.remove(id);
626 }
627 }
628 }
629 match slot_changes.effective_slot_gas {
630 DeferredRegistryGasChange::Set(v) => self.effective_slot_gas = v,
631 DeferredRegistryGasChange::Keep => {}
632 }
633 match slot_changes.base_fee {
634 DeferredRegistryGasChange::Set(v) => self.slot_base_fee = v,
635 DeferredRegistryGasChange::Keep => {}
636 }
637 }
638}
639
640#[cfg(test)]
641mod deferred_slot_calls_tests {
642 use super::*;
643 use massa_models::amount::Amount;
644
645 #[test]
648 fn apply_changes_ignores_standalone_effective_total_gas() {
649 let slot = Slot::new(1, 0);
650 let other_slot = Slot::new(2, 0);
651
652 let mut view = DeferredSlotCalls::new(slot);
653 view.effective_slot_gas = 3;
654 view.slot_base_fee = Amount::from_raw(7);
655
656 let mut changes = DeferredCallRegistryChanges::default();
657 changes.set_effective_total_gas(42);
658 changes.set_effective_slot_gas(other_slot, 99);
659
660 view.apply_changes(&changes);
661
662 assert_eq!(view.effective_slot_gas, 3);
663 assert_eq!(view.slot_base_fee, Amount::from_raw(7));
664 assert!(view.slot_calls.is_empty());
665 }
666
667 #[test]
668 fn apply_changes_applies_slot_local_fields() {
669 let slot = Slot::new(1, 0);
670 let mut view = DeferredSlotCalls::new(slot);
671
672 let mut changes = DeferredCallRegistryChanges::default();
673 changes.set_effective_slot_gas(slot, 55);
674 changes.set_slot_base_fee(slot, Amount::from_raw(9));
675 changes.set_effective_total_gas(100); view.apply_changes(&changes);
678
679 assert_eq!(view.effective_slot_gas, 55);
680 assert_eq!(view.slot_base_fee, Amount::from_raw(9));
681 }
682}