Skip to content

Commit a0047f2

Browse files
committed
compress works
1 parent 1f49556 commit a0047f2

File tree

12 files changed

+209
-105
lines changed

12 files changed

+209
-105
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

program-tests/sdk-token-test/src/lib.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ pub mod sdk_token_test {
2020
mint: Pubkey, // TODO: deserialize from token account.
2121
amount: u64,
2222
) -> Result<()> {
23-
let light_cpi_accounts =
24-
CpiAccounts::new(ctx.accounts.signer.as_ref(), ctx.remaining_accounts);
25-
2623
let mut token_account = light_compressed_token_sdk::account::CTokenAccount::new_empty(
2724
mint,
2825
recipient,
@@ -32,10 +29,29 @@ pub mod sdk_token_test {
3229

3330
let cpi_inputs = CpiInputs::new_compress(vec![token_account]);
3431

32+
let light_cpi_accounts = CpiAccounts::new_compress(
33+
ctx.accounts.signer.as_ref(),
34+
ctx.accounts.signer.as_ref(),
35+
ctx.remaining_accounts,
36+
);
37+
msg!(
38+
"light_cpi_accounts config {:?}",
39+
light_cpi_accounts.config()
40+
);
41+
msg!(
42+
"light_cpi_accounts config is_compress_or_decompress {:?}",
43+
light_cpi_accounts.config().is_compress_or_decompress()
44+
);
45+
msg!(
46+
"ctx.remaining_accounts len {:?}",
47+
ctx.remaining_accounts.len()
48+
);
3549
// TODO: add to program error conversion
3650
let instruction =
3751
create_compressed_token_instruction(cpi_inputs, &light_cpi_accounts).unwrap();
3852
let account_infos = light_cpi_accounts.to_account_infos();
53+
msg!("account_infos {:?}", account_infos);
54+
msg!("instruction {:?}", instruction);
3955
invoke(&instruction, account_infos.as_slice())?;
4056

4157
Ok(())
@@ -60,8 +76,11 @@ pub mod sdk_token_test {
6076

6177
let cpi_inputs =
6278
CpiInputs::new(vec![token_account, recipient_token_account], validity_proof);
63-
let light_cpi_accounts =
64-
CpiAccounts::new(ctx.accounts.signer.as_ref(), ctx.remaining_accounts);
79+
let light_cpi_accounts = CpiAccounts::new(
80+
ctx.accounts.signer.as_ref(),
81+
ctx.accounts.signer.as_ref(),
82+
ctx.remaining_accounts,
83+
);
6584

6685
// TODO: add to program error conversion
6786
let instruction =
@@ -90,13 +109,18 @@ pub mod sdk_token_test {
90109
token_account.decompress(10).unwrap();
91110

92111
let cpi_inputs = CpiInputs::new(vec![token_account], validity_proof);
93-
let light_cpi_accounts =
94-
CpiAccounts::new(ctx.accounts.signer.as_ref(), ctx.remaining_accounts);
112+
let light_cpi_accounts = CpiAccounts::new_decompress(
113+
ctx.accounts.signer.as_ref(),
114+
ctx.accounts.signer.as_ref(),
115+
ctx.remaining_accounts,
116+
);
95117

96118
// TODO: add to program error conversion
97119
let instruction =
98120
create_compressed_token_instruction(cpi_inputs, &light_cpi_accounts).unwrap();
99121
let account_infos = light_cpi_accounts.to_account_infos();
122+
msg!("account_infos {:?}", account_infos);
123+
msg!("instruction {:?}", instruction);
100124
// TODO: make invoke_signed
101125
invoke(&instruction, account_infos.as_slice())?;
102126

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use solana_sdk::{
2121
#[tokio::test]
2222
async fn test_compress_spl_tokens() {
2323
// Initialize the test environment
24-
let mut rpc = LightProgramTest::new(ProgramTestConfig::new(
24+
let mut rpc = LightProgramTest::new(ProgramTestConfig::new_v2(
2525
false,
2626
Some(vec![("sdk_token_test", sdk_token_test::ID)]),
2727
))
@@ -118,9 +118,10 @@ async fn compress_spl_tokens(
118118
false,
119119
);
120120
remaining_accounts.add_pre_accounts_signer_mut(payer.pubkey());
121+
let metas = get_transfer_instruction_account_metas(config);
122+
println!("metas {:?}", metas.to_vec());
121123
// Add the token account to pre_accounts for the compression
122-
remaining_accounts
123-
.add_pre_accounts_metas(get_transfer_instruction_account_metas(config).as_slice());
124+
remaining_accounts.add_pre_accounts_metas(metas.as_slice());
124125

125126
let output_tree_index = rpc
126127
.get_random_state_tree_info()
@@ -129,14 +130,11 @@ async fn compress_spl_tokens(
129130
.unwrap();
130131

131132
let (remaining_accounts, _, _) = remaining_accounts.to_account_metas();
133+
println!("remaining_accounts {:?}", remaining_accounts.to_vec());
132134

133135
let instruction = Instruction {
134136
program_id: sdk_token_test::ID,
135-
accounts: [
136-
vec![AccountMeta::new(payer.pubkey(), true)],
137-
remaining_accounts,
138-
]
139-
.concat(),
137+
accounts: [remaining_accounts].concat(),
140138
data: sdk_token_test::instruction::Compress {
141139
output_tree_index,
142140
recipient,

sdk-libs/compressed-token-sdk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ light-macros = { workspace = true }
1616
thiserror = { workspace = true }
1717
# Serialization
1818
borsh = { workspace = true }
19-
19+
solana-msg = { workspace = true }
2020
# Solana dependencies
2121
solana-pubkey = { workspace = true, features = ["sha2", "curve25519"] }
2222
solana-instruction = { workspace = true }

sdk-libs/compressed-token-sdk/src/cpi/accounts.rs

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use anchor_lang::Key;
12
use light_compressed_token_types::{
23
constants::{
34
ACCOUNT_COMPRESSION_PROGRAM_ID, CPI_AUTHORITY_PDA, LIGHT_SYSTEM_PROGRAM_ID,
@@ -27,10 +28,7 @@ pub fn to_compressed_token_account_metas(
2728

2829
// authority (signer)
2930
account_metas.push(AccountMeta {
30-
pubkey: *cpi_accounts
31-
.authority()
32-
.map_err(|_| TokenSdkError::CpiError("Missing authority".to_string()))?
33-
.key,
31+
pubkey: *cpi_accounts.authority().key,
3432
is_signer: true,
3533
is_writable: false,
3634
});
@@ -51,6 +49,7 @@ pub fn to_compressed_token_account_metas(
5149

5250
// registered_program_pda
5351
account_metas.push(AccountMeta {
52+
// TODO: hardcode
5453
pubkey: *cpi_accounts
5554
.registered_program_pda()
5655
.map_err(|_| TokenSdkError::CpiError("Missing registered program PDA".to_string()))?
@@ -89,12 +88,14 @@ pub fn to_compressed_token_account_metas(
8988
is_signer: false,
9089
is_writable: false,
9190
});
91+
solana_msg::msg!("cpi_accounts.config() {:?}", cpi_accounts.config());
9292

9393
// token_pool_pda - if not configured, use compressed token program ID (like anchor does for None)
94-
if cpi_accounts.config().token_pool_pda {
94+
if cpi_accounts.config().is_compress_or_decompress() {
9595
let account = cpi_accounts
96-
.sol_pool_pda()
96+
.token_pool_pda()
9797
.map_err(|_| TokenSdkError::CpiError("Missing token pool PDA".to_string()))?;
98+
solana_msg::msg!("token_pool_pda {}", account.key);
9899
account_metas.push(AccountMeta {
99100
pubkey: *account.key,
100101
is_signer: false,
@@ -108,9 +109,9 @@ pub fn to_compressed_token_account_metas(
108109
is_writable: false,
109110
});
110111
}
111-
112+
solana_msg::msg!("cpi_accounts.config() {:?}", cpi_accounts.config());
112113
// compress_or_decompress_token_account - if not configured, use compressed token program ID
113-
if cpi_accounts.config().compress_or_decompress_token_account {
114+
if cpi_accounts.config().is_compress_or_decompress() {
114115
let account = cpi_accounts.decompression_recipient().map_err(|_| {
115116
TokenSdkError::CpiError("Missing compress/decompress account".to_string())
116117
})?;
@@ -128,40 +129,41 @@ pub fn to_compressed_token_account_metas(
128129
});
129130
}
130131

131-
// token_program - if not configured, use compressed token program ID
132-
if cpi_accounts.config().cpi_context {
133-
let account = cpi_accounts
134-
.cpi_context()
135-
.map_err(|_| TokenSdkError::CpiError("Missing token program".to_string()))?;
136-
account_metas.push(AccountMeta {
137-
pubkey: *account.key,
138-
is_signer: false,
139-
is_writable: false,
140-
});
141-
} else {
142-
// Anchor represents None optional accounts as the program ID being invoked
143-
account_metas.push(AccountMeta {
144-
pubkey: Pubkey::from(COMPRESSED_TOKEN_PROGRAM_ID),
145-
is_signer: false,
146-
is_writable: false,
147-
});
148-
}
149-
132+
// // token_program - if not configured, use compressed token program ID
133+
// if cpi_accounts.config().cpi_context {
134+
// let account = cpi_accounts
135+
// .cpi_context()
136+
// .map_err(|_| TokenSdkError::CpiError("Missing token program".to_string()))?;
137+
// account_metas.push(AccountMeta {
138+
// pubkey: *account.key,
139+
// is_signer: false,
140+
// is_writable: false,
141+
// });
142+
// } else {
143+
// // Anchor represents None optional accounts as the program ID being invoked
144+
// account_metas.push(AccountMeta {
145+
// pubkey: Pubkey::from(COMPRESSED_TOKEN_PROGRAM_ID),
146+
// is_signer: false,
147+
// is_writable: false,
148+
// });
149+
// }
150+
account_metas.push(AccountMeta {
151+
pubkey: cpi_accounts.spl_token_program().unwrap().key(),
152+
is_signer: false,
153+
is_writable: false,
154+
});
150155
// system_program (always last according to TransferInstruction definition)
151156
account_metas.push(AccountMeta {
152157
pubkey: Pubkey::default(), // System program ID
153158
is_signer: false,
154159
is_writable: false,
155160
});
156161

157-
// Add any remaining tree accounts
158-
let system_len = account_metas.len();
159-
let tree_accounts = cpi_accounts
160-
.account_infos()
161-
.get(system_len..)
162-
.unwrap_or(&[]);
162+
// TODO: implement error conversion
163+
let tree_accounts = cpi_accounts.tree_accounts().unwrap_or_default();
163164

164165
for account in tree_accounts {
166+
solana_msg::msg!("tree account: {}", account.key);
165167
account_metas.push(AccountMeta {
166168
pubkey: *account.key,
167169
is_signer: false,

sdk-libs/compressed-token-sdk/src/cpi/invoke.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use light_compressed_token_types::{
33
constants::{PROGRAM_ID as COMPRESSED_TOKEN_PROGRAM_ID, TRANSFER},
44
cpi_accounts::CpiAccounts,
55
instruction::transfer::CompressedTokenInstructionDataTransfer,
6-
AnchorSerialize, CompressedCpiContext,
6+
CompressedCpiContext,
77
};
88
use solana_account_info::AccountInfo;
99
use solana_instruction::Instruction;
@@ -13,6 +13,7 @@ use crate::{
1313
account::CTokenAccount,
1414
cpi::accounts::to_compressed_token_account_metas,
1515
error::{Result, TokenSdkError},
16+
AnchorSerialize,
1617
};
1718

1819
/// CPI inputs for compressed token operations
@@ -53,9 +54,31 @@ pub fn create_compressed_token_instruction(
5354
.token_accounts
5455
.iter()
5556
.any(|acc| acc.is_compress());
57+
let is_decompress = cpi_inputs
58+
.token_accounts
59+
.iter()
60+
.any(|acc| acc.is_decompress());
5661
let mint = *cpi_inputs.token_accounts[0].mint();
5762
let compress_or_decompress_amount: Option<u64> =
5863
Some(cpi_inputs.token_accounts.iter().map(|acc| acc.amount).sum());
64+
65+
// Check 1: cpi accounts must be decompress or compress consistent with accounts
66+
if (is_compress && !cpi_accounts.config().compress)
67+
|| (is_decompress && !cpi_accounts.config().decompress)
68+
{
69+
return Err(TokenSdkError::InconsistentCompressDecompressState);
70+
}
71+
72+
// Check 2: there can only be compress or decompress not both
73+
if is_compress && is_decompress {
74+
return Err(TokenSdkError::BothCompressAndDecompress);
75+
}
76+
77+
// Check 3: compress_or_decompress_amount must be Some
78+
if compress_or_decompress_amount.is_none() {
79+
return Err(TokenSdkError::InvalidCompressDecompressAmount);
80+
}
81+
5982
// Extract input and output data from token accounts
6083
let mut input_token_data_with_context = Vec::new();
6184
let mut output_compressed_accounts = Vec::new();

sdk-libs/compressed-token-sdk/src/error.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ pub enum TokenSdkError {
1212
CpiError(String),
1313
#[error("Cannot compress and decompress")]
1414
CannotCompressAndDecompress,
15+
#[error("Inconsistent compress/decompress state")]
16+
InconsistentCompressDecompressState,
17+
#[error("Both compress and decompress specified")]
18+
BothCompressAndDecompress,
19+
#[error("Invalid compress/decompress amount")]
20+
InvalidCompressDecompressAmount,
1521
}
1622

17-
// Keep old error type for backwards compatibility
18-
pub type CTokenSdkError = TokenSdkError;

0 commit comments

Comments
 (0)