Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit d85ea9f

Browse files
StanChengundotra
andauthored
account-compression: fix for a stack overflow issue on macro usage (#6827)
* account-compression: fix for a stack overflow issue on macro usage * clippy: removed unnecessary references * update cmt tests * fix rustfmt * bump spl-concurrent-merkle-tree to 0.3.0 for API changes --------- Co-authored-by: ngundotra <noah@gundotra.org> Co-authored-by: Noah Gundotra <ngundotra@users.noreply.github.com>
1 parent 61794be commit d85ea9f

File tree

8 files changed

+301
-173
lines changed

8 files changed

+301
-173
lines changed

Cargo.lock

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

account-compression/programs/account-compression/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ default = []
2121
anchor-lang = "0.29.0"
2222
bytemuck = "1.13"
2323
solana-program = ">=1.18.11,<=2"
24-
spl-concurrent-merkle-tree = { version = "0.2.0", path = "../../../libraries/concurrent-merkle-tree", features = [
25-
"sol-log",
24+
spl-concurrent-merkle-tree = { version = "0.3.0", path = "../../../libraries/concurrent-merkle-tree", features = [
25+
"sol-log",
2626
] }
2727
spl-noop = { version = "0.2.0", path = "../noop", features = ["no-entrypoint"] }
2828

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//! This module provides a wrapper around the `ConcurrentMerkleTree` struct from
2+
//! the `spl_concurrent_merkle_tree` crate. It provides a set of functions that
3+
//! can be called from the Anchor program to interact with the tree.
4+
//! The functions are used to initialize the tree, set a leaf, fill empty or
5+
//! append a leaf, and prove a leaf. As the tree is generic over the depth and
6+
//! buffer size, the functions are implemented using macros that infer the depth
7+
//! and buffer size from the header information stored on-chain. Usage of the
8+
//! macros directly is discouraged, as they have huge match statements with
9+
//! every case taking it's own stack frame. Instead, use the exported functions
10+
//! from this module and refenrece or Box the arguments to the functions to
11+
//! avoid the stack frame explosion.
12+
13+
pub use crate::error::AccountCompressionError;
14+
/// Exported for Anchor / Solita
15+
pub use spl_concurrent_merkle_tree::{
16+
concurrent_merkle_tree::{
17+
ConcurrentMerkleTree, FillEmptyOrAppendArgs, InitializeWithRootArgs, ProveLeafArgs,
18+
SetLeafArgs,
19+
},
20+
error::ConcurrentMerkleTreeError,
21+
node::Node,
22+
node::EMPTY,
23+
};
24+
use {
25+
crate::{
26+
events::ChangeLogEvent, macros::*, state::ConcurrentMerkleTreeHeader, zero_copy::ZeroCopy,
27+
},
28+
anchor_lang::prelude::*,
29+
};
30+
31+
pub fn merkle_tree_initialize_with_root(
32+
header: &ConcurrentMerkleTreeHeader,
33+
tree_id: Pubkey,
34+
tree_bytes: &mut [u8],
35+
args: &InitializeWithRootArgs,
36+
) -> Result<Box<ChangeLogEvent>> {
37+
merkle_tree_apply_fn_mut!(header, tree_id, tree_bytes, initialize_with_root, args)
38+
}
39+
40+
pub fn merkle_tree_set_leaf(
41+
header: &ConcurrentMerkleTreeHeader,
42+
tree_id: Pubkey,
43+
tree_bytes: &mut [u8],
44+
args: &SetLeafArgs,
45+
) -> Result<Box<ChangeLogEvent>> {
46+
merkle_tree_apply_fn_mut!(header, tree_id, tree_bytes, set_leaf, args)
47+
}
48+
49+
pub fn merkle_tree_fill_empty_or_append(
50+
header: &ConcurrentMerkleTreeHeader,
51+
tree_id: Pubkey,
52+
tree_bytes: &mut [u8],
53+
args: &FillEmptyOrAppendArgs,
54+
) -> Result<Box<ChangeLogEvent>> {
55+
merkle_tree_apply_fn_mut!(header, tree_id, tree_bytes, fill_empty_or_append, args)
56+
}
57+
58+
pub fn merkle_tree_prove_leaf(
59+
header: &ConcurrentMerkleTreeHeader,
60+
tree_id: Pubkey,
61+
tree_bytes: &[u8],
62+
args: &ProveLeafArgs,
63+
) -> Result<Box<ChangeLogEvent>> {
64+
merkle_tree_apply_fn!(header, tree_id, tree_bytes, prove_leaf, args)
65+
}

account-compression/programs/account-compression/src/lib.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use anchor_lang::{
2929
use borsh::{BorshDeserialize, BorshSerialize};
3030

3131
pub mod canopy;
32+
pub mod concurrent_tree_wrapper;
3233
pub mod error;
3334
pub mod events;
3435
#[macro_use]
@@ -40,6 +41,7 @@ pub mod zero_copy;
4041
pub use crate::noop::{wrap_application_data_v1, Noop};
4142

4243
use crate::canopy::{fill_in_proof_from_canopy, update_canopy};
44+
use crate::concurrent_tree_wrapper::*;
4345
pub use crate::error::AccountCompressionError;
4446
pub use crate::events::{AccountCompressionEvent, ChangeLogEvent};
4547
use crate::noop::wrap_event;
@@ -50,7 +52,9 @@ use crate::zero_copy::ZeroCopy;
5052

5153
/// Exported for Anchor / Solita
5254
pub use spl_concurrent_merkle_tree::{
53-
concurrent_merkle_tree::ConcurrentMerkleTree, error::ConcurrentMerkleTreeError, node::Node,
55+
concurrent_merkle_tree::{ConcurrentMerkleTree, FillEmptyOrAppendArgs},
56+
error::ConcurrentMerkleTreeError,
57+
node::Node,
5458
};
5559

5660
declare_id!("cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK");
@@ -270,17 +274,15 @@ pub mod spl_account_compression {
270274
fill_in_proof_from_canopy(canopy_bytes, header.get_max_depth(), index, &mut proof)?;
271275
let id = ctx.accounts.merkle_tree.key();
272276
// A call is made to ConcurrentMerkleTree::set_leaf(root, previous_leaf, new_leaf, proof, index)
273-
let change_log_event = merkle_tree_apply_fn_mut!(
274-
header,
275-
id,
276-
tree_bytes,
277-
set_leaf,
278-
root,
277+
let args = &SetLeafArgs {
278+
current_root: root,
279279
previous_leaf,
280280
new_leaf,
281-
&proof,
281+
proof_vec: proof,
282282
index,
283-
)?;
283+
};
284+
let change_log_event = merkle_tree_set_leaf(&header, id, tree_bytes, args)?;
285+
284286
update_canopy(
285287
canopy_bytes,
286288
header.get_max_depth(),
@@ -347,7 +349,14 @@ pub mod spl_account_compression {
347349
fill_in_proof_from_canopy(canopy_bytes, header.get_max_depth(), index, &mut proof)?;
348350
let id = ctx.accounts.merkle_tree.key();
349351

350-
merkle_tree_apply_fn!(header, id, tree_bytes, prove_leaf, root, leaf, &proof, index)?;
352+
let args = &ProveLeafArgs {
353+
current_root: root,
354+
leaf,
355+
proof_vec: proof,
356+
index,
357+
};
358+
merkle_tree_prove_leaf(&header, id, tree_bytes, args)?;
359+
351360
Ok(())
352361
}
353362

@@ -418,16 +427,14 @@ pub mod spl_account_compression {
418427
fill_in_proof_from_canopy(canopy_bytes, header.get_max_depth(), index, &mut proof)?;
419428
// A call is made to ConcurrentMerkleTree::fill_empty_or_append
420429
let id = ctx.accounts.merkle_tree.key();
421-
let change_log_event = merkle_tree_apply_fn_mut!(
422-
header,
423-
id,
424-
tree_bytes,
425-
fill_empty_or_append,
426-
root,
430+
let args = &FillEmptyOrAppendArgs {
431+
current_root: root,
427432
leaf,
428-
&proof,
433+
proof_vec: proof,
429434
index,
430-
)?;
435+
};
436+
let change_log_event = merkle_tree_fill_empty_or_append(&header, id, tree_bytes, args)?;
437+
431438
update_canopy(
432439
canopy_bytes,
433440
header.get_max_depth(),

account-compression/programs/account-compression/src/macros.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ enum TreeLoad {
44
Mutable,
55
}
66

7-
/// This macro applies functions on a ConcurrentMerkleT:ee and emits leaf information
8-
/// needed to sync the merkle tree state with off-chain indexers.
7+
/// This macro applies functions on a ConcurrentMerkleT:ee and emits leaf
8+
/// information needed to sync the merkle tree state with off-chain indexers.
99
#[macro_export]
1010
macro_rules! _merkle_tree_depth_size_apply_fn {
1111
($max_depth:literal, $max_size:literal, $id:ident, $bytes:ident, $func:ident, TreeLoad::Mutable, $($arg:tt)*)
@@ -118,3 +118,8 @@ macro_rules! merkle_tree_apply_fn {
118118
_merkle_tree_apply_fn!($header, $id, $bytes, $func, TreeLoad::Immutable, $($arg)*)
119119
};
120120
}
121+
122+
pub(crate) use {
123+
_merkle_tree_apply_fn, _merkle_tree_depth_size_apply_fn, merkle_tree_apply_fn,
124+
merkle_tree_apply_fn_mut,
125+
};

libraries/concurrent-merkle-tree/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "spl-concurrent-merkle-tree"
3-
version = "0.2.0"
3+
version = "0.3.0"
44
description = "Solana Program Library Concurrent Merkle Tree"
55
authors = ["Solana Labs Maintainers <maintainers@solanalabs.com>"]
66
repository = "https://github.com/solana-labs/solana-program-library"
@@ -9,7 +9,7 @@ edition = "2021"
99

1010
[features]
1111
log = []
12-
sol-log = [ "log" ]
12+
sol-log = ["log"]
1313

1414
[dependencies]
1515
solana-program = "1.16"

0 commit comments

Comments
 (0)