iota_types/block/output/
rent.rs1use core::mem::size_of;
5
6use packable::{
7 error::{UnpackError, UnpackErrorExt},
8 packer::Packer,
9 unpacker::Unpacker,
10 Packable,
11};
12
13use crate::block::{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 byte_factor_key(mut self, weight: u8) -> Self {
48 self.v_byte_factor_key.replace(weight);
49 self
50 }
51
52 pub fn byte_factor_data(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(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
76pub struct RentStructure {
77 #[cfg_attr(feature = "serde", serde(alias = "vByteCost"))]
79 v_byte_cost: u32,
80 #[cfg_attr(feature = "serde", serde(alias = "vByteFactorKey"))]
82 v_byte_factor_key: u8,
83 #[cfg_attr(feature = "serde", serde(alias = "vByteFactorData"))]
85 v_byte_factor_data: u8,
86 #[cfg_attr(feature = "serde", serde(alias = "vByteOffset"))]
88 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 new(byte_cost: u32, byte_factor_key: u8, byte_factor_data: u8) -> Self {
100 Self::build()
101 .byte_cost(byte_cost)
102 .byte_factor_key(byte_factor_key)
103 .byte_factor_data(byte_factor_data)
104 .finish()
105 }
106
107 pub fn build() -> RentStructureBuilder {
109 RentStructureBuilder::new()
110 }
111
112 pub fn byte_cost(&self) -> u32 {
114 self.v_byte_cost
115 }
116
117 pub fn byte_factor_key(&self) -> u8 {
119 self.v_byte_factor_key
120 }
121
122 pub fn byte_factor_data(&self) -> u8 {
124 self.v_byte_factor_data
125 }
126
127 pub fn byte_offset(&self) -> u32 {
129 self.v_byte_offset
130 }
131}
132
133impl Packable for RentStructure {
134 type UnpackError = Error;
135 type UnpackVisitor = ();
136
137 fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
138 self.v_byte_cost.pack(packer)?;
139 self.v_byte_factor_data.pack(packer)?;
140 self.v_byte_factor_key.pack(packer)?;
141
142 Ok(())
143 }
144
145 fn unpack<U: Unpacker, const VERIFY: bool>(
146 unpacker: &mut U,
147 visitor: &Self::UnpackVisitor,
148 ) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
149 let v_byte_cost = u32::unpack::<_, VERIFY>(unpacker, visitor).coerce()?;
150 let v_byte_factor_data = u8::unpack::<_, VERIFY>(unpacker, visitor).coerce()?;
151 let v_byte_factor_key = u8::unpack::<_, VERIFY>(unpacker, visitor).coerce()?;
152 let v_byte_offset = v_byte_offset(v_byte_factor_key, v_byte_factor_data);
153
154 Ok(Self {
155 v_byte_cost,
156 v_byte_factor_key,
157 v_byte_factor_data,
158 v_byte_offset,
159 })
160 }
161}
162
163pub trait Rent {
165 fn weighted_bytes(&self, config: &RentStructure) -> u64;
167
168 fn rent_cost(&self, config: &RentStructure) -> u64 {
170 config.v_byte_cost as u64 * (self.weighted_bytes(config) + config.v_byte_offset as u64)
171 }
172}
173
174impl<T: Rent, const N: usize> Rent for [T; N] {
175 fn weighted_bytes(&self, config: &RentStructure) -> u64 {
176 self.iter().map(|elem| elem.weighted_bytes(config)).sum()
177 }
178}
179
180fn v_byte_offset(v_byte_factor_key: u8, v_byte_factor_data: u8) -> u32 {
181 size_of::<OutputId>() as u32 * v_byte_factor_key as u32
182 + size_of::<BlockId>() as u32 * v_byte_factor_data as u32
183 + size_of::<MilestoneIndex>() as u32 * v_byte_factor_data as u32
184 + size_of::<ConfirmationUnixTimestamp>() as u32 * v_byte_factor_data as u32
185}
186
187#[cfg(feature = "dto")]
188#[allow(missing_docs)]
189pub mod dto {
190
191 use super::*;
192
193 #[derive(Clone, Debug, PartialEq, Eq)]
194 #[cfg_attr(
195 feature = "serde",
196 derive(serde::Serialize, serde::Deserialize),
197 serde(rename_all = "camelCase")
198 )]
199 pub struct RentStructureDto {
200 pub v_byte_cost: u32,
201 pub v_byte_factor_key: u8,
202 pub v_byte_factor_data: u8,
203 }
204
205 impl From<RentStructureDto> for RentStructure {
206 fn from(value: RentStructureDto) -> Self {
207 Self::new(value.v_byte_cost, value.v_byte_factor_key, value.v_byte_factor_data)
208 }
209 }
210}