Merge pull request #246 from logos-blockchain/marvin/private_keys

private key protocol fixes
This commit is contained in:
jonesmarvin8 2026-02-16 21:00:53 -05:00 committed by GitHub
commit 8cf73c00a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
58 changed files with 1300 additions and 1401 deletions

View File

@ -92,7 +92,7 @@ wallet account new private
# Output:
Generated new account with account_id Private/HMRHZdPw4pbyPVZHNGrV6K5AA95wACFsHTRST84fr3CF
With npk 6a2dfe433cf28e525aa0196d719be3c16146f7ee358ca39595323f94fde38f93
With ipk 03d59abf4bee974cc12ddb44641c19f0b5441fef39191f047c988c29a77252a577
With vpk 03d59abf4bee974cc12ddb44641c19f0b5441fef39191f047c988c29a77252a577
```
2. Create the token (Token B):

View File

@ -154,11 +154,11 @@ wallet account new private
# Output:
Generated new account with account_id Private/HacPU3hakLYzWtSqUPw6TUr8fqoMieVWovsUR6sJf7cL
With npk e6366f79d026c8bd64ae6b3d601f0506832ec682ab54897f205fffe64ec0d951
With ipk 02ddc96d0eb56e00ce14994cfdaec5ae1f76244180a919545983156e3519940a17
With vpk 02ddc96d0eb56e00ce14994cfdaec5ae1f76244180a919545983156e3519940a17
```
> [!Tip]
> Focus on the account ID for now. The `npk` and `ipk` values are stored locally and used to build privacy-preserving transactions. The private account ID is derived from `npk`.
> Focus on the account ID for now. The `npk` and `vpk` values are stored locally and used to build privacy-preserving transactions. The private account ID is derived from `npk`.
Just like public accounts, new private accounts start out uninitialized:
@ -228,17 +228,17 @@ wallet account new private
# Output:
Generated new account with account_id Private/AukXPRBmrYVqoqEW2HTs7N3hvTn3qdNFDcxDHVr5hMm5
With npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e
With ipk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72
With vpk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72
```
> [!Tip]
> Ignore the private account ID here and use the `npk` and `ipk` values to send to a foreign private account.
> Ignore the private account ID here and use the `npk` and `vpk` values to send to a foreign private account.
```bash
wallet auth-transfer send \
--from Public/Ev1JprP9BmhbFVQyBcbznU8bAXcwrzwRoPTetXdQPAWS \
--to-npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e \
--to-ipk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72 \
--to-vpk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72 \
--amount 3
```

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -97,7 +97,7 @@ _wallet_auth_transfer() {
'--from[Source account ID]:from_account:_wallet_account_ids' \
'--to[Destination account ID (for owned accounts)]:to_account:_wallet_account_ids' \
'--to-npk[Destination nullifier public key (for foreign private accounts)]:npk:' \
'--to-ipk[Destination viewing public key (for foreign private accounts)]:ipk:' \
'--to-vpk[Destination viewing public key (for foreign private accounts)]:vpk:' \
'--amount[Amount of native tokens to send]:amount:'
;;
esac
@ -164,7 +164,7 @@ _wallet_account() {
get)
_arguments \
'(-r --raw)'{-r,--raw}'[Get raw account data]' \
'(-k --keys)'{-k,--keys}'[Display keys (pk for public accounts, npk/ipk for private accounts)]' \
'(-k --keys)'{-k,--keys}'[Display keys (pk for public accounts, npk/vpk for private accounts)]' \
'(-a --account-id)'{-a,--account-id}'[Account ID to query]:account_id:_wallet_account_ids'
;;
list|ls)
@ -255,7 +255,7 @@ _wallet_token() {
'--from[Source holding account ID]:from_account:_wallet_account_ids' \
'--to[Destination holding account ID (for owned accounts)]:to_account:_wallet_account_ids' \
'--to-npk[Destination nullifier public key (for foreign private accounts)]:npk:' \
'--to-ipk[Destination viewing public key (for foreign private accounts)]:ipk:' \
'--to-vpk[Destination viewing public key (for foreign private accounts)]:vpk:' \
'--amount[Amount of tokens to send]:amount:'
;;
burn)
@ -269,7 +269,7 @@ _wallet_token() {
'--definition[Definition account ID]:definition_account:_wallet_account_ids' \
'--holder[Holder account ID (for owned accounts)]:holder_account:_wallet_account_ids' \
'--holder-npk[Holder nullifier public key (for foreign private accounts)]:npk:' \
'--holder-ipk[Holder viewing public key (for foreign private accounts)]:ipk:' \
'--holder-vpk[Holder viewing public key (for foreign private accounts)]:vpk:' \
'--amount[Amount of tokens to mint]:amount:'
;;
esac

View File

@ -29,40 +29,7 @@
],
"initial_commitments": [
{
"npk": [
63,
202,
178,
231,
183,
82,
237,
212,
216,
221,
215,
255,
153,
101,
177,
161,
254,
210,
128,
122,
54,
190,
230,
151,
183,
64,
225,
229,
113,
1,
228,
97
],
"npk": [13, 25, 40, 5, 198, 248, 210, 248, 237, 121, 124, 145, 186, 142, 253, 216, 236, 69, 193, 32, 166, 167, 49, 133, 172, 111, 159, 46, 84, 17, 157, 23],
"account": {
"program_owner": [
0,
@ -80,40 +47,7 @@
}
},
{
"npk": [
192,
251,
166,
243,
167,
236,
84,
249,
35,
136,
130,
172,
219,
225,
161,
139,
229,
89,
243,
125,
194,
213,
209,
30,
23,
174,
100,
244,
124,
74,
140,
47
],
"npk": [32, 67, 72, 164, 106, 53, 66, 239, 141, 15, 52, 230, 136, 177, 2, 236, 207, 243, 134, 135, 210, 143, 87, 232, 215, 128, 194, 120, 113, 224, 4, 165],
"account": {
"program_owner": [
0,

View File

@ -102,7 +102,7 @@ async fn amm_public() -> Result<()> {
from: format_public_account_id(supply_account_id_1),
to: Some(format_public_account_id(recipient_account_id_1)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 7,
};
@ -126,7 +126,7 @@ async fn amm_public() -> Result<()> {
from: format_public_account_id(supply_account_id_2),
to: Some(format_public_account_id(recipient_account_id_2)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 7,
};

View File

@ -26,7 +26,7 @@ async fn private_transfer_to_owned_account() -> Result<()> {
from: format_private_account_id(from),
to: Some(format_private_account_id(to)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 100,
});
@ -59,13 +59,13 @@ async fn private_transfer_to_foreign_account() -> Result<()> {
let from: AccountId = ctx.existing_private_accounts()[0];
let to_npk = NullifierPublicKey([42; 32]);
let to_npk_string = hex::encode(to_npk.0);
let to_ipk = Secp256k1Point::from_scalar(to_npk.0);
let to_vpk = Secp256k1Point::from_scalar(to_npk.0);
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
from: format_private_account_id(from),
to: None,
to_npk: Some(to_npk_string),
to_ipk: Some(hex::encode(to_ipk.0)),
to_vpk: Some(hex::encode(to_vpk.0)),
amount: 100,
});
@ -113,7 +113,7 @@ async fn deshielded_transfer_to_public_account() -> Result<()> {
from: format_private_account_id(from),
to: Some(format_public_account_id(to)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 100,
});
@ -168,12 +168,12 @@ async fn private_transfer_to_owned_account_using_claiming_path() -> Result<()> {
.cloned()
.context("Failed to get private account")?;
// Send to this account using claiming path (using npk and ipk instead of account ID)
// 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_ipk: Some(hex::encode(to_keys.incoming_viewing_public_key.0)),
to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)),
amount: 100,
});
@ -221,7 +221,7 @@ async fn shielded_transfer_to_owned_private_account() -> Result<()> {
from: format_public_account_id(from),
to: Some(format_private_account_id(to)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 100,
});
@ -256,14 +256,14 @@ async fn shielded_transfer_to_foreign_account() -> Result<()> {
let to_npk = NullifierPublicKey([42; 32]);
let to_npk_string = hex::encode(to_npk.0);
let to_ipk = Secp256k1Point::from_scalar(to_npk.0);
let to_vpk = Secp256k1Point::from_scalar(to_npk.0);
let from: AccountId = ctx.existing_public_accounts()[0];
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
from: format_public_account_id(from),
to: None,
to_npk: Some(to_npk_string),
to_ipk: Some(hex::encode(to_ipk.0)),
to_vpk: Some(hex::encode(to_vpk.0)),
amount: 100,
});
@ -325,12 +325,12 @@ async fn private_transfer_to_owned_account_continuous_run_path() -> Result<()> {
.cloned()
.context("Failed to get private account")?;
// Send transfer using nullifier and incoming viewing public keys
// Send transfer using nullifier and viewing public keys
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_ipk: Some(hex::encode(to_keys.incoming_viewing_public_key.0)),
to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)),
amount: 100,
});

View File

@ -19,7 +19,7 @@ async fn successful_transfer_to_existing_account() -> Result<()> {
from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 100,
});
@ -72,7 +72,7 @@ pub async fn successful_transfer_to_new_account() -> Result<()> {
from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(new_persistent_account_id)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 100,
});
@ -108,7 +108,7 @@ async fn failed_transfer_with_insufficient_balance() -> Result<()> {
from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 1000000,
});
@ -146,7 +146,7 @@ async fn two_consecutive_successful_transfers() -> Result<()> {
from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 100,
});
@ -178,7 +178,7 @@ async fn two_consecutive_successful_transfers() -> Result<()> {
from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 100,
});

View File

@ -50,7 +50,7 @@ async fn restore_keys_from_seed() -> Result<()> {
from: format_private_account_id(from),
to: Some(format_private_account_id(to_account_id1)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 100,
});
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -60,7 +60,7 @@ async fn restore_keys_from_seed() -> Result<()> {
from: format_private_account_id(from),
to: Some(format_private_account_id(to_account_id2)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 101,
});
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -96,7 +96,7 @@ async fn restore_keys_from_seed() -> Result<()> {
from: format_public_account_id(from),
to: Some(format_public_account_id(to_account_id3)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 102,
});
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -106,7 +106,7 @@ async fn restore_keys_from_seed() -> Result<()> {
from: format_public_account_id(from),
to: Some(format_public_account_id(to_account_id4)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 103,
});
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -169,7 +169,7 @@ async fn restore_keys_from_seed() -> Result<()> {
from: format_private_account_id(to_account_id1),
to: Some(format_private_account_id(to_account_id2)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 10,
});
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -178,7 +178,7 @@ async fn restore_keys_from_seed() -> Result<()> {
from: format_public_account_id(to_account_id3),
to: Some(format_public_account_id(to_account_id4)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: 11,
});
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;

View File

@ -115,7 +115,7 @@ async fn create_and_transfer_public_token() -> Result<()> {
from: format_public_account_id(supply_account_id),
to: Some(format_public_account_id(recipient_account_id)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -208,7 +208,7 @@ async fn create_and_transfer_public_token() -> Result<()> {
definition: format_public_account_id(definition_account_id),
holder: Some(format_public_account_id(recipient_account_id)),
holder_npk: None,
holder_ipk: None,
holder_vpk: None,
amount: mint_amount,
};
@ -343,7 +343,7 @@ async fn create_and_transfer_token_with_private_supply() -> Result<()> {
from: format_private_account_id(supply_account_id),
to: Some(format_private_account_id(recipient_account_id)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -525,7 +525,7 @@ async fn create_token_with_private_definition() -> Result<()> {
definition: format_private_account_id(definition_account_id),
holder: Some(format_public_account_id(recipient_account_id_public)),
holder_npk: None,
holder_ipk: None,
holder_vpk: None,
amount: mint_amount_public,
};
@ -572,7 +572,7 @@ async fn create_token_with_private_definition() -> Result<()> {
definition: format_private_account_id(definition_account_id),
holder: Some(format_private_account_id(recipient_account_id_private)),
holder_npk: None,
holder_ipk: None,
holder_vpk: None,
amount: mint_amount_private,
};
@ -701,7 +701,7 @@ async fn create_token_with_private_definition_and_supply() -> Result<()> {
from: format_private_account_id(supply_account_id),
to: Some(format_private_account_id(recipient_account_id)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -819,7 +819,7 @@ async fn shielded_token_transfer() -> Result<()> {
from: format_public_account_id(supply_account_id),
to: Some(format_private_account_id(recipient_account_id)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -933,7 +933,7 @@ async fn deshielded_token_transfer() -> Result<()> {
from: format_private_account_id(supply_account_id),
to: Some(format_public_account_id(recipient_account_id)),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -1056,7 +1056,7 @@ async fn token_claiming_path_with_private_accounts() -> Result<()> {
definition: format_private_account_id(definition_account_id),
holder: None,
holder_npk: Some(hex::encode(holder_keys.nullifer_public_key.0)),
holder_ipk: Some(hex::encode(holder_keys.incoming_viewing_public_key.0)),
holder_vpk: Some(hex::encode(holder_keys.viewing_public_key.0)),
amount: mint_amount,
};

View File

@ -16,7 +16,7 @@ use nssa::{
use nssa_core::{
MembershipProof, NullifierPublicKey,
account::{AccountWithMetadata, data::Data},
encryption::IncomingViewingPublicKey,
encryption::ViewingPublicKey,
};
use tokio::test;
@ -192,8 +192,8 @@ impl TpsTestManager {
fn build_privacy_transaction() -> PrivacyPreservingTransaction {
let program = Program::authenticated_transfer_program();
let sender_nsk = [1; 32];
let sender_isk = [99; 32];
let sender_ipk = IncomingViewingPublicKey::from_scalar(sender_isk);
let sender_vsk = [99; 32];
let sender_vpk = ViewingPublicKey::from_scalar(sender_vsk);
let sender_npk = NullifierPublicKey::from(&sender_nsk);
let sender_pre = AccountWithMetadata::new(
Account {
@ -206,18 +206,18 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
AccountId::from(&sender_npk),
);
let recipient_nsk = [2; 32];
let recipient_isk = [99; 32];
let recipient_ipk = IncomingViewingPublicKey::from_scalar(recipient_isk);
let recipient_vsk = [99; 32];
let recipient_vpk = ViewingPublicKey::from_scalar(recipient_vsk);
let recipient_npk = NullifierPublicKey::from(&recipient_nsk);
let recipient_pre =
AccountWithMetadata::new(Account::default(), false, AccountId::from(&recipient_npk));
let eph_holder_from = EphemeralKeyHolder::new(&sender_npk);
let sender_ss = eph_holder_from.calculate_shared_secret_sender(&sender_ipk);
let sender_ss = eph_holder_from.calculate_shared_secret_sender(&sender_vpk);
let sender_epk = eph_holder_from.generate_ephemeral_public_key();
let eph_holder_to = EphemeralKeyHolder::new(&recipient_npk);
let recipient_ss = eph_holder_to.calculate_shared_secret_sender(&recipient_ipk);
let recipient_ss = eph_holder_to.calculate_shared_secret_sender(&recipient_vpk);
let recipient_epk = eph_holder_from.generate_ephemeral_public_key();
let balance_to_move: u128 = 1;
@ -246,8 +246,8 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
vec![],
vec![],
vec![
(sender_npk, sender_ipk, sender_epk),
(recipient_npk, recipient_ipk, recipient_epk),
(sender_npk, sender_vpk, sender_epk),
(recipient_npk, recipient_vpk, recipient_epk),
],
output,
)

View File

@ -600,10 +600,10 @@ fn test_wallet_ffi_get_private_account_keys() -> Result<()> {
.0;
let expected_npk = &key_chain.nullifer_public_key;
let expected_ivk = &key_chain.incoming_viewing_public_key;
let expected_vpk = &key_chain.viewing_public_key;
assert_eq!(&keys.npk(), expected_npk);
assert_eq!(&keys.ivk().unwrap(), expected_ivk);
assert_eq!(&keys.vpk().unwrap(), expected_vpk);
unsafe {
wallet_ffi_free_private_account_keys((&mut keys) as *mut FfiPrivateAccountKeys);

View File

@ -1,6 +1,6 @@
use nssa_core::{
NullifierPublicKey, SharedSecretKey,
encryption::{EphemeralPublicKey, EphemeralSecretKey, IncomingViewingPublicKey},
encryption::{EphemeralPublicKey, EphemeralSecretKey, ViewingPublicKey},
};
use rand::{RngCore, rngs::OsRng};
use sha2::Digest;
@ -13,12 +13,12 @@ pub struct EphemeralKeyHolder {
}
pub fn produce_one_sided_shared_secret_receiver(
ipk: &IncomingViewingPublicKey,
vpk: &ViewingPublicKey,
) -> (SharedSecretKey, EphemeralPublicKey) {
let mut esk = [0; 32];
OsRng.fill_bytes(&mut esk);
(
SharedSecretKey::new(&esk, ipk),
SharedSecretKey::new(&esk, vpk),
EphemeralPublicKey::from_scalar(esk),
)
}
@ -42,11 +42,8 @@ impl EphemeralKeyHolder {
pub fn calculate_shared_secret_sender(
&self,
receiver_incoming_viewing_public_key: &IncomingViewingPublicKey,
receiver_viewing_public_key: &ViewingPublicKey,
) -> SharedSecretKey {
SharedSecretKey::new(
&self.ephemeral_secret_key,
receiver_incoming_viewing_public_key,
)
SharedSecretKey::new(&self.ephemeral_secret_key, receiver_viewing_public_key)
}
}

View File

@ -1,5 +1,5 @@
use k256::{Scalar, elliptic_curve::PrimeField};
use nssa_core::encryption::IncomingViewingPublicKey;
use nssa_core::{NullifierPublicKey, encryption::ViewingPublicKey};
use serde::{Deserialize, Serialize};
use crate::key_management::{
@ -18,7 +18,7 @@ pub struct ChildKeysPrivate {
impl KeyNode for ChildKeysPrivate {
fn root(seed: [u8; 64]) -> Self {
let hash_value = hmac_sha512::HMAC::mac(seed, "NSSA_master_priv");
let hash_value = hmac_sha512::HMAC::mac(seed, b"LEE_master_priv");
let ssk = SecretSpendingKey(
*hash_value
@ -29,23 +29,21 @@ impl KeyNode for ChildKeysPrivate {
.last_chunk::<32>()
.expect("hash_value is 64 bytes, must be safe to get last 32");
let nsk = ssk.generate_nullifier_secret_key();
let isk = ssk.generate_incoming_viewing_secret_key();
let ovk = ssk.generate_outgoing_viewing_secret_key();
let nsk = ssk.generate_nullifier_secret_key(None);
let vsk = ssk.generate_viewing_secret_key(None);
let npk = (&nsk).into();
let ipk = IncomingViewingPublicKey::from_scalar(isk);
let npk = NullifierPublicKey::from(&nsk);
let vpk = ViewingPublicKey::from_scalar(vsk);
Self {
value: (
KeyChain {
secret_spending_key: ssk,
nullifer_public_key: npk,
incoming_viewing_public_key: ipk,
viewing_public_key: vpk,
private_key_holder: PrivateKeyHolder {
nullifier_secret_key: nsk,
incoming_viewing_secret_key: isk,
outgoing_viewing_secret_key: ovk,
viewing_secret_key: vsk,
},
},
nssa::Account::default(),
@ -56,27 +54,14 @@ impl KeyNode for ChildKeysPrivate {
}
fn nth_child(&self, cci: u32) -> Self {
let parent_pt = Scalar::from_repr(
self.value
.0
.private_key_holder
.outgoing_viewing_secret_key
.into(),
)
.expect("Key generated as scalar, must be valid representation")
+ Scalar::from_repr(self.value.0.private_key_holder.nullifier_secret_key.into())
let parent_pt =
Scalar::from_repr(self.value.0.private_key_holder.nullifier_secret_key.into())
.expect("Key generated as scalar, must be valid representation")
* Scalar::from_repr(
self.value
.0
.private_key_holder
.incoming_viewing_secret_key
.into(),
)
.expect("Key generated as scalar, must be valid representation");
* Scalar::from_repr(self.value.0.private_key_holder.viewing_secret_key.into())
.expect("Key generated as scalar, must be valid representation");
let mut input = vec![];
input.extend_from_slice(b"NSSA_seed_priv");
input.extend_from_slice(b"LEE_seed_priv");
input.extend_from_slice(&parent_pt.to_bytes());
input.extend_from_slice(&cci.to_le_bytes());
@ -91,23 +76,21 @@ impl KeyNode for ChildKeysPrivate {
.last_chunk::<32>()
.expect("hash_value is 64 bytes, must be safe to get last 32");
let nsk = ssk.generate_nullifier_secret_key();
let isk = ssk.generate_incoming_viewing_secret_key();
let ovk = ssk.generate_outgoing_viewing_secret_key();
let nsk = ssk.generate_nullifier_secret_key(Some(cci));
let vsk = ssk.generate_viewing_secret_key(Some(cci));
let npk = (&nsk).into();
let ipk = IncomingViewingPublicKey::from_scalar(isk);
let npk = NullifierPublicKey::from(&nsk);
let vpk = ViewingPublicKey::from_scalar(vsk);
Self {
value: (
KeyChain {
secret_spending_key: ssk,
nullifer_public_key: npk,
incoming_viewing_public_key: ipk,
viewing_public_key: vpk,
private_key_holder: PrivateKeyHolder {
nullifier_secret_key: nsk,
incoming_viewing_secret_key: isk,
outgoing_viewing_secret_key: ovk,
viewing_secret_key: vsk,
},
},
nssa::Account::default(),
@ -144,120 +127,98 @@ impl<'a> From<&'a mut ChildKeysPrivate> for &'a mut (KeyChain, nssa::Account) {
#[cfg(test)]
mod tests {
use nssa_core::{NullifierPublicKey, NullifierSecretKey};
use super::*;
use crate::key_management::{self, secret_holders::ViewingSecretKey};
#[test]
fn test_keys_deterministic_generation() {
let root_keys = ChildKeysPrivate::root([42; 64]);
let child_keys = root_keys.nth_child(5);
fn test_master_key_generation() {
let seed: [u8; 64] = [
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
129, 223, 176, 198, 5, 150, 157, 70, 210, 254, 14, 105, 89, 191, 246, 27, 52, 170, 56,
114, 39, 38, 118, 197, 205, 225,
];
assert_eq!(root_keys.cci, None);
assert_eq!(child_keys.cci, Some(5));
let keys = ChildKeysPrivate::root(seed);
assert_eq!(
root_keys.value.0.secret_spending_key.0,
[
249, 83, 253, 32, 174, 204, 185, 44, 253, 167, 61, 92, 128, 5, 152, 4, 220, 21, 88,
84, 167, 180, 154, 249, 44, 77, 33, 136, 59, 131, 203, 152
]
);
assert_eq!(
child_keys.value.0.secret_spending_key.0,
[
16, 242, 229, 242, 252, 158, 153, 210, 234, 120, 70, 85, 83, 196, 5, 53, 28, 26,
187, 230, 22, 193, 146, 232, 237, 3, 166, 184, 122, 1, 233, 93
]
);
let expected_ssk: SecretSpendingKey = key_management::secret_holders::SecretSpendingKey([
246, 79, 26, 124, 135, 95, 52, 51, 201, 27, 48, 194, 2, 144, 51, 219, 245, 128, 139,
222, 42, 195, 105, 33, 115, 97, 186, 0, 97, 14, 218, 191,
]);
assert_eq!(
root_keys.value.0.private_key_holder.nullifier_secret_key,
[
38, 195, 52, 182, 16, 66, 167, 156, 9, 14, 65, 100, 17, 93, 166, 71, 27, 148, 93,
85, 116, 109, 130, 8, 195, 222, 159, 214, 141, 41, 124, 57
]
);
assert_eq!(
child_keys.value.0.private_key_holder.nullifier_secret_key,
[
215, 46, 2, 151, 174, 60, 86, 154, 5, 3, 175, 245, 12, 176, 220, 58, 250, 118, 236,
49, 254, 221, 229, 58, 40, 1, 170, 145, 175, 108, 23, 170
]
);
let expected_ccc = [
56, 114, 70, 249, 67, 169, 206, 9, 192, 11, 180, 168, 149, 129, 42, 95, 43, 157, 130,
111, 13, 5, 195, 75, 20, 255, 162, 85, 40, 251, 8, 168,
];
assert_eq!(
root_keys
.value
.0
.private_key_holder
.incoming_viewing_secret_key,
[
153, 161, 15, 34, 96, 184, 165, 165, 27, 244, 155, 40, 70, 5, 241, 133, 78, 40, 61,
118, 48, 148, 226, 5, 97, 18, 201, 128, 82, 248, 163, 72
]
);
assert_eq!(
child_keys
.value
.0
.private_key_holder
.incoming_viewing_secret_key,
[
192, 155, 55, 43, 164, 115, 71, 145, 227, 225, 21, 57, 55, 12, 226, 44, 10, 103,
39, 73, 230, 173, 60, 69, 69, 122, 110, 241, 164, 3, 192, 57
]
);
let expected_nsk: NullifierSecretKey = [
154, 102, 103, 5, 34, 235, 227, 13, 22, 182, 226, 11, 7, 67, 110, 162, 99, 193, 174,
34, 234, 19, 222, 2, 22, 12, 163, 252, 88, 11, 0, 163,
];
assert_eq!(
root_keys
.value
.0
.private_key_holder
.outgoing_viewing_secret_key,
[
205, 87, 71, 129, 90, 242, 217, 200, 140, 252, 124, 46, 207, 7, 33, 156, 83, 166,
150, 81, 98, 131, 182, 156, 110, 92, 78, 140, 125, 218, 152, 154
]
);
assert_eq!(
child_keys
.value
.0
.private_key_holder
.outgoing_viewing_secret_key,
[
131, 202, 219, 172, 219, 29, 48, 120, 226, 209, 209, 10, 216, 173, 48, 167, 233,
17, 35, 155, 30, 217, 176, 120, 72, 146, 250, 226, 165, 178, 255, 90
]
);
let expected_npk: NullifierPublicKey = nssa_core::NullifierPublicKey([
7, 123, 125, 191, 233, 183, 201, 4, 20, 214, 155, 210, 45, 234, 27, 240, 194, 111, 97,
247, 155, 113, 122, 246, 192, 0, 70, 61, 76, 71, 70, 2,
]);
let expected_vsk: ViewingSecretKey = [
155, 90, 54, 75, 228, 130, 68, 201, 129, 251, 180, 195, 250, 64, 34, 230, 241, 204,
216, 50, 149, 156, 10, 67, 208, 74, 9, 10, 47, 59, 50, 202,
];
assert_eq!(
root_keys.value.0.nullifer_public_key.0,
[
65, 176, 149, 243, 192, 45, 216, 177, 169, 56, 229, 7, 28, 66, 204, 87, 109, 83,
152, 64, 14, 188, 179, 210, 147, 60, 22, 251, 203, 70, 89, 215
]
);
assert_eq!(
child_keys.value.0.nullifer_public_key.0,
[
69, 104, 130, 115, 48, 134, 19, 188, 67, 148, 163, 54, 155, 237, 57, 27, 136, 228,
111, 233, 205, 158, 149, 31, 84, 11, 241, 176, 243, 12, 138, 249
]
);
let expected_vpk_as_bytes: [u8; 33] = [
2, 191, 99, 102, 114, 40, 131, 109, 166, 8, 222, 186, 107, 29, 156, 106, 206, 96, 127,
80, 170, 66, 217, 79, 38, 80, 11, 74, 147, 123, 221, 159, 166,
];
assert_eq!(
root_keys.value.0.incoming_viewing_public_key.0,
&[
3, 174, 56, 136, 244, 179, 18, 122, 38, 220, 36, 50, 200, 41, 104, 167, 70, 18, 60,
202, 93, 193, 29, 16, 125, 252, 96, 51, 199, 152, 47, 233, 178
]
);
assert_eq!(
child_keys.value.0.incoming_viewing_public_key.0,
&[
3, 18, 202, 246, 79, 141, 169, 51, 55, 202, 120, 169, 244, 201, 156, 162, 216, 115,
126, 53, 46, 94, 235, 125, 114, 178, 215, 81, 171, 93, 93, 88, 117
]
);
assert!(expected_ssk == keys.value.0.secret_spending_key);
assert!(expected_ccc == keys.ccc);
assert!(expected_nsk == keys.value.0.private_key_holder.nullifier_secret_key);
assert!(expected_npk == keys.value.0.nullifer_public_key);
assert!(expected_vsk == keys.value.0.private_key_holder.viewing_secret_key);
assert!(expected_vpk_as_bytes == keys.value.0.viewing_public_key.to_bytes());
}
#[test]
fn test_child_keys_generation() {
let seed: [u8; 64] = [
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
129, 223, 176, 198, 5, 150, 157, 70, 210, 254, 14, 105, 89, 191, 246, 27, 52, 170, 56,
114, 39, 38, 118, 197, 205, 225,
];
let root_node = ChildKeysPrivate::root(seed);
let child_node = ChildKeysPrivate::nth_child(&root_node, 42u32);
let expected_ccc: [u8; 32] = [
145, 59, 225, 32, 54, 168, 14, 45, 60, 253, 57, 202, 31, 86, 142, 234, 51, 57, 154, 88,
132, 200, 92, 191, 220, 144, 42, 184, 108, 35, 226, 146,
];
let expected_nsk: NullifierSecretKey = [
19, 100, 119, 73, 191, 225, 234, 219, 129, 88, 40, 229, 63, 225, 189, 136, 69, 172,
221, 186, 147, 83, 150, 207, 70, 17, 228, 70, 113, 87, 227, 31,
];
let expected_npk: NullifierPublicKey = nssa_core::NullifierPublicKey([
133, 235, 223, 151, 12, 69, 26, 222, 60, 125, 235, 125, 167, 212, 201, 168, 101, 242,
111, 239, 1, 228, 12, 252, 146, 53, 75, 17, 187, 255, 122, 181,
]);
let expected_vsk: ViewingSecretKey = [
218, 219, 193, 132, 160, 6, 178, 194, 139, 248, 199, 81, 17, 133, 37, 201, 58, 104, 49,
222, 187, 46, 156, 93, 14, 118, 209, 243, 38, 101, 77, 45,
];
let expected_vpk_as_bytes: [u8; 33] = [
3, 164, 65, 167, 88, 167, 179, 51, 159, 27, 241, 174, 77, 174, 142, 106, 128, 96, 69,
74, 117, 231, 42, 193, 235, 153, 206, 116, 102, 7, 101, 192, 45,
];
assert!(expected_ccc == child_node.ccc);
assert!(expected_nsk == child_node.value.0.private_key_holder.nullifier_secret_key);
assert!(expected_npk == child_node.value.0.nullifer_public_key);
assert!(expected_vsk == child_node.value.0.private_key_holder.viewing_secret_key);
assert!(expected_vpk_as_bytes == child_node.value.0.viewing_public_key.to_bytes());
}
}

View File

@ -1,6 +1,6 @@
use nssa_core::{
NullifierPublicKey, SharedSecretKey,
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
encryption::{EphemeralPublicKey, ViewingPublicKey},
};
use secret_holders::{PrivateKeyHolder, SecretSpendingKey, SeedHolder};
use serde::{Deserialize, Serialize};
@ -17,7 +17,7 @@ pub struct KeyChain {
pub secret_spending_key: SecretSpendingKey,
pub private_key_holder: PrivateKeyHolder,
pub nullifer_public_key: NullifierPublicKey,
pub incoming_viewing_public_key: IncomingViewingPublicKey,
pub viewing_public_key: ViewingPublicKey,
}
impl KeyChain {
@ -27,16 +27,16 @@ impl KeyChain {
let seed_holder = SeedHolder::new_os_random();
let secret_spending_key = seed_holder.produce_top_secret_key_holder();
let private_key_holder = secret_spending_key.produce_private_key_holder();
let private_key_holder = secret_spending_key.produce_private_key_holder(None);
let nullifer_public_key = private_key_holder.generate_nullifier_public_key();
let incoming_viewing_public_key = private_key_holder.generate_incoming_viewing_public_key();
let viewing_public_key = private_key_holder.generate_viewing_public_key();
Self {
secret_spending_key,
private_key_holder,
nullifer_public_key,
incoming_viewing_public_key,
viewing_public_key,
}
}
@ -46,16 +46,16 @@ impl KeyChain {
let seed_holder = SeedHolder::new_mnemonic(passphrase);
let secret_spending_key = seed_holder.produce_top_secret_key_holder();
let private_key_holder = secret_spending_key.produce_private_key_holder();
let private_key_holder = secret_spending_key.produce_private_key_holder(None);
let nullifer_public_key = private_key_holder.generate_nullifier_public_key();
let incoming_viewing_public_key = private_key_holder.generate_incoming_viewing_public_key();
let viewing_public_key = private_key_holder.generate_viewing_public_key();
Self {
secret_spending_key,
private_key_holder,
nullifer_public_key,
incoming_viewing_public_key,
viewing_public_key,
}
}
@ -64,9 +64,7 @@ impl KeyChain {
ephemeral_public_key_sender: EphemeralPublicKey,
) -> SharedSecretKey {
SharedSecretKey::new(
&self
.secret_spending_key
.generate_incoming_viewing_secret_key(),
&self.secret_spending_key.generate_viewing_secret_key(None),
&ephemeral_public_key_sender,
)
}
@ -112,10 +110,10 @@ mod tests {
let seed_holder = SeedHolder::new_os_random();
let top_secret_key_holder = seed_holder.produce_top_secret_key_holder();
let utxo_secret_key_holder = top_secret_key_holder.produce_private_key_holder();
let utxo_secret_key_holder = top_secret_key_holder.produce_private_key_holder(None);
let nullifer_public_key = utxo_secret_key_holder.generate_nullifier_public_key();
let viewing_public_key = utxo_secret_key_holder.generate_incoming_viewing_public_key();
let viewing_public_key = utxo_secret_key_holder.generate_viewing_public_key();
let pub_account_signing_key = nssa::PrivateKey::new_os_random();

View File

@ -2,7 +2,7 @@ use bip39::Mnemonic;
use common::HashType;
use nssa_core::{
NullifierPublicKey, NullifierSecretKey,
encryption::{IncomingViewingPublicKey, Scalar},
encryption::{Scalar, ViewingPublicKey},
};
use rand::{RngCore, rngs::OsRng};
use serde::{Deserialize, Serialize};
@ -18,20 +18,18 @@ pub struct SeedHolder {
pub(crate) seed: Vec<u8>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
/// Secret spending key object. Can produce `PrivateKeyHolder` objects.
pub struct SecretSpendingKey(pub(crate) [u8; 32]);
pub type IncomingViewingSecretKey = Scalar;
pub type OutgoingViewingSecretKey = Scalar;
pub type ViewingSecretKey = Scalar;
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Private key holder. Produces public keys. Can produce account_id. Can produce shared secret for
/// recepient.
pub struct PrivateKeyHolder {
pub nullifier_secret_key: NullifierSecretKey,
pub(crate) incoming_viewing_secret_key: IncomingViewingSecretKey,
pub outgoing_viewing_secret_key: OutgoingViewingSecretKey,
pub(crate) viewing_secret_key: ViewingSecretKey,
}
impl SeedHolder {
@ -75,44 +73,49 @@ impl SeedHolder {
}
impl SecretSpendingKey {
pub fn generate_nullifier_secret_key(&self) -> NullifierSecretKey {
let mut hasher = sha2::Sha256::new();
pub fn generate_nullifier_secret_key(&self, index: Option<u32>) -> NullifierSecretKey {
let index = match index {
None => 0u32,
_ => index.expect("Expect a valid u32"),
};
hasher.update("NSSA_keys");
const PREFIX: &[u8; 8] = b"LEE/keys";
const SUFFIX_1: &[u8; 1] = &[1];
const SUFFIX_2: &[u8; 19] = &[0; 19];
let mut hasher = sha2::Sha256::new();
hasher.update(PREFIX);
hasher.update(self.0);
hasher.update([1u8]);
hasher.update([0u8; 22]);
hasher.update(SUFFIX_1);
hasher.update(index.to_le_bytes());
hasher.update(SUFFIX_2);
<NullifierSecretKey>::from(hasher.finalize_fixed())
}
pub fn generate_incoming_viewing_secret_key(&self) -> IncomingViewingSecretKey {
let mut hasher = sha2::Sha256::new();
pub fn generate_viewing_secret_key(&self, index: Option<u32>) -> ViewingSecretKey {
let index = match index {
None => 0u32,
_ => index.expect("Expect a valid u32"),
};
const PREFIX: &[u8; 8] = b"LEE/keys";
const SUFFIX_1: &[u8; 1] = &[2];
const SUFFIX_2: &[u8; 19] = &[0; 19];
hasher.update("NSSA_keys");
let mut hasher = sha2::Sha256::new();
hasher.update(PREFIX);
hasher.update(self.0);
hasher.update([2u8]);
hasher.update([0u8; 22]);
hasher.update(SUFFIX_1);
hasher.update(index.to_le_bytes());
hasher.update(SUFFIX_2);
hasher.finalize_fixed().into()
}
pub fn generate_outgoing_viewing_secret_key(&self) -> OutgoingViewingSecretKey {
let mut hasher = sha2::Sha256::new();
hasher.update("NSSA_keys");
hasher.update(self.0);
hasher.update([3u8]);
hasher.update([0u8; 22]);
hasher.finalize_fixed().into()
}
pub fn produce_private_key_holder(&self) -> PrivateKeyHolder {
pub fn produce_private_key_holder(&self, index: Option<u32>) -> PrivateKeyHolder {
PrivateKeyHolder {
nullifier_secret_key: self.generate_nullifier_secret_key(),
incoming_viewing_secret_key: self.generate_incoming_viewing_secret_key(),
outgoing_viewing_secret_key: self.generate_outgoing_viewing_secret_key(),
nullifier_secret_key: self.generate_nullifier_secret_key(index),
viewing_secret_key: self.generate_viewing_secret_key(index),
}
}
}
@ -122,8 +125,8 @@ impl PrivateKeyHolder {
(&self.nullifier_secret_key).into()
}
pub fn generate_incoming_viewing_public_key(&self) -> IncomingViewingPublicKey {
IncomingViewingPublicKey::from_scalar(self.incoming_viewing_secret_key)
pub fn generate_viewing_public_key(&self) -> ViewingPublicKey {
ViewingPublicKey::from_scalar(self.viewing_secret_key)
}
}
@ -131,6 +134,7 @@ impl PrivateKeyHolder {
mod tests {
use super::*;
// TODO? are these necessary?
#[test]
fn seed_generation_test() {
let seed_holder = SeedHolder::new_os_random();
@ -155,18 +159,7 @@ mod tests {
let top_secret_key_holder = seed_holder.produce_top_secret_key_holder();
let _ = top_secret_key_holder.generate_incoming_viewing_secret_key();
}
#[test]
fn ovs_generation_test() {
let seed_holder = SeedHolder::new_os_random();
assert_eq!(seed_holder.seed.len(), 64);
let top_secret_key_holder = seed_holder.produce_top_secret_key_holder();
let _ = top_secret_key_holder.generate_outgoing_viewing_secret_key();
let _ = top_secret_key_holder.generate_viewing_secret_key(None);
}
#[test]

View File

@ -159,6 +159,7 @@ mod tests {
assert_eq!(new_acc_with_metadata.account_id, fingerprint);
}
#[cfg(feature = "host")]
#[test]
fn parse_valid_account_id() {
let base58_str = "11111111111111111111111111111111";
@ -166,6 +167,7 @@ mod tests {
assert_eq!(account_id.value, [0u8; 32]);
}
#[cfg(feature = "host")]
#[test]
fn parse_invalid_base58() {
let base58_str = "00".repeat(32); // invalid base58 chars
@ -173,6 +175,7 @@ mod tests {
assert!(matches!(result, AccountIdError::InvalidBase58(_)));
}
#[cfg(feature = "host")]
#[test]
fn parse_wrong_length_short() {
let base58_str = "11".repeat(31); // 62 chars = 31 bytes
@ -180,6 +183,7 @@ mod tests {
assert!(matches!(result, AccountIdError::InvalidLength(_)));
}
#[cfg(feature = "host")]
#[test]
fn parse_wrong_length_long() {
let base58_str = "11".repeat(33); // 66 chars = 33 bytes

View File

@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
pub mod shared_key_derivation;
#[cfg(feature = "host")]
pub use shared_key_derivation::{EphemeralPublicKey, EphemeralSecretKey, IncomingViewingPublicKey};
pub use shared_key_derivation::{EphemeralPublicKey, EphemeralSecretKey, ViewingPublicKey};
use crate::{Commitment, account::Account};

View File

@ -28,7 +28,7 @@ impl Secp256k1Point {
pub type EphemeralSecretKey = Scalar;
pub type EphemeralPublicKey = Secp256k1Point;
pub type IncomingViewingPublicKey = Secp256k1Point;
pub type ViewingPublicKey = Secp256k1Point;
impl From<&EphemeralSecretKey> for EphemeralPublicKey {
fn from(value: &EphemeralSecretKey) -> Self {
Secp256k1Point::from_scalar(*value)

View File

@ -10,7 +10,8 @@ pub struct NullifierPublicKey(pub [u8; 32]);
impl From<&NullifierPublicKey> for AccountId {
fn from(value: &NullifierPublicKey) -> Self {
const PRIVATE_ACCOUNT_ID_PREFIX: &[u8; 32] = b"/NSSA/v0.2/AccountId/Private/\x00\x00\x00";
const PRIVATE_ACCOUNT_ID_PREFIX: &[u8; 32] =
b"/LEE/v0.3/AccountId/Private/\x00\x00\x00\x00";
let mut bytes = [0; 64];
bytes[0..32].copy_from_slice(PRIVATE_ACCOUNT_ID_PREFIX);
@ -28,9 +29,9 @@ impl AsRef<[u8]> for NullifierPublicKey {
impl From<&NullifierSecretKey> for NullifierPublicKey {
fn from(value: &NullifierSecretKey) -> Self {
let mut bytes = Vec::new();
const PREFIX: &[u8; 9] = b"NSSA_keys";
const PREFIX: &[u8; 8] = b"LEE/keys";
const SUFFIX_1: &[u8; 1] = &[7];
const SUFFIX_2: &[u8; 22] = &[0; 22];
const SUFFIX_2: &[u8; 23] = &[0; 23];
bytes.extend_from_slice(PREFIX);
bytes.extend_from_slice(value);
bytes.extend_from_slice(SUFFIX_1);
@ -102,8 +103,8 @@ mod tests {
196, 134, 22, 224, 211, 237, 120, 136, 225, 188, 220, 249, 28,
];
let expected_npk = NullifierPublicKey([
202, 120, 42, 189, 194, 218, 78, 244, 31, 6, 108, 169, 29, 61, 22, 221, 69, 138, 197,
161, 241, 39, 142, 242, 242, 50, 188, 201, 99, 28, 176, 238,
78, 20, 20, 5, 177, 198, 233, 100, 175, 134, 174, 200, 24, 205, 68, 215, 130, 74, 35,
54, 154, 184, 219, 42, 168, 106, 126, 147, 133, 244, 18, 218,
]);
let npk = NullifierPublicKey::from(&nsk);
assert_eq!(npk, expected_npk);
@ -117,8 +118,8 @@ mod tests {
];
let npk = NullifierPublicKey::from(&nsk);
let expected_account_id = AccountId::new([
18, 153, 225, 78, 35, 214, 212, 205, 152, 83, 18, 246, 69, 41, 20, 217, 85, 1, 108, 7,
87, 133, 181, 53, 247, 221, 174, 12, 112, 194, 34, 121,
139, 72, 194, 222, 215, 187, 147, 56, 55, 35, 222, 205, 156, 12, 204, 227, 166, 44, 30,
81, 186, 14, 167, 234, 28, 236, 32, 213, 125, 251, 193, 233,
]);
let account_id = AccountId::from(&npk);

View File

@ -223,7 +223,7 @@ mod tests {
let expected_sender_pre = sender.clone();
let esk = [3; 32];
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.vpk());
let (output, proof) = execute_and_prove(
vec![sender, recipient],
@ -316,10 +316,10 @@ mod tests {
];
let esk_1 = [3; 32];
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.ivk());
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.vpk());
let esk_2 = [5; 32];
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.vpk());
let (output, proof) = execute_and_prove(
vec![sender_pre.clone(), recipient],

View File

@ -2,7 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize};
use nssa_core::{
Commitment, CommitmentSetDigest, Nullifier, NullifierPublicKey, PrivacyPreservingCircuitOutput,
account::{Account, Nonce},
encryption::{Ciphertext, EphemeralPublicKey, IncomingViewingPublicKey},
encryption::{Ciphertext, EphemeralPublicKey, ViewingPublicKey},
};
use sha2::{Digest, Sha256};
@ -21,10 +21,10 @@ impl EncryptedAccountData {
fn new(
ciphertext: Ciphertext,
npk: NullifierPublicKey,
ivk: IncomingViewingPublicKey,
vpk: ViewingPublicKey,
epk: EphemeralPublicKey,
) -> Self {
let view_tag = Self::compute_view_tag(npk, ivk);
let view_tag = Self::compute_view_tag(npk, vpk);
Self {
ciphertext,
epk,
@ -32,12 +32,12 @@ impl EncryptedAccountData {
}
}
/// Computes the tag as the first byte of SHA256("/NSSA/v0.2/ViewTag/" || Npk || Ivk)
pub fn compute_view_tag(npk: NullifierPublicKey, ivk: IncomingViewingPublicKey) -> ViewTag {
/// Computes the tag as the first byte of SHA256("/NSSA/v0.2/ViewTag/" || Npk || vpk)
pub fn compute_view_tag(npk: NullifierPublicKey, vpk: ViewingPublicKey) -> ViewTag {
let mut hasher = Sha256::new();
hasher.update(b"/NSSA/v0.2/ViewTag/");
hasher.update(npk.to_byte_array());
hasher.update(ivk.to_bytes());
hasher.update(vpk.to_bytes());
let digest: [u8; 32] = hasher.finalize().into();
digest[0]
}
@ -57,11 +57,7 @@ impl Message {
pub fn try_from_circuit_output(
public_account_ids: Vec<AccountId>,
nonces: Vec<Nonce>,
public_keys: Vec<(
NullifierPublicKey,
IncomingViewingPublicKey,
EphemeralPublicKey,
)>,
public_keys: Vec<(NullifierPublicKey, ViewingPublicKey, EphemeralPublicKey)>,
output: PrivacyPreservingCircuitOutput,
) -> Result<Self, NssaError> {
if public_keys.len() != output.ciphertexts.len() {
@ -74,8 +70,8 @@ impl Message {
.ciphertexts
.into_iter()
.zip(public_keys)
.map(|(ciphertext, (npk, ivk, epk))| {
EncryptedAccountData::new(ciphertext, npk, ivk, epk)
.map(|(ciphertext, (npk, vpk, epk))| {
EncryptedAccountData::new(ciphertext, npk, vpk, epk)
})
.collect();
Ok(Self {
@ -94,7 +90,7 @@ pub mod tests {
use nssa_core::{
Commitment, EncryptionScheme, Nullifier, NullifierPublicKey, SharedSecretKey,
account::Account,
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
encryption::{EphemeralPublicKey, ViewingPublicKey},
};
use sha2::{Digest, Sha256};
@ -142,21 +138,21 @@ pub mod tests {
#[test]
fn test_encrypted_account_data_constructor() {
let npk = NullifierPublicKey::from(&[1; 32]);
let ivk = IncomingViewingPublicKey::from_scalar([2; 32]);
let vpk = ViewingPublicKey::from_scalar([2; 32]);
let account = Account::default();
let commitment = Commitment::new(&npk, &account);
let esk = [3; 32];
let shared_secret = SharedSecretKey::new(&esk, &ivk);
let shared_secret = SharedSecretKey::new(&esk, &vpk);
let epk = EphemeralPublicKey::from_scalar(esk);
let ciphertext = EncryptionScheme::encrypt(&account, &shared_secret, &commitment, 2);
let encrypted_account_data =
EncryptedAccountData::new(ciphertext.clone(), npk.clone(), ivk.clone(), epk.clone());
EncryptedAccountData::new(ciphertext.clone(), npk.clone(), vpk.clone(), epk.clone());
let expected_view_tag = {
let mut hasher = Sha256::new();
hasher.update(b"/NSSA/v0.2/ViewTag/");
hasher.update(npk.to_byte_array());
hasher.update(ivk.to_bytes());
hasher.update(vpk.to_bytes());
let digest: [u8; 32] = hasher.finalize().into();
digest[0]
};
@ -165,7 +161,7 @@ pub mod tests {
assert_eq!(encrypted_account_data.epk, epk);
assert_eq!(
encrypted_account_data.view_tag,
EncryptedAccountData::compute_view_tag(npk, ivk)
EncryptedAccountData::compute_view_tag(npk, vpk)
);
assert_eq!(encrypted_account_data.view_tag, expected_view_tag);
}

View File

@ -315,7 +315,7 @@ pub mod tests {
use nssa_core::{
Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
account::{Account, AccountId, AccountWithMetadata, Nonce, data::Data},
encryption::{EphemeralPublicKey, IncomingViewingPublicKey, Scalar},
encryption::{EphemeralPublicKey, Scalar, ViewingPublicKey},
program::{PdaSeed, ProgramId},
};
use token_core::{TokenDefinition, TokenHolding};
@ -864,7 +864,7 @@ pub mod tests {
pub struct TestPrivateKeys {
pub nsk: NullifierSecretKey,
pub isk: Scalar,
pub vsk: Scalar,
}
impl TestPrivateKeys {
@ -872,22 +872,22 @@ pub mod tests {
NullifierPublicKey::from(&self.nsk)
}
pub fn ivk(&self) -> IncomingViewingPublicKey {
IncomingViewingPublicKey::from_scalar(self.isk)
pub fn vpk(&self) -> ViewingPublicKey {
ViewingPublicKey::from_scalar(self.vsk)
}
}
pub fn test_private_account_keys_1() -> TestPrivateKeys {
TestPrivateKeys {
nsk: [13; 32],
isk: [31; 32],
vsk: [31; 32],
}
}
pub fn test_private_account_keys_2() -> TestPrivateKeys {
TestPrivateKeys {
nsk: [38; 32],
isk: [83; 32],
vsk: [83; 32],
}
}
@ -908,7 +908,7 @@ pub mod tests {
let recipient = AccountWithMetadata::new(Account::default(), false, &recipient_keys.npk());
let esk = [3; 32];
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.vpk());
let epk = EphemeralPublicKey::from_scalar(esk);
let (output, proof) = circuit::execute_and_prove(
@ -926,7 +926,7 @@ pub mod tests {
let message = Message::try_from_circuit_output(
vec![sender_keys.account_id()],
vec![sender_nonce],
vec![(recipient_keys.npk(), recipient_keys.ivk(), epk)],
vec![(recipient_keys.npk(), recipient_keys.vpk(), epk)],
output,
)
.unwrap();
@ -951,11 +951,11 @@ pub mod tests {
AccountWithMetadata::new(Account::default(), false, &recipient_keys.npk());
let esk_1 = [3; 32];
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.ivk());
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.vpk());
let epk_1 = EphemeralPublicKey::from_scalar(esk_1);
let esk_2 = [3; 32];
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.vpk());
let epk_2 = EphemeralPublicKey::from_scalar(esk_2);
let (output, proof) = circuit::execute_and_prove(
@ -977,8 +977,8 @@ pub mod tests {
vec![],
vec![],
vec![
(sender_keys.npk(), sender_keys.ivk(), epk_1),
(recipient_keys.npk(), recipient_keys.ivk(), epk_2),
(sender_keys.npk(), sender_keys.vpk(), epk_1),
(recipient_keys.npk(), recipient_keys.vpk(), epk_2),
],
output,
)
@ -1008,7 +1008,7 @@ pub mod tests {
);
let esk = [3; 32];
let shared_secret = SharedSecretKey::new(&esk, &sender_keys.ivk());
let shared_secret = SharedSecretKey::new(&esk, &sender_keys.vpk());
let epk = EphemeralPublicKey::from_scalar(esk);
let (output, proof) = circuit::execute_and_prove(
@ -1026,7 +1026,7 @@ pub mod tests {
let message = Message::try_from_circuit_output(
vec![*recipient_account_id],
vec![],
vec![(sender_keys.npk(), sender_keys.ivk(), epk)],
vec![(sender_keys.npk(), sender_keys.vpk(), epk)],
output,
)
.unwrap();
@ -1538,11 +1538,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
vec![sender_keys.nsk],
@ -1572,7 +1572,7 @@ pub mod tests {
// Setting only one key for an execution with two private accounts.
let private_account_keys = [(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
)];
let result = execute_and_prove(
vec![private_account_1, private_account_2],
@ -1615,11 +1615,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
vec![sender_keys.nsk],
@ -1657,11 +1657,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
private_account_nsks.to_vec(),
@ -1693,12 +1693,12 @@ pub mod tests {
// First private account is the sender
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
// Second private account is the recipient
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
];
@ -1753,11 +1753,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
vec![sender_keys.nsk],
@ -1801,11 +1801,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
vec![sender_keys.nsk],
@ -1848,11 +1848,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
vec![sender_keys.nsk],
@ -1895,11 +1895,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
vec![sender_keys.nsk],
@ -1940,11 +1940,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
vec![sender_keys.nsk],
@ -2013,11 +2013,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
vec![sender_keys.nsk],
@ -2050,15 +2050,15 @@ pub mod tests {
let private_account_keys = [
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
(
sender_keys.npk(),
SharedSecretKey::new(&[57; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[57; 32], &sender_keys.vpk()),
),
];
let result = execute_and_prove(
@ -2105,11 +2105,11 @@ pub mod tests {
vec![
(
sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
),
(
recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
),
],
private_account_nsks.to_vec(),
@ -2192,7 +2192,7 @@ pub mod tests {
let visibility_mask = [1, 1];
let private_account_nsks = [sender_keys.nsk, sender_keys.nsk];
let private_account_membership_proofs = [Some((1, vec![])), Some((1, vec![]))];
let shared_secret = SharedSecretKey::new(&[55; 32], &sender_keys.ivk());
let shared_secret = SharedSecretKey::new(&[55; 32], &sender_keys.vpk());
let result = execute_and_prove(
vec![private_account_1.clone(), private_account_1],
Program::serialize_instruction(100u128).unwrap(),
@ -3809,11 +3809,11 @@ pub mod tests {
);
let from_esk = [3; 32];
let from_ss = SharedSecretKey::new(&from_esk, &from_keys.ivk());
let from_ss = SharedSecretKey::new(&from_esk, &from_keys.vpk());
let from_epk = EphemeralPublicKey::from_scalar(from_esk);
let to_esk = [3; 32];
let to_ss = SharedSecretKey::new(&to_esk, &to_keys.ivk());
let to_ss = SharedSecretKey::new(&to_esk, &to_keys.vpk());
let to_epk = EphemeralPublicKey::from_scalar(to_esk);
let mut dependencies = HashMap::new();
@ -3858,8 +3858,8 @@ pub mod tests {
vec![],
vec![],
vec![
(to_keys.npk(), to_keys.ivk(), to_epk),
(from_keys.npk(), from_keys.ivk(), from_epk),
(to_keys.npk(), to_keys.vpk(), to_epk),
(from_keys.npk(), from_keys.vpk(), from_epk),
],
output,
)
@ -4069,7 +4069,7 @@ pub mod tests {
// Set up parameters for the new account
let esk = [3; 32];
let shared_secret = SharedSecretKey::new(&esk, &private_keys.ivk());
let shared_secret = SharedSecretKey::new(&esk, &private_keys.vpk());
let epk = EphemeralPublicKey::from_scalar(esk);
// Balance to initialize the account with (0 for a new account)
@ -4094,7 +4094,7 @@ pub mod tests {
let message = Message::try_from_circuit_output(
vec![],
vec![],
vec![(private_keys.npk(), private_keys.ivk(), epk)],
vec![(private_keys.npk(), private_keys.vpk(), epk)],
output,
)
.unwrap();
@ -4124,7 +4124,7 @@ pub mod tests {
// Set up parameters for claiming the new account
let esk = [3; 32];
let shared_secret = SharedSecretKey::new(&esk, &private_keys.ivk());
let shared_secret = SharedSecretKey::new(&esk, &private_keys.vpk());
let epk = EphemeralPublicKey::from_scalar(esk);
let balance: u128 = 0;
@ -4146,7 +4146,7 @@ pub mod tests {
let message = Message::try_from_circuit_output(
vec![],
vec![],
vec![(private_keys.npk(), private_keys.ivk(), epk)],
vec![(private_keys.npk(), private_keys.vpk(), epk)],
output,
)
.unwrap();
@ -4174,7 +4174,7 @@ pub mod tests {
let noop_program = Program::noop();
let esk2 = [4; 32];
let shared_secret2 = SharedSecretKey::new(&esk2, &private_keys.ivk());
let shared_secret2 = SharedSecretKey::new(&esk2, &private_keys.vpk());
let nonce2 = 0xdeadbeef2;
@ -4256,7 +4256,7 @@ pub mod tests {
vec![2],
vec![(
sender_keys.npk(),
SharedSecretKey::new(&[3; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[3; 32], &sender_keys.vpk()),
)],
vec![sender_keys.nsk],
vec![Some((0, vec![]))],
@ -4284,7 +4284,7 @@ pub mod tests {
vec![2],
vec![(
sender_keys.npk(),
SharedSecretKey::new(&[3; 32], &sender_keys.ivk()),
SharedSecretKey::new(&[3; 32], &sender_keys.vpk()),
)],
vec![sender_keys.nsk],
vec![Some((0, vec![]))],
@ -4327,7 +4327,7 @@ pub mod tests {
let instruction = (balance_to_transfer, auth_transfers.id());
let recipient_esk = [3; 32];
let recipient = SharedSecretKey::new(&recipient_esk, &recipient_keys.ivk());
let recipient = SharedSecretKey::new(&recipient_esk, &recipient_keys.vpk());
let mut dependencies = HashMap::new();
dependencies.insert(auth_transfers.id(), auth_transfers);

View File

@ -73,7 +73,7 @@ pub unsafe extern "C" fn wallet_ffi_get_public_account_key(
/// Get keys for a private account.
///
/// Returns the nullifier public key (NPK) and incoming viewing public key (IPK)
/// Returns the nullifier public key (NPK) and viewing public key (VPK)
/// for the specified private account. These keys are safe to share publicly.
///
/// # Parameters
@ -130,17 +130,17 @@ pub unsafe extern "C" fn wallet_ffi_get_private_account_keys(
// NPK is a 32-byte array
let npk_bytes = key_chain.nullifer_public_key.0;
// IPK is a compressed secp256k1 point (33 bytes)
let ipk_bytes = key_chain.incoming_viewing_public_key.to_bytes();
let ipk_len = ipk_bytes.len();
let ipk_vec = ipk_bytes.to_vec();
let ipk_boxed = ipk_vec.into_boxed_slice();
let ipk_ptr = Box::into_raw(ipk_boxed) as *const u8;
// VPK is a compressed secp256k1 point (33 bytes)
let vpk_bytes = key_chain.viewing_public_key.to_bytes();
let vpk_len = vpk_bytes.len();
let vpk_vec = vpk_bytes.to_vec();
let vpk_boxed = vpk_vec.into_boxed_slice();
let vpk_ptr = Box::into_raw(vpk_boxed) as *const u8;
unsafe {
(*out_keys).nullifier_public_key.data = npk_bytes;
(*out_keys).incoming_viewing_public_key = ipk_ptr;
(*out_keys).incoming_viewing_public_key_len = ipk_len;
(*out_keys).viewing_public_key = vpk_ptr;
(*out_keys).viewing_public_key_len = vpk_len;
}
WalletFfiError::Success
@ -159,10 +159,10 @@ pub unsafe extern "C" fn wallet_ffi_free_private_account_keys(keys: *mut FfiPriv
unsafe {
let keys = &*keys;
if !keys.incoming_viewing_public_key.is_null() && keys.incoming_viewing_public_key_len > 0 {
if !keys.viewing_public_key.is_null() && keys.viewing_public_key_len > 0 {
let slice = std::slice::from_raw_parts_mut(
keys.incoming_viewing_public_key as *mut u8,
keys.incoming_viewing_public_key_len,
keys.viewing_public_key as *mut u8,
keys.viewing_public_key_len,
);
drop(Box::from_raw(slice as *mut [u8]));
}

View File

@ -150,8 +150,8 @@ pub unsafe extern "C" fn wallet_ffi_transfer_shielded(
let from_id = AccountId::new(unsafe { (*from).data });
let to_npk = (*to_keys).npk();
let to_ipk = match (*to_keys).ivk() {
Ok(ipk) => ipk,
let to_vpk = match (*to_keys).vpk() {
Ok(vpk) => vpk,
Err(e) => {
print_error("Invalid viewing key");
return e;
@ -162,7 +162,7 @@ pub unsafe extern "C" fn wallet_ffi_transfer_shielded(
let transfer = NativeTokenTransfer(&wallet);
match block_on(
transfer.send_shielded_transfer_to_outer_account(from_id, to_npk, to_ipk, amount),
transfer.send_shielded_transfer_to_outer_account(from_id, to_npk, to_vpk, amount),
) {
Ok(Ok((response, _shared_key))) => {
let tx_hash = CString::new(response.tx_hash)
@ -323,8 +323,8 @@ pub unsafe extern "C" fn wallet_ffi_transfer_private(
let from_id = AccountId::new(unsafe { (*from).data });
let to_npk = (*to_keys).npk();
let to_ipk = match (*to_keys).ivk() {
Ok(ipk) => ipk,
let to_vpk = match (*to_keys).vpk() {
Ok(vpk) => vpk,
Err(e) => {
print_error("Invalid viewing key");
return e;
@ -334,7 +334,7 @@ pub unsafe extern "C" fn wallet_ffi_transfer_private(
let transfer = NativeTokenTransfer(&wallet);
match block_on(transfer.send_private_transfer_to_outer_account(from_id, to_npk, to_ipk, amount))
match block_on(transfer.send_private_transfer_to_outer_account(from_id, to_npk, to_vpk, amount))
{
Ok(Ok((response, _shared_key))) => {
let tx_hash = CString::new(response.tx_hash)

View File

@ -72,18 +72,18 @@ impl Default for FfiAccount {
pub struct FfiPrivateAccountKeys {
/// Nullifier public key (32 bytes)
pub nullifier_public_key: FfiBytes32,
/// Incoming viewing public key (compressed secp256k1 point)
pub incoming_viewing_public_key: *const u8,
/// Length of incoming viewing public key (typically 33 bytes)
pub incoming_viewing_public_key_len: usize,
/// viewing public key (compressed secp256k1 point)
pub viewing_public_key: *const u8,
/// Length of viewing public key (typically 33 bytes)
pub viewing_public_key_len: usize,
}
impl Default for FfiPrivateAccountKeys {
fn default() -> Self {
Self {
nullifier_public_key: FfiBytes32::default(),
incoming_viewing_public_key: std::ptr::null(),
incoming_viewing_public_key_len: 0,
viewing_public_key: std::ptr::null(),
viewing_public_key_len: 0,
}
}
}
@ -157,13 +157,10 @@ impl FfiPrivateAccountKeys {
nssa_core::NullifierPublicKey(self.nullifier_public_key.data)
}
pub fn ivk(&self) -> Result<nssa_core::encryption::IncomingViewingPublicKey, WalletFfiError> {
if self.incoming_viewing_public_key_len == 33 {
pub fn vpk(&self) -> Result<nssa_core::encryption::ViewingPublicKey, WalletFfiError> {
if self.viewing_public_key_len == 33 {
let slice = unsafe {
slice::from_raw_parts(
self.incoming_viewing_public_key,
self.incoming_viewing_public_key_len,
)
slice::from_raw_parts(self.viewing_public_key, self.viewing_public_key_len)
};
Ok(Secp256k1Point(slice.to_vec()))
} else {

679
wallet-ffi/wallet_ffi.h Normal file
View File

@ -0,0 +1,679 @@
/**
* NSSA Wallet FFI Bindings
*
* Thread Safety: All functions are thread-safe. The wallet handle can be
* shared across threads, but operations are serialized internally.
*
* Memory Management:
* - Functions returning pointers allocate memory that must be freed
* - Use the corresponding wallet_ffi_free_* function to free memory
* - Never free memory returned by FFI using standard C free()
*
* Error Handling:
* - Functions return WalletFfiError codes
* - On error, call wallet_ffi_get_last_error() for detailed message
* - The error string must be freed with wallet_ffi_free_error_string()
*
* Initialization:
* 1. Call wallet_ffi_init_runtime() before any other function
* 2. Create wallet with wallet_ffi_create_new() or wallet_ffi_open()
* 3. Destroy wallet with wallet_ffi_destroy() when done
*/
#ifndef WALLET_FFI_H
#define WALLET_FFI_H
/* Generated with cbindgen:0.29.2 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/**
* Error codes returned by FFI functions.
*/
typedef enum WalletFfiError {
/**
* Operation completed successfully
*/
SUCCESS = 0,
/**
* A null pointer was passed where a valid pointer was expected
*/
NULL_POINTER = 1,
/**
* Invalid UTF-8 string
*/
INVALID_UTF8 = 2,
/**
* Wallet handle is not initialized
*/
WALLET_NOT_INITIALIZED = 3,
/**
* Configuration error
*/
CONFIG_ERROR = 4,
/**
* Storage/persistence error
*/
STORAGE_ERROR = 5,
/**
* Network/RPC error
*/
NETWORK_ERROR = 6,
/**
* Account not found
*/
ACCOUNT_NOT_FOUND = 7,
/**
* Key not found for account
*/
KEY_NOT_FOUND = 8,
/**
* Insufficient funds for operation
*/
INSUFFICIENT_FUNDS = 9,
/**
* Invalid account ID format
*/
INVALID_ACCOUNT_ID = 10,
/**
* Tokio runtime error
*/
RUNTIME_ERROR = 11,
/**
* Password required but not provided
*/
PASSWORD_REQUIRED = 12,
/**
* Block synchronization error
*/
SYNC_ERROR = 13,
/**
* Serialization/deserialization error
*/
SERIALIZATION_ERROR = 14,
/**
* Invalid conversion from FFI types to NSSA types
*/
INVALID_TYPE_CONVERSION = 15,
/**
* Invalid Key value
*/
INVALID_KEY_VALUE = 16,
/**
* Internal error (catch-all)
*/
INTERNAL_ERROR = 99,
} WalletFfiError;
/**
* Opaque pointer to the Wallet instance.
*
* This type is never instantiated directly - it's used as an opaque handle
* to hide the internal wallet structure from C code.
*/
typedef struct WalletHandle {
uint8_t _private[0];
} WalletHandle;
/**
* 32-byte array type for AccountId, keys, hashes, etc.
*/
typedef struct FfiBytes32 {
uint8_t data[32];
} FfiBytes32;
/**
* Single entry in the account list.
*/
typedef struct FfiAccountListEntry {
struct FfiBytes32 account_id;
bool is_public;
} FfiAccountListEntry;
/**
* List of accounts returned by wallet_ffi_list_accounts.
*/
typedef struct FfiAccountList {
struct FfiAccountListEntry *entries;
uintptr_t count;
} FfiAccountList;
/**
* Program ID - 8 u32 values (32 bytes total).
*/
typedef struct FfiProgramId {
uint32_t data[8];
} FfiProgramId;
/**
* U128 - 16 bytes little endian
*/
typedef struct FfiU128 {
uint8_t data[16];
} FfiU128;
/**
* Account data structure - C-compatible version of nssa Account.
*
* Note: `balance` and `nonce` are u128 values represented as little-endian
* byte arrays since C doesn't have native u128 support.
*/
typedef struct FfiAccount {
struct FfiProgramId program_owner;
/**
* Balance as little-endian [u8; 16]
*/
struct FfiU128 balance;
/**
* Pointer to account data bytes
*/
const uint8_t *data;
/**
* Length of account data
*/
uintptr_t data_len;
/**
* Nonce as little-endian [u8; 16]
*/
struct FfiU128 nonce;
} FfiAccount;
/**
* Public key info for a public account.
*/
typedef struct FfiPublicAccountKey {
struct FfiBytes32 public_key;
} FfiPublicAccountKey;
/**
* Public keys for a private account (safe to expose).
*/
typedef struct FfiPrivateAccountKeys {
/**
* Nullifier public key (32 bytes)
*/
struct FfiBytes32 nullifier_public_key;
/**
* viewing public key (compressed secp256k1 point)
*/
const uint8_t *viewing_public_key;
/**
* Length of viewing public key (typically 33 bytes)
*/
uintptr_t viewing_public_key_len;
} FfiPrivateAccountKeys;
/**
* Result of a transfer operation.
*/
typedef struct FfiTransferResult {
/**
* Transaction hash (null-terminated string, or null on failure)
*/
char *tx_hash;
/**
* Whether the transfer succeeded
*/
bool success;
} FfiTransferResult;
/**
* Create a new public account.
*
* Public accounts use standard transaction signing and are suitable for
* non-private operations.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_account_id`: Output pointer for the new account ID (32 bytes)
*
* # Returns
* - `Success` on successful creation
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_account_id` must be a valid pointer to a `FfiBytes32` struct
*/
enum WalletFfiError wallet_ffi_create_account_public(struct WalletHandle *handle,
struct FfiBytes32 *out_account_id);
/**
* Create a new private account.
*
* Private accounts use privacy-preserving transactions with nullifiers
* and commitments.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_account_id`: Output pointer for the new account ID (32 bytes)
*
* # Returns
* - `Success` on successful creation
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_account_id` must be a valid pointer to a `FfiBytes32` struct
*/
enum WalletFfiError wallet_ffi_create_account_private(struct WalletHandle *handle,
struct FfiBytes32 *out_account_id);
/**
* List all accounts in the wallet.
*
* Returns both public and private accounts managed by this wallet.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_list`: Output pointer for the account list
*
* # Returns
* - `Success` on successful listing
* - Error code on failure
*
* # Memory
* The returned list must be freed with `wallet_ffi_free_account_list()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_list` must be a valid pointer to a `FfiAccountList` struct
*/
enum WalletFfiError wallet_ffi_list_accounts(struct WalletHandle *handle,
struct FfiAccountList *out_list);
/**
* Free an account list returned by `wallet_ffi_list_accounts`.
*
* # Safety
* The list must be either null or a valid list returned by `wallet_ffi_list_accounts`.
*/
void wallet_ffi_free_account_list(struct FfiAccountList *list);
/**
* Get account balance.
*
* For public accounts, this fetches the balance from the network.
* For private accounts, this returns the locally cached balance.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: The account ID (32 bytes)
* - `is_public`: Whether this is a public account
* - `out_balance`: Output for balance as little-endian [u8; 16]
*
* # Returns
* - `Success` on successful query
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_balance` must be a valid pointer to a `[u8; 16]` array
*/
enum WalletFfiError wallet_ffi_get_balance(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
bool is_public,
uint8_t (*out_balance)[16]);
/**
* Get full public account data from the network.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: The account ID (32 bytes)
* - `out_account`: Output pointer for account data
*
* # Returns
* - `Success` on successful query
* - Error code on failure
*
* # Memory
* The account data must be freed with `wallet_ffi_free_account_data()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_account` must be a valid pointer to a `FfiAccount` struct
*/
enum WalletFfiError wallet_ffi_get_account_public(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
struct FfiAccount *out_account);
/**
* Free account data returned by `wallet_ffi_get_account_public`.
*
* # Safety
* The account must be either null or a valid account returned by
* `wallet_ffi_get_account_public`.
*/
void wallet_ffi_free_account_data(struct FfiAccount *account);
/**
* Get the public key for a public account.
*
* This returns the public key derived from the account's signing key.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: The account ID (32 bytes)
* - `out_public_key`: Output pointer for the public key
*
* # Returns
* - `Success` on successful retrieval
* - `KeyNotFound` if the account's key is not in this wallet
* - Error code on other failures
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_public_key` must be a valid pointer to a `FfiPublicAccountKey` struct
*/
enum WalletFfiError wallet_ffi_get_public_account_key(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
struct FfiPublicAccountKey *out_public_key);
/**
* Get keys for a private account.
*
* Returns the nullifier public key (NPK) and viewing public key (VPK)
* for the specified private account. These keys are safe to share publicly.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: The account ID (32 bytes)
* - `out_keys`: Output pointer for the key data
*
* # Returns
* - `Success` on successful retrieval
* - `AccountNotFound` if the private account is not in this wallet
* - Error code on other failures
*
* # Memory
* The keys structure must be freed with `wallet_ffi_free_private_account_keys()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_keys` must be a valid pointer to a `FfiPrivateAccountKeys` struct
*/
enum WalletFfiError wallet_ffi_get_private_account_keys(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
struct FfiPrivateAccountKeys *out_keys);
/**
* Free private account keys returned by `wallet_ffi_get_private_account_keys`.
*
* # Safety
* The keys must be either null or valid keys returned by
* `wallet_ffi_get_private_account_keys`.
*/
void wallet_ffi_free_private_account_keys(struct FfiPrivateAccountKeys *keys);
/**
* Convert an account ID to a Base58 string.
*
* # Parameters
* - `account_id`: The account ID (32 bytes)
*
* # Returns
* - Pointer to null-terminated Base58 string on success
* - Null pointer on error
*
* # Memory
* The returned string must be freed with `wallet_ffi_free_string()`.
*
* # Safety
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
*/
char *wallet_ffi_account_id_to_base58(const struct FfiBytes32 *account_id);
/**
* Parse a Base58 string into an account ID.
*
* # Parameters
* - `base58_str`: Null-terminated Base58 string
* - `out_account_id`: Output pointer for the account ID (32 bytes)
*
* # Returns
* - `Success` on successful parsing
* - `InvalidAccountId` if the string is not valid Base58
* - Error code on other failures
*
* # Safety
* - `base58_str` must be a valid pointer to a null-terminated C string
* - `out_account_id` must be a valid pointer to a `FfiBytes32` struct
*/
enum WalletFfiError wallet_ffi_account_id_from_base58(const char *base58_str,
struct FfiBytes32 *out_account_id);
/**
* Synchronize private accounts to a specific block.
*
* This scans the blockchain from the last synced block to the specified block,
* updating private account balances based on any relevant transactions.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `block_id`: Target block number to sync to
*
* # Returns
* - `Success` if synchronization completed
* - `SyncError` if synchronization failed
* - Error code on other failures
*
* # Note
* This operation can take a while for large block ranges. The wallet
* internally uses a progress bar which may output to stdout.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
*/
enum WalletFfiError wallet_ffi_sync_to_block(struct WalletHandle *handle, uint64_t block_id);
/**
* Get the last synced block number.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_block_id`: Output pointer for the block number
*
* # Returns
* - `Success` on success
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_block_id` must be a valid pointer to a `u64`
*/
enum WalletFfiError wallet_ffi_get_last_synced_block(struct WalletHandle *handle,
uint64_t *out_block_id);
/**
* Get the current block height from the sequencer.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_block_height`: Output pointer for the current block height
*
* # Returns
* - `Success` on success
* - `NetworkError` if the sequencer is unreachable
* - Error code on other failures
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_block_height` must be a valid pointer to a `u64`
*/
enum WalletFfiError wallet_ffi_get_current_block_height(struct WalletHandle *handle,
uint64_t *out_block_height);
/**
* Send a public token transfer.
*
* Transfers tokens from one public account to another on the network.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `from`: Source account ID (must be owned by this wallet)
* - `to`: Destination account ID
* - `amount`: Amount to transfer as little-endian [u8; 16]
* - `out_result`: Output pointer for transfer result
*
* # Returns
* - `Success` if the transfer was submitted successfully
* - `InsufficientFunds` if the source account doesn't have enough balance
* - `KeyNotFound` if the source account's signing key is not in this wallet
* - Error code on other failures
*
* # Memory
* The result must be freed with `wallet_ffi_free_transfer_result()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `from` must be a valid pointer to a `FfiBytes32` struct
* - `to` must be a valid pointer to a `FfiBytes32` struct
* - `amount` must be a valid pointer to a `[u8; 16]` array
* - `out_result` must be a valid pointer to a `FfiTransferResult` struct
*/
enum WalletFfiError wallet_ffi_transfer_public(struct WalletHandle *handle,
const struct FfiBytes32 *from,
const struct FfiBytes32 *to,
const uint8_t (*amount)[16],
struct FfiTransferResult *out_result);
/**
* Register a public account on the network.
*
* This initializes a public account on the blockchain. The account must be
* owned by this wallet.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: Account ID to register
* - `out_result`: Output pointer for registration result
*
* # Returns
* - `Success` if the registration was submitted successfully
* - Error code on failure
*
* # Memory
* The result must be freed with `wallet_ffi_free_transfer_result()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_result` must be a valid pointer to a `FfiTransferResult` struct
*/
enum WalletFfiError wallet_ffi_register_public_account(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
struct FfiTransferResult *out_result);
/**
* Free a transfer result returned by `wallet_ffi_transfer_public` or
* `wallet_ffi_register_public_account`.
*
* # Safety
* The result must be either null or a valid result from a transfer function.
*/
void wallet_ffi_free_transfer_result(struct FfiTransferResult *result);
/**
* Create a new wallet with fresh storage.
*
* This initializes a new wallet with a new seed derived from the password.
* Use this for first-time wallet creation.
*
* # Parameters
* - `config_path`: Path to the wallet configuration file (JSON)
* - `storage_path`: Path where wallet data will be stored
* - `password`: Password for encrypting the wallet seed
*
* # Returns
* - Opaque wallet handle on success
* - Null pointer on error (call `wallet_ffi_get_last_error()` for details)
*
* # Safety
* All string parameters must be valid null-terminated UTF-8 strings.
*/
struct WalletHandle *wallet_ffi_create_new(const char *config_path,
const char *storage_path,
const char *password);
/**
* Open an existing wallet from storage.
*
* This loads a wallet that was previously created with `wallet_ffi_create_new()`.
*
* # Parameters
* - `config_path`: Path to the wallet configuration file (JSON)
* - `storage_path`: Path where wallet data is stored
*
* # Returns
* - Opaque wallet handle on success
* - Null pointer on error (call `wallet_ffi_get_last_error()` for details)
*
* # Safety
* All string parameters must be valid null-terminated UTF-8 strings.
*/
struct WalletHandle *wallet_ffi_open(const char *config_path, const char *storage_path);
/**
* Destroy a wallet handle and free its resources.
*
* After calling this function, the handle is invalid and must not be used.
*
* # Safety
* - The handle must be either null or a valid handle from `wallet_ffi_create_new()` or
* `wallet_ffi_open()`.
* - The handle must not be used after this call.
*/
void wallet_ffi_destroy(struct WalletHandle *handle);
/**
* Save wallet state to persistent storage.
*
* This should be called periodically or after important operations to ensure
* wallet data is persisted to disk.
*
* # Parameters
* - `handle`: Valid wallet handle
*
* # Returns
* - `Success` on successful save
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
*/
enum WalletFfiError wallet_ffi_save(struct WalletHandle *handle);
/**
* Get the sequencer address from the wallet configuration.
*
* # Parameters
* - `handle`: Valid wallet handle
*
* # Returns
* - Pointer to null-terminated string on success (caller must free with
* `wallet_ffi_free_string()`)
* - Null pointer on error
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
*/
char *wallet_ffi_get_sequencer_addr(struct WalletHandle *handle);
/**
* Free a string returned by wallet FFI functions.
*
* # Safety
* The pointer must be either null or a valid string returned by an FFI function.
*/
void wallet_ffi_free_string(char *ptr);
#endif /* WALLET_FFI_H */

View File

@ -84,9 +84,9 @@
]
}
},
{
{
"Private": {
"account_id": "3oCG8gqdKLMegw4rRfyaMQvuPHpcASt7xwttsmnZLSkw",
"account_id": "2ECgkFTaXzwjJBXR7ZKmXYQtpHbvTTHK9Auma4NL9AUo",
"account": {
"program_owner": [
0,
@ -103,219 +103,19 @@
"nonce": 0
},
"key_chain": {
"secret_spending_key": [
251,
82,
235,
1,
146,
96,
30,
81,
162,
234,
33,
15,
123,
129,
116,
0,
84,
136,
176,
70,
190,
224,
161,
54,
134,
142,
154,
1,
18,
251,
242,
189
],
"secret_spending_key": [112, 17, 152, 192, 217, 201, 142, 92, 111, 68, 85, 222, 107, 73, 78, 196, 118, 226, 37, 17, 185, 177, 149, 182, 9, 85, 187, 152, 163, 144, 68, 121],
"private_key_holder": {
"nullifier_secret_key": [
29,
250,
10,
187,
35,
123,
180,
250,
246,
97,
216,
153,
44,
156,
16,
93,
241,
26,
174,
219,
72,
84,
34,
247,
112,
101,
217,
243,
189,
173,
75,
20
],
"incoming_viewing_secret_key": [
251,
201,
22,
154,
100,
165,
218,
108,
163,
190,
135,
91,
145,
84,
69,
241,
46,
117,
217,
110,
197,
248,
91,
193,
14,
104,
88,
103,
67,
153,
182,
158
],
"outgoing_viewing_secret_key": [
25,
67,
121,
76,
175,
100,
30,
198,
105,
123,
49,
169,
75,
178,
75,
210,
100,
143,
210,
243,
228,
243,
21,
18,
36,
84,
164,
186,
139,
113,
214,
12
]
"nullifier_secret_key": [52, 33, 235, 245, 42, 132, 163, 182, 114, 56, 144, 187, 147, 23, 184, 227, 128, 12, 180, 142, 217, 110, 188, 177, 155, 141, 23, 127, 216, 185, 33, 126],
"viewing_secret_key": [44, 81, 165, 166, 34, 188, 192, 240, 40, 9, 83, 189, 215, 184, 246, 154, 247, 227, 155, 16, 121, 238, 4, 245, 63, 135, 192, 213, 222, 247, 120, 86]
},
"nullifer_public_key": [
63,
202,
178,
231,
183,
82,
237,
212,
216,
221,
215,
255,
153,
101,
177,
161,
254,
210,
128,
122,
54,
190,
230,
151,
183,
64,
225,
229,
113,
1,
228,
97
],
"incoming_viewing_public_key": [
3,
235,
139,
131,
237,
177,
122,
189,
6,
177,
167,
178,
202,
117,
246,
58,
28,
65,
132,
79,
220,
139,
119,
243,
187,
160,
212,
121,
61,
247,
116,
72,
205
]
"nullifer_public_key": [13, 25, 40, 5, 198, 248, 210, 248, 237, 121, 124, 145, 186, 142, 253, 216, 236, 69, 193, 32, 166, 167, 49, 133, 172, 111, 159, 46, 84, 17, 157, 23],
"viewing_public_key": [3, 43, 116, 165, 161, 27, 150, 158, 175, 198, 215, 27, 121, 126, 158, 224, 249, 92, 168, 163, 173, 115, 120, 122, 89, 173, 133, 94, 39, 238, 62, 52, 193]
}
}
},
{
"Private": {
"account_id": "AKTcXgJ1xoynta1Ec7y6Jso1z1JQtHqd7aPQ1h9er6xX",
"account_id": "E8HwiTyQe4H9HK7icTvn95HQMnzx49mP9A2ddtMLpNaN",
"account": {
"program_owner": [
0,
@ -332,213 +132,13 @@
"nonce": 0
},
"key_chain": {
"secret_spending_key": [
238,
171,
241,
69,
111,
217,
85,
64,
19,
82,
18,
189,
32,
91,
78,
175,
107,
7,
109,
60,
52,
44,
243,
230,
72,
244,
192,
92,
137,
33,
118,
254
],
"secret_spending_key": [48, 175, 124, 10, 230, 240, 166, 14, 249, 254, 157, 226, 208, 124, 122, 177, 203, 139, 192, 180, 43, 120, 55, 151, 50, 21, 113, 22, 254, 83, 148, 56],
"private_key_holder": {
"nullifier_secret_key": [
25,
211,
215,
119,
57,
223,
247,
37,
245,
144,
122,
29,
118,
245,
83,
228,
23,
9,
101,
120,
88,
33,
238,
207,
128,
61,
110,
2,
89,
62,
164,
13
],
"incoming_viewing_secret_key": [
193,
181,
14,
196,
142,
84,
15,
65,
128,
101,
70,
196,
241,
47,
130,
221,
23,
146,
161,
237,
221,
40,
19,
126,
59,
15,
169,
236,
25,
105,
104,
231
],
"outgoing_viewing_secret_key": [
20,
170,
220,
108,
41,
23,
155,
217,
247,
190,
175,
168,
247,
34,
105,
134,
114,
74,
104,
91,
211,
62,
126,
13,
130,
100,
241,
214,
250,
236,
38,
150
]
"nullifier_secret_key": [99, 82, 190, 140, 234, 10, 61, 163, 15, 211, 179, 54, 70, 166, 87, 5, 182, 68, 117, 244, 217, 23, 99, 9, 4, 177, 230, 125, 109, 91, 160, 30],
"viewing_secret_key": [205, 32, 76, 251, 255, 236, 96, 119, 61, 111, 65, 100, 75, 218, 12, 22, 17, 170, 55, 226, 21, 154, 161, 34, 208, 74, 27, 1, 119, 13, 88, 128]
},
"nullifer_public_key": [
192,
251,
166,
243,
167,
236,
84,
249,
35,
136,
130,
172,
219,
225,
161,
139,
229,
89,
243,
125,
194,
213,
209,
30,
23,
174,
100,
244,
124,
74,
140,
47
],
"incoming_viewing_public_key": [
2,
181,
98,
93,
216,
241,
241,
110,
58,
198,
119,
174,
250,
184,
1,
204,
200,
173,
44,
238,
37,
247,
170,
156,
100,
254,
116,
242,
28,
183,
187,
77,
255
]
"nullifer_public_key": [32, 67, 72, 164, 106, 53, 66, 239, 141, 15, 52, 230, 136, 177, 2, 236, 207, 243, 134, 135, 210, 143, 87, 232, 215, 128, 194, 120, 113, 224, 4, 165],
"viewing_public_key": [2, 79, 110, 46, 203, 29, 206, 205, 18, 86, 27, 189, 104, 103, 113, 181, 110, 53, 78, 172, 11, 171, 190, 18, 126, 214, 81, 77, 192, 154, 58, 195, 238]
}
}
}

View File

@ -20,7 +20,7 @@ pub enum AccountSubcommand {
/// Flag to get raw account data
#[arg(short, long)]
raw: bool,
/// Display keys (pk for public accounts, npk/ipk for private accounts)
/// Display keys (pk for public accounts, npk/vpk for private accounts)
#[arg(short, long)]
keys: bool,
/// Valid 32 byte base58 string with privacy prefix
@ -107,8 +107,8 @@ impl WalletSubcommand for NewSubcommand {
);
println!("With npk {}", hex::encode(key.nullifer_public_key.0));
println!(
"With ipk {}",
hex::encode(key.incoming_viewing_public_key.to_bytes())
"With vpk {}",
hex::encode(key.viewing_public_key.to_bytes())
);
wallet_core.store_persistent_data().await?;
@ -207,10 +207,7 @@ impl WalletSubcommand for AccountSubcommand {
.ok_or(anyhow::anyhow!("Private account not found in storage"))?;
println!("npk {}", hex::encode(key.nullifer_public_key.0));
println!(
"ipk {}",
hex::encode(key.incoming_viewing_public_key.to_bytes())
);
println!("vpk {}", hex::encode(key.viewing_public_key.to_bytes()));
}
}
Ok(())

View File

@ -22,7 +22,7 @@ pub enum AuthTransferSubcommand {
},
/// Send native tokens from one account to another with variable privacy
///
/// If receiver is private, then `to` and (`to_npk` , `to_ipk`) is a mutually exclusive
/// If receiver is private, then `to` and (`to_npk` , `to_vpk`) is a mutually exclusive
/// patterns.
///
/// First is used for owned accounts, second otherwise.
@ -36,9 +36,9 @@ pub enum AuthTransferSubcommand {
/// to_npk - valid 32 byte hex string
#[arg(long)]
to_npk: Option<String>,
/// to_ipk - valid 33 byte hex string
/// to_vpk - valid 33 byte hex string
#[arg(long)]
to_ipk: Option<String>,
to_vpk: Option<String>,
/// amount - amount of balance to move
#[arg(long)]
amount: u128,
@ -102,10 +102,10 @@ impl WalletSubcommand for AuthTransferSubcommand {
from,
to,
to_npk,
to_ipk,
to_vpk,
amount,
} => {
let underlying_subcommand = match (to, to_npk, to_ipk) {
let underlying_subcommand = match (to, to_npk, to_vpk) {
(None, None, None) => {
anyhow::bail!(
"Provide either account account_id of receiver or their public keys"
@ -154,7 +154,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
}
}
}
(None, Some(to_npk), Some(to_ipk)) => {
(None, Some(to_npk), Some(to_vpk)) => {
let (from, from_privacy) = parse_addr_with_privacy_prefix(&from)?;
match from_privacy {
@ -163,7 +163,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
NativeTokenTransferProgramSubcommandPrivate::PrivateForeign {
from,
to_npk,
to_ipk,
to_vpk,
amount,
},
)
@ -173,7 +173,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
NativeTokenTransferProgramSubcommandShielded::ShieldedForeign {
from,
to_npk,
to_ipk,
to_vpk,
amount,
},
)
@ -255,9 +255,9 @@ pub enum NativeTokenTransferProgramSubcommandShielded {
/// to_npk - valid 32 byte hex string
#[arg(long)]
to_npk: String,
/// to_ipk - valid 33 byte hex string
/// to_vpk - valid 33 byte hex string
#[arg(long)]
to_ipk: String,
to_vpk: String,
/// amount - amount of balance to move
#[arg(long)]
amount: u128,
@ -292,9 +292,9 @@ pub enum NativeTokenTransferProgramSubcommandPrivate {
/// to_npk - valid 32 byte hex string
#[arg(long)]
to_npk: String,
/// to_ipk - valid 33 byte hex string
/// to_vpk - valid 33 byte hex string
#[arg(long)]
to_ipk: String,
to_vpk: String,
/// amount - amount of balance to move
#[arg(long)]
amount: u128,
@ -336,7 +336,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate {
NativeTokenTransferProgramSubcommandPrivate::PrivateForeign {
from,
to_npk,
to_ipk,
to_vpk,
amount,
} => {
let from: AccountId = from.parse().unwrap();
@ -345,14 +345,14 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate {
to_npk.copy_from_slice(&to_npk_res);
let to_npk = nssa_core::NullifierPublicKey(to_npk);
let to_ipk_res = hex::decode(to_ipk)?;
let mut to_ipk = [0u8; 33];
to_ipk.copy_from_slice(&to_ipk_res);
let to_ipk =
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec());
let to_vpk_res = hex::decode(to_vpk)?;
let mut to_vpk = [0u8; 33];
to_vpk.copy_from_slice(&to_vpk_res);
let to_vpk =
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_vpk.to_vec());
let (res, [secret_from, _]) = NativeTokenTransfer(wallet_core)
.send_private_transfer_to_outer_account(from, to_npk, to_ipk, amount)
.send_private_transfer_to_outer_account(from, to_npk, to_vpk, amount)
.await?;
println!("Results of tx send are {res:#?}");
@ -412,7 +412,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
NativeTokenTransferProgramSubcommandShielded::ShieldedForeign {
from,
to_npk,
to_ipk,
to_vpk,
amount,
} => {
let from: AccountId = from.parse().unwrap();
@ -422,14 +422,14 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
to_npk.copy_from_slice(&to_npk_res);
let to_npk = nssa_core::NullifierPublicKey(to_npk);
let to_ipk_res = hex::decode(to_ipk)?;
let mut to_ipk = [0u8; 33];
to_ipk.copy_from_slice(&to_ipk_res);
let to_ipk =
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec());
let to_vpk_res = hex::decode(to_vpk)?;
let mut to_vpk = [0u8; 33];
to_vpk.copy_from_slice(&to_vpk_res);
let to_vpk =
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_vpk.to_vec());
let (res, _) = NativeTokenTransfer(wallet_core)
.send_shielded_transfer_to_outer_account(from, to_npk, to_ipk, amount)
.send_shielded_transfer_to_outer_account(from, to_npk, to_vpk, amount)
.await?;
println!("Results of tx send are {res:#?}");

View File

@ -29,7 +29,7 @@ pub enum TokenProgramAgnosticSubcommand {
},
/// Send tokens from one account to another with variable privacy
///
/// If receiver is private, then `to` and (`to_npk` , `to_ipk`) is a mutually exclusive
/// If receiver is private, then `to` and (`to_npk` , `to_vpk`) is a mutually exclusive
/// patterns.
///
/// First is used for owned accounts, second otherwise.
@ -43,9 +43,9 @@ pub enum TokenProgramAgnosticSubcommand {
/// to_npk - valid 32 byte hex string
#[arg(long)]
to_npk: Option<String>,
/// to_ipk - valid 33 byte hex string
/// to_vpk - valid 33 byte hex string
#[arg(long)]
to_ipk: Option<String>,
to_vpk: Option<String>,
/// amount - amount of balance to move
#[arg(long)]
amount: u128,
@ -71,7 +71,7 @@ pub enum TokenProgramAgnosticSubcommand {
///
/// `definition` is owned
///
/// If `holder` is private, then `holder` and (`holder_npk` , `holder_ipk`) is a mutually
/// If `holder` is private, then `holder` and (`holder_npk` , `holder_vpk`) is a mutually
/// exclusive patterns.
///
/// First is used for owned accounts, second otherwise.
@ -85,9 +85,9 @@ pub enum TokenProgramAgnosticSubcommand {
/// holder_npk - valid 32 byte hex string
#[arg(long)]
holder_npk: Option<String>,
/// to_ipk - valid 33 byte hex string
/// to_vpk - valid 33 byte hex string
#[arg(long)]
holder_ipk: Option<String>,
holder_vpk: Option<String>,
/// amount - amount of balance to mint
#[arg(long)]
amount: u128,
@ -160,10 +160,10 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
from,
to,
to_npk,
to_ipk,
to_vpk,
amount,
} => {
let underlying_subcommand = match (to, to_npk, to_ipk) {
let underlying_subcommand = match (to, to_npk, to_vpk) {
(None, None, None) => {
anyhow::bail!(
"Provide either account account_id of receiver or their public keys"
@ -220,7 +220,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
}
}
}
(None, Some(to_npk), Some(to_ipk)) => {
(None, Some(to_npk), Some(to_vpk)) => {
let (from, from_privacy) = parse_addr_with_privacy_prefix(&from)?;
match from_privacy {
@ -228,7 +228,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
TokenProgramSubcommandPrivate::TransferTokenPrivateForeign {
sender_account_id: from,
recipient_npk: to_npk,
recipient_ipk: to_ipk,
recipient_vpk: to_vpk,
balance_to_move: amount,
},
),
@ -236,7 +236,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
TokenProgramSubcommandShielded::TransferTokenShieldedForeign {
sender_account_id: from,
recipient_npk: to_npk,
recipient_ipk: to_ipk,
recipient_vpk: to_vpk,
balance_to_move: amount,
},
),
@ -302,10 +302,10 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
definition,
holder,
holder_npk,
holder_ipk,
holder_vpk,
amount,
} => {
let underlying_subcommand = match (holder, holder_npk, holder_ipk) {
let underlying_subcommand = match (holder, holder_npk, holder_vpk) {
(None, None, None) => {
anyhow::bail!(
"Provide either account account_id of holder or their public keys"
@ -363,7 +363,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
}
}
}
(None, Some(holder_npk), Some(holder_ipk)) => {
(None, Some(holder_npk), Some(holder_vpk)) => {
let (definition, definition_privacy) =
parse_addr_with_privacy_prefix(&definition)?;
@ -372,7 +372,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
TokenProgramSubcommandPrivate::MintTokenPrivateForeign {
definition_account_id: definition,
holder_npk,
holder_ipk,
holder_vpk,
amount,
},
),
@ -380,7 +380,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
TokenProgramSubcommandShielded::MintTokenShieldedForeign {
definition_account_id: definition,
holder_npk,
holder_ipk,
holder_vpk,
amount,
},
),
@ -465,9 +465,9 @@ pub enum TokenProgramSubcommandPrivate {
/// recipient_npk - valid 32 byte hex string
#[arg(long)]
recipient_npk: String,
/// recipient_ipk - valid 33 byte hex string
/// recipient_vpk - valid 33 byte hex string
#[arg(long)]
recipient_ipk: String,
recipient_vpk: String,
#[arg(short, long)]
balance_to_move: u128,
},
@ -496,7 +496,7 @@ pub enum TokenProgramSubcommandPrivate {
#[arg(short, long)]
holder_npk: String,
#[arg(short, long)]
holder_ipk: String,
holder_vpk: String,
#[arg(short, long)]
amount: u128,
},
@ -553,9 +553,9 @@ pub enum TokenProgramSubcommandShielded {
/// recipient_npk - valid 32 byte hex string
#[arg(long)]
recipient_npk: String,
/// recipient_ipk - valid 33 byte hex string
/// recipient_vpk - valid 33 byte hex string
#[arg(long)]
recipient_ipk: String,
recipient_vpk: String,
#[arg(short, long)]
balance_to_move: u128,
},
@ -584,7 +584,7 @@ pub enum TokenProgramSubcommandShielded {
#[arg(short, long)]
holder_npk: String,
#[arg(short, long)]
holder_ipk: String,
holder_vpk: String,
#[arg(short, long)]
amount: u128,
},
@ -745,7 +745,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
TokenProgramSubcommandPrivate::TransferTokenPrivateForeign {
sender_account_id,
recipient_npk,
recipient_ipk,
recipient_vpk,
balance_to_move,
} => {
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
@ -754,18 +754,18 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
recipient_npk.copy_from_slice(&recipient_npk_res);
let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk);
let recipient_ipk_res = hex::decode(recipient_ipk)?;
let mut recipient_ipk = [0u8; 33];
recipient_ipk.copy_from_slice(&recipient_ipk_res);
let recipient_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
recipient_ipk.to_vec(),
let recipient_vpk_res = hex::decode(recipient_vpk)?;
let mut recipient_vpk = [0u8; 33];
recipient_vpk.copy_from_slice(&recipient_vpk_res);
let recipient_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
recipient_vpk.to_vec(),
);
let (res, [secret_sender, _]) = Token(wallet_core)
.send_transfer_transaction_private_foreign_account(
sender_account_id,
recipient_npk,
recipient_ipk,
recipient_vpk,
balance_to_move,
)
.await?;
@ -865,7 +865,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
TokenProgramSubcommandPrivate::MintTokenPrivateForeign {
definition_account_id,
holder_npk,
holder_ipk,
holder_vpk,
amount,
} => {
let definition_account_id: AccountId = definition_account_id.parse().unwrap();
@ -875,18 +875,18 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
holder_npk.copy_from_slice(&holder_npk_res);
let holder_npk = nssa_core::NullifierPublicKey(holder_npk);
let holder_ipk_res = hex::decode(holder_ipk)?;
let mut holder_ipk = [0u8; 33];
holder_ipk.copy_from_slice(&holder_ipk_res);
let holder_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
holder_ipk.to_vec(),
let holder_vpk_res = hex::decode(holder_vpk)?;
let mut holder_vpk = [0u8; 33];
holder_vpk.copy_from_slice(&holder_vpk_res);
let holder_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
holder_vpk.to_vec(),
);
let (res, [secret_definition, _]) = Token(wallet_core)
.send_mint_transaction_private_foreign_account(
definition_account_id,
holder_npk,
holder_ipk,
holder_vpk,
amount,
)
.await?;
@ -1034,7 +1034,7 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
TokenProgramSubcommandShielded::TransferTokenShieldedForeign {
sender_account_id,
recipient_npk,
recipient_ipk,
recipient_vpk,
balance_to_move,
} => {
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
@ -1043,18 +1043,18 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
recipient_npk.copy_from_slice(&recipient_npk_res);
let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk);
let recipient_ipk_res = hex::decode(recipient_ipk)?;
let mut recipient_ipk = [0u8; 33];
recipient_ipk.copy_from_slice(&recipient_ipk_res);
let recipient_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
recipient_ipk.to_vec(),
let recipient_vpk_res = hex::decode(recipient_vpk)?;
let mut recipient_vpk = [0u8; 33];
recipient_vpk.copy_from_slice(&recipient_vpk_res);
let recipient_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
recipient_vpk.to_vec(),
);
let (res, _) = Token(wallet_core)
.send_transfer_transaction_shielded_foreign_account(
sender_account_id,
recipient_npk,
recipient_ipk,
recipient_vpk,
balance_to_move,
)
.await?;
@ -1177,7 +1177,7 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
TokenProgramSubcommandShielded::MintTokenShieldedForeign {
definition_account_id,
holder_npk,
holder_ipk,
holder_vpk,
amount,
} => {
let definition_account_id: AccountId = definition_account_id.parse().unwrap();
@ -1187,18 +1187,18 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
holder_npk.copy_from_slice(&holder_npk_res);
let holder_npk = nssa_core::NullifierPublicKey(holder_npk);
let holder_ipk_res = hex::decode(holder_ipk)?;
let mut holder_ipk = [0u8; 33];
holder_ipk.copy_from_slice(&holder_ipk_res);
let holder_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
holder_ipk.to_vec(),
let holder_vpk_res = hex::decode(holder_vpk)?;
let mut holder_vpk = [0u8; 33];
holder_vpk.copy_from_slice(&holder_vpk_res);
let holder_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
holder_vpk.to_vec(),
);
let (res, _) = Token(wallet_core)
.send_mint_transaction_shielded_foreign_account(
definition_account_id,
holder_npk,
holder_ipk,
holder_vpk,
amount,
)
.await?;

View File

@ -292,7 +292,7 @@ impl Default for WalletConfig {
},
{
"Private": {
"account_id": "3oCG8gqdKLMegw4rRfyaMQvuPHpcASt7xwttsmnZLSkw",
"account_id": "FpdcxBrMkHWqXCBQ6FG98eYfWGY6jWZRsKNSi1FwDMxy",
"account": {
"program_owner": [
0,
@ -310,218 +310,151 @@ impl Default for WalletConfig {
},
"key_chain": {
"secret_spending_key": [
251,
82,
235,
1,
146,
96,
30,
81,
162,
234,
239,
27,
159,
83,
199,
194,
132,
33,
15,
123,
129,
116,
0,
20,
28,
217,
103,
101,
57,
27,
125,
84,
136,
176,
70,
190,
224,
57,
19,
86,
98,
135,
161,
54,
134,
142,
154,
1,
18,
251,
242,
189
221,
108,
125,
152,
174,
161,
64,
16,
200
],
"private_key_holder": {
"nullifier_secret_key": [
29,
250,
10,
187,
35,
123,
180,
250,
246,
97,
216,
153,
44,
156,
71,
195,
16,
93,
241,
26,
174,
219,
72,
84,
34,
247,
112,
101,
217,
243,
189,
173,
75,
20
],
"incoming_viewing_secret_key": [
251,
201,
22,
154,
100,
165,
218,
108,
163,
190,
135,
91,
145,
84,
69,
241,
46,
117,
217,
110,
197,
248,
91,
193,
14,
104,
88,
103,
67,
153,
182,
158
],
"outgoing_viewing_secret_key": [
25,
67,
121,
76,
175,
100,
30,
198,
105,
123,
49,
169,
75,
178,
75,
210,
100,
143,
210,
243,
228,
243,
21,
18,
36,
84,
164,
186,
119,
0,
98,
35,
106,
139,
113,
214,
12
82,
145,
50,
27,
140,
206,
19,
53,
122,
166,
76,
195,
0,
16,
19,
21,
143,
155,
119,
9,
200,
81,
105
],
"viewing_secret_key": [
5,
117,
221,
27,
236,
199,
53,
22,
249,
231,
98,
147,
213,
116,
191,
82,
188,
148,
175,
98,
139,
52,
232,
249,
220,
217,
83,
58,
112,
155,
197,
196
]
},
"nullifer_public_key": [
63,
202,
178,
231,
183,
82,
237,
212,
216,
221,
215,
255,
153,
101,
177,
161,
254,
210,
128,
122,
54,
190,
230,
151,
183,
64,
225,
229,
113,
1,
228,
97
],
"incoming_viewing_public_key": [
3,
235,
139,
131,
237,
177,
122,
189,
6,
177,
167,
178,
202,
117,
246,
58,
28,
65,
132,
79,
220,
139,
119,
11,
87,
38,
254,
159,
231,
165,
1,
94,
64,
137,
243,
187,
160,
212,
121,
61,
247,
116,
72,
205
]
76,
249,
101,
251,
129,
33,
101,
189,
30,
42,
11,
191,
34,
103,
186,
227,
230
],
"viewing_public_key": [
2, 69, 126, 43, 158, 209, 172, 144, 23, 185, 208, 25, 163, 166, 176, 200, 225, 251, 106, 211, 4, 199, 112, 243, 207, 144, 135, 56, 157, 167, 32, 219, 38]
}
}
},
{
"Private": {
"account_id": "AKTcXgJ1xoynta1Ec7y6Jso1z1JQtHqd7aPQ1h9er6xX",
"account_id": "E8HwiTyQe4H9HK7icTvn95HQMnzx49mP9A2ddtMLpNaN",
"account": {
"program_owner": [
0,
@ -539,211 +472,20 @@ impl Default for WalletConfig {
},
"key_chain": {
"secret_spending_key": [
238,
171,
241,
69,
111,
217,
85,
64,
19,
82,
18,
189,
32,
91,
78,
175,
107,
7,
109,
60,
52,
44,
243,
230,
72,
244,
192,
92,
137,
33,
118,
254
],
48, 175, 124, 10, 230, 240, 166, 14, 249, 254, 157, 226, 208, 124, 122, 177, 203, 139, 192, 180, 43, 120, 55, 151, 50, 21, 113, 22, 254, 83, 148, 56],
"private_key_holder": {
"nullifier_secret_key": [
25,
211,
215,
119,
57,
223,
247,
37,
245,
144,
122,
29,
118,
245,
83,
228,
23,
9,
101,
120,
88,
33,
238,
207,
128,
61,
110,
2,
89,
62,
164,
13
99, 82, 190, 140, 234, 10, 61, 163, 15, 211, 179, 54, 70, 166, 87, 5, 182, 68, 117, 244, 217, 23, 99, 9, 4, 177, 230, 125, 109, 91, 160, 30
],
"incoming_viewing_secret_key": [
193,
181,
14,
196,
142,
84,
15,
65,
128,
101,
70,
196,
241,
47,
130,
221,
23,
146,
161,
237,
221,
40,
19,
126,
59,
15,
169,
236,
25,
105,
104,
231
],
"outgoing_viewing_secret_key": [
20,
170,
220,
108,
41,
23,
155,
217,
247,
190,
175,
168,
247,
34,
105,
134,
114,
74,
104,
91,
211,
62,
126,
13,
130,
100,
241,
214,
250,
236,
38,
150
"viewing_secret_key": [
205, 32, 76, 251, 255, 236, 96, 119, 61, 111, 65, 100, 75, 218, 12, 22, 17, 170, 55, 226, 21, 154, 161, 34, 208, 74, 27, 1, 119, 13, 88, 128
]
},
"nullifer_public_key": [
192,
251,
166,
243,
167,
236,
84,
249,
35,
136,
130,
172,
219,
225,
161,
139,
229,
89,
243,
125,
194,
213,
209,
30,
23,
174,
100,
244,
124,
74,
140,
47
32, 67, 72, 164, 106, 53, 66, 239, 141, 15, 52, 230, 136, 177, 2, 236, 207, 243, 134, 135, 210, 143, 87, 232, 215, 128, 194, 120, 113, 224, 4, 165
],
"incoming_viewing_public_key": [
2,
181,
98,
93,
216,
241,
241,
110,
58,
198,
119,
174,
250,
184,
1,
204,
200,
173,
44,
238,
37,
247,
170,
156,
100,
254,
116,
242,
28,
183,
187,
77,
255
"viewing_public_key": [
2, 79, 110, 46, 203, 29, 206, 205, 18, 86, 27, 189, 104, 103, 113, 181, 110, 53, 78, 172, 11, 171, 190, 18, 126, 214, 81, 77, 192, 154, 58, 195, 238
]
}
}

View File

@ -345,7 +345,7 @@ impl WalletCore {
Vec::from_iter(acc_manager.public_account_nonces()),
private_account_keys
.iter()
.map(|keys| (keys.npk.clone(), keys.ipk.clone(), keys.epk.clone()))
.map(|keys| (keys.npk.clone(), keys.vpk.clone(), keys.epk.clone()))
.collect(),
output,
)
@ -429,7 +429,7 @@ impl WalletCore {
.flat_map(|(acc_account_id, key_chain)| {
let view_tag = EncryptedAccountData::compute_view_tag(
key_chain.nullifer_public_key.clone(),
key_chain.incoming_viewing_public_key.clone(),
key_chain.viewing_public_key.clone(),
);
tx.message()

View File

@ -36,7 +36,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: winner_nsk,
npk: winner_npk,
ipk: winner_ipk,
vpk: winner_vpk,
auth_acc: winner_pre,
proof: _,
} = self
@ -50,7 +50,7 @@ impl WalletCore {
let pinata_pre = AccountWithMetadata::new(pinata_acc.clone(), false, pinata_account_id);
let eph_holder_winner = EphemeralKeyHolder::new(&winner_npk);
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_ipk);
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_vpk);
let (output, proof) = circuit::execute_and_prove(
&[pinata_pre, winner_pre],
@ -70,7 +70,7 @@ impl WalletCore {
vec![],
vec![(
winner_npk.clone(),
winner_ipk.clone(),
winner_vpk.clone(),
eph_holder_winner.generate_ephemeral_public_key(),
)],
output,
@ -103,7 +103,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: _,
npk: winner_npk,
ipk: winner_ipk,
vpk: winner_vpk,
auth_acc: winner_pre,
proof: _,
} = self
@ -117,7 +117,7 @@ impl WalletCore {
let pinata_pre = AccountWithMetadata::new(pinata_acc.clone(), false, pinata_account_id);
let eph_holder_winner = EphemeralKeyHolder::new(&winner_npk);
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_ipk);
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_vpk);
let (output, proof) = circuit::execute_and_prove(
&[pinata_pre, winner_pre],
@ -137,7 +137,7 @@ impl WalletCore {
vec![],
vec![(
winner_npk.clone(),
winner_ipk.clone(),
winner_vpk.clone(),
eph_holder_winner.generate_ephemeral_public_key(),
)],
output,

View File

@ -5,7 +5,7 @@ use nssa::{AccountId, PrivateKey};
use nssa_core::{
MembershipProof, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
account::{AccountWithMetadata, Nonce},
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
encryption::{EphemeralPublicKey, ViewingPublicKey},
};
use crate::WalletCore;
@ -16,7 +16,7 @@ pub enum PrivacyPreservingAccount {
PrivateOwned(AccountId),
PrivateForeign {
npk: NullifierPublicKey,
ipk: IncomingViewingPublicKey,
vpk: ViewingPublicKey,
},
}
@ -28,7 +28,7 @@ impl PrivacyPreservingAccount {
pub fn is_private(&self) -> bool {
matches!(
&self,
Self::PrivateOwned(_) | Self::PrivateForeign { npk: _, ipk: _ }
Self::PrivateOwned(_) | Self::PrivateForeign { npk: _, vpk: _ }
)
}
}
@ -36,7 +36,7 @@ impl PrivacyPreservingAccount {
pub struct PrivateAccountKeys {
pub npk: NullifierPublicKey,
pub ssk: SharedSecretKey,
pub ipk: IncomingViewingPublicKey,
pub vpk: ViewingPublicKey,
pub epk: EphemeralPublicKey,
}
@ -80,13 +80,13 @@ impl AccountManager {
(State::Private(pre), mask)
}
PrivacyPreservingAccount::PrivateForeign { npk, ipk } => {
PrivacyPreservingAccount::PrivateForeign { npk, vpk } => {
let acc = nssa_core::account::Account::default();
let auth_acc = AccountWithMetadata::new(acc, false, &npk);
let pre = AccountPreparedData {
nsk: None,
npk,
ipk,
vpk,
pre_state: auth_acc,
proof: None,
};
@ -138,8 +138,8 @@ impl AccountManager {
Some(PrivateAccountKeys {
npk: pre.npk.clone(),
ssk: eph_holder.calculate_shared_secret_sender(&pre.ipk),
ipk: pre.ipk.clone(),
ssk: eph_holder.calculate_shared_secret_sender(&pre.vpk),
vpk: pre.vpk.clone(),
epk: eph_holder.generate_ephemeral_public_key(),
})
}
@ -192,7 +192,7 @@ impl AccountManager {
struct AccountPreparedData {
nsk: Option<NullifierSecretKey>,
npk: NullifierPublicKey,
ipk: IncomingViewingPublicKey,
vpk: ViewingPublicKey,
pre_state: AccountWithMetadata,
proof: Option<MembershipProof>,
}
@ -213,7 +213,7 @@ async fn private_acc_preparation(
let nsk = from_keys.private_key_holder.nullifier_secret_key;
let from_npk = from_keys.nullifer_public_key;
let from_ipk = from_keys.incoming_viewing_public_key;
let from_vpk = from_keys.viewing_public_key;
// TODO: Remove this unwrap, error types must be compatible
let proof = wallet
@ -228,7 +228,7 @@ async fn private_acc_preparation(
Ok(AccountPreparedData {
nsk: Some(nsk),
npk: from_npk,
ipk: from_ipk,
vpk: from_vpk,
pre_state: sender_pre,
proof,
})

View File

@ -2,7 +2,7 @@ use std::vec;
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
use nssa::{AccountId, program::Program};
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey};
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
use super::{NativeTokenTransfer, auth_transfer_preparation};
use crate::PrivacyPreservingAccount;
@ -32,7 +32,7 @@ impl NativeTokenTransfer<'_> {
&self,
from: AccountId,
to_npk: NullifierPublicKey,
to_ipk: IncomingViewingPublicKey,
to_vpk: ViewingPublicKey,
balance_to_move: u128,
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move);
@ -43,7 +43,7 @@ impl NativeTokenTransfer<'_> {
PrivacyPreservingAccount::PrivateOwned(from),
PrivacyPreservingAccount::PrivateForeign {
npk: to_npk,
ipk: to_ipk,
vpk: to_vpk,
},
],
instruction_data,

View File

@ -1,6 +1,6 @@
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
use nssa::AccountId;
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey};
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
use super::{NativeTokenTransfer, auth_transfer_preparation};
use crate::PrivacyPreservingAccount;
@ -38,7 +38,7 @@ impl NativeTokenTransfer<'_> {
&self,
from: AccountId,
to_npk: NullifierPublicKey,
to_ipk: IncomingViewingPublicKey,
to_vpk: ViewingPublicKey,
balance_to_move: u128,
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move);
@ -49,7 +49,7 @@ impl NativeTokenTransfer<'_> {
PrivacyPreservingAccount::Public(from),
PrivacyPreservingAccount::PrivateForeign {
npk: to_npk,
ipk: to_ipk,
vpk: to_vpk,
},
],
instruction_data,

View File

@ -1,6 +1,6 @@
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
use nssa::{AccountId, program::Program};
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey};
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
use token_core::Instruction;
use crate::{PrivacyPreservingAccount, WalletCore};
@ -194,7 +194,7 @@ impl Token<'_> {
&self,
sender_account_id: AccountId,
recipient_npk: NullifierPublicKey,
recipient_ipk: IncomingViewingPublicKey,
recipient_vpk: ViewingPublicKey,
amount: u128,
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
let instruction = Instruction::Transfer {
@ -209,7 +209,7 @@ impl Token<'_> {
PrivacyPreservingAccount::PrivateOwned(sender_account_id),
PrivacyPreservingAccount::PrivateForeign {
npk: recipient_npk,
ipk: recipient_ipk,
vpk: recipient_vpk,
},
],
instruction_data,
@ -290,7 +290,7 @@ impl Token<'_> {
&self,
sender_account_id: AccountId,
recipient_npk: NullifierPublicKey,
recipient_ipk: IncomingViewingPublicKey,
recipient_vpk: ViewingPublicKey,
amount: u128,
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Transfer {
@ -305,7 +305,7 @@ impl Token<'_> {
PrivacyPreservingAccount::Public(sender_account_id),
PrivacyPreservingAccount::PrivateForeign {
npk: recipient_npk,
ipk: recipient_ipk,
vpk: recipient_vpk,
},
],
instruction_data,
@ -525,7 +525,7 @@ impl Token<'_> {
&self,
definition_account_id: AccountId,
holder_npk: NullifierPublicKey,
holder_ipk: IncomingViewingPublicKey,
holder_vpk: ViewingPublicKey,
amount: u128,
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
let instruction = Instruction::Mint {
@ -540,7 +540,7 @@ impl Token<'_> {
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
PrivacyPreservingAccount::PrivateForeign {
npk: holder_npk,
ipk: holder_ipk,
vpk: holder_vpk,
},
],
instruction_data,
@ -621,7 +621,7 @@ impl Token<'_> {
&self,
definition_account_id: AccountId,
holder_npk: NullifierPublicKey,
holder_ipk: IncomingViewingPublicKey,
holder_vpk: ViewingPublicKey,
amount: u128,
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Mint {
@ -636,7 +636,7 @@ impl Token<'_> {
PrivacyPreservingAccount::Public(definition_account_id),
PrivacyPreservingAccount::PrivateForeign {
npk: holder_npk,
ipk: holder_ipk,
vpk: holder_vpk,
},
],
instruction_data,

View File

@ -7,7 +7,7 @@ use nssa::{
};
use nssa_core::{
Commitment, MembershipProof, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
account::AccountWithMetadata, encryption::IncomingViewingPublicKey, program::InstructionData,
account::AccountWithMetadata, encryption::ViewingPublicKey, program::InstructionData,
};
use crate::{WalletCore, helperfunctions::produce_random_nonces};
@ -15,7 +15,7 @@ use crate::{WalletCore, helperfunctions::produce_random_nonces};
pub(crate) struct AccountPreparedData {
pub nsk: Option<NullifierSecretKey>,
pub npk: NullifierPublicKey,
pub ipk: IncomingViewingPublicKey,
pub vpk: ViewingPublicKey,
pub auth_acc: AccountWithMetadata,
pub proof: Option<MembershipProof>,
}
@ -40,7 +40,7 @@ impl WalletCore {
let mut proof = None;
let from_npk = from_keys.nullifer_public_key;
let from_ipk = from_keys.incoming_viewing_public_key;
let from_vpk = from_keys.viewing_public_key;
let sender_commitment = Commitment::new(&from_npk, &from_acc);
@ -61,7 +61,7 @@ impl WalletCore {
Ok(AccountPreparedData {
nsk,
npk: from_npk,
ipk: from_ipk,
vpk: from_vpk,
auth_acc: sender_pre,
proof,
})
@ -79,7 +79,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: from_nsk,
npk: from_npk,
ipk: from_ipk,
vpk: from_vpk,
auth_acc: sender_pre,
proof: from_proof,
} = self.private_acc_preparation(from, true, true).await?;
@ -87,7 +87,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: to_nsk,
npk: to_npk,
ipk: to_ipk,
vpk: to_vpk,
auth_acc: recipient_pre,
proof: _,
} = self.private_acc_preparation(to, true, false).await?;
@ -95,10 +95,10 @@ impl WalletCore {
tx_pre_check(&sender_pre.account, &recipient_pre.account)?;
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_vpk);
let eph_holder_to = EphemeralKeyHolder::new(&to_npk);
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_ipk);
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_vpk);
let (output, proof) = circuit::execute_and_prove(
&[sender_pre, recipient_pre],
@ -123,12 +123,12 @@ impl WalletCore {
vec![
(
from_npk.clone(),
from_ipk.clone(),
from_vpk.clone(),
eph_holder_from.generate_ephemeral_public_key(),
),
(
to_npk.clone(),
to_ipk.clone(),
to_vpk.clone(),
eph_holder_to.generate_ephemeral_public_key(),
),
],
@ -156,7 +156,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: from_nsk,
npk: from_npk,
ipk: from_ipk,
vpk: from_vpk,
auth_acc: sender_pre,
proof: from_proof,
} = self.private_acc_preparation(from, true, true).await?;
@ -164,7 +164,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: _,
npk: to_npk,
ipk: to_ipk,
vpk: to_vpk,
auth_acc: recipient_pre,
proof: _,
} = self.private_acc_preparation(to, false, false).await?;
@ -172,10 +172,10 @@ impl WalletCore {
tx_pre_check(&sender_pre.account, &recipient_pre.account)?;
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_vpk);
let eph_holder_to = EphemeralKeyHolder::new(&to_npk);
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_ipk);
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_vpk);
let (output, proof) = circuit::execute_and_prove(
&[sender_pre, recipient_pre],
@ -197,12 +197,12 @@ impl WalletCore {
vec![
(
from_npk.clone(),
from_ipk.clone(),
from_vpk.clone(),
eph_holder_from.generate_ephemeral_public_key(),
),
(
to_npk.clone(),
to_ipk.clone(),
to_vpk.clone(),
eph_holder_to.generate_ephemeral_public_key(),
),
],
@ -223,7 +223,7 @@ impl WalletCore {
&self,
from: AccountId,
to_npk: NullifierPublicKey,
to_ipk: IncomingViewingPublicKey,
to_vpk: ViewingPublicKey,
instruction_data: InstructionData,
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
program: Program,
@ -231,7 +231,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: from_nsk,
npk: from_npk,
ipk: from_ipk,
vpk: from_vpk,
auth_acc: sender_pre,
proof: from_proof,
} = self.private_acc_preparation(from, true, true).await?;
@ -244,8 +244,8 @@ impl WalletCore {
let eph_holder = EphemeralKeyHolder::new(&to_npk);
let shared_secret_from = eph_holder.calculate_shared_secret_sender(&from_ipk);
let shared_secret_to = eph_holder.calculate_shared_secret_sender(&to_ipk);
let shared_secret_from = eph_holder.calculate_shared_secret_sender(&from_vpk);
let shared_secret_to = eph_holder.calculate_shared_secret_sender(&to_vpk);
let (output, proof) = circuit::execute_and_prove(
&[sender_pre, recipient_pre],
@ -267,12 +267,12 @@ impl WalletCore {
vec![
(
from_npk.clone(),
from_ipk.clone(),
from_vpk.clone(),
eph_holder.generate_ephemeral_public_key(),
),
(
to_npk.clone(),
to_ipk.clone(),
to_vpk.clone(),
eph_holder.generate_ephemeral_public_key(),
),
],
@ -301,7 +301,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: from_nsk,
npk: from_npk,
ipk: from_ipk,
vpk: from_vpk,
auth_acc: sender_pre,
proof: from_proof,
} = self.private_acc_preparation(from, true, true).await?;
@ -315,7 +315,7 @@ impl WalletCore {
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, to);
let eph_holder = EphemeralKeyHolder::new(&from_npk);
let shared_secret = eph_holder.calculate_shared_secret_sender(&from_ipk);
let shared_secret = eph_holder.calculate_shared_secret_sender(&from_vpk);
let (output, proof) = circuit::execute_and_prove(
&[sender_pre, recipient_pre],
@ -333,7 +333,7 @@ impl WalletCore {
vec![],
vec![(
from_npk.clone(),
from_ipk.clone(),
from_vpk.clone(),
eph_holder.generate_ephemeral_public_key(),
)],
output,
@ -366,7 +366,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: to_nsk,
npk: to_npk,
ipk: to_ipk,
vpk: to_vpk,
auth_acc: recipient_pre,
proof: _,
} = self.private_acc_preparation(to, true, false).await?;
@ -376,7 +376,7 @@ impl WalletCore {
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
let eph_holder = EphemeralKeyHolder::new(&to_npk);
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_vpk);
let (output, proof) = circuit::execute_and_prove(
&[sender_pre, recipient_pre],
@ -394,7 +394,7 @@ impl WalletCore {
vec![from_acc.nonce],
vec![(
to_npk.clone(),
to_ipk.clone(),
to_vpk.clone(),
eph_holder.generate_ephemeral_public_key(),
)],
output,
@ -432,7 +432,7 @@ impl WalletCore {
let AccountPreparedData {
nsk: _,
npk: to_npk,
ipk: to_ipk,
vpk: to_vpk,
auth_acc: recipient_pre,
proof: _,
} = self.private_acc_preparation(to, false, false).await?;
@ -442,7 +442,7 @@ impl WalletCore {
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
let eph_holder = EphemeralKeyHolder::new(&to_npk);
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_vpk);
let (output, proof) = circuit::execute_and_prove(
&[sender_pre, recipient_pre],
@ -460,7 +460,7 @@ impl WalletCore {
vec![from_acc.nonce],
vec![(
to_npk.clone(),
to_ipk.clone(),
to_vpk.clone(),
eph_holder.generate_ephemeral_public_key(),
)],
output,
@ -487,7 +487,7 @@ impl WalletCore {
&self,
from: AccountId,
to_npk: NullifierPublicKey,
to_ipk: IncomingViewingPublicKey,
to_vpk: ViewingPublicKey,
instruction_data: InstructionData,
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
program: Program,
@ -504,7 +504,7 @@ impl WalletCore {
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
let eph_holder = EphemeralKeyHolder::new(&to_npk);
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_vpk);
let (output, proof) = circuit::execute_and_prove(
&[sender_pre, recipient_pre],
@ -522,7 +522,7 @@ impl WalletCore {
vec![from_acc.nonce],
vec![(
to_npk.clone(),
to_ipk.clone(),
to_vpk.clone(),
eph_holder.generate_ephemeral_public_key(),
)],
output,
@ -548,13 +548,13 @@ impl WalletCore {
let AccountPreparedData {
nsk: _,
npk: from_npk,
ipk: from_ipk,
vpk: from_vpk,
auth_acc: sender_pre,
proof: _,
} = self.private_acc_preparation(from, false, false).await?;
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_vpk);
let instruction: u128 = 0;
@ -574,7 +574,7 @@ impl WalletCore {
vec![],
vec![(
from_npk.clone(),
from_ipk.clone(),
from_vpk.clone(),
eph_holder_from.generate_ephemeral_public_key(),
)],
output,