1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Copyright 2024 MaidSafe.net limited.
//
// This Autonomi Software is licensed under the MIT license <LICENSE-MIT or
// https://opensource.org/licenses/MIT> or the Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, at your
// option. This file may not be copied, modified, or distributed except
// according to those terms.
use crate::common::U256;
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Formatter, Result as FmtResult};
/// Quoting metrics used to generate a quote, or to track peer's status.
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct QuotingMetrics {
/// DataTypes presented as its `index`
pub data_type: u32,
/// data size of the record
pub data_size: usize,
/// the records stored
pub close_records_stored: usize,
/// each entry to be `(data_type_index, num_of_records_of_that_type)`
pub records_per_type: Vec<(u32, u32)>,
/// number of times that got paid
pub received_payment_count: usize,
/// the duration that node keeps connected to the network, measured in hours
pub live_time: u64,
/// network density from this node's perspective, which is the responsible_range as well
/// This could be calculated via sampling, or equation calculation.
pub network_density: Option<[u8; 32]>,
/// estimated network size
pub network_size: Option<u64>,
}
impl Debug for QuotingMetrics {
fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
let density_u256 = self.network_density.map(U256::from_be_bytes);
write!(
formatter,
"QuotingMetrics {{ data_type: {}, data_size: {}, close_records_stored: {}, records_per_type {:?}, received_payment_count: {}, live_time: {}, network_density: {density_u256:?}, network_size: {:?} }}",
self.data_type,
self.data_size,
self.close_records_stored,
self.records_per_type,
self.received_payment_count,
self.live_time,
self.network_size
)
}
}
impl QuotingMetrics {
/// Convert to deterministic byte representation for hashing
///
/// Uses fixed-width encoding (u64) for all numeric fields to ensure
/// architecture-independent serialization across 32-bit and 64-bit platforms.
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.extend_from_slice(&self.data_type.to_le_bytes());
bytes.extend_from_slice(&(self.data_size as u64).to_le_bytes());
bytes.extend_from_slice(&(self.close_records_stored as u64).to_le_bytes());
bytes.extend_from_slice(&(self.records_per_type.len() as u32).to_le_bytes());
for (dtype, count) in &self.records_per_type {
bytes.extend_from_slice(&dtype.to_le_bytes());
bytes.extend_from_slice(&count.to_le_bytes());
}
bytes.extend_from_slice(&(self.received_payment_count as u64).to_le_bytes());
bytes.extend_from_slice(&self.live_time.to_le_bytes());
if let Some(density) = &self.network_density {
bytes.push(1); // Option::Some marker
bytes.extend_from_slice(density);
} else {
bytes.push(0); // Option::None marker
}
if let Some(size) = self.network_size {
bytes.push(1); // Option::Some marker
bytes.extend_from_slice(&size.to_le_bytes());
} else {
bytes.push(0); // Option::None marker
}
bytes
}
}