feat(compression/cnft-burn): add pinocchio example - #719
Conversation
Ports the Anchor cnft-burn example to Pinocchio: a single instruction that CPIs into mpl-bubblegum's `Burn` to remove a compressed NFT's leaf from its concurrent merkle tree. The merkle proof arrives as a variable-length account tail, so the CPI account list is built into a fixed-size stack array and passed with `invoke_with_bounds` rather than the const-generic `invoke`. Unlike the Anchor variant, whose tests need devnet and a DAS indexer, the LiteSVM suite runs entirely locally: it creates a tree, mints a cNFT and burns it against the mainnet-dumped bubblegum, account-compression and noop programs, recomputing the leaf and root off-chain to check them against the tree's own state.
Greptile SummaryThe PR adds a Pinocchio compressed-NFT burn example that forwards Bubblegum burn arguments through CPI and verifies the flow with LiteSVM.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the previously reported persistent Solana CLI endpoint mutation is removed by applying the mainnet override only to each program-dump command. Important Files Changed
Reviews (3): Last reviewed commit: "cnft-burn: raise the proof cap to the pr..." | Re-trigger Greptile |
`solana config set -um` persisted mainnet into the developer's CLI config, so a plain `pnpm install` could silently redirect their later deploys. Passing `-um` to `solana program dump` targets mainnet for that command alone.
A 24-node cap could reject a valid proof: proofs are `max_depth - canopy_depth` nodes and SPL Account Compression allows a max_depth of 30, so a canopy-less deep tree needs all 30 — and address lookup tables make that transaction fit. At 30 the bound can no longer reject anything valid; it only keeps the CPI account list on the stack.
|
@amilz could you take a look at this one when you get a chance? No open review threads left on it, so it is ready for maintainer review. It is one of 23 open Pinocchio ports I have up — they are independent and self-contained, so they can be reviewed and merged in any order: https://github.com/solana-developers/program-examples/pulls/MarkFeder |
Ports
compression/cnft-burnto Pinocchio — the first Pinocchio example incompression/.Program
A single instruction that CPIs into mpl-bubblegum's
Burn, replacing a compressed NFT's leaf with an empty node. The burn arguments (root,data_hash,creator_hash,nonce,index) are already in bubblegum's wire order, so the CPI data is the discriminator followed by the instruction data verbatim — no borsh round-trip.Two things differ from the Anchor variant:
invoke_with_boundsinstead of the const-genericinvoke.MAX_PROOF_ACCOUNTSis capped at 24, which keeps the list off the heap and covers any proof that fits in a transaction.Tests
The Anchor variant is in
.ghaignorebecause its tests need devnet and a DAS indexer. This one runs entirely under LiteSVM against the mainnet-dumped bubblegum, account-compression and noop programs (prepare.mjsdumps them on postinstall, same pattern asnft-operations):create_treemint_v1Steps 1 and 2 recompute the expected root off-chain and assert it against the tree's own change log, so the leaf, data and creator hashes the burn depends on are verified independently rather than just "the transaction succeeded". Step 3 asserts the tree is empty again afterwards.
Verification
cargo build-sbf, isolated and workspaceclippy -D warnings,cargo fmt --check --all,tsc --noEmit,prettier --check, and the 3-test LiteSVM suite all pass locally.