Skip to content

Commit 5cc5ff4

Browse files
use config, add unified header struct (just last_written_slot) for now
1 parent b13d0c7 commit 5cc5ff4

File tree

10 files changed

+109
-52
lines changed

10 files changed

+109
-52
lines changed

program-tests/sdk-test/src/compress_dynamic_pda.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub fn compress_dynamic_pda(
4747
cpi_accounts,
4848
&crate::ID,
4949
rent_recipient,
50-
config.compression_delay as u64,
50+
&config,
5151
)?;
5252

5353
// any other program logic here...

program-tests/sdk-test/src/create_config.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
use borsh::{BorshDeserialize, BorshSerialize};
2-
use light_sdk::{
3-
compressible::{create_config, CompressibleConfig},
4-
error::LightSdkError,
5-
};
2+
use light_sdk::{compressible::create_compression_config_checked, error::LightSdkError};
63
use solana_program::account_info::AccountInfo;
74
use solana_program::pubkey::Pubkey;
85

program-tests/sdk-test/src/create_dynamic_pda.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
use borsh::{BorshDeserialize, BorshSerialize};
22
use light_sdk::{
3-
compressible::{compress_pda_new, CompressibleConfig},
3+
compressible::{compress_pda_new, CompressibleConfig, CompressionMetadata},
44
cpi::CpiAccounts,
55
error::LightSdkError,
66
instruction::{PackedAddressTreeInfo, ValidityProof},
77
};
8-
use light_sdk_types::CpiAccountsConfig;
9-
use solana_clock::Clock;
108
use solana_program::account_info::AccountInfo;
11-
use solana_sysvar::Sysvar;
129

1310
use crate::decompress_dynamic_pda::MyPdaAccount;
1411

@@ -48,8 +45,9 @@ pub fn create_dynamic_pda(
4845
// of this invocation.
4946
let mut pda_account_data = MyPdaAccount::try_from_slice(&pda_account.data.borrow())
5047
.map_err(|_| LightSdkError::Borsh)?;
51-
pda_account_data.last_written_slot = Clock::get()?.slot;
52-
pda_account_data.compression_delay = config.compression_delay as u64;
48+
49+
// Initialize compression metadata with current slot
50+
pda_account_data.compression_metadata = CompressionMetadata::new()?;
5351

5452
compress_pda_new::<MyPdaAccount>(
5553
pda_account,

program-tests/sdk-test/src/decompress_dynamic_pda.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use borsh::{BorshDeserialize, BorshSerialize};
22
use light_sdk::{
33
account::LightAccount,
4-
compressible::{decompress_idempotent, CompressionTiming},
4+
compressible::{decompress_idempotent, CompressionMetadata, HasCompressionMetadata},
55
cpi::CpiAccounts,
66
error::LightSdkError,
77
instruction::{account_meta::CompressedAccountMeta, ValidityProof},
@@ -176,22 +176,17 @@ pub struct MyCompressedAccount {
176176
Clone, Debug, Default, LightHasher, LightDiscriminator, BorshDeserialize, BorshSerialize,
177177
)]
178178
pub struct MyPdaAccount {
179-
pub last_written_slot: u64,
180-
pub compression_delay: u64,
179+
pub compression_metadata: CompressionMetadata,
181180
pub data: [u8; 31],
182181
}
183182

184-
// Implement the CompressionTiming trait
185-
impl CompressionTiming for MyPdaAccount {
186-
fn last_written_slot(&self) -> u64 {
187-
self.last_written_slot
183+
// Implement the HasCompressionMetadata trait
184+
impl HasCompressionMetadata for MyPdaAccount {
185+
fn compression_metadata(&self) -> &CompressionMetadata {
186+
&self.compression_metadata
188187
}
189188

190-
fn compression_delay(&self) -> u64 {
191-
self.compression_delay
192-
}
193-
194-
fn set_last_written_slot(&mut self, slot: u64) {
195-
self.last_written_slot = slot;
189+
fn compression_metadata_mut(&mut self) -> &mut CompressionMetadata {
190+
&mut self.compression_metadata
196191
}
197192
}

program-tests/sdk-test/tests/test.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,7 @@ pub async fn decompress_pda(
246246
compressed_account: MyCompressedAccount {
247247
meta,
248248
data: MyPdaAccount {
249-
last_written_slot: compressed_account.compressed_account.lamports, // Use lamports field to store slot
250-
compression_delay: COMPRESSION_DELAY,
249+
compression_metadata: light_sdk::compressible::CompressionMetadata::default(),
251250
data: compressed_account
252251
.compressed_account
253252
.data

sdk-libs/sdk/src/compressible/compress_pda.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::{
22
account::LightAccount,
3+
compressible::{metadata::CompressionMetadata, CompressibleConfig},
34
cpi::{CpiAccounts, CpiInputs},
45
error::LightSdkError,
56
instruction::{account_meta::CompressedAccountMeta, ValidityProof},
@@ -17,11 +18,10 @@ use solana_program_error::ProgramError;
1718
use solana_pubkey::Pubkey;
1819
use solana_sysvar::Sysvar;
1920

20-
/// Trait for PDA accounts that can be compressed
21-
pub trait CompressionTiming {
22-
fn last_written_slot(&self) -> u64;
23-
fn compression_delay(&self) -> u64;
24-
fn set_last_written_slot(&mut self, slot: u64);
21+
/// Trait for accounts that contain CompressionMetadata
22+
pub trait HasCompressionMetadata {
23+
fn compression_metadata(&self) -> &CompressionMetadata;
24+
fn compression_metadata_mut(&mut self) -> &mut CompressionMetadata;
2525
}
2626

2727
/// Helper function to compress a PDA and reclaim rent.
@@ -41,6 +41,7 @@ pub trait CompressionTiming {
4141
/// * `cpi_accounts` - Accounts needed for CPI
4242
/// * `owner_program` - The program that will own the compressed account
4343
/// * `rent_recipient` - The account to receive the PDA's rent
44+
/// * `config` - The compression config containing delay settings
4445
//
4546
// TODO:
4647
// - check if any explicit checks required for compressed account?
@@ -52,15 +53,15 @@ pub fn compress_pda<A>(
5253
cpi_accounts: CpiAccounts,
5354
owner_program: &Pubkey,
5455
rent_recipient: &AccountInfo,
55-
expected_compression_delay: u64,
56+
config: &CompressibleConfig,
5657
) -> Result<(), LightSdkError>
5758
where
5859
A: DataHasher
5960
+ LightDiscriminator
6061
+ BorshSerialize
6162
+ BorshDeserialize
6263
+ Default
63-
+ CompressionTiming,
64+
+ HasCompressionMetadata,
6465
{
6566
// Check that the PDA account is owned by the caller program
6667
if pda_account.owner != owner_program {
@@ -79,12 +80,12 @@ where
7980
let pda_account_data = A::try_from_slice(&pda_data[8..]).map_err(|_| LightSdkError::Borsh)?;
8081
drop(pda_data);
8182

82-
let last_written_slot = pda_account_data.last_written_slot();
83+
let last_written_slot = pda_account_data.compression_metadata().last_written_slot();
8384

84-
if current_slot < last_written_slot + expected_compression_delay {
85+
if current_slot < last_written_slot + config.compression_delay as u64 {
8586
msg!(
8687
"Cannot compress yet. {} slots remaining",
87-
(last_written_slot + expected_compression_delay).saturating_sub(current_slot)
88+
(last_written_slot + config.compression_delay as u64).saturating_sub(current_slot)
8889
);
8990
return Err(LightSdkError::ConstraintViolation);
9091
}

sdk-libs/sdk/src/compressible/compress_pda_new.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ use solana_msg::msg;
1717
use solana_program_error::ProgramError;
1818
use solana_pubkey::Pubkey;
1919

20-
use crate::compressible::compress_pda::CompressionTiming;
21-
2220
/// Helper function to compress an onchain PDA into a new compressed account.
2321
///
2422
/// This function handles the entire compression operation: creates a compressed account,
@@ -50,13 +48,7 @@ pub fn compress_pda_new<'info, A>(
5048
expected_address_space: &Pubkey,
5149
) -> Result<(), LightSdkError>
5250
where
53-
A: DataHasher
54-
+ LightDiscriminator
55-
+ BorshSerialize
56-
+ BorshDeserialize
57-
+ Default
58-
+ CompressionTiming
59-
+ Clone,
51+
A: DataHasher + LightDiscriminator + BorshSerialize + BorshDeserialize + Default + Clone,
6052
{
6153
compress_multiple_pdas_new::<A>(
6254
&[pda_account],

sdk-libs/sdk/src/compressible/decompress_idempotent.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::{
22
account::LightAccount,
3+
compressible::compress_pda::HasCompressionMetadata,
34
cpi::{CpiAccounts, CpiInputs},
45
error::LightSdkError,
56
instruction::ValidityProof,
@@ -20,8 +21,6 @@ use solana_rent::Rent;
2021
use solana_system_interface::instruction as system_instruction;
2122
use solana_sysvar::Sysvar;
2223

23-
use crate::compressible::compress_pda::CompressionTiming;
24-
2524
pub const COMPRESSION_DELAY: u64 = 100;
2625

2726
/// Helper function to decompress a compressed account into a PDA idempotently with seeds.
@@ -57,7 +56,7 @@ where
5756
+ BorshDeserialize
5857
+ Default
5958
+ Clone
60-
+ CompressionTiming,
59+
+ HasCompressionMetadata,
6160
{
6261
decompress_multiple_idempotent(
6362
&[pda_account],
@@ -103,7 +102,7 @@ where
103102
+ BorshDeserialize
104103
+ Default
105104
+ Clone
106-
+ CompressionTiming,
105+
+ HasCompressionMetadata,
107106
{
108107
// Validate input lengths
109108
if pda_accounts.len() != compressed_accounts.len() || pda_accounts.len() != signer_seeds.len() {
@@ -181,7 +180,9 @@ where
181180

182181
// Initialize PDA with decompressed data and update slot
183182
let mut decompressed_pda = compressed_account.account.clone();
184-
decompressed_pda.set_last_written_slot(current_slot);
183+
decompressed_pda
184+
.compression_metadata_mut()
185+
.set_last_written_slot_value(current_slot);
185186

186187
// Write discriminator
187188
// TODO: we don't mind the onchain account being different?
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use crate::error::LightSdkError;
2+
#[cfg(feature = "anchor")]
3+
use anchor_lang::{AnchorDeserialize as BorshDeserialize, AnchorSerialize as BorshSerialize};
4+
#[cfg(not(feature = "anchor"))]
5+
use borsh::{BorshDeserialize, BorshSerialize};
6+
use light_hasher::{to_byte_array::ToByteArray, DataHasher, Hasher, HasherError};
7+
use solana_clock::Clock;
8+
use solana_sysvar::Sysvar;
9+
10+
/// Metadata for compressible accounts that tracks when the account was last written
11+
#[derive(Clone, Debug, Default, BorshSerialize, BorshDeserialize)]
12+
pub struct CompressionMetadata {
13+
/// The slot when this account was last written/decompressed
14+
pub last_written_slot: u64,
15+
}
16+
17+
impl CompressionMetadata {
18+
/// Creates new compression metadata with the current slot
19+
pub fn new() -> Result<Self, LightSdkError> {
20+
Ok(Self {
21+
last_written_slot: Clock::get()?.slot,
22+
})
23+
}
24+
25+
/// Updates the last written slot to the current slot
26+
pub fn set_last_written_slot(&mut self) -> Result<(), LightSdkError> {
27+
self.last_written_slot = Clock::get()?.slot;
28+
Ok(())
29+
}
30+
31+
/// Sets the last written slot to a specific value
32+
pub fn set_last_written_slot_value(&mut self, slot: u64) {
33+
self.last_written_slot = slot;
34+
}
35+
36+
/// Gets the last written slot
37+
pub fn last_written_slot(&self) -> u64 {
38+
self.last_written_slot
39+
}
40+
41+
/// Checks if the account can be compressed based on the delay
42+
pub fn can_compress(&self, compression_delay: u64) -> Result<bool, LightSdkError> {
43+
let current_slot = Clock::get()?.slot;
44+
Ok(current_slot >= self.last_written_slot + compression_delay)
45+
}
46+
47+
/// Gets the number of slots remaining before compression is allowed
48+
pub fn slots_until_compressible(&self, compression_delay: u64) -> Result<u64, LightSdkError> {
49+
let current_slot = Clock::get()?.slot;
50+
Ok((self.last_written_slot + compression_delay).saturating_sub(current_slot))
51+
}
52+
}
53+
54+
// Implement ToByteArray for CompressionMetadata
55+
impl ToByteArray for CompressionMetadata {
56+
const NUM_FIELDS: usize = 1;
57+
const IS_PRIMITIVE: bool = false;
58+
59+
fn to_byte_array(&self) -> Result<[u8; 32], HasherError> {
60+
self.last_written_slot.to_byte_array()
61+
}
62+
}
63+
64+
// Implement DataHasher for CompressionMetadata
65+
impl DataHasher for CompressionMetadata {
66+
fn hash<H: Hasher>(&self) -> Result<[u8; 32], HasherError> {
67+
self.to_byte_array()
68+
}
69+
}

sdk-libs/sdk/src/compressible/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@ pub mod compress_pda;
44
pub mod compress_pda_new;
55
pub mod config;
66
pub mod decompress_idempotent;
7+
pub mod metadata;
78

8-
pub use compress_pda::{compress_pda, CompressionTiming};
9+
pub use compress_pda::{compress_pda, HasCompressionMetadata};
910
pub use compress_pda_new::{compress_multiple_pdas_new, compress_pda_new};
10-
pub use config::{create_config, update_config, CompressibleConfig, COMPRESSIBLE_CONFIG_SEED};
11+
pub use config::{
12+
create_compression_config_checked, create_compression_config_unchecked, update_config,
13+
CompressibleConfig, COMPRESSIBLE_CONFIG_SEED,
14+
};
1115
pub use decompress_idempotent::{decompress_idempotent, decompress_multiple_idempotent};
16+
pub use metadata::CompressionMetadata;

0 commit comments

Comments
 (0)