Skip to content

Commit c5eb33f

Browse files
authored
pinocchio: Use SIMD-0194 exemption threshold value (#243)
* simd-0194 exemption threshold * Fix typo
1 parent dcc06b3 commit c5eb33f

File tree

1 file changed

+67
-18
lines changed

1 file changed

+67
-18
lines changed

sdk/pinocchio/src/sysvars/rent.rs

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ pub const RENT_ID: Pubkey = [
2626
/// - `$3.65` per megabyte year
2727
pub const DEFAULT_LAMPORTS_PER_BYTE_YEAR: u64 = 1_000_000_000 / 100 * 365 / (1024 * 1024);
2828

29+
/// SIMD-0194
30+
///
31+
/// This equates to the integer value of 3480. To account for 2 years of rent
32+
/// exemption, we multiply this value by 2 to make it 6960.
33+
pub const DEFAULT_LAMPORTS_PER_BYTE: u64 = 6960;
34+
2935
/// Default amount of time (in years) the balance has to include rent for the
3036
/// account to be rent exempt.
3137
pub const DEFAULT_EXEMPTION_THRESHOLD: f64 = 2.0;
@@ -39,6 +45,13 @@ const DEFAULT_EXEMPTION_THRESHOLD_AS_U64: u64 = 2;
3945
/// This is used to check whether the `f64` value can be safely cast to a `u64`.
4046
const F64_EXEMPTION_THRESHOLD_AS_U64: u64 = 4611686018427387904;
4147

48+
/// The `u64` representation of the deprecated exemption threshold.
49+
///
50+
/// This value is equivalent to `1f64`. It is only used to check whether
51+
/// the exemption threshold is the deprecated value to avoid performing
52+
/// floating-point operations on-chain.
53+
const F64_SIMD0194_EXEMPTION_THRESHOLD_AS_U64: u64 = 4607182418800017408;
54+
4255
/// Default percentage of collected rent that is burned.
4356
///
4457
/// Valid values are in the range [0, 100]. The remaining percentage is
@@ -56,9 +69,18 @@ pub const ACCOUNT_STORAGE_OVERHEAD: u64 = 128;
5669
#[derive(Clone, Copy, Debug)]
5770
pub struct Rent {
5871
/// Rental rate in lamports per byte-year
72+
#[deprecated(
73+
since = "0.9.2",
74+
note = "SIMD-0194 will rename this field to `lamports_per_byte`"
75+
)]
5976
pub lamports_per_byte_year: u64,
6077

61-
/// Exemption threshold in years
78+
/// Exemption threshold in years.
79+
///
80+
/// SIMD-0194 will deprecate this value. The current implementation checks
81+
/// the value against known defaults to avoid performing a floating-point
82+
/// operation on-chain.
83+
#[deprecated(since = "0.9.2", note = "SIMD-0194 will deprecate this value")]
6284
pub exemption_threshold: f64,
6385

6486
/// Burn percentage
@@ -150,6 +172,7 @@ impl Rent {
150172

151173
/// Rent due for account that is known to be not exempt.
152174
#[inline]
175+
#[allow(deprecated)]
153176
pub fn due_amount(&self, data_len: usize, years_elapsed: f64) -> u64 {
154177
let actual_data_len = data_len as u64 + ACCOUNT_STORAGE_OVERHEAD;
155178
let lamports_per_year = self.lamports_per_byte_year * actual_data_len;
@@ -169,15 +192,23 @@ impl Rent {
169192
///
170193
/// The minimum balance in lamports for rent exemption.
171194
#[inline]
195+
#[allow(deprecated)]
172196
pub fn minimum_balance(&self, data_len: usize) -> u64 {
173197
let bytes = data_len as u64;
174-
175-
if self.is_default_rent_threshold() {
176-
((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year)
177-
* DEFAULT_EXEMPTION_THRESHOLD_AS_U64
178-
} else {
179-
(((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year) as f64
180-
* self.exemption_threshold) as u64
198+
let exemption_threshold_as_u64 = u64::from_le_bytes(self.exemption_threshold.to_le_bytes());
199+
200+
match exemption_threshold_as_u64 {
201+
F64_SIMD0194_EXEMPTION_THRESHOLD_AS_U64 => {
202+
(ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year
203+
}
204+
F64_EXEMPTION_THRESHOLD_AS_U64 => {
205+
((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year)
206+
* DEFAULT_EXEMPTION_THRESHOLD_AS_U64
207+
}
208+
_ => {
209+
(((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year) as f64
210+
* self.exemption_threshold) as u64
211+
}
181212
}
182213
}
183214

@@ -195,15 +226,6 @@ impl Rent {
195226
pub fn is_exempt(&self, lamports: u64, data_len: usize) -> bool {
196227
lamports >= self.minimum_balance(data_len)
197228
}
198-
199-
/// Determines if the `exemption_threshold` is the default value.
200-
///
201-
/// This is used to check whether the `f64` value can be safely cast to a `u64`
202-
/// to avoid floating-point operations.
203-
#[inline]
204-
fn is_default_rent_threshold(&self) -> bool {
205-
u64::from_le_bytes(self.exemption_threshold.to_le_bytes()) == F64_EXEMPTION_THRESHOLD_AS_U64
206-
}
207229
}
208230

209231
impl Sysvar for Rent {
@@ -238,10 +260,11 @@ impl RentDue {
238260
}
239261

240262
#[cfg(test)]
263+
#[allow(deprecated)]
241264
mod tests {
242265
use crate::sysvars::rent::{
243266
ACCOUNT_STORAGE_OVERHEAD, DEFAULT_BURN_PERCENT, DEFAULT_EXEMPTION_THRESHOLD,
244-
DEFAULT_LAMPORTS_PER_BYTE_YEAR,
267+
DEFAULT_LAMPORTS_PER_BYTE, DEFAULT_LAMPORTS_PER_BYTE_YEAR,
245268
};
246269

247270
#[test]
@@ -271,4 +294,30 @@ mod tests {
271294
assert!(calculated > 0);
272295
assert_eq!(balance, calculated);
273296
}
297+
298+
#[test]
299+
pub fn test_minimum_balance_simd0194() {
300+
let mut rent = super::Rent {
301+
lamports_per_byte_year: DEFAULT_LAMPORTS_PER_BYTE,
302+
exemption_threshold: 1.0, // SIMD-0194 default
303+
burn_percent: DEFAULT_BURN_PERCENT,
304+
};
305+
306+
// Using the default exemption threshold.
307+
308+
let balance = rent.minimum_balance(100);
309+
let calculated = (ACCOUNT_STORAGE_OVERHEAD + 100) * rent.lamports_per_byte_year;
310+
311+
assert!(calculated > 0);
312+
assert_eq!(balance, calculated);
313+
314+
// Using a different lamports per byte value.
315+
rent.lamports_per_byte_year = DEFAULT_LAMPORTS_PER_BYTE * 2;
316+
317+
let balance = rent.minimum_balance(100);
318+
let calculated = (ACCOUNT_STORAGE_OVERHEAD + 100) * rent.lamports_per_byte_year;
319+
320+
assert!(calculated > 0);
321+
assert_eq!(balance, calculated);
322+
}
274323
}

0 commit comments

Comments
 (0)