Skip to content

Commit f3d16e9

Browse files
committed
test: correct root
1 parent 77609d0 commit f3d16e9

3 files changed

Lines changed: 114 additions & 58 deletions

File tree

src/api/method/get_transaction_with_compression_info.rs

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use super::{
44
use crate::api::method::utils::parse_account_model_with_context;
55
use crate::common::typedefs::account::AccountV2;
66
use crate::common::typedefs::account::AccountWithContext;
7+
use crate::common::typedefs::hash::Hash;
78
use crate::common::typedefs::token_data::TokenData;
89
use crate::common::typedefs::{account::Account, serializable_signature::SerializableSignature};
910
use crate::dao::generated::accounts::Model;
@@ -99,11 +100,19 @@ pub struct AccountWithOptionalTokenDataV2 {
99100
pub optionalTokenData: Option<TokenData>,
100101
}
101102

103+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, ToSchema)]
104+
#[serde(deny_unknown_fields, rename_all = "camelCase")]
105+
#[allow(non_snake_case)]
106+
pub struct ClosedAccountWithOptionalTokenData {
107+
pub account: ClosedAccount,
108+
pub optionalTokenData: Option<TokenData>,
109+
}
110+
102111
#[derive(Debug, Clone, PartialEq, Eq, Serialize, ToSchema)]
103112
#[serde(deny_unknown_fields, rename_all = "camelCase")]
104113
#[allow(non_snake_case)]
105114
pub struct CompressionInfoV2 {
106-
pub closedAccounts: Vec<AccountWithOptionalTokenDataV2>,
115+
pub closedAccounts: Vec<ClosedAccountWithOptionalTokenData>,
107116
pub openedAccounts: Vec<AccountWithOptionalTokenDataV2>,
108117
}
109118

@@ -245,6 +254,30 @@ fn parse_optional_token_data_v2(
245254
})
246255
}
247256

257+
fn parse_optional_token_data_for_multiple_accounts_closed_account(
258+
accounts: Vec<ClosedAccount>,
259+
) -> Result<Vec<ClosedAccountWithOptionalTokenData>, PhotonApiError> {
260+
accounts
261+
.into_iter()
262+
.map(parse_optional_token_data_closed_account)
263+
.collect()
264+
}
265+
266+
fn parse_optional_token_data_closed_account(
267+
account: ClosedAccount,
268+
) -> Result<ClosedAccountWithOptionalTokenData, PhotonApiError> {
269+
let hash = account.account.hash.clone();
270+
Ok(ClosedAccountWithOptionalTokenData {
271+
optionalTokenData: parse_token_data_v2(&account.account).map_err(|e| {
272+
PhotonApiError::UnexpectedError(format!(
273+
"Failed to parse token data for account {}: {}",
274+
hash, e
275+
))
276+
})?,
277+
account,
278+
})
279+
}
280+
248281
fn parse_optional_token_data_for_multiple_accounts_v2(
249282
accounts: Vec<AccountV2>,
250283
) -> Result<Vec<AccountWithOptionalTokenDataV2>, PhotonApiError> {
@@ -254,6 +287,14 @@ fn parse_optional_token_data_for_multiple_accounts_v2(
254287
.collect()
255288
}
256289

290+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, ToSchema, Default)]
291+
#[serde(deny_unknown_fields, rename_all = "camelCase")]
292+
pub struct ClosedAccount {
293+
pub account: AccountV2,
294+
pub nullifier: Hash,
295+
pub tx_hash: Hash,
296+
}
297+
257298
pub async fn get_transaction_helper_v2(
258299
conn: &DatabaseConnection,
259300
signature: SerializableSignature,
@@ -297,21 +338,32 @@ pub async fn get_transaction_helper_v2(
297338

298339
println!("closed_accounts: {:?}", closed_accounts);
299340

300-
let closed_accounts = closed_accounts
301-
.into_iter()
302-
.map(|x| AccountV2 {
303-
hash: x.account.hash,
304-
address: x.account.address,
305-
data: x.account.data,
306-
owner: x.account.owner,
307-
lamports: x.account.lamports,
308-
tree: x.account.tree,
309-
leaf_index: x.account.leaf_index,
310-
seq: x.account.seq,
311-
slot_created: x.account.slot_created,
312-
queue: x.context.queue,
313-
})
314-
.collect::<Vec<AccountV2>>();
341+
let closed_accounts =
342+
closed_accounts
343+
.into_iter()
344+
.map(|x| -> Result<ClosedAccount, PhotonApiError> {
345+
Ok(ClosedAccount {
346+
account: AccountV2 {
347+
hash: x.account.hash,
348+
address: x.account.address,
349+
data: x.account.data,
350+
owner: x.account.owner,
351+
lamports: x.account.lamports,
352+
tree: x.account.tree,
353+
leaf_index: x.account.leaf_index,
354+
seq: x.account.seq,
355+
slot_created: x.account.slot_created,
356+
queue: x.context.queue,
357+
},
358+
nullifier: x.context.nullifier.ok_or(PhotonApiError::UnexpectedError(
359+
String::from("Nullifier does not exist for closed account."),
360+
))?,
361+
tx_hash: x.context.tx_hash.ok_or(PhotonApiError::UnexpectedError(
362+
String::from("Nullifier does not exist for closed account."),
363+
))?,
364+
})
365+
})
366+
.collect::<Result<Vec<ClosedAccount>, PhotonApiError>>()?;
315367

316368
let out_accounts = status_update
317369
.out_accounts
@@ -333,7 +385,9 @@ pub async fn get_transaction_helper_v2(
333385
Ok(GetTransactionResponseV2 {
334386
transaction: txn,
335387
compressionInfo: CompressionInfoV2 {
336-
closedAccounts: parse_optional_token_data_for_multiple_accounts_v2(closed_accounts)?,
388+
closedAccounts: parse_optional_token_data_for_multiple_accounts_closed_account(
389+
closed_accounts,
390+
)?,
337391
openedAccounts: parse_optional_token_data_for_multiple_accounts_v2(out_accounts)?,
338392
},
339393
})

tests/integration_tests/batched_state_tree_test.rs renamed to tests/integration_tests/batched_state_tree_tests.rs

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use photon_indexer::api::method::get_compressed_token_balances_by_owner::{
77
GetCompressedTokenBalancesByOwnerRequest, TokenBalance,
88
};
99
use photon_indexer::api::method::get_multiple_compressed_account_proofs::HashList;
10-
use photon_indexer::api::method::get_transaction_with_compression_info::get_transaction_helper;
10+
use photon_indexer::api::method::get_transaction_with_compression_info::{
11+
get_transaction_helper, get_transaction_helper_v2,
12+
};
1113
use photon_indexer::api::method::utils::GetCompressedTokenAccountsByOwner;
1214
use photon_indexer::common::typedefs::serializable_pubkey::SerializablePubkey;
1315
use photon_indexer::common::typedefs::serializable_signature::SerializableSignature;
@@ -26,6 +28,10 @@ use solana_transaction_status::EncodedConfirmedTransactionWithStatusMeta;
2628
use std::str::FromStr;
2729
use std::sync::Arc;
2830

31+
/// Test:
32+
/// 1. get compressed account by owner
33+
/// 2. get compressed account proofs
34+
/// 3. correct root update after batch append and batch nullify events
2935
#[named]
3036
#[rstest]
3137
#[tokio::test]
@@ -69,7 +75,7 @@ async fn test_batched_tree_transactions(
6975

7076
// use get_transaction_helper because get_transaction_with_compression_info requires an rpc endpoint.
7177
// It fetches the instruction and parses the data.
72-
let accounts = get_transaction_helper(
78+
let accounts = get_transaction_helper_v2(
7379
&setup.db_conn,
7480
SerializableSignature(Signature::from_str(signature).unwrap()),
7581
transaction,
@@ -78,28 +84,23 @@ async fn test_batched_tree_transactions(
7884
.unwrap()
7985
.compressionInfo;
8086
for account in accounts.closedAccounts.iter() {
81-
// let full_account = setup
82-
// .api
83-
// .get_compressed_accounts_by_owner_v2(GetCompressedAccountsByOwnerRequest {
84-
// owner: account.account.owner,
85-
// ..Default::default()
86-
// })
87-
// .await
88-
// .unwrap();
89-
// merkle_tree
90-
// .update(
91-
// &full_account.value.items[0]
92-
// .context
93-
// .nullifier
94-
// .as_ref()
95-
// .unwrap()
96-
// .0,
97-
// account.account.leaf_index.0 as usize,
98-
// )
99-
// .unwrap();
87+
merkle_tree
88+
.update(
89+
&account.account.nullifier.0,
90+
account.account.account.leaf_index.0 as usize,
91+
)
92+
.unwrap();
10093
}
10194
for account in accounts.openedAccounts.iter() {
102-
merkle_tree.append(&account.account.hash.0).unwrap();
95+
while merkle_tree.rightmost_index <= account.account.leaf_index.0 as usize + 2 {
96+
merkle_tree.append(&[0u8; 32]).unwrap();
97+
}
98+
merkle_tree
99+
.update(
100+
&account.account.hash.0,
101+
account.account.leaf_index.0 as usize,
102+
)
103+
.unwrap();
103104
}
104105
}
105106

@@ -124,13 +125,12 @@ async fn test_batched_tree_transactions(
124125
})
125126
.await
126127
.unwrap();
127-
println!("accounts {:?}", accounts);
128128
assert_eq!(accounts.value.items.len(), 1);
129129
let account = &accounts.value.items[0];
130-
assert_eq!(account.account.lamports.0, 1_000_000u64);
131-
assert_eq!(account.account.owner.0, owner);
130+
assert_eq!(account.lamports.0, 1_000_000u64);
131+
assert_eq!(account.owner.0, owner);
132132
assert_eq!(
133-
account.account.leaf_index.0,
133+
account.leaf_index.0,
134134
leaf_index,
135135
"owner {:?} i {}",
136136
owner.to_bytes(),
@@ -143,23 +143,25 @@ async fn test_batched_tree_transactions(
143143
.to_vec();
144144
let merkle_proof = setup
145145
.api
146-
.get_multiple_compressed_account_proofs(HashList(vec![account
147-
.account
148-
.hash
149-
.clone()]))
146+
.get_multiple_compressed_account_proofs(HashList(vec![account.hash.clone()]))
150147
.await
151148
.unwrap();
149+
assert_eq!(merkle_proof.value[0].hash.0, account.hash.0,);
150+
assert_eq!(
151+
merkle_proof.value[0].hash.0,
152+
merkle_tree.leaf(leaf_index as usize)
153+
);
154+
assert_eq!(account.hash.0, merkle_tree.leaf(leaf_index as usize));
152155
assert_eq!(merkle_proof.value.len(), 1);
153-
// TODO: enable when nullifiers are correctly inserted into the reference tree.
154-
// assert_eq!(merkle_proof.value[0].root.0, merkle_tree.root());
155-
// assert_eq!(
156-
// merkle_proof.value[0]
157-
// .proof
158-
// .iter()
159-
// .map(|x| x.0)
160-
// .collect::<Vec<[u8; 32]>>(),
161-
// reference_merkle_proof
162-
// );
156+
assert_eq!(merkle_proof.value[0].root.0, merkle_tree.root());
157+
assert_eq!(
158+
merkle_proof.value[0]
159+
.proof
160+
.iter()
161+
.map(|x| x.0)
162+
.collect::<Vec<[u8; 32]>>(),
163+
reference_merkle_proof
164+
);
163165
leaf_index += 2;
164166
}
165167
}

tests/integration_tests/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// binary. This has a number of benefits:
33
// 1. Faster compile time since we only have 1 binary.
44
// 2. The ability to add global locks on the DB to prevent tests from interfering with each other.
5-
mod batched_state_tree_test;
5+
mod batched_state_tree_tests;
66
mod e2e_tests;
77
mod mock_tests;
88
mod open_api_tests;

0 commit comments

Comments
 (0)