From 7ba20c24ac1cab2b04bca3ad499a739c68878131 Mon Sep 17 00:00:00 2001 From: mubariz Date: Sat, 7 Sep 2024 16:57:54 +0500 Subject: [PATCH 01/10] update dep --- .../state-compression/generalized-state-compression.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index 4333e308d..66c83d860 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -636,9 +636,9 @@ enabled. Let’s add it as a dependency in `programs/compressed-notes/Cargo.toml ```toml [dependencies] -anchor-lang = "0.28.0" -spl-account-compression = { version="0.2.0", features = ["cpi"] } -solana-program = "1.16.0" +anchor-lang = "0.30.1" +spl-account-compression = { version="0.3.1", features = ["cpi"] } +solana-program = ">=1.18.11,<=2" ``` We’ll be testing locally but we need both the Compression program and the Noop From 14cb737210e60c3e88a9488ae02ae50afe454564 Mon Sep 17 00:00:00 2001 From: mubariz Date: Sat, 7 Sep 2024 17:05:41 +0500 Subject: [PATCH 02/10] fix : bump seed parameter --- .../state-compression/generalized-state-compression.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index 66c83d860..6ab5dbef5 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -806,7 +806,7 @@ pub mod compressed_notes { // Define the seeds for pda signing let signer_seeds: &[&[&[u8]]] = &[&[ merkle_tree.as_ref(), // The address of the Merkle tree account as a seed - &[*ctx.bumps.get("tree_authority").unwrap()], // The bump seed for the pda + &[ctx.bumps.tree_authority], // The bump seed for the pda ]]; // Create cpi context for init_empty_merkle_tree instruction. @@ -878,7 +878,7 @@ pub mod compressed_notes { // Define the seeds for pda signing let signer_seeds: &[&[&[u8]]] = &[&[ merkle_tree.as_ref(), // The address of the Merkle tree account as a seed - &[*ctx.bumps.get("tree_authority").unwrap()], // The bump seed for the pda + &[ctx.bumps.tree_authority], // The bump seed for the pda ]]; // Create a new cpi context and append the leaf node to the Merkle tree. let cpi_ctx = CpiContext::new_with_signer( @@ -958,7 +958,7 @@ pub mod compressed_notes { // Define the seeds for pda signing let signer_seeds: &[&[&[u8]]] = &[&[ merkle_tree.as_ref(), // The address of the Merkle tree account as a seed - &[*ctx.bumps.get("tree_authority").unwrap()], // The bump seed for the pda + &[ctx.bumps.tree_authority], // The bump seed for the pda ]]; // Verify Leaf From 2fe7bd24825a577bdcb162bc43719f8a9266b640 Mon Sep 17 00:00:00 2001 From: mubariz Date: Sat, 7 Sep 2024 17:41:30 +0500 Subject: [PATCH 03/10] npm installation command --- .../state-compression/generalized-state-compression.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index 6ab5dbef5..2b0670cf8 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -1019,6 +1019,12 @@ install it: yarn add @solana/spl-account-compression ``` +or + +```bash +npm install @solana/spl-account-compression +``` + Next, we’re going to give you the contents of a utility file we’ve created to make testing easier. Create a `utils.ts` file in the `tests` directory, add in the below, then we’ll explain it. From b2d879861c39bfda075e99604075cf04b84b1c23 Mon Sep 17 00:00:00 2001 From: mubariz Date: Tue, 10 Sep 2024 11:40:31 +0500 Subject: [PATCH 04/10] link merkle tree --- .../courses/state-compression/generalized-state-compression.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index 2b0670cf8..53bf6979e 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -14,7 +14,7 @@ description: - State Compression on Solana is most commonly used for compressed NFTs, but it's possible to use it for arbitrary data - State Compression lowers the amount of data you have to store onchain by - leveraging Merkle trees. + leveraging [Merkle trees](https://en.wikipedia.org/wiki/Merkle_tree). - Merkle trees store a single hash that represents an entire binary tree of hashes. Each leaf on a Merkle tree is a hash of that leaf's data. - Concurrent Merkle trees are a specialized version of Merkle trees that allow From baa7cbef4fae2b794c2ffc7be33dd47d03c88b32 Mon Sep 17 00:00:00 2001 From: mubariz Date: Tue, 10 Sep 2024 12:10:43 +0500 Subject: [PATCH 05/10] Added Missing MessageAccounts in Message struct guide --- .../generalized-state-compression.md | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index 53bf6979e..fcea2abba 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -263,18 +263,48 @@ a simple messaging program, your `Message` struct might look as follows: ```rust #[derive(AnchorSerialize)] pub struct MessageLog { - leaf_node: [u8; 32], // The leaf node hash - from: Pubkey, // Pubkey of the message sender - to: Pubkey, // Pubkey of the message recipient - message: String, // The message to send + pub leaf_node: [u8; 32], // leaf node hash + pub from: Pubkey, + pub to: Pubkey, + pub message: String, // message to send } impl MessageLog { // Constructs a new message log from given leaf node and message pub fn new(leaf_node: [u8; 32], from: Pubkey, to: Pubkey, message: String) -> Self { - Self { leaf_node, from, to, message } + Self { + leaf_node, + from, + to, + message, + } } } + +#[derive(Accounts)] +pub struct MessageAccounts<'info> { + // The payer for the transaction + #[account(mut)] + pub owner: Signer<'info>, + + // The pda authority for the merkle tree, only used for signing + #[account( + seeds = [merkle_tree.key().as_ref()], + bump, + )] + pub tree_authority: SystemAccount<'info>, + + // The merkle tree account + /// CHECK: This account is validated by the spl account compression program + #[account(mut)] + pub merkle_tree: UncheckedAccount<'info>, + + // The noop program to log data + pub log_wrapper: Program<'info, Noop>, + + // The spl account compression program + pub compression_program: Program<'info, SplAccountCompression>, +} ``` To be abundantly clear, **this is not an account that you will be able to read From 2127f43bfed1f6630d943d582e206112cb0a1921 Mon Sep 17 00:00:00 2001 From: mubariz Date: Tue, 10 Sep 2024 12:19:01 +0500 Subject: [PATCH 06/10] update import functions for create_message_tree --- .../state-compression/generalized-state-compression.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index fcea2abba..fd6f7d0a2 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -341,18 +341,19 @@ pub fn create_messages_tree( ) -> Result<()> { // Get the address for the Merkle tree account let merkle_tree = ctx.accounts.merkle_tree.key(); + // Define the seeds for pda signing let signer_seeds: &[&[&[u8]]] = &[ &[ merkle_tree.as_ref(), // The address of the Merkle tree account as a seed - &[*ctx.bumps.get("tree_authority").unwrap()], // The bump seed for the pda + &[ctx.bumps.tree_authority], // The bump seed for the pda ], ]; // Create cpi context for init_empty_merkle_tree instruction. let cpi_ctx = CpiContext::new_with_signer( ctx.accounts.compression_program.to_account_info(), // The spl account compression program - Initialize { + spl_account_compression::cpi::accounts::Initialize { authority: ctx.accounts.tree_authority.to_account_info(), // The authority for the Merkle tree, using a PDA merkle_tree: ctx.accounts.merkle_tree.to_account_info(), // The Merkle tree account to be initialized noop: ctx.accounts.log_wrapper.to_account_info(), // The noop program to log data @@ -361,7 +362,7 @@ pub fn create_messages_tree( ); // CPI to initialize an empty Merkle tree with given max depth and buffer size - init_empty_merkle_tree(cpi_ctx, max_depth, max_buffer_size)?; + spl_account_compression::cpi::init_empty_merkle_tree(cpi_ctx, max_depth, max_buffer_size)?; Ok(()) } From 3c744e92669a4a985819307f519ddbd98714690e Mon Sep 17 00:00:00 2001 From: mubariz Date: Tue, 10 Sep 2024 12:31:30 +0500 Subject: [PATCH 07/10] update append_messgae --- .../generalized-state-compression.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index fd6f7d0a2..d470d93b0 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -398,19 +398,29 @@ like this: pub fn append_message(ctx: Context, message: String) -> Result<()> { // Hash the message + whatever key should have update authority let leaf_node = keccak::hashv(&[message.as_bytes(), ctx.accounts.sender.key().as_ref()]).to_bytes(); - // Create a new "message log" using the leaf node hash, sender, receipient, and message - let message_log = MessageLog::new(leaf_node.clone(), ctx.accounts.sender.key().clone(), ctx.accounts.receipient.key().clone(), message); + + // Create a new "message log" using the leaf node hash, sender, recipient, and message + let message_log = MessageLog::new( + leaf_node.clone(), + *ctx.accounts.sender.key, + *ctx.accounts.recipient.key, + message.clone() + ); + // Log the "message log" data using noop program wrap_application_data_v1(message_log.try_to_vec()?, &ctx.accounts.log_wrapper)?; + // Get the address for the Merkle tree account let merkle_tree = ctx.accounts.merkle_tree.key(); + // Define the seeds for pda signing let signer_seeds: &[&[&[u8]]] = &[ &[ merkle_tree.as_ref(), // The address of the Merkle tree account as a seed - &[*ctx.bumps.get("tree_authority").unwrap()], // The bump seed for the pda + &[ctx.bumps.tree_authority], // The bump seed for the pda ], ]; + // Create a new cpi context and append the leaf node to the Merkle tree. let cpi_ctx = CpiContext::new_with_signer( ctx.accounts.compression_program.to_account_info(), // The spl account compression program @@ -421,8 +431,10 @@ pub fn append_message(ctx: Context, message: String) -> Result< }, signer_seeds // The seeds for pda signing ); + // CPI to append the leaf node to the Merkle tree append(cpi_ctx, leaf_node)?; + Ok(()) } ``` From 252f590fd8729998b1eb2b5cc36615b2363b2a90 Mon Sep 17 00:00:00 2001 From: mubariz Date: Tue, 10 Sep 2024 12:57:07 +0500 Subject: [PATCH 08/10] update update_message --- .../generalized-state-compression.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index d470d93b0..c5c352140 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -402,9 +402,9 @@ pub fn append_message(ctx: Context, message: String) -> Result< // Create a new "message log" using the leaf node hash, sender, recipient, and message let message_log = MessageLog::new( leaf_node.clone(), - *ctx.accounts.sender.key, - *ctx.accounts.recipient.key, - message.clone() + ctx.accounts.sender.key().clone(), + ctx.accounts.recipient.key().clone(), + message ); // Log the "message log" data using noop program @@ -485,17 +485,14 @@ pub fn update_message( old_message: String, new_message: String ) -> Result<()> { - let old_leaf = keccak - ::hashv(&[old_message.as_bytes(), ctx.accounts.sender.key().as_ref()]) - .to_bytes(); - + let old_leaf = keccak::hashv(&[old_message.as_bytes(), ctx.accounts.sender.key().as_ref()]).to_bytes(); let merkle_tree = ctx.accounts.merkle_tree.key(); // Define the seeds for pda signing let signer_seeds: &[&[&[u8]]] = &[ &[ merkle_tree.as_ref(), // The address of the Merkle tree account as a seed - &[*ctx.bumps.get("tree_authority").unwrap()], // The bump seed for the pda + &[ctx.bumps.tree_authority], // The bump seed for the pda ], ]; @@ -505,7 +502,6 @@ pub fn update_message( msg!("Messages are the same!"); return Ok(()); } - let cpi_ctx = CpiContext::new_with_signer( ctx.accounts.compression_program.to_account_info(), // The spl account compression program VerifyLeaf { @@ -517,12 +513,16 @@ pub fn update_message( verify_leaf(cpi_ctx, root, old_leaf, index)?; } - let new_leaf = keccak - ::hashv(&[new_message.as_bytes(), ctx.accounts.sender.key().as_ref()]) - .to_bytes(); + let new_leaf = keccak::hashv(&[new_message.as_bytes(), ctx.accounts.sender.key().as_ref()]).to_bytes(); // Log out for indexers - let message_log = MessageLog::new(new_leaf.clone(), ctx.accounts.sender.key().clone(), ctx.accounts.recipient.key().clone(), new_message); + let message_log = MessageLog::new( + new_leaf.clone(), + ctx.accounts.sender.key().clone(), + ctx.accounts.recipient.key().clone(), + new_message + ); + // Log the "message log" data using noop program wrap_application_data_v1(message_log.try_to_vec()?, &ctx.accounts.log_wrapper)?; @@ -537,7 +537,7 @@ pub fn update_message( }, signer_seeds // The seeds for pda signing ); - // CPI to append the leaf node to the Merkle tree + // CPI to replace the leaf node in the Merkle tree replace_leaf(cpi_ctx, root, old_leaf, new_leaf, index)?; } From 92e1ea20811cf4d119d65e083ba442203fd5badb Mon Sep 17 00:00:00 2001 From: baraz <161754323+mubarizkyc@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:26:26 +0500 Subject: [PATCH 09/10] Update generalized-state-compression.md --- .../courses/state-compression/generalized-state-compression.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index c5c352140..276b18813 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -671,7 +671,7 @@ app. Start by initializing an Anchor program: ```bash -anchor init compressed-notes +anchor init compressed-notes --template=multiple ``` We’ll be using the `spl-account-compression` crate with the `cpi` feature From b12c333c04fd8a5a7392811da82a490deb4f0411 Mon Sep 17 00:00:00 2001 From: baraz <161754323+mubarizkyc@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:32:22 +0500 Subject: [PATCH 10/10] Update generalized-state-compression.md --- .../state-compression/generalized-state-compression.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/courses/state-compression/generalized-state-compression.md b/content/courses/state-compression/generalized-state-compression.md index 276b18813..2ab747d71 100644 --- a/content/courses/state-compression/generalized-state-compression.md +++ b/content/courses/state-compression/generalized-state-compression.md @@ -679,8 +679,8 @@ enabled. Let’s add it as a dependency in `programs/compressed-notes/Cargo.toml ```toml [dependencies] -anchor-lang = "0.30.1" -spl-account-compression = { version="0.3.1", features = ["cpi"] } +anchor-lang = "0.28.0" +spl-account-compression = { version="0.2.0", features = ["cpi"] } solana-program = ">=1.18.11,<=2" ```