1use {
2 crate::SerializedTxid,
3 bitcoincore_rpc::json::GetMempoolEntryResult,
4 borsh::{BorshDeserialize, BorshSerialize},
5 serde::{Deserialize, Serialize},
6 std::io::{Read, Result, Write},
7};
8
9#[derive(
10 Debug, Clone, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize, Serialize, Deserialize,
11)]
12pub struct MempoolEntryFee {
13 pub base: u64,
14 pub descendant: u64,
15 pub ancestor: u64,
16}
17
18#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
19pub struct MempoolEntry {
20 pub vsize: u64,
21 pub weight: Option<u64>,
22 pub descendant_count: u64,
23 pub descendant_size: u64,
24 pub ancestor_count: u64,
25 pub ancestor_size: u64,
26 pub fees: MempoolEntryFee,
27 pub depends: Vec<SerializedTxid>,
28 #[serde(rename = "spentby")]
29 pub spent_by: Vec<SerializedTxid>,
30}
31
32impl From<&GetMempoolEntryResult> for MempoolEntry {
33 fn from(value: &GetMempoolEntryResult) -> Self {
34 Self {
35 vsize: value.vsize,
36 weight: value.weight,
37 descendant_count: value.descendant_count,
38 descendant_size: value.descendant_size,
39 ancestor_count: value.ancestor_count,
40 ancestor_size: value.ancestor_size,
41 fees: MempoolEntryFee {
42 base: value.fees.base.to_sat(),
43 descendant: value.fees.descendant.to_sat(),
44 ancestor: value.fees.ancestor.to_sat(),
45 },
46 depends: value.depends.iter().map(|txid| txid.into()).collect(),
47 spent_by: value.spent_by.iter().map(|txid| txid.into()).collect(),
48 }
49 }
50}
51
52impl BorshSerialize for MempoolEntry {
53 fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
54 BorshSerialize::serialize(&self.vsize, writer)?;
55
56 if let Some(weight) = self.weight {
57 BorshSerialize::serialize(&true, writer)?;
58 BorshSerialize::serialize(&weight, writer)?;
59 } else {
60 BorshSerialize::serialize(&false, writer)?;
61 }
62
63 BorshSerialize::serialize(&self.descendant_count, writer)?;
64 BorshSerialize::serialize(&self.descendant_size, writer)?;
65 BorshSerialize::serialize(&self.ancestor_count, writer)?;
66 BorshSerialize::serialize(&self.ancestor_size, writer)?;
67 BorshSerialize::serialize(&self.fees, writer)?;
68
69 BorshSerialize::serialize(&(self.depends.len() as u64), writer)?;
70 for txid in &self.depends {
71 BorshSerialize::serialize(&txid, writer)?;
72 }
73
74 BorshSerialize::serialize(&(self.spent_by.len() as u64), writer)?;
75 for txid in &self.spent_by {
76 BorshSerialize::serialize(&txid, writer)?;
77 }
78 Ok(())
79 }
80}
81
82impl BorshDeserialize for MempoolEntry {
83 fn deserialize_reader<R: Read>(reader: &mut R) -> Result<Self> {
84 let vsize = u64::deserialize_reader(reader)?;
85
86 let weight_exists = bool::deserialize_reader(reader)?;
87 let weight = if weight_exists {
88 Some(u64::deserialize_reader(reader)?)
89 } else {
90 None
91 };
92
93 let descendant_count = u64::deserialize_reader(reader)?;
94 let descendant_size = u64::deserialize_reader(reader)?;
95 let ancestor_count = u64::deserialize_reader(reader)?;
96 let ancestor_size = u64::deserialize_reader(reader)?;
97 let fees = MempoolEntryFee::deserialize_reader(reader)?;
98
99 let depends_len = u64::deserialize_reader(reader)?;
100 let mut depends = Vec::new();
101 for _ in 0..depends_len {
102 let txid = SerializedTxid::deserialize_reader(reader)?;
103 depends.push(txid);
104 }
105
106 let spent_by_len = u64::deserialize_reader(reader)?;
107 let mut spent_by = Vec::new();
108 for _ in 0..spent_by_len {
109 let txid = SerializedTxid::deserialize_reader(reader)?;
110 spent_by.push(txid);
111 }
112
113 Ok(Self {
114 vsize,
115 weight,
116 descendant_count,
117 descendant_size,
118 ancestor_count,
119 ancestor_size,
120 fees,
121 depends,
122 spent_by,
123 })
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use borsh::{BorshDeserialize, BorshSerialize};
131
132 fn create_test_mempool_entry() -> MempoolEntry {
133 MempoolEntry {
134 vsize: 250,
135 weight: Some(1000),
136 descendant_count: 5,
137 descendant_size: 1500,
138 ancestor_count: 3,
139 ancestor_size: 800,
140 fees: MempoolEntryFee {
141 base: 5000,
142 descendant: 7500,
143 ancestor: 4200,
144 },
145 depends: vec![
146 SerializedTxid::from([1u8; 32]),
147 SerializedTxid::from([2u8; 32]),
148 ],
149 spent_by: vec![SerializedTxid::from([3u8; 32])],
150 }
151 }
152
153 fn create_minimal_mempool_entry() -> MempoolEntry {
154 MempoolEntry {
155 vsize: 100,
156 weight: None,
157 descendant_count: 0,
158 descendant_size: 0,
159 ancestor_count: 0,
160 ancestor_size: 0,
161 fees: MempoolEntryFee {
162 base: 1000,
163 descendant: 1000,
164 ancestor: 1000,
165 },
166 depends: vec![],
167 spent_by: vec![],
168 }
169 }
170
171 fn serialize_entry(entry: &MempoolEntry) -> std::io::Result<Vec<u8>> {
172 let mut buffer = Vec::new();
173 BorshSerialize::serialize(entry, &mut buffer)?;
174 Ok(buffer)
175 }
176
177 fn deserialize_entry(data: &[u8]) -> std::io::Result<MempoolEntry> {
178 MempoolEntry::deserialize_reader(&mut data.as_ref())
179 }
180
181 fn serialize_fee(fee: &MempoolEntryFee) -> std::io::Result<Vec<u8>> {
182 let mut buffer = Vec::new();
183 BorshSerialize::serialize(fee, &mut buffer)?;
184 Ok(buffer)
185 }
186
187 fn deserialize_fee(data: &[u8]) -> std::io::Result<MempoolEntryFee> {
188 MempoolEntryFee::deserialize_reader(&mut data.as_ref())
189 }
190
191 #[test]
192 fn test_mempool_entry_serialization_deserialization_round_trip() {
193 let original = create_test_mempool_entry();
194
195 let serialized = serialize_entry(&original).expect("Serialization should succeed");
197
198 let deserialized = deserialize_entry(&serialized).expect("Deserialization should succeed");
200
201 assert_eq!(original, deserialized);
203 }
204
205 #[test]
206 fn test_mempool_entry_minimal_serialization_deserialization() {
207 let original = create_minimal_mempool_entry();
208
209 let serialized = serialize_entry(&original).expect("Serialization should succeed");
211
212 let deserialized = deserialize_entry(&serialized).expect("Deserialization should succeed");
214
215 assert_eq!(original, deserialized);
217 }
218
219 #[test]
220 fn test_mempool_entry_with_none_weight() {
221 let mut entry = create_test_mempool_entry();
222 entry.weight = None;
223
224 let serialized = serialize_entry(&entry).expect("Serialization should succeed");
225 let deserialized = deserialize_entry(&serialized).expect("Deserialization should succeed");
226
227 assert_eq!(entry, deserialized);
228 assert_eq!(deserialized.weight, None);
229 }
230
231 #[test]
232 fn test_mempool_entry_with_some_weight() {
233 let mut entry = create_test_mempool_entry();
234 entry.weight = Some(42000);
235
236 let serialized = serialize_entry(&entry).expect("Serialization should succeed");
237 let deserialized = deserialize_entry(&serialized).expect("Deserialization should succeed");
238
239 assert_eq!(entry, deserialized);
240 assert_eq!(deserialized.weight, Some(42000));
241 }
242
243 #[test]
244 fn test_mempool_entry_empty_vectors() {
245 let mut entry = create_test_mempool_entry();
246 entry.depends = vec![];
247 entry.spent_by = vec![];
248
249 let serialized = serialize_entry(&entry).expect("Serialization should succeed");
250 let deserialized = deserialize_entry(&serialized).expect("Deserialization should succeed");
251
252 assert_eq!(entry, deserialized);
253 assert!(deserialized.depends.is_empty());
254 assert!(deserialized.spent_by.is_empty());
255 }
256
257 #[test]
258 fn test_mempool_entry_large_vectors() {
259 let mut entry = create_test_mempool_entry();
260
261 entry.depends = (0..10)
263 .map(|i| SerializedTxid::from([i as u8; 32]))
264 .collect();
265 entry.spent_by = (10..15)
266 .map(|i| SerializedTxid::from([i as u8; 32]))
267 .collect();
268
269 let serialized = serialize_entry(&entry).expect("Serialization should succeed");
270 let deserialized = deserialize_entry(&serialized).expect("Deserialization should succeed");
271
272 assert_eq!(entry, deserialized);
273 assert_eq!(deserialized.depends.len(), 10);
274 assert_eq!(deserialized.spent_by.len(), 5);
275 }
276
277 #[test]
278 fn test_mempool_entry_fee_serialization() {
279 let fee = MempoolEntryFee {
280 base: u64::MAX,
281 descendant: 0,
282 ancestor: 12345,
283 };
284
285 let serialized = serialize_fee(&fee).expect("Fee serialization should succeed");
286 let deserialized =
287 deserialize_fee(&serialized).expect("Fee deserialization should succeed");
288
289 assert_eq!(fee, deserialized);
290 }
291
292 #[test]
293 fn test_mempool_entry_extreme_values() {
294 let entry = MempoolEntry {
295 vsize: u64::MAX,
296 weight: Some(u64::MAX),
297 descendant_count: u64::MAX,
298 descendant_size: u64::MAX,
299 ancestor_count: u64::MAX,
300 ancestor_size: u64::MAX,
301 fees: MempoolEntryFee {
302 base: u64::MAX,
303 descendant: u64::MAX,
304 ancestor: u64::MAX,
305 },
306 depends: vec![SerializedTxid::all_zeros()],
307 spent_by: vec![SerializedTxid::from([255u8; 32])],
308 };
309
310 let serialized = serialize_entry(&entry).expect("Serialization should succeed");
311 let deserialized = deserialize_entry(&serialized).expect("Deserialization should succeed");
312
313 assert_eq!(entry, deserialized);
314 }
315
316 #[test]
317 fn test_mempool_entry_zero_values() {
318 let entry = MempoolEntry {
319 vsize: 0,
320 weight: Some(0),
321 descendant_count: 0,
322 descendant_size: 0,
323 ancestor_count: 0,
324 ancestor_size: 0,
325 fees: MempoolEntryFee {
326 base: 0,
327 descendant: 0,
328 ancestor: 0,
329 },
330 depends: vec![],
331 spent_by: vec![],
332 };
333
334 let serialized = serialize_entry(&entry).expect("Serialization should succeed");
335 let deserialized = deserialize_entry(&serialized).expect("Deserialization should succeed");
336
337 assert_eq!(entry, deserialized);
338 }
339
340 #[test]
341 fn test_serialized_data_consistency() {
342 let entry1 = create_test_mempool_entry();
343 let entry2 = create_test_mempool_entry();
344
345 let serialized1 = serialize_entry(&entry1).expect("Serialization should succeed");
346 let serialized2 = serialize_entry(&entry2).expect("Serialization should succeed");
347
348 assert_eq!(serialized1, serialized2);
350 }
351
352 #[test]
353 fn test_serialization_size_efficiency() {
354 let minimal = create_minimal_mempool_entry();
355 let full = create_test_mempool_entry();
356
357 let minimal_size = serialize_entry(&minimal).unwrap().len();
358 let full_size = serialize_entry(&full).unwrap().len();
359
360 assert!(full_size > minimal_size);
362
363 println!("Minimal entry serialized size: {} bytes", minimal_size);
365 println!("Full entry serialized size: {} bytes", full_size);
366 }
367
368 #[test]
369 fn test_invalid_deserialization_handling() {
370 let incomplete_data = vec![1, 2, 3]; let result = deserialize_entry(&incomplete_data);
373 assert!(
374 result.is_err(),
375 "Should fail to deserialize incomplete data"
376 );
377 }
378}