Skip to content

feat: ctoken pinocchio #1861

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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
40 changes: 0 additions & 40 deletions .cargo/config.toml

This file was deleted.

88 changes: 88 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Testing

This repository uses a comprehensive two-tier testing strategy:

- **[Unit Testing Guide](./UNIT_TESTING.md)** - For testing individual functions in isolation using mock account infos. Tests are located in `tests/` directories within each crate.

- **[Integration Testing Guide](./INTEGRATION_TESTING.md)** - For testing complete program workflows using full SVM simulation. Tests are located in the `program-tests/` directory.

## Key Testing Requirements

All tests must follow these mandatory requirements:
- **Functional test for every usage flow**
- **Failing test for every error condition**
- **Complete output verification** with single `assert_eq!` against expected structs
- **1k iteration randomized tests** for complex functions and ZeroCopy structs

# Debugging with LightProgramTest

## Transaction Log File

The light-program-test library automatically creates detailed transaction logs in:
```
target/light_program_test.log
```

### Features

- **Always enabled**: Logs are written to file regardless of environment variables
- **Clean format**: Plain text without ANSI color codes for easy reading and processing
- **Session-based**: Each test session starts with a timestamp header, transactions append to the same file
- **Comprehensive details**: Includes transaction signatures, fees, compute usage, instruction hierarchies, Light Protocol instruction parsing, and compressed account information

### Configuration

Enhanced logging is enabled by default. To disable:
```rust
let mut config = ProgramTestConfig::default();
config.enhanced_logging.enabled = false;
```

Console output requires `RUST_BACKTRACE` environment variable and can be controlled separately from file logging.

### Log File Location

The log file is automatically placed in the cargo workspace target directory, making it consistent across different test environments and working directories.

# Program Performance
- send bump seeds
- avoid deriving addresses
- avoid vectors stack over heap use ArrayVec

# Program Security

- every input (instruction data and account infos) must be checked
- inclusion of instruction data in an input compressed account data hash counts as checked

### Account checks
- ownership is checked
- cpis should use hardcoded

### Compressed accounts
- the program id is the owner of the compressed account
- data hash must be computed in the owning program
- all data that is in an input compressed account is checked implicitly by inclusion in the data hash, the data hash is part of the compressed account hash that is in the Merkle tree or queue which we prove inclusion in by zkp or index
- input compressed account
- is existing state
- validity is proven by index (zkp is None) or zkp
- no data is sent to the system program
- data hash must be computed in the owning program
- output compressed account
- this is new state, no validity proof
- data hash must be computed in the owning program
- no changes to data after data hash has been computed
- minimize use of instruction data, ie do not send data twice.
1. example, owner pubkey
if a compressed account has an owner pubkey field which should be a tx signer, send it as signer account info, set it in the custom program, and do not sending it as instruction data. No comparison in the program is required.
2. example, values from accounts

-

- a compressed account the state update is atomic through the cpi to the light system program, writes to the cpi context can produce non atomic transactions if solana accounts are involved and instantly updated for compressed accounts atomicity still applies, in case that a written cpi context account is not executed the state update is never actually applied only prepared.


# Zero Copies
- the derive macros ZeroCopy and ZeroCopyMut derive zero copy deserialization methods and should be used in programs
- in client code borsh is preferable
- ZeroCopy is borsh compatible
- Z and Z*Mut structs are derived by the ZeroCopy and ZeroCopyMut macros and cannot be searched with grep or rg, search for the non prefixed struct instead the zero copy struct has the same structure with zero copy types.
22 changes: 22 additions & 0 deletions COMMON_ERRORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
1. │ ERROR: Not enough accounts. Requested 'burn change account owner' at index 3 but only 0 accounts available. programs/compressed-token/program/src/mint_action/burn.rs:142:41
- means that packed accounts doesn't contain enough accounts
-
2. `NotEnoughSigners`
- `create_and_send_transaction(&[instruction], &payer.pubkey(), &signers)`
- needs more signers
- signers must be unique you must not pass the same twice it will result in an error
3. `CompressedAccountError::ZeroCopyExpectedAddress => 12017`
- when setting output compressed accounts in a zero copy we expect an address to be provided the address is allocated as Some by the ZeroCopyConfig but None is provided
- any error that contains Expected and is an CompressedAccountError means this for the specied compressed account field
4. `Signer/Program cannot write into an account it doesn't own.`
```mode Small
│ Signer/Program cannot write into an account it doesn't own. Write access check failed, compressed account owner [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] != invoking_program_id [9, 21, 163, 87, 35, 121, 78, 143, 182, 93, 7, 91, 107, 114, 105, 156, 56, 221, 2, 229, 148, 139, 117, 176, 229, 160, 65, 142, 128, 151, 91, 68].
│ Program SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7 consumed 17422 of 1186879 compute units
│ Program SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7 failed: custom program error: 0x177d
│ Program cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m consumed 230543 of 1400000 compute units
│ Program cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m failed: custom program error: 0x177d
```
- the compressed output account owner is not set
5. ` Program SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7 failed: custom program error: 0x179a`
-
- the index for a state Merkle tree in the packed accounts is wrong
Loading
Loading