1use massa_models::{
2 address::{Address, AddressDeserializer, AddressSerializer},
3 amount::{Amount, AmountDeserializer, AmountSerializer},
4 prehash::PreHashMap,
5 slot::Slot,
6};
7use massa_serialization::{
8 Deserializer, SerializeError, Serializer, U64VarIntDeserializer, U64VarIntSerializer,
9};
10use nom::{
11 error::{context, ContextError, ParseError},
12 multi::length_count,
13 sequence::tuple,
14 IResult, Parser,
15};
16use serde::{Deserialize, Serialize};
17use std::{
18 collections::BTreeMap,
19 fmt::Debug,
20 ops::{Bound::Included, RangeBounds},
21};
22
23#[derive(Clone, Serialize, Deserialize)]
24pub struct DeferredCredits {
26 pub credits: BTreeMap<Slot, PreHashMap<Address, Amount>>,
28}
29
30impl Debug for DeferredCredits {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 write!(f, "{:?}", self.credits)
33 }
34}
35
36impl Default for DeferredCredits {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl DeferredCredits {
43 pub fn is_empty(&self) -> bool {
45 self.credits.is_empty()
46 }
47
48 pub fn new() -> Self {
50 Self {
51 credits: Default::default(),
52 }
53 }
54
55 pub fn for_each<F>(&mut self, mut f: F)
57 where
58 F: FnMut(&Slot, &Address, &mut Amount),
59 {
60 for (slot, credits) in &mut self.credits {
61 for (address, amount) in credits {
62 f(slot, address, amount);
63 }
64 }
65 }
66
67 pub fn get_slot_range<R>(&self, range: R) -> DeferredCredits
69 where
70 R: RangeBounds<Slot>,
71 {
72 DeferredCredits {
73 credits: self
74 .credits
75 .range(range)
76 .map(|(s, map)| (*s, map.clone()))
77 .collect(),
78 }
79 }
80
81 pub fn extend(&mut self, other: Self) {
83 for (slot, credits) in other.credits {
84 for (address, amount) in credits {
85 self.insert(slot, address, amount);
86 }
87 }
88 }
89
90 pub fn remove_zeros(&mut self) {
92 let mut empty_slots = Vec::new();
93
94 let Self {
97 ref mut credits, ..
98 } = self;
99
100 for (slot, credits) in credits {
101 credits.retain(|_, amount| {
102 !amount.is_zero()
104 });
105 if credits.is_empty() {
106 empty_slots.push(*slot);
107 }
108 }
109 for slot in empty_slots {
110 self.credits.remove(&slot);
111 }
112 }
113
114 pub fn get_address_credits_for_slot(&self, addr: &Address, slot: &Slot) -> Option<Amount> {
116 self.credits
117 .get(slot)
118 .and_then(|slot_credits| slot_credits.get(addr))
119 .copied()
120 }
121
122 pub fn insert(&mut self, slot: Slot, address: Address, amount: Amount) -> Option<Amount> {
124 self.credits
125 .entry(slot)
126 .or_default()
127 .insert(address, amount)
128 }
129}
130
131#[derive(Clone)]
132#[allow(missing_docs)]
133pub struct DeferredCreditSerializer {
135 pub u64_ser: U64VarIntSerializer,
136 pub address_ser: AddressSerializer,
137 pub amount_ser: AmountSerializer,
138}
139
140impl Default for DeferredCreditSerializer {
141 fn default() -> Self {
142 Self::new()
143 }
144}
145
146impl DeferredCreditSerializer {
147 pub fn new() -> Self {
149 Self {
150 u64_ser: U64VarIntSerializer::new(),
151 address_ser: AddressSerializer::new(),
152 amount_ser: AmountSerializer::new(),
153 }
154 }
155}
156
157impl Serializer<PreHashMap<Address, Amount>> for DeferredCreditSerializer {
158 fn serialize(
159 &self,
160 value: &PreHashMap<Address, Amount>,
161 buffer: &mut Vec<u8>,
162 ) -> Result<(), SerializeError> {
163 self.u64_ser.serialize(&(value.len() as u64), buffer)?;
165 for (addr, amount) in value {
167 self.address_ser.serialize(addr, buffer)?;
169 self.amount_ser.serialize(amount, buffer)?;
171 }
172 Ok(())
173 }
174}
175
176#[derive(Clone)]
177#[allow(missing_docs)]
178pub struct DeferredCreditDeserializer {
180 u64_deserializer: U64VarIntDeserializer,
181 pub address_deserializer: AddressDeserializer,
182 pub amount_deserializer: AmountDeserializer,
183}
184
185impl DeferredCreditDeserializer {
186 pub fn new(max_credits_length: u64) -> DeferredCreditDeserializer {
188 DeferredCreditDeserializer {
189 u64_deserializer: U64VarIntDeserializer::new(
190 Included(u64::MIN),
191 Included(max_credits_length),
192 ),
193 address_deserializer: AddressDeserializer::new(),
194 amount_deserializer: AmountDeserializer::new(
195 Included(Amount::MIN),
196 Included(Amount::MAX),
197 ),
198 }
199 }
200}
201
202impl Deserializer<PreHashMap<Address, Amount>> for DeferredCreditDeserializer {
203 fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
204 &self,
205 buffer: &'a [u8],
206 ) -> IResult<&'a [u8], PreHashMap<Address, Amount>, E> {
207 context(
208 "Failed Credit deserialization",
209 length_count(
210 context("Failed length deserialization", |input| {
211 self.u64_deserializer.deserialize(input)
212 }),
213 tuple((
214 context("Failed address deserialization", |input| {
215 self.address_deserializer.deserialize(input)
216 }),
217 context("Failed amount deserialization", |input| {
218 self.amount_deserializer.deserialize(input)
219 }),
220 )),
221 ),
222 )
223 .map(|elements| elements.into_iter().collect())
224 .parse(buffer)
225 }
226}