1use core::mem::size_of;
5
6use packable::{
7 error::{UnpackError, UnpackErrorExt},
8 packer::Packer,
9 unpacker::Unpacker,
10 Packable,
11};
12
13use crate::{output::OutputId, payload::milestone::MilestoneIndex, BlockId, Error};
14
15const DEFAULT_BYTE_COST: u32 = 100;
16const DEFAULT_BYTE_COST_FACTOR_KEY: u8 = 10;
17const DEFAULT_BYTE_COST_FACTOR_DATA: u8 = 1;
18
19type ConfirmationUnixTimestamp = u32;
20
21#[derive(Default, Eq, PartialEq)]
23#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
24#[must_use]
25pub struct RentStructureBuilder {
26 #[cfg_attr(feature = "serde", serde(alias = "vByteCost"))]
27 v_byte_cost: Option<u32>,
28 #[cfg_attr(feature = "serde", serde(alias = "vByteFactorKey"))]
29 v_byte_factor_key: Option<u8>,
30 #[cfg_attr(feature = "serde", serde(alias = "vByteFactorData"))]
31 v_byte_factor_data: Option<u8>,
32}
33
34impl RentStructureBuilder {
35 pub fn new() -> Self {
37 Default::default()
38 }
39
40 pub fn byte_cost(mut self, byte_cost: u32) -> Self {
42 self.v_byte_cost.replace(byte_cost);
43 self
44 }
45
46 pub fn key_factor(mut self, weight: u8) -> Self {
48 self.v_byte_factor_key.replace(weight);
49 self
50 }
51
52 pub fn data_factor(mut self, weight: u8) -> Self {
54 self.v_byte_factor_data.replace(weight);
55 self
56 }
57
58 pub fn finish(self) -> RentStructure {
60 let v_byte_factor_key = self.v_byte_factor_key.unwrap_or(DEFAULT_BYTE_COST_FACTOR_KEY);
61 let v_byte_factor_data = self.v_byte_factor_data.unwrap_or(DEFAULT_BYTE_COST_FACTOR_DATA);
62 let v_byte_offset = v_byte_offset(v_byte_factor_key, v_byte_factor_data);
63
64 RentStructure {
65 v_byte_cost: self.v_byte_cost.unwrap_or(DEFAULT_BYTE_COST),
66 v_byte_factor_key,
67 v_byte_factor_data,
68 v_byte_offset,
69 }
70 }
71}
72
73#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
75#[cfg_attr(
76 feature = "serde",
77 derive(serde::Serialize, serde::Deserialize),
78 serde(rename_all = "camelCase")
79)]
80pub struct RentStructure {
81 pub v_byte_cost: u32,
83 pub v_byte_factor_key: u8,
85 pub v_byte_factor_data: u8,
87 v_byte_offset: u32,
89}
90
91impl Default for RentStructure {
92 fn default() -> Self {
93 RentStructureBuilder::new().finish()
94 }
95}
96
97impl RentStructure {
98 pub fn build() -> RentStructureBuilder {
100 RentStructureBuilder::new()
101 }
102}
103
104impl Packable for RentStructure {
105 type UnpackError = Error;
106 type UnpackVisitor = ();
107
108 fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
109 self.v_byte_cost.pack(packer)?;
110 self.v_byte_factor_key.pack(packer)?;
111 self.v_byte_factor_data.pack(packer)?;
112
113 Ok(())
114 }
115
116 fn unpack<U: Unpacker, const VERIFY: bool>(
117 unpacker: &mut U,
118 visitor: &Self::UnpackVisitor,
119 ) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
120 let v_byte_cost = u32::unpack::<_, VERIFY>(unpacker, visitor).coerce()?;
121 let v_byte_factor_key = u8::unpack::<_, VERIFY>(unpacker, visitor).coerce()?;
122 let v_byte_factor_data = u8::unpack::<_, VERIFY>(unpacker, visitor).coerce()?;
123 let v_byte_offset = v_byte_offset(v_byte_factor_key, v_byte_factor_data);
124
125 Ok(Self {
126 v_byte_cost,
127 v_byte_factor_key,
128 v_byte_factor_data,
129 v_byte_offset,
130 })
131 }
132}
133
134pub trait Rent {
136 fn weighted_bytes(&self, config: &RentStructure) -> u64;
138
139 fn rent_cost(&self, config: &RentStructure) -> u64 {
141 config.v_byte_cost as u64 * (self.weighted_bytes(config) + config.v_byte_offset as u64)
142 }
143}
144
145impl<T: Rent, const N: usize> Rent for [T; N] {
146 fn weighted_bytes(&self, config: &RentStructure) -> u64 {
147 self.iter().map(|elem| elem.weighted_bytes(config)).sum()
148 }
149}
150
151fn v_byte_offset(v_byte_factor_key: u8, v_byte_factor_data: u8) -> u32 {
152 size_of::<OutputId>() as u32 * v_byte_factor_key as u32
153 + size_of::<BlockId>() as u32 * v_byte_factor_data as u32
154 + size_of::<MilestoneIndex>() as u32 * v_byte_factor_data as u32
155 + size_of::<ConfirmationUnixTimestamp>() as u32 * v_byte_factor_data as u32
156}