-
Notifications
You must be signed in to change notification settings - Fork 67
feat: opt ctoken #1844
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: opt ctoken #1844
Conversation
WalkthroughThis update introduces comprehensive support for compressed mints in the compressed token program. It adds new instructions and processing logic for creating compressed mints, minting tokens to compressed accounts, and creating corresponding SPL mints. The changes include new data structures, hashing logic, CPI serialization, and extensive tests covering the compressed mint lifecycle. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Program
participant LightSystem
participant AccountCompression
participant Token2022
User->>Program: create_compressed_mint(params, proof)
Program->>LightSystem: CPI to create compressed mint account
LightSystem->>AccountCompression: Validate and store compressed account
LightSystem-->>Program: Success
User->>Program: mint_to_compressed(params, compressed_mint_inputs)
Program->>LightSystem: CPI to mint tokens to compressed accounts
LightSystem->>AccountCompression: Update compressed accounts
LightSystem-->>Program: Success
User->>Program: create_spl_mint(params, compressed_mint_inputs)
Program->>Token2022: Create SPL mint account
Program->>Token2022: Initialize mint and token pool
Program->>LightSystem: CPI to mark compressed mint as decompressed
LightSystem-->>Program: Success
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Nitpick comments (7)
programs/compressed-token/src/instructions/create_spl_mint.rs (2)
19-19
: Add CHECK comment for mint_signerThe
mint_signer
account should have a CHECK comment explaining its validation or usage, consistent with other unchecked accounts in this struct.+ /// CHECK: Used for PDA derivation pub mint_signer: UncheckedAccount<'info>,
49-49
: Track the TODO for account packing optimizationConsider creating an issue to track this optimization opportunity.
Would you like me to create an issue to track the account packing optimization?
programs/compressed-token/src/process_create_spl_mint.rs (1)
28-28
: Remove unused parameterThe
_token_pool_bump
parameter is not used in the function.- _token_pool_bump: u8,
program-tests/compressed-token-test/tests/test.rs (1)
6547-6552
: Consider implementing the decompression test or tracking it as a TODO.The decompression test is skipped because the tokens were minted to a pubkey rather than a keypair that can sign. This leaves an important part of the compressed mint lifecycle untested.
Would you like me to help implement a complete decompression test by either:
- Modifying the test to mint tokens to a keypair that can sign for decompression
- Creating a separate test specifically for decompression functionality
- Opening an issue to track this missing test coverage?
programs/compressed-token/src/create_mint.rs (1)
8-9
: Address TODO: Consider adding is_native_compressed field.The TODO suggests adding an
is_native_compressed
field to track sync state with SPL mint. This seems important for maintaining consistency between compressed and SPL representations. Please resolve this design decision.Would you like me to help implement the
is_native_compressed
field and update the related logic?programs/compressed-token/src/lib.rs (1)
120-120
: Consider using a simpler import path.The fully qualified path
instructions::create_token_pool::assert_mint_extensions
seems verbose. If there's no naming conflict, consider importing the function directly or using a shorter path.programs/compressed-token/src/process_mint.rs (1)
262-263
: Address TODO: Consider optimizing hash computation.The TODO suggests using hashed inputs for efficiency. This could improve performance by avoiding redundant hashing operations.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
program-tests/compressed-token-test/tests/test.rs
(2 hunks)programs/compressed-token/src/constants.rs
(1 hunks)programs/compressed-token/src/create_mint.rs
(1 hunks)programs/compressed-token/src/instructions/create_compressed_mint.rs
(1 hunks)programs/compressed-token/src/instructions/create_spl_mint.rs
(1 hunks)programs/compressed-token/src/instructions/mod.rs
(1 hunks)programs/compressed-token/src/lib.rs
(5 hunks)programs/compressed-token/src/process_create_compressed_mint.rs
(1 hunks)programs/compressed-token/src/process_create_spl_mint.rs
(1 hunks)programs/compressed-token/src/process_mint.rs
(16 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
programs/compressed-token/src/instructions/mod.rs (1)
programs/compressed-token/src/lib.rs (5)
create_compressed_mint
(50-68)create_spl_mint
(95-111)freeze
(251-257)freeze
(256-256)freeze
(266-266)
programs/compressed-token/src/process_create_spl_mint.rs (5)
js/stateless.js/src/state/compressed-account.ts (2)
CompressedAccount
(29-51)PackedCompressedAccountWithMerkleContext
(204-221)js/stateless.js/src/state/types.ts (3)
CompressedAccountData
(199-212)OutputCompressedAccountWithPackedContext
(170-173)InstructionDataInvokeCpi
(311-345)js/compressed-token/src/constants.ts (1)
POOL_SEED
(2-2)programs/compressed-token/src/lib.rs (1)
create_spl_mint
(95-111)programs/compressed-token/src/process_transfer.rs (2)
process_transfer
(39-179)get_cpi_signer_seeds
(379-383)
program-tests/compressed-token-test/tests/test.rs (8)
program-tests/utils/src/e2e_test_env.rs (3)
rpc
(389-390)new
(346-434)accounts
(2510-2523)sdk-libs/program-test/src/program_test/light_program_test.rs (1)
new
(49-132)program-libs/compressed-account/src/address.rs (2)
derive_address
(30-41)accounts
(163-170)programs/compressed-token/src/process_transfer.rs (2)
process_transfer
(39-179)get_cpi_authority_pda
(718-720)programs/system/src/utils.rs (3)
get_cpi_authority_pda
(15-17)get_registered_program_pda
(11-13)get_sol_pool_pda
(19-21)programs/compressed-token/src/instructions/transfer.rs (2)
get_registered_program_pda
(45-47)get_sol_pool_pda
(65-67)program-tests/utils/src/spl.rs (2)
create_token_pool
(231-259)create_token_2022_account
(436-489)programs/compressed-token/src/instructions/create_token_pool.rs (1)
find_token_pool_pda_with_index
(45-53)
⏰ Context from checks skipped due to timeout of 90000ms (25)
- GitHub Check: test-double-registration
- GitHub Check: test-e2e
- GitHub Check: test-address-batched
- GitHub Check: test-state-batched
- GitHub Check: test-state-photon-batched
- GitHub Check: test-2-foresters
- GitHub Check: Test batched-merkle-tree-simulate
- GitHub Check: Test concurrent-merkle-tree
- GitHub Check: Test program-libs-slow
- GitHub Check: Test sdk-libs
- GitHub Check: Test program-libs-fast
- GitHub Check: system-programs (system-cpi-test-v2-other, ["cargo-test-sbf -p system-cpi-v2-test -- --skip funct...
- GitHub Check: system-programs (system-cpi-test-v2-functional, ["cargo-test-sbf -p system-cpi-v2-test -- functio...
- GitHub Check: system-programs (random-e2e-test, ["cargo-test-sbf -p e2e-test"])
- GitHub Check: cli-v1
- GitHub Check: cli-v2
- GitHub Check: system-programs (system-cpi-test-v2-event, ["cargo-test-sbf -p system-cpi-v2-test -- event::parse"])
- GitHub Check: lint
- GitHub Check: system-programs (account-compression, ["cargo-test-sbf -p account-compression-test"])
- GitHub Check: system-programs (light-system-program, ["cargo-test-sbf -p system-test"])
- GitHub Check: stateless-js-v1
- GitHub Check: system-programs (light-registry, ["cargo-test-sbf -p registry-test"])
- GitHub Check: stateless-js-v2
- GitHub Check: system-programs (light-compressed-token, ["cargo-test-sbf -p compressed-token-test"])
- GitHub Check: system-programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test"])
🔇 Additional comments (6)
programs/compressed-token/src/constants.rs (1)
1-2
: LGTM!The new discriminator constant follows the established pattern and is correctly defined as 1 in little-endian format.
programs/compressed-token/src/instructions/mod.rs (1)
2-3
: LGTM!The new instruction modules are properly declared and re-exported following the established pattern.
Also applies to: 10-11
programs/compressed-token/src/instructions/create_compressed_mint.rs (1)
1-48
: LGTM!The instruction struct is well-designed with appropriate account types and validation annotations. The CHECK comments correctly indicate external validation by the light-system-program.
program-tests/compressed-token-test/tests/test.rs (1)
6103-6562
: LGTM! Comprehensive test for compressed mint lifecycle.The test thoroughly validates the compressed mint creation, minting to compressed accounts, and SPL mint creation flow. The test structure is clear and well-documented.
programs/compressed-token/src/process_create_compressed_mint.rs (2)
93-95
: Verify the hardcoded indices are intentional.The
address_merkle_tree_account_index
andaddress_queue_account_index
are hardcoded to 0. Ensure this is the intended behavior and consider making them configurable if needed.
120-120
: Verify merkle_tree_index value of 1 is correct.The
merkle_tree_index
is hardcoded to 1, but typically indices start at 0. Please verify this is the correct value for the first output account in the merkle tree.
/// Output queue account where compressed mint will be stored | ||
/// CHECK: Validated by light-system-program | ||
#[account(mut)] | ||
pub in_output_queue: AccountInfo<'info>, | ||
/// Output queue account where compressed mint will be stored | ||
/// CHECK: Validated by light-system-program | ||
#[account(mut)] | ||
pub in_merkle_tree: AccountInfo<'info>, | ||
/// Output queue account where compressed mint will be stored | ||
/// CHECK: Validated by light-system-program | ||
#[account(mut)] | ||
pub out_output_queue: AccountInfo<'info>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix misleading CHECK comments
The CHECK comments for these accounts are incorrect. The in_merkle_tree
account is not an output queue.
- /// Output queue account where compressed mint will be stored
+ /// Input output queue for compressed account updates
/// CHECK: Validated by light-system-program
#[account(mut)]
pub in_output_queue: AccountInfo<'info>,
- /// Output queue account where compressed mint will be stored
+ /// Input merkle tree for compressed account verification
/// CHECK: Validated by light-system-program
#[account(mut)]
pub in_merkle_tree: AccountInfo<'info>,
- /// Output queue account where compressed mint will be stored
+ /// Output queue for updated compressed mint
/// CHECK: Validated by light-system-program
#[account(mut)]
pub out_output_queue: AccountInfo<'info>,
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
/// Output queue account where compressed mint will be stored | |
/// CHECK: Validated by light-system-program | |
#[account(mut)] | |
pub in_output_queue: AccountInfo<'info>, | |
/// Output queue account where compressed mint will be stored | |
/// CHECK: Validated by light-system-program | |
#[account(mut)] | |
pub in_merkle_tree: AccountInfo<'info>, | |
/// Output queue account where compressed mint will be stored | |
/// CHECK: Validated by light-system-program | |
#[account(mut)] | |
pub out_output_queue: AccountInfo<'info>, | |
} | |
/// Input output queue for compressed account updates | |
/// CHECK: Validated by light-system-program | |
#[account(mut)] | |
pub in_output_queue: AccountInfo<'info>, | |
/// Input merkle tree for compressed account verification | |
/// CHECK: Validated by light-system-program | |
#[account(mut)] | |
pub in_merkle_tree: AccountInfo<'info>, | |
/// Output queue for updated compressed mint | |
/// CHECK: Validated by light-system-program | |
#[account(mut)] | |
pub out_output_queue: AccountInfo<'info>, | |
} |
🤖 Prompt for AI Agents
In programs/compressed-token/src/instructions/create_spl_mint.rs between lines
50 and 62, the CHECK comments incorrectly describe the in_merkle_tree account as
an output queue. Update the CHECK comment for in_merkle_tree to accurately
reflect its purpose, removing the misleading reference to output queue and
specifying that it is validated by the light-system-program or the correct
validation context.
let mut updated_compressed_mint = CompressedMint { | ||
spl_mint: compressed_mint_inputs.compressed_mint_input.spl_mint, | ||
supply: compressed_mint_inputs.compressed_mint_input.supply, | ||
decimals, | ||
is_decompressed: false, // Mark as decompressed | ||
mint_authority: Some(mint_authority), | ||
freeze_authority, | ||
num_extensions: compressed_mint_inputs.compressed_mint_input.num_extensions, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect is_decompressed value
The comment says "Mark as decompressed" but the code sets is_decompressed: false
. This appears to be a bug since the value is correctly set to true
later on line 124.
spl_mint: compressed_mint_inputs.compressed_mint_input.spl_mint,
supply: compressed_mint_inputs.compressed_mint_input.supply,
decimals,
- is_decompressed: false, // Mark as decompressed
+ is_decompressed: false, // Initial value before update
mint_authority: Some(mint_authority),
freeze_authority,
num_extensions: compressed_mint_inputs.compressed_mint_input.num_extensions,
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
let mut updated_compressed_mint = CompressedMint { | |
spl_mint: compressed_mint_inputs.compressed_mint_input.spl_mint, | |
supply: compressed_mint_inputs.compressed_mint_input.supply, | |
decimals, | |
is_decompressed: false, // Mark as decompressed | |
mint_authority: Some(mint_authority), | |
freeze_authority, | |
num_extensions: compressed_mint_inputs.compressed_mint_input.num_extensions, | |
}; | |
let mut updated_compressed_mint = CompressedMint { | |
spl_mint: compressed_mint_inputs.compressed_mint_input.spl_mint, | |
supply: compressed_mint_inputs.compressed_mint_input.supply, | |
decimals, | |
is_decompressed: false, // Initial value before update | |
mint_authority: Some(mint_authority), | |
freeze_authority, | |
num_extensions: compressed_mint_inputs.compressed_mint_input.num_extensions, | |
}; |
🤖 Prompt for AI Agents
In programs/compressed-token/src/process_create_spl_mint.rs around lines 89 to
97, the field is_decompressed is incorrectly set to false despite the comment
saying "Mark as decompressed." Change is_decompressed to true here to correctly
reflect the decompressed state, matching the intended logic and consistency with
line 124.
fn create_token_pool_account_manual<'info>( | ||
ctx: &Context<'_, '_, '_, 'info, CreateSplMintInstruction<'info>>, | ||
) -> Result<()> { | ||
let token_account_size = 165; // Size of Token account |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Consider using constants for account sizes
Hardcoded account sizes (165 for token account, 82 for mint account) could break if the account structures change. Consider using constants or deriving sizes programmatically.
Also applies to: 303-303
🏁 Script executed:
#!/bin/bash
# Description: Check if these account sizes are defined as constants elsewhere in the codebase
# Search for token account size constants
rg -A 2 "token.*account.*size|TOKEN.*SIZE" --type rust
# Search for mint account size constants
rg -A 2 "mint.*account.*size|MINT.*SIZE" --type rust
# Check Token-2022 program for size definitions
fd -e rs | xargs rg "165|82" -B 2 -A 2
Length of output: 265323
Replace hardcoded SPL account sizes with official constants
Hardcoding 165
and 82
risks breakage if the SPL Token account layouts evolve. Use the LEN
constants from spl_token::state
instead:
• programs/compressed-token/src/process_create_spl_mint.rs, line 231
Replace
let token_account_size = 165; // Size of Token account
With
let token_account_size = spl_token::state::Account::LEN;
• programs/compressed-token/src/process_create_spl_mint.rs, line 303
Replace
let mint_account_size = 82; // Size of Token-2022 Mint account
With
let mint_account_size = spl_token::state::Mint::LEN;
Diff example:
- let token_account_size = 165; // Size of Token account
+ let token_account_size = spl_token::state::Account::LEN;
- let mint_account_size = 82; // Size of Token-2022 Mint account
+ let mint_account_size = spl_token::state::Mint::LEN;
This ensures your code always matches the on-chain account definitions.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
let token_account_size = 165; // Size of Token account | |
// replace at line 231 | |
let token_account_size = spl_token::state::Account::LEN; | |
// ... | |
// replace at line 303 | |
let mint_account_size = spl_token::state::Mint::LEN; |
🤖 Prompt for AI Agents
In programs/compressed-token/src/process_create_spl_mint.rs at line 231, replace
the hardcoded token account size value 165 with the official constant
spl_token::state::Account::LEN. Similarly, at line 303, replace the hardcoded
mint account size 82 with spl_token::state::Mint::LEN. This ensures the code
uses the authoritative SPL Token account size constants and remains compatible
with any future changes.
token_pool_pda: Pubkey::new_unique(), // No token pool for pure compressed mint | ||
token_program: spl_token::ID, // No token program for pure compressed mint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect token pool PDA setup for pure compressed mints.
The token pool PDA is set to a random pubkey (Pubkey::new_unique()
) which appears incorrect. For pure compressed mints without an SPL mint, this should either be a proper PDA or handled differently. Additionally, the comment on line 6286 says "No token program for pure compressed mint" but still sets spl_token::ID
.
Consider using a deterministic PDA or clarifying the intended behavior for pure compressed mints:
- token_pool_pda: Pubkey::new_unique(), // No token pool for pure compressed mint
- token_program: spl_token::ID, // No token program for pure compressed mint
+ token_pool_pda: Pubkey::default(), // Use default pubkey for pure compressed mint
+ token_program: spl_token::ID, // Required for account structure validation
🤖 Prompt for AI Agents
In program-tests/compressed-token-test/tests/test.rs around lines 6285 to 6286,
the token_pool_pda is incorrectly set to a random Pubkey using
Pubkey::new_unique(), which is not appropriate for pure compressed mints.
Replace this with a deterministic PDA derived from the mint or relevant seeds to
correctly represent the token pool. Also, since the comment states there is no
token program for pure compressed mints, remove or adjust the token_program
field to reflect this, either by setting it to None or an appropriate value
indicating no SPL token program is used.
], | ||
&crate::ID, | ||
) | ||
.map_err(|_| crate::ErrorCode::InvalidTokenPoolPda)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use appropriate error code for mint PDA creation failure.
The error code InvalidTokenPoolPda
is misleading when the mint PDA creation fails. Consider using InvalidMintPda
instead.
- .map_err(|_| crate::ErrorCode::InvalidTokenPoolPda)?;
+ .map_err(|_| crate::ErrorCode::InvalidMintPda)?;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
.map_err(|_| crate::ErrorCode::InvalidTokenPoolPda)?; | |
.map_err(|_| crate::ErrorCode::InvalidMintPda)?; |
🤖 Prompt for AI Agents
In programs/compressed-token/src/process_create_compressed_mint.rs at line 153,
the error code used for mint PDA creation failure is incorrectly set to
InvalidTokenPoolPda. Change this error code to InvalidMintPda to accurately
reflect the mint PDA creation failure.
|
||
let seeds = get_cpi_signer_seeds(); | ||
let mut inputs = Vec::new(); | ||
InstructionDataInvokeCpi::serialize(&inputs_struct, &mut inputs).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace unwrap() with proper error handling.
Using unwrap()
can cause the program to panic. Use proper error handling to avoid panics in production code.
- InstructionDataInvokeCpi::serialize(&inputs_struct, &mut inputs).unwrap();
+ InstructionDataInvokeCpi::serialize(&inputs_struct, &mut inputs)?;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
InstructionDataInvokeCpi::serialize(&inputs_struct, &mut inputs).unwrap(); | |
InstructionDataInvokeCpi::serialize(&inputs_struct, &mut inputs)?; |
🤖 Prompt for AI Agents
In programs/compressed-token/src/process_create_compressed_mint.rs at line 26,
replace the use of unwrap() on the result of InstructionDataInvokeCpi::serialize
with proper error handling. Instead of calling unwrap(), handle the Result by
using a match statement or the ? operator to propagate the error, ensuring the
program does not panic and handles serialization failures gracefully.
// Not necessary. | ||
// /// Is `true` if this structure has been initialized | ||
// pub is_initialized: bool, | ||
pub num_extensions: u8, // TODO: check again how token22 does it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Address TODO: Verify token22 extension handling.
The TODO indicates uncertainty about how Token-2022 handles extensions. This should be verified to ensure compatibility.
🌐 Web query:
How does Token-2022 handle extensions and what is the proper way to count num_extensions?
💡 Result:
In the Token-2022 program, extensions are additional features that can be enabled on token mints and accounts to enhance their functionality. These extensions are optional and can be added during the initialization of a mint or token account. Each extension introduces specific state variables, and the total number of extensions enabled on a mint or account is tracked by the num_extensions
field.
Understanding num_extensions
:
The num_extensions
field indicates the number of extensions currently enabled on a mint or token account. This field is crucial for correctly unpacking and interpreting the account data, as the presence of extensions affects the account's data structure.
Proper Way to Count num_extensions
:
To accurately determine the number of extensions enabled on a mint or token account, you should unpack the account data using the StateWithExtensions
structure provided by the spl-token-2022
library. This structure allows you to deserialize the base state of the mint or account and access the extensions in a way that accounts for the variable length of the extensions.
Here's how you can do this in Rust:
use spl_token_2022::{extension::StateWithExtensions, state::Mint, state::Account};
fn get_num_extensions_mint(account_data: &[u8]) -> usize {
let mint_state = StateWithExtensions::<Mint>::unpack(account_data).unwrap();
mint_state.get_extension_types().unwrap().len()
}
fn get_num_extensions_account(account_data: &[u8]) -> usize {
let account_state = StateWithExtensions::<Account>::unpack(account_data).unwrap();
account_state.get_extension_types().unwrap().len()
}
In this code:
-
StateWithExtensions::<Mint>::unpack(account_data)
unpacks the mint account data, allowing access to both the base state and the extensions. -
get_extension_types()
retrieves the types of extensions enabled on the mint. -
len()
returns the number of extensions.
By using this approach, you can accurately determine the number of extensions enabled on a mint or token account, ensuring proper handling and interpretation of the account data.
For more detailed information on Token-2022 extensions and their usage, refer to the Solana Program Library's Extension Guide. (spl.solana.com)
Citations:
Implement accurate Token-2022 extension counting
The num_extensions
field should reflect the actual number of enabled extensions on a mint, not a hard-coded placeholder. Use the StateWithExtensions
helper in spl-token-2022
to deserialize the mint and count its extensions.
– In programs/compressed-token/src/create_mint.rs
at the num_extensions
declaration (line 32):
- Remove the
// TODO…
comment. - When initializing the mint, unpack and count its extensions:
use spl_token_2022::{extension::StateWithExtensions, state::Mint}; // after loading `account_data: &[u8]` for the new mint… let mint_state = StateWithExtensions::<Mint>::unpack(account_data) .map_err(|_| ProgramError::InvalidAccountData)?; let num_extensions = mint_state .get_extension_types() .map_err(|_| ProgramError::InvalidAccountData)? .len() as u8; // assign to your struct: YourMintConfig { num_extensions, /* … */ }
This ensures num_extensions
always matches the actual extensions present.
🤖 Prompt for AI Agents
In programs/compressed-token/src/create_mint.rs at line 32, replace the
hard-coded num_extensions field and remove the TODO comment. Instead, when
initializing the mint, use spl_token_2022's StateWithExtensions to unpack the
mint data and count the actual enabled extensions. Import StateWithExtensions
and Mint, unpack the mint from the account data, retrieve the extension types,
count them, and assign this count to num_extensions to ensure it accurately
reflects the mint's extensions.
let option_compressed_mint_inputs = if compressed_mint_inputs.is_some() { | ||
356 | ||
} else { | ||
0 | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace hardcoded size with precise calculation.
The hardcoded value of 356 bytes for option_compressed_mint_inputs
is fragile and could lead to memory allocation errors if the data structure size changes. Calculate the exact size based on the actual data structures.
Would you like me to help calculate the exact size based on the CompressedMintInputs structure?
Also applies to: 121-121
🤖 Prompt for AI Agents
In programs/compressed-token/src/process_mint.rs at lines 96 to 100 and line
121, replace the hardcoded size value 356 for option_compressed_mint_inputs with
a precise calculation based on the actual size of the CompressedMintInputs
structure. Use Rust's std::mem::size_of_val or size_of to dynamically compute
the size of the data structure instance or type, ensuring the size reflects any
changes in the structure and prevents memory allocation errors.
// msg!( | ||
// "compressed_inputs.output_merkle_tree_index {}", | ||
// compressed_inputs.output_merkle_tree_index | ||
// ); | ||
|
||
// Ok((input_compressed_account, output_compressed_mint_account)) | ||
// } | ||
|
||
// #[cfg(target_os = "solana")] | ||
// #[inline(never)] | ||
// pub fn cpi_execute_compressed_transaction_mint_to_with_inputs<'info>( | ||
// ctx: &Context<'_, '_, '_, 'info, MintToInstruction<'info>>, | ||
// input_compressed_accounts: Vec<PackedCompressedAccountWithMerkleContext>, | ||
// output_compressed_accounts: Vec<OutputCompressedAccountWithPackedContext>, | ||
// proof: Option<CompressedProof>, | ||
// inputs: &mut Vec<u8>, | ||
// pre_compressed_accounts_pos: usize, | ||
// ) -> Result<()> { | ||
// bench_sbf_start!("tm_cpi_mint_update"); | ||
|
||
// let signer_seeds = get_cpi_signer_seeds(); | ||
|
||
// // Serialize CPI instruction data with inputs | ||
// serialize_mint_to_cpi_instruction_data_with_inputs( | ||
// inputs, | ||
// &input_compressed_accounts, | ||
// &output_compressed_accounts, | ||
// proof, | ||
// ); | ||
|
||
// GLOBAL_ALLOCATOR.free_heap(pre_compressed_accounts_pos)?; | ||
|
||
// use anchor_lang::InstructionData; | ||
|
||
// let instructiondata = light_system_program::instruction::InvokeCpi { | ||
// inputs: inputs.to_owned(), | ||
// }; | ||
|
||
// let (sol_pool_pda, is_writable) = if let Some(pool_pda) = ctx.accounts.sol_pool_pda.as_ref() { | ||
// (pool_pda.to_account_info(), true) | ||
// } else { | ||
// (ctx.accounts.light_system_program.to_account_info(), false) | ||
// }; | ||
|
||
// // Build account infos including both output merkle tree and remaining accounts (compressed mint merkle tree) | ||
// let mut account_infos = vec![ | ||
// ctx.accounts.fee_payer.to_account_info(), | ||
// ctx.accounts.cpi_authority_pda.to_account_info(), | ||
// ctx.accounts.registered_program_pda.to_account_info(), | ||
// ctx.accounts.noop_program.to_account_info(), | ||
// ctx.accounts.account_compression_authority.to_account_info(), | ||
// ctx.accounts.account_compression_program.to_account_info(), | ||
// ctx.accounts.self_program.to_account_info(), | ||
// sol_pool_pda, | ||
// ctx.accounts.light_system_program.to_account_info(), | ||
// ctx.accounts.system_program.to_account_info(), | ||
// ctx.accounts.light_system_program.to_account_info(), // cpi_context_account placeholder | ||
// ctx.accounts.merkle_tree.to_account_info(), // output merkle tree | ||
// ]; | ||
|
||
// // Add remaining accounts (compressed mint merkle tree, etc.) | ||
// account_infos.extend_from_slice(ctx.remaining_accounts); | ||
|
||
// // Build account metas | ||
// let mut accounts = vec![ | ||
// AccountMeta::new(account_infos[0].key(), true), // fee_payer | ||
// AccountMeta::new_readonly(account_infos[1].key(), true), // cpi_authority_pda (signer) | ||
// AccountMeta::new_readonly(account_infos[2].key(), false), // registered_program_pda | ||
// AccountMeta::new_readonly(account_infos[3].key(), false), // noop_program | ||
// AccountMeta::new_readonly(account_infos[4].key(), false), // account_compression_authority | ||
// AccountMeta::new_readonly(account_infos[5].key(), false), // account_compression_program | ||
// AccountMeta::new_readonly(account_infos[6].key(), false), // self_program | ||
// AccountMeta::new(account_infos[7].key(), is_writable), // sol_pool_pda | ||
// AccountMeta::new_readonly(account_infos[8].key(), false), // decompression_recipient placeholder | ||
// AccountMeta::new_readonly(account_infos[9].key(), false), // system_program | ||
// AccountMeta::new_readonly(account_infos[10].key(), false), // cpi_context_account placeholder | ||
// AccountMeta::new(account_infos[11].key(), false), // output merkle tree (writable) | ||
// ]; | ||
|
||
// // Add remaining account metas (compressed mint merkle tree should be writable) | ||
// for remaining in &account_infos[12..] { | ||
// accounts.push(AccountMeta::new(remaining.key(), false)); | ||
// } | ||
|
||
// let instruction = anchor_lang::solana_program::instruction::Instruction { | ||
// program_id: light_system_program::ID, | ||
// accounts, | ||
// data: instructiondata.data(), | ||
// }; | ||
|
||
// bench_sbf_end!("tm_cpi_mint_update"); | ||
// bench_sbf_start!("tm_invoke_mint_update"); | ||
// anchor_lang::solana_program::program::invoke_signed( | ||
// &instruction, | ||
// account_infos.as_slice(), | ||
// &[&signer_seeds[..]], | ||
// )?; | ||
// bench_sbf_end!("tm_invoke_mint_update"); | ||
// Ok(()) | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove commented-out code.
Large blocks of commented-out code should be removed. If this code is needed for reference, consider moving it to documentation or a separate branch.
🤖 Prompt for AI Agents
In programs/compressed-token/src/process_mint.rs between lines 530 and 680,
there is a large block of commented-out code that should be removed to keep the
codebase clean. Delete all the commented-out functions and related code in this
range. If the code needs to be preserved for reference, move it to documentation
or a separate branch instead of leaving it commented out in the source file.
} | ||
|
||
#[cfg(test)] | ||
mod tests { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to separate test file
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Documentation
Chores