From 4950c1277cc3651c4c8bf73b70488d51e9e528a9 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Thu, 5 Mar 2026 17:25:53 +0200 Subject: [PATCH] fix: suggestions fix --- integration_tests/tests/keys_restoration.rs | 93 ++++++++- integration_tests/tests/token.rs | 15 -- key_protocol/Cargo.toml | 2 + key_protocol/src/key_management/mod.rs | 199 ++------------------ 4 files changed, 112 insertions(+), 197 deletions(-) diff --git a/integration_tests/tests/keys_restoration.rs b/integration_tests/tests/keys_restoration.rs index 24299a56..1bd207be 100644 --- a/integration_tests/tests/keys_restoration.rs +++ b/integration_tests/tests/keys_restoration.rs @@ -1,9 +1,9 @@ use std::{str::FromStr, time::Duration}; -use anyhow::Result; +use anyhow::{Context, Result}; use integration_tests::{ - TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, format_private_account_id, - format_public_account_id, verify_commitment_is_in_state, + TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, fetch_privacy_preserving_tx, + format_private_account_id, format_public_account_id, verify_commitment_is_in_state, }; use key_protocol::key_management::key_tree::chain_index::ChainIndex; use log::info; @@ -15,6 +15,93 @@ use wallet::cli::{ programs::native_token_transfer::AuthTransferSubcommand, }; +#[test] +async fn sync_private_account_with_non_zero_chain_index() -> Result<()> { + let mut ctx = TestContext::new().await?; + + let from: AccountId = ctx.existing_private_accounts()[0]; + + // Create a new private account + let command = Command::Account(AccountSubcommand::New(NewSubcommand::Private { + cci: None, + label: None, + })); + + for _ in 0..3 { + // Key Tree shift + // This way we have account with child index > 0. + let result = wallet::cli::execute_subcommand( + ctx.wallet_mut(), + Command::Account(AccountSubcommand::New(NewSubcommand::Private { + cci: None, + label: None, + })), + ) + .await?; + let SubcommandReturnValue::RegisterAccount { account_id: _ } = result else { + anyhow::bail!("Expected RegisterAccount return value"); + }; + } + + let sub_ret = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; + let SubcommandReturnValue::RegisterAccount { + account_id: to_account_id, + } = sub_ret + else { + anyhow::bail!("Expected RegisterAccount return value"); + }; + + // Get the keys for the newly created account + let (to_keys, _) = ctx + .wallet() + .storage() + .user_data + .get_private_account(to_account_id) + .cloned() + .context("Failed to get private account")?; + + // Send to this account using claiming path (using npk and vpk instead of account ID) + let command = Command::AuthTransfer(AuthTransferSubcommand::Send { + from: format_private_account_id(from), + to: None, + to_npk: Some(hex::encode(to_keys.nullifer_public_key.0)), + to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)), + amount: 100, + }); + + let sub_ret = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; + let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = sub_ret else { + anyhow::bail!("Expected PrivacyPreservingTransfer return value"); + }; + + let tx = fetch_privacy_preserving_tx(ctx.sequencer_client(), tx_hash).await; + + // Sync the wallet to claim the new account + let command = Command::Account(AccountSubcommand::SyncPrivate {}); + wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; + + let new_commitment1 = ctx + .wallet() + .get_private_account_commitment(from) + .context("Failed to get private account commitment for sender")?; + assert_eq!(tx.message.new_commitments[0], new_commitment1); + + assert_eq!(tx.message.new_commitments.len(), 2); + for commitment in tx.message.new_commitments.into_iter() { + assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await); + } + + let to_res_acc = ctx + .wallet() + .get_account_private(to_account_id) + .context("Failed to get recipient's private account")?; + assert_eq!(to_res_acc.balance, 100); + + info!("Successfully transferred using claiming path"); + + Ok(()) +} + #[test] async fn restore_keys_from_seed() -> Result<()> { let mut ctx = TestContext::new().await?; diff --git a/integration_tests/tests/token.rs b/integration_tests/tests/token.rs index bcd63556..0ff6eee5 100644 --- a/integration_tests/tests/token.rs +++ b/integration_tests/tests/token.rs @@ -1087,21 +1087,6 @@ async fn token_claiming_path_with_private_accounts() -> Result<()> { info!("Waiting for next block creation"); tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; - // Key Tree shift - // This way we have account with child index > 0. - // Shared secret derivation dependant of child index, so this way we can test it as well. - let result = wallet::cli::execute_subcommand( - ctx.wallet_mut(), - Command::Account(AccountSubcommand::New(NewSubcommand::Private { - cci: None, - label: None, - })), - ) - .await?; - let SubcommandReturnValue::RegisterAccount { account_id: _ } = result else { - anyhow::bail!("Expected RegisterAccount return value"); - }; - // Create new private account for claiming path let result = wallet::cli::execute_subcommand( ctx.wallet_mut(), diff --git a/key_protocol/Cargo.toml b/key_protocol/Cargo.toml index c45671aa..0f16e21b 100644 --- a/key_protocol/Cargo.toml +++ b/key_protocol/Cargo.toml @@ -23,4 +23,6 @@ bip39.workspace = true hmac-sha512.workspace = true thiserror.workspace = true itertools.workspace = true + +[dev-dependencies] serde_json.workspace = true diff --git a/key_protocol/src/key_management/mod.rs b/key_protocol/src/key_management/mod.rs index b99e437d..6e2891ce 100644 --- a/key_protocol/src/key_management/mod.rs +++ b/key_protocol/src/key_management/mod.rs @@ -79,7 +79,9 @@ mod tests { use rand::RngCore; use super::*; - use crate::key_management::ephemeral_key_holder::EphemeralKeyHolder; + use crate::key_management::{ + ephemeral_key_holder::EphemeralKeyHolder, key_tree::KeyTreePrivate, + }; #[test] fn test_new_os_random() { @@ -154,185 +156,24 @@ mod tests { } fn account_with_chain_index_2_for_tests() -> KeyChain { - let key_chain_raw = r#" - { - "secret_spending_key": [ - 208, - 155, - 82, - 128, - 101, - 206, - 20, - 95, - 241, - 147, - 159, - 231, - 207, - 78, - 152, - 28, - 114, - 111, - 61, - 69, - 254, - 51, - 242, - 28, - 28, - 195, - 170, - 242, - 160, - 24, - 47, - 189 - ], - "private_key_holder": { - "nullifier_secret_key": [ - 142, - 76, - 154, - 157, - 42, - 40, - 174, - 199, - 151, - 63, - 2, - 216, - 52, - 103, - 81, - 42, - 200, - 177, - 189, - 49, - 81, - 39, - 166, - 139, - 203, - 154, - 156, - 166, - 88, - 159, - 11, - 151 - ], - "viewing_secret_key": [ - 122, - 94, - 159, - 21, - 28, - 49, - 169, - 79, - 12, - 156, - 171, - 90, - 41, - 216, - 203, - 75, - 251, - 192, - 204, - 217, - 18, - 49, - 28, - 219, - 213, - 147, - 244, - 194, - 205, - 237, - 134, - 36 - ] - }, - "nullifer_public_key": [ - 235, - 24, - 62, - 99, - 243, - 236, - 137, - 35, - 153, - 149, - 6, - 10, - 118, - 239, - 117, - 188, - 64, - 8, - 33, - 52, - 220, - 231, - 11, - 39, - 180, - 117, - 1, - 22, - 62, - 199, - 164, - 169 - ], - "viewing_public_key": [ - 2, - 253, - 204, - 5, - 212, - 86, - 249, - 156, - 132, - 143, - 1, - 172, - 80, - 61, - 18, - 185, - 233, - 36, - 221, - 58, - 64, - 110, - 89, - 242, - 202, - 230, - 154, - 66, - 45, - 252, - 138, - 174, - 37 - ] - } - "#; + let seed = SeedHolder::new_os_random(); + let mut key_tree_private = KeyTreePrivate::new(&seed); - serde_json::from_str(key_chain_raw).unwrap() + // /0 + key_tree_private.generate_new_node_layered().unwrap(); + // /1 + key_tree_private.generate_new_node_layered().unwrap(); + // /0/0 + key_tree_private.generate_new_node_layered().unwrap(); + // /2 + let (second_child_id, _) = key_tree_private.generate_new_node_layered().unwrap(); + + key_tree_private + .get_node(second_child_id) + .unwrap() + .value + .0 + .clone() } #[test]