Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions program-libs/compressed-account/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ new-unique = ["dep:solana-pubkey"]
profile-program = []
profile-heap = ["dep:light-heap"]
poseidon = ["dep:light-poseidon", "light-hasher/poseidon"]
keccak = ["light-hasher/keccak"]
sha256 = ["light-hasher/sha256"]

[dependencies]
thiserror = { workspace = true }
Expand Down
12 changes: 12 additions & 0 deletions sdk-libs/client/src/indexer/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ pub enum IndexerError {
IndexerNotSyncedToSlot,
#[error("Address Merkle trees cannot be packed as output Merkle trees.")]
InvalidPackTreeType,
#[error("Cannot mix v1 and v2 trees in the same validity proof. State tree version: {state_version}, Address tree version: {address_version}")]
MixedTreeVersions {
state_version: String,
address_version: String,
},
}

impl IndexerError {
Expand Down Expand Up @@ -143,6 +148,13 @@ impl Clone for IndexerError {
IndexerError::NotInitialized => IndexerError::NotInitialized,
IndexerError::IndexerNotSyncedToSlot => IndexerError::IndexerNotSyncedToSlot,
IndexerError::InvalidPackTreeType => IndexerError::InvalidPackTreeType,
IndexerError::MixedTreeVersions {
state_version,
address_version,
} => IndexerError::MixedTreeVersions {
state_version: state_version.clone(),
address_version: address_version.clone(),
},
}
}
}
33 changes: 32 additions & 1 deletion sdk-libs/client/src/rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,9 +764,40 @@ impl Rpc for LightClient {

/// Gets a random active state tree.
/// State trees are cached and have to be fetched or set.
/// Returns v1 state trees by default, v2 state trees when v2 feature is enabled.
fn get_random_state_tree_info(&self) -> Result<TreeInfo, RpcError> {
let mut rng = rand::thread_rng();
select_state_tree_info(&mut rng, &self.state_merkle_trees)

#[cfg(feature = "v2")]
let filtered_trees: Vec<TreeInfo> = self
.state_merkle_trees
.iter()
.filter(|tree| tree.tree_type == TreeType::StateV2)
.copied()
.collect();

#[cfg(not(feature = "v2"))]
let filtered_trees: Vec<TreeInfo> = self
.state_merkle_trees
.iter()
.filter(|tree| tree.tree_type == TreeType::StateV1)
.copied()
.collect();

select_state_tree_info(&mut rng, &filtered_trees)
}

/// Gets a random v1 state tree.
/// State trees are cached and have to be fetched or set.
fn get_random_state_tree_info_v1(&self) -> Result<TreeInfo, RpcError> {
let mut rng = rand::thread_rng();
let v1_trees: Vec<TreeInfo> = self
.state_merkle_trees
.iter()
.filter(|tree| tree.tree_type == TreeType::StateV1)
.copied()
.collect();
select_state_tree_info(&mut rng, &v1_trees)
}

fn get_address_tree_v1(&self) -> TreeInfo {
Expand Down
5 changes: 5 additions & 0 deletions sdk-libs/client/src/rpc/rpc_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,13 @@ pub trait Rpc: Send + Sync + Debug + 'static {

/// Gets a random state tree info.
/// State trees are cached and have to be fetched or set.
/// Returns v1 state trees by default, v2 state trees when v2 feature is enabled.
fn get_random_state_tree_info(&self) -> Result<TreeInfo, RpcError>;

/// Gets a random v1 state tree info.
/// State trees are cached and have to be fetched or set.
fn get_random_state_tree_info_v1(&self) -> Result<TreeInfo, RpcError>;

fn get_address_tree_v1(&self) -> TreeInfo;

fn get_address_tree_v2(&self) -> TreeInfo;
Expand Down
22 changes: 22 additions & 0 deletions sdk-libs/program-test/src/indexer/test_indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2222,6 +2222,28 @@ impl TestIndexer {
addresses,
)
.await?;

// Validate that we're not mixing v1 and v2 tree versions
match (inclusion_payload.is_some(), non_inclusion_payload.is_some()) {
(true, true) | (false, false) => {
// Both v2 or both v1 - OK, proceed
}
(false, true) => {
// v1 state trees (height 26) with v2 address trees (height 40)
return Err(IndexerError::MixedTreeVersions {
state_version: "v1 (state tree height 26)".to_string(),
address_version: "v2 (address tree height 40)".to_string(),
});
}
(true, false) => {
// v2 state trees with v1 address trees (height 26)
return Err(IndexerError::MixedTreeVersions {
state_version: "v2 (state tree)".to_string(),
address_version: "v1 (address tree height 26)".to_string(),
});
}
}

let json_payload = if let Some(non_inclusion_payload) =
non_inclusion_payload
{
Expand Down
13 changes: 13 additions & 0 deletions sdk-libs/program-test/src/program_test/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,19 @@ impl Rpc for LightProgramTest {
}
}

/// Gets a random v1 state tree.
/// State trees are cached and have to be fetched or set.
fn get_random_state_tree_info_v1(&self) -> Result<TreeInfo, RpcError> {
use rand::Rng;
let mut rng = rand::thread_rng();
if self.test_accounts.v1_state_trees.is_empty() {
return Err(RpcError::NoStateTreesAvailable);
}
Ok(self.test_accounts.v1_state_trees
[rng.gen_range(0..self.test_accounts.v1_state_trees.len())]
.into())
}

fn get_address_tree_v1(&self) -> TreeInfo {
TreeInfo {
tree: pubkey!("amt1Ayt45jfbdw5YSo7iz6WZxUmnZsQTYXy82hVwyC2"),
Expand Down
2 changes: 1 addition & 1 deletion sdk-libs/sdk-pinocchio/src/cpi/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub trait LightCpiInstruction: Sized {
#[cfg(feature = "light-account")]
fn with_light_account<A>(
self,
account: crate::LightAccount<'_, A>,
account: crate::LightAccount<A>,
) -> Result<Self, pinocchio::program_error::ProgramError>
where
A: borsh::BorshSerialize
Expand Down
2 changes: 1 addition & 1 deletion sdk-libs/sdk-pinocchio/src/cpi/v1/invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl LightCpiInstruction for LightSystemProgramCpi {
#[cfg(feature = "light-account")]
fn with_light_account<A>(
mut self,
account: crate::LightAccount<'_, A>,
account: crate::LightAccount<A>,
) -> Result<Self, pinocchio::program_error::ProgramError>
where
A: crate::BorshSerialize
Expand Down
4 changes: 2 additions & 2 deletions sdk-libs/sdk-pinocchio/src/cpi/v2/invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl LightCpiInstruction for InstructionDataInvokeCpiWithReadOnly {
#[cfg(feature = "light-account")]
fn with_light_account<A>(
mut self,
account: crate::LightAccount<'_, A>,
account: crate::LightAccount<A>,
) -> Result<Self, pinocchio::program_error::ProgramError>
where
A: crate::BorshSerialize
Expand Down Expand Up @@ -98,7 +98,7 @@ impl LightCpiInstruction for InstructionDataInvokeCpiWithAccountInfo {
#[cfg(feature = "light-account")]
fn with_light_account<A>(
mut self,
account: crate::LightAccount<'_, A>,
account: crate::LightAccount<A>,
) -> Result<Self, pinocchio::program_error::ProgramError>
where
A: crate::BorshSerialize
Expand Down
2 changes: 2 additions & 0 deletions sdk-libs/sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ v2 = ["light-sdk-types/v2"]
cpi-context = ["light-sdk-types/cpi-context"]
devnet = []
poseidon = ["light-hasher/poseidon", "light-compressed-account/poseidon"]
keccak = ["light-hasher/keccak", "light-compressed-account/keccak"]
sha256 = ["light-hasher/sha256", "light-compressed-account/sha256"]
merkle-tree = ["light-concurrent-merkle-tree/solana"]


Expand Down
Loading
Loading