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: # Output:
Generated new account with account_id Private/HMRHZdPw4pbyPVZHNGrV6K5AA95wACFsHTRST84fr3CF Generated new account with account_id Private/HMRHZdPw4pbyPVZHNGrV6K5AA95wACFsHTRST84fr3CF
With npk 6a2dfe433cf28e525aa0196d719be3c16146f7ee358ca39595323f94fde38f93 With npk 6a2dfe433cf28e525aa0196d719be3c16146f7ee358ca39595323f94fde38f93
With ipk 03d59abf4bee974cc12ddb44641c19f0b5441fef39191f047c988c29a77252a577 With vpk 03d59abf4bee974cc12ddb44641c19f0b5441fef39191f047c988c29a77252a577
``` ```
2. Create the token (Token B): 2. Create the token (Token B):

View File

@ -154,11 +154,11 @@ wallet account new private
# Output: # Output:
Generated new account with account_id Private/HacPU3hakLYzWtSqUPw6TUr8fqoMieVWovsUR6sJf7cL Generated new account with account_id Private/HacPU3hakLYzWtSqUPw6TUr8fqoMieVWovsUR6sJf7cL
With npk e6366f79d026c8bd64ae6b3d601f0506832ec682ab54897f205fffe64ec0d951 With npk e6366f79d026c8bd64ae6b3d601f0506832ec682ab54897f205fffe64ec0d951
With ipk 02ddc96d0eb56e00ce14994cfdaec5ae1f76244180a919545983156e3519940a17 With vpk 02ddc96d0eb56e00ce14994cfdaec5ae1f76244180a919545983156e3519940a17
``` ```
> [!Tip] > [!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: Just like public accounts, new private accounts start out uninitialized:
@ -228,17 +228,17 @@ wallet account new private
# Output: # Output:
Generated new account with account_id Private/AukXPRBmrYVqoqEW2HTs7N3hvTn3qdNFDcxDHVr5hMm5 Generated new account with account_id Private/AukXPRBmrYVqoqEW2HTs7N3hvTn3qdNFDcxDHVr5hMm5
With npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e With npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e
With ipk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72 With vpk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72
``` ```
> [!Tip] > [!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 ```bash
wallet auth-transfer send \ wallet auth-transfer send \
--from Public/Ev1JprP9BmhbFVQyBcbznU8bAXcwrzwRoPTetXdQPAWS \ --from Public/Ev1JprP9BmhbFVQyBcbznU8bAXcwrzwRoPTetXdQPAWS \
--to-npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e \ --to-npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e \
--to-ipk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72 \ --to-vpk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72 \
--amount 3 --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' \ '--from[Source account ID]:from_account:_wallet_account_ids' \
'--to[Destination account ID (for owned accounts)]:to_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-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:' '--amount[Amount of native tokens to send]:amount:'
;; ;;
esac esac
@ -164,7 +164,7 @@ _wallet_account() {
get) get)
_arguments \ _arguments \
'(-r --raw)'{-r,--raw}'[Get raw account data]' \ '(-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' '(-a --account-id)'{-a,--account-id}'[Account ID to query]:account_id:_wallet_account_ids'
;; ;;
list|ls) list|ls)
@ -255,7 +255,7 @@ _wallet_token() {
'--from[Source holding account ID]:from_account:_wallet_account_ids' \ '--from[Source holding account ID]:from_account:_wallet_account_ids' \
'--to[Destination holding account ID (for owned accounts)]:to_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-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:' '--amount[Amount of tokens to send]:amount:'
;; ;;
burn) burn)
@ -269,7 +269,7 @@ _wallet_token() {
'--definition[Definition account ID]:definition_account:_wallet_account_ids' \ '--definition[Definition account ID]:definition_account:_wallet_account_ids' \
'--holder[Holder account ID (for owned accounts)]:holder_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-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:' '--amount[Amount of tokens to mint]:amount:'
;; ;;
esac esac

View File

@ -29,40 +29,7 @@
], ],
"initial_commitments": [ "initial_commitments": [
{ {
"npk": [ "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],
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
],
"account": { "account": {
"program_owner": [ "program_owner": [
0, 0,
@ -80,40 +47,7 @@
} }
}, },
{ {
"npk": [ "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],
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
],
"account": { "account": {
"program_owner": [ "program_owner": [
0, 0,

View File

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

View File

@ -26,7 +26,7 @@ async fn private_transfer_to_owned_account() -> Result<()> {
from: format_private_account_id(from), from: format_private_account_id(from),
to: Some(format_private_account_id(to)), to: Some(format_private_account_id(to)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 100, amount: 100,
}); });
@ -59,13 +59,13 @@ async fn private_transfer_to_foreign_account() -> Result<()> {
let from: AccountId = ctx.existing_private_accounts()[0]; let from: AccountId = ctx.existing_private_accounts()[0];
let to_npk = NullifierPublicKey([42; 32]); let to_npk = NullifierPublicKey([42; 32]);
let to_npk_string = hex::encode(to_npk.0); 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 { let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
from: format_private_account_id(from), from: format_private_account_id(from),
to: None, to: None,
to_npk: Some(to_npk_string), to_npk: Some(to_npk_string),
to_ipk: Some(hex::encode(to_ipk.0)), to_vpk: Some(hex::encode(to_vpk.0)),
amount: 100, amount: 100,
}); });
@ -113,7 +113,7 @@ async fn deshielded_transfer_to_public_account() -> Result<()> {
from: format_private_account_id(from), from: format_private_account_id(from),
to: Some(format_public_account_id(to)), to: Some(format_public_account_id(to)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 100, amount: 100,
}); });
@ -168,12 +168,12 @@ async fn private_transfer_to_owned_account_using_claiming_path() -> Result<()> {
.cloned() .cloned()
.context("Failed to get private account")?; .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 { let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
from: format_private_account_id(from), from: format_private_account_id(from),
to: None, to: None,
to_npk: Some(hex::encode(to_keys.nullifer_public_key.0)), 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, amount: 100,
}); });
@ -221,7 +221,7 @@ async fn shielded_transfer_to_owned_private_account() -> Result<()> {
from: format_public_account_id(from), from: format_public_account_id(from),
to: Some(format_private_account_id(to)), to: Some(format_private_account_id(to)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 100, amount: 100,
}); });
@ -256,14 +256,14 @@ async fn shielded_transfer_to_foreign_account() -> Result<()> {
let to_npk = NullifierPublicKey([42; 32]); let to_npk = NullifierPublicKey([42; 32]);
let to_npk_string = hex::encode(to_npk.0); 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 from: AccountId = ctx.existing_public_accounts()[0];
let command = Command::AuthTransfer(AuthTransferSubcommand::Send { let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
from: format_public_account_id(from), from: format_public_account_id(from),
to: None, to: None,
to_npk: Some(to_npk_string), to_npk: Some(to_npk_string),
to_ipk: Some(hex::encode(to_ipk.0)), to_vpk: Some(hex::encode(to_vpk.0)),
amount: 100, amount: 100,
}); });
@ -325,12 +325,12 @@ async fn private_transfer_to_owned_account_continuous_run_path() -> Result<()> {
.cloned() .cloned()
.context("Failed to get private account")?; .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 { let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
from: format_private_account_id(from), from: format_private_account_id(from),
to: None, to: None,
to_npk: Some(hex::encode(to_keys.nullifer_public_key.0)), 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, 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]), from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])), to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 100, 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]), from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(new_persistent_account_id)), to: Some(format_public_account_id(new_persistent_account_id)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 100, amount: 100,
}); });
@ -108,7 +108,7 @@ async fn failed_transfer_with_insufficient_balance() -> Result<()> {
from: format_public_account_id(ctx.existing_public_accounts()[0]), from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])), to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 1000000, amount: 1000000,
}); });
@ -146,7 +146,7 @@ async fn two_consecutive_successful_transfers() -> Result<()> {
from: format_public_account_id(ctx.existing_public_accounts()[0]), from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])), to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 100, amount: 100,
}); });
@ -178,7 +178,7 @@ async fn two_consecutive_successful_transfers() -> Result<()> {
from: format_public_account_id(ctx.existing_public_accounts()[0]), from: format_public_account_id(ctx.existing_public_accounts()[0]),
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])), to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 100, amount: 100,
}); });

View File

@ -50,7 +50,7 @@ async fn restore_keys_from_seed() -> Result<()> {
from: format_private_account_id(from), from: format_private_account_id(from),
to: Some(format_private_account_id(to_account_id1)), to: Some(format_private_account_id(to_account_id1)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 100, amount: 100,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; 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), from: format_private_account_id(from),
to: Some(format_private_account_id(to_account_id2)), to: Some(format_private_account_id(to_account_id2)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 101, amount: 101,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; 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), from: format_public_account_id(from),
to: Some(format_public_account_id(to_account_id3)), to: Some(format_public_account_id(to_account_id3)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 102, amount: 102,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; 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), from: format_public_account_id(from),
to: Some(format_public_account_id(to_account_id4)), to: Some(format_public_account_id(to_account_id4)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 103, amount: 103,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; 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), from: format_private_account_id(to_account_id1),
to: Some(format_private_account_id(to_account_id2)), to: Some(format_private_account_id(to_account_id2)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 10, amount: 10,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; 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), from: format_public_account_id(to_account_id3),
to: Some(format_public_account_id(to_account_id4)), to: Some(format_public_account_id(to_account_id4)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: 11, amount: 11,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; 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), from: format_public_account_id(supply_account_id),
to: Some(format_public_account_id(recipient_account_id)), to: Some(format_public_account_id(recipient_account_id)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
}; };
@ -208,7 +208,7 @@ async fn create_and_transfer_public_token() -> Result<()> {
definition: format_public_account_id(definition_account_id), definition: format_public_account_id(definition_account_id),
holder: Some(format_public_account_id(recipient_account_id)), holder: Some(format_public_account_id(recipient_account_id)),
holder_npk: None, holder_npk: None,
holder_ipk: None, holder_vpk: None,
amount: mint_amount, 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), from: format_private_account_id(supply_account_id),
to: Some(format_private_account_id(recipient_account_id)), to: Some(format_private_account_id(recipient_account_id)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
}; };
@ -525,7 +525,7 @@ async fn create_token_with_private_definition() -> Result<()> {
definition: format_private_account_id(definition_account_id), definition: format_private_account_id(definition_account_id),
holder: Some(format_public_account_id(recipient_account_id_public)), holder: Some(format_public_account_id(recipient_account_id_public)),
holder_npk: None, holder_npk: None,
holder_ipk: None, holder_vpk: None,
amount: mint_amount_public, amount: mint_amount_public,
}; };
@ -572,7 +572,7 @@ async fn create_token_with_private_definition() -> Result<()> {
definition: format_private_account_id(definition_account_id), definition: format_private_account_id(definition_account_id),
holder: Some(format_private_account_id(recipient_account_id_private)), holder: Some(format_private_account_id(recipient_account_id_private)),
holder_npk: None, holder_npk: None,
holder_ipk: None, holder_vpk: None,
amount: mint_amount_private, 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), from: format_private_account_id(supply_account_id),
to: Some(format_private_account_id(recipient_account_id)), to: Some(format_private_account_id(recipient_account_id)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
}; };
@ -819,7 +819,7 @@ async fn shielded_token_transfer() -> Result<()> {
from: format_public_account_id(supply_account_id), from: format_public_account_id(supply_account_id),
to: Some(format_private_account_id(recipient_account_id)), to: Some(format_private_account_id(recipient_account_id)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
}; };
@ -933,7 +933,7 @@ async fn deshielded_token_transfer() -> Result<()> {
from: format_private_account_id(supply_account_id), from: format_private_account_id(supply_account_id),
to: Some(format_public_account_id(recipient_account_id)), to: Some(format_public_account_id(recipient_account_id)),
to_npk: None, to_npk: None,
to_ipk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
}; };
@ -1056,7 +1056,7 @@ async fn token_claiming_path_with_private_accounts() -> Result<()> {
definition: format_private_account_id(definition_account_id), definition: format_private_account_id(definition_account_id),
holder: None, holder: None,
holder_npk: Some(hex::encode(holder_keys.nullifer_public_key.0)), 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, amount: mint_amount,
}; };

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
use k256::{Scalar, elliptic_curve::PrimeField}; use k256::{Scalar, elliptic_curve::PrimeField};
use nssa_core::encryption::IncomingViewingPublicKey; use nssa_core::{NullifierPublicKey, encryption::ViewingPublicKey};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::key_management::{ use crate::key_management::{
@ -18,7 +18,7 @@ pub struct ChildKeysPrivate {
impl KeyNode for ChildKeysPrivate { impl KeyNode for ChildKeysPrivate {
fn root(seed: [u8; 64]) -> Self { 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( let ssk = SecretSpendingKey(
*hash_value *hash_value
@ -29,23 +29,21 @@ impl KeyNode for ChildKeysPrivate {
.last_chunk::<32>() .last_chunk::<32>()
.expect("hash_value is 64 bytes, must be safe to get last 32"); .expect("hash_value is 64 bytes, must be safe to get last 32");
let nsk = ssk.generate_nullifier_secret_key(); let nsk = ssk.generate_nullifier_secret_key(None);
let isk = ssk.generate_incoming_viewing_secret_key(); let vsk = ssk.generate_viewing_secret_key(None);
let ovk = ssk.generate_outgoing_viewing_secret_key();
let npk = (&nsk).into(); let npk = NullifierPublicKey::from(&nsk);
let ipk = IncomingViewingPublicKey::from_scalar(isk); let vpk = ViewingPublicKey::from_scalar(vsk);
Self { Self {
value: ( value: (
KeyChain { KeyChain {
secret_spending_key: ssk, secret_spending_key: ssk,
nullifer_public_key: npk, nullifer_public_key: npk,
incoming_viewing_public_key: ipk, viewing_public_key: vpk,
private_key_holder: PrivateKeyHolder { private_key_holder: PrivateKeyHolder {
nullifier_secret_key: nsk, nullifier_secret_key: nsk,
incoming_viewing_secret_key: isk, viewing_secret_key: vsk,
outgoing_viewing_secret_key: ovk,
}, },
}, },
nssa::Account::default(), nssa::Account::default(),
@ -56,27 +54,14 @@ impl KeyNode for ChildKeysPrivate {
} }
fn nth_child(&self, cci: u32) -> Self { fn nth_child(&self, cci: u32) -> Self {
let parent_pt = Scalar::from_repr( let parent_pt =
self.value Scalar::from_repr(self.value.0.private_key_holder.nullifier_secret_key.into())
.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())
.expect("Key generated as scalar, must be valid representation") .expect("Key generated as scalar, must be valid representation")
* Scalar::from_repr( * Scalar::from_repr(self.value.0.private_key_holder.viewing_secret_key.into())
self.value .expect("Key generated as scalar, must be valid representation");
.0
.private_key_holder
.incoming_viewing_secret_key
.into(),
)
.expect("Key generated as scalar, must be valid representation");
let mut input = vec![]; 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(&parent_pt.to_bytes());
input.extend_from_slice(&cci.to_le_bytes()); input.extend_from_slice(&cci.to_le_bytes());
@ -91,23 +76,21 @@ impl KeyNode for ChildKeysPrivate {
.last_chunk::<32>() .last_chunk::<32>()
.expect("hash_value is 64 bytes, must be safe to get last 32"); .expect("hash_value is 64 bytes, must be safe to get last 32");
let nsk = ssk.generate_nullifier_secret_key(); let nsk = ssk.generate_nullifier_secret_key(Some(cci));
let isk = ssk.generate_incoming_viewing_secret_key(); let vsk = ssk.generate_viewing_secret_key(Some(cci));
let ovk = ssk.generate_outgoing_viewing_secret_key();
let npk = (&nsk).into(); let npk = NullifierPublicKey::from(&nsk);
let ipk = IncomingViewingPublicKey::from_scalar(isk); let vpk = ViewingPublicKey::from_scalar(vsk);
Self { Self {
value: ( value: (
KeyChain { KeyChain {
secret_spending_key: ssk, secret_spending_key: ssk,
nullifer_public_key: npk, nullifer_public_key: npk,
incoming_viewing_public_key: ipk, viewing_public_key: vpk,
private_key_holder: PrivateKeyHolder { private_key_holder: PrivateKeyHolder {
nullifier_secret_key: nsk, nullifier_secret_key: nsk,
incoming_viewing_secret_key: isk, viewing_secret_key: vsk,
outgoing_viewing_secret_key: ovk,
}, },
}, },
nssa::Account::default(), nssa::Account::default(),
@ -144,120 +127,98 @@ impl<'a> From<&'a mut ChildKeysPrivate> for &'a mut (KeyChain, nssa::Account) {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use nssa_core::{NullifierPublicKey, NullifierSecretKey};
use super::*; use super::*;
use crate::key_management::{self, secret_holders::ViewingSecretKey};
#[test] #[test]
fn test_keys_deterministic_generation() { fn test_master_key_generation() {
let root_keys = ChildKeysPrivate::root([42; 64]); let seed: [u8; 64] = [
let child_keys = root_keys.nth_child(5); 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); let keys = ChildKeysPrivate::root(seed);
assert_eq!(child_keys.cci, Some(5));
assert_eq!( let expected_ssk: SecretSpendingKey = key_management::secret_holders::SecretSpendingKey([
root_keys.value.0.secret_spending_key.0, 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,
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
]
);
assert_eq!( let expected_ccc = [
root_keys.value.0.private_key_holder.nullifier_secret_key, 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,
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
]
);
assert_eq!( let expected_nsk: NullifierSecretKey = [
root_keys 154, 102, 103, 5, 34, 235, 227, 13, 22, 182, 226, 11, 7, 67, 110, 162, 99, 193, 174,
.value 34, 234, 19, 222, 2, 22, 12, 163, 252, 88, 11, 0, 163,
.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
]
);
assert_eq!( let expected_npk: NullifierPublicKey = nssa_core::NullifierPublicKey([
root_keys 7, 123, 125, 191, 233, 183, 201, 4, 20, 214, 155, 210, 45, 234, 27, 240, 194, 111, 97,
.value 247, 155, 113, 122, 246, 192, 0, 70, 61, 76, 71, 70, 2,
.0 ]);
.private_key_holder let expected_vsk: ViewingSecretKey = [
.outgoing_viewing_secret_key, 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,
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
]
);
assert_eq!( let expected_vpk_as_bytes: [u8; 33] = [
root_keys.value.0.nullifer_public_key.0, 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,
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
]
);
assert_eq!( assert!(expected_ssk == keys.value.0.secret_spending_key);
root_keys.value.0.incoming_viewing_public_key.0, assert!(expected_ccc == keys.ccc);
&[ assert!(expected_nsk == keys.value.0.private_key_holder.nullifier_secret_key);
3, 174, 56, 136, 244, 179, 18, 122, 38, 220, 36, 50, 200, 41, 104, 167, 70, 18, 60, assert!(expected_npk == keys.value.0.nullifer_public_key);
202, 93, 193, 29, 16, 125, 252, 96, 51, 199, 152, 47, 233, 178 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());
); }
assert_eq!(
child_keys.value.0.incoming_viewing_public_key.0, #[test]
&[ fn test_child_keys_generation() {
3, 18, 202, 246, 79, 141, 169, 51, 55, 202, 120, 169, 244, 201, 156, 162, 216, 115, let seed: [u8; 64] = [
126, 53, 46, 94, 235, 125, 114, 178, 215, 81, 171, 93, 93, 88, 117 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::{ use nssa_core::{
NullifierPublicKey, SharedSecretKey, NullifierPublicKey, SharedSecretKey,
encryption::{EphemeralPublicKey, IncomingViewingPublicKey}, encryption::{EphemeralPublicKey, ViewingPublicKey},
}; };
use secret_holders::{PrivateKeyHolder, SecretSpendingKey, SeedHolder}; use secret_holders::{PrivateKeyHolder, SecretSpendingKey, SeedHolder};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -17,7 +17,7 @@ pub struct KeyChain {
pub secret_spending_key: SecretSpendingKey, pub secret_spending_key: SecretSpendingKey,
pub private_key_holder: PrivateKeyHolder, pub private_key_holder: PrivateKeyHolder,
pub nullifer_public_key: NullifierPublicKey, pub nullifer_public_key: NullifierPublicKey,
pub incoming_viewing_public_key: IncomingViewingPublicKey, pub viewing_public_key: ViewingPublicKey,
} }
impl KeyChain { impl KeyChain {
@ -27,16 +27,16 @@ impl KeyChain {
let seed_holder = SeedHolder::new_os_random(); let seed_holder = SeedHolder::new_os_random();
let secret_spending_key = seed_holder.produce_top_secret_key_holder(); 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 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 { Self {
secret_spending_key, secret_spending_key,
private_key_holder, private_key_holder,
nullifer_public_key, nullifer_public_key,
incoming_viewing_public_key, viewing_public_key,
} }
} }
@ -46,16 +46,16 @@ impl KeyChain {
let seed_holder = SeedHolder::new_mnemonic(passphrase); let seed_holder = SeedHolder::new_mnemonic(passphrase);
let secret_spending_key = seed_holder.produce_top_secret_key_holder(); 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 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 { Self {
secret_spending_key, secret_spending_key,
private_key_holder, private_key_holder,
nullifer_public_key, nullifer_public_key,
incoming_viewing_public_key, viewing_public_key,
} }
} }
@ -64,9 +64,7 @@ impl KeyChain {
ephemeral_public_key_sender: EphemeralPublicKey, ephemeral_public_key_sender: EphemeralPublicKey,
) -> SharedSecretKey { ) -> SharedSecretKey {
SharedSecretKey::new( SharedSecretKey::new(
&self &self.secret_spending_key.generate_viewing_secret_key(None),
.secret_spending_key
.generate_incoming_viewing_secret_key(),
&ephemeral_public_key_sender, &ephemeral_public_key_sender,
) )
} }
@ -112,10 +110,10 @@ mod tests {
let seed_holder = SeedHolder::new_os_random(); let seed_holder = SeedHolder::new_os_random();
let top_secret_key_holder = seed_holder.produce_top_secret_key_holder(); 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 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(); let pub_account_signing_key = nssa::PrivateKey::new_os_random();

View File

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

View File

@ -159,6 +159,7 @@ mod tests {
assert_eq!(new_acc_with_metadata.account_id, fingerprint); assert_eq!(new_acc_with_metadata.account_id, fingerprint);
} }
#[cfg(feature = "host")]
#[test] #[test]
fn parse_valid_account_id() { fn parse_valid_account_id() {
let base58_str = "11111111111111111111111111111111"; let base58_str = "11111111111111111111111111111111";
@ -166,6 +167,7 @@ mod tests {
assert_eq!(account_id.value, [0u8; 32]); assert_eq!(account_id.value, [0u8; 32]);
} }
#[cfg(feature = "host")]
#[test] #[test]
fn parse_invalid_base58() { fn parse_invalid_base58() {
let base58_str = "00".repeat(32); // invalid base58 chars let base58_str = "00".repeat(32); // invalid base58 chars
@ -173,6 +175,7 @@ mod tests {
assert!(matches!(result, AccountIdError::InvalidBase58(_))); assert!(matches!(result, AccountIdError::InvalidBase58(_)));
} }
#[cfg(feature = "host")]
#[test] #[test]
fn parse_wrong_length_short() { fn parse_wrong_length_short() {
let base58_str = "11".repeat(31); // 62 chars = 31 bytes let base58_str = "11".repeat(31); // 62 chars = 31 bytes
@ -180,6 +183,7 @@ mod tests {
assert!(matches!(result, AccountIdError::InvalidLength(_))); assert!(matches!(result, AccountIdError::InvalidLength(_)));
} }
#[cfg(feature = "host")]
#[test] #[test]
fn parse_wrong_length_long() { fn parse_wrong_length_long() {
let base58_str = "11".repeat(33); // 66 chars = 33 bytes 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; pub mod shared_key_derivation;
#[cfg(feature = "host")] #[cfg(feature = "host")]
pub use shared_key_derivation::{EphemeralPublicKey, EphemeralSecretKey, IncomingViewingPublicKey}; pub use shared_key_derivation::{EphemeralPublicKey, EphemeralSecretKey, ViewingPublicKey};
use crate::{Commitment, account::Account}; use crate::{Commitment, account::Account};

View File

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

View File

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

View File

@ -223,7 +223,7 @@ mod tests {
let expected_sender_pre = sender.clone(); let expected_sender_pre = sender.clone();
let esk = [3; 32]; 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( let (output, proof) = execute_and_prove(
vec![sender, recipient], vec![sender, recipient],
@ -316,10 +316,10 @@ mod tests {
]; ];
let esk_1 = [3; 32]; 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 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( let (output, proof) = execute_and_prove(
vec![sender_pre.clone(), recipient], vec![sender_pre.clone(), recipient],

View File

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

View File

@ -315,7 +315,7 @@ pub mod tests {
use nssa_core::{ use nssa_core::{
Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey, Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
account::{Account, AccountId, AccountWithMetadata, Nonce, data::Data}, account::{Account, AccountId, AccountWithMetadata, Nonce, data::Data},
encryption::{EphemeralPublicKey, IncomingViewingPublicKey, Scalar}, encryption::{EphemeralPublicKey, Scalar, ViewingPublicKey},
program::{PdaSeed, ProgramId}, program::{PdaSeed, ProgramId},
}; };
use token_core::{TokenDefinition, TokenHolding}; use token_core::{TokenDefinition, TokenHolding};
@ -864,7 +864,7 @@ pub mod tests {
pub struct TestPrivateKeys { pub struct TestPrivateKeys {
pub nsk: NullifierSecretKey, pub nsk: NullifierSecretKey,
pub isk: Scalar, pub vsk: Scalar,
} }
impl TestPrivateKeys { impl TestPrivateKeys {
@ -872,22 +872,22 @@ pub mod tests {
NullifierPublicKey::from(&self.nsk) NullifierPublicKey::from(&self.nsk)
} }
pub fn ivk(&self) -> IncomingViewingPublicKey { pub fn vpk(&self) -> ViewingPublicKey {
IncomingViewingPublicKey::from_scalar(self.isk) ViewingPublicKey::from_scalar(self.vsk)
} }
} }
pub fn test_private_account_keys_1() -> TestPrivateKeys { pub fn test_private_account_keys_1() -> TestPrivateKeys {
TestPrivateKeys { TestPrivateKeys {
nsk: [13; 32], nsk: [13; 32],
isk: [31; 32], vsk: [31; 32],
} }
} }
pub fn test_private_account_keys_2() -> TestPrivateKeys { pub fn test_private_account_keys_2() -> TestPrivateKeys {
TestPrivateKeys { TestPrivateKeys {
nsk: [38; 32], 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 recipient = AccountWithMetadata::new(Account::default(), false, &recipient_keys.npk());
let esk = [3; 32]; 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 epk = EphemeralPublicKey::from_scalar(esk);
let (output, proof) = circuit::execute_and_prove( let (output, proof) = circuit::execute_and_prove(
@ -926,7 +926,7 @@ pub mod tests {
let message = Message::try_from_circuit_output( let message = Message::try_from_circuit_output(
vec![sender_keys.account_id()], vec![sender_keys.account_id()],
vec![sender_nonce], vec![sender_nonce],
vec![(recipient_keys.npk(), recipient_keys.ivk(), epk)], vec![(recipient_keys.npk(), recipient_keys.vpk(), epk)],
output, output,
) )
.unwrap(); .unwrap();
@ -951,11 +951,11 @@ pub mod tests {
AccountWithMetadata::new(Account::default(), false, &recipient_keys.npk()); AccountWithMetadata::new(Account::default(), false, &recipient_keys.npk());
let esk_1 = [3; 32]; 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 epk_1 = EphemeralPublicKey::from_scalar(esk_1);
let esk_2 = [3; 32]; 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 epk_2 = EphemeralPublicKey::from_scalar(esk_2);
let (output, proof) = circuit::execute_and_prove( let (output, proof) = circuit::execute_and_prove(
@ -977,8 +977,8 @@ pub mod tests {
vec![], vec![],
vec![], vec![],
vec![ vec![
(sender_keys.npk(), sender_keys.ivk(), epk_1), (sender_keys.npk(), sender_keys.vpk(), epk_1),
(recipient_keys.npk(), recipient_keys.ivk(), epk_2), (recipient_keys.npk(), recipient_keys.vpk(), epk_2),
], ],
output, output,
) )
@ -1008,7 +1008,7 @@ pub mod tests {
); );
let esk = [3; 32]; 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 epk = EphemeralPublicKey::from_scalar(esk);
let (output, proof) = circuit::execute_and_prove( let (output, proof) = circuit::execute_and_prove(
@ -1026,7 +1026,7 @@ pub mod tests {
let message = Message::try_from_circuit_output( let message = Message::try_from_circuit_output(
vec![*recipient_account_id], vec![*recipient_account_id],
vec![], vec![],
vec![(sender_keys.npk(), sender_keys.ivk(), epk)], vec![(sender_keys.npk(), sender_keys.vpk(), epk)],
output, output,
) )
.unwrap(); .unwrap();
@ -1538,11 +1538,11 @@ pub mod tests {
vec![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
vec![sender_keys.nsk], vec![sender_keys.nsk],
@ -1572,7 +1572,7 @@ pub mod tests {
// Setting only one key for an execution with two private accounts. // Setting only one key for an execution with two private accounts.
let private_account_keys = [( let private_account_keys = [(
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
)]; )];
let result = execute_and_prove( let result = execute_and_prove(
vec![private_account_1, private_account_2], vec![private_account_1, private_account_2],
@ -1615,11 +1615,11 @@ pub mod tests {
vec![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
vec![sender_keys.nsk], vec![sender_keys.nsk],
@ -1657,11 +1657,11 @@ pub mod tests {
vec![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
private_account_nsks.to_vec(), private_account_nsks.to_vec(),
@ -1693,12 +1693,12 @@ pub mod tests {
// First private account is the sender // First private account is the sender
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
// Second private account is the recipient // Second private account is the recipient
( (
recipient_keys.npk(), 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![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
vec![sender_keys.nsk], vec![sender_keys.nsk],
@ -1801,11 +1801,11 @@ pub mod tests {
vec![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
vec![sender_keys.nsk], vec![sender_keys.nsk],
@ -1848,11 +1848,11 @@ pub mod tests {
vec![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
vec![sender_keys.nsk], vec![sender_keys.nsk],
@ -1895,11 +1895,11 @@ pub mod tests {
vec![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
vec![sender_keys.nsk], vec![sender_keys.nsk],
@ -1940,11 +1940,11 @@ pub mod tests {
vec![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
vec![sender_keys.nsk], vec![sender_keys.nsk],
@ -2013,11 +2013,11 @@ pub mod tests {
vec![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
vec![sender_keys.nsk], vec![sender_keys.nsk],
@ -2050,15 +2050,15 @@ pub mod tests {
let private_account_keys = [ let private_account_keys = [
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[57; 32], &sender_keys.ivk()), SharedSecretKey::new(&[57; 32], &sender_keys.vpk()),
), ),
]; ];
let result = execute_and_prove( let result = execute_and_prove(
@ -2105,11 +2105,11 @@ pub mod tests {
vec![ vec![
( (
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()), SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
), ),
( (
recipient_keys.npk(), recipient_keys.npk(),
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()), SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
), ),
], ],
private_account_nsks.to_vec(), private_account_nsks.to_vec(),
@ -2192,7 +2192,7 @@ pub mod tests {
let visibility_mask = [1, 1]; let visibility_mask = [1, 1];
let private_account_nsks = [sender_keys.nsk, sender_keys.nsk]; let private_account_nsks = [sender_keys.nsk, sender_keys.nsk];
let private_account_membership_proofs = [Some((1, vec![])), Some((1, vec![]))]; 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( let result = execute_and_prove(
vec![private_account_1.clone(), private_account_1], vec![private_account_1.clone(), private_account_1],
Program::serialize_instruction(100u128).unwrap(), Program::serialize_instruction(100u128).unwrap(),
@ -3809,11 +3809,11 @@ pub mod tests {
); );
let from_esk = [3; 32]; 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 from_epk = EphemeralPublicKey::from_scalar(from_esk);
let to_esk = [3; 32]; 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 to_epk = EphemeralPublicKey::from_scalar(to_esk);
let mut dependencies = HashMap::new(); let mut dependencies = HashMap::new();
@ -3858,8 +3858,8 @@ pub mod tests {
vec![], vec![],
vec![], vec![],
vec![ vec![
(to_keys.npk(), to_keys.ivk(), to_epk), (to_keys.npk(), to_keys.vpk(), to_epk),
(from_keys.npk(), from_keys.ivk(), from_epk), (from_keys.npk(), from_keys.vpk(), from_epk),
], ],
output, output,
) )
@ -4069,7 +4069,7 @@ pub mod tests {
// Set up parameters for the new account // Set up parameters for the new account
let esk = [3; 32]; 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 epk = EphemeralPublicKey::from_scalar(esk);
// Balance to initialize the account with (0 for a new account) // 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( let message = Message::try_from_circuit_output(
vec![], vec![],
vec![], vec![],
vec![(private_keys.npk(), private_keys.ivk(), epk)], vec![(private_keys.npk(), private_keys.vpk(), epk)],
output, output,
) )
.unwrap(); .unwrap();
@ -4124,7 +4124,7 @@ pub mod tests {
// Set up parameters for claiming the new account // Set up parameters for claiming the new account
let esk = [3; 32]; 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 epk = EphemeralPublicKey::from_scalar(esk);
let balance: u128 = 0; let balance: u128 = 0;
@ -4146,7 +4146,7 @@ pub mod tests {
let message = Message::try_from_circuit_output( let message = Message::try_from_circuit_output(
vec![], vec![],
vec![], vec![],
vec![(private_keys.npk(), private_keys.ivk(), epk)], vec![(private_keys.npk(), private_keys.vpk(), epk)],
output, output,
) )
.unwrap(); .unwrap();
@ -4174,7 +4174,7 @@ pub mod tests {
let noop_program = Program::noop(); let noop_program = Program::noop();
let esk2 = [4; 32]; 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; let nonce2 = 0xdeadbeef2;
@ -4256,7 +4256,7 @@ pub mod tests {
vec![2], vec![2],
vec![( vec![(
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[3; 32], &sender_keys.ivk()), SharedSecretKey::new(&[3; 32], &sender_keys.vpk()),
)], )],
vec![sender_keys.nsk], vec![sender_keys.nsk],
vec![Some((0, vec![]))], vec![Some((0, vec![]))],
@ -4284,7 +4284,7 @@ pub mod tests {
vec![2], vec![2],
vec![( vec![(
sender_keys.npk(), sender_keys.npk(),
SharedSecretKey::new(&[3; 32], &sender_keys.ivk()), SharedSecretKey::new(&[3; 32], &sender_keys.vpk()),
)], )],
vec![sender_keys.nsk], vec![sender_keys.nsk],
vec![Some((0, vec![]))], vec![Some((0, vec![]))],
@ -4327,7 +4327,7 @@ pub mod tests {
let instruction = (balance_to_transfer, auth_transfers.id()); let instruction = (balance_to_transfer, auth_transfers.id());
let recipient_esk = [3; 32]; 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(); let mut dependencies = HashMap::new();
dependencies.insert(auth_transfers.id(), auth_transfers); 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. /// 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. /// for the specified private account. These keys are safe to share publicly.
/// ///
/// # Parameters /// # Parameters
@ -130,17 +130,17 @@ pub unsafe extern "C" fn wallet_ffi_get_private_account_keys(
// NPK is a 32-byte array // NPK is a 32-byte array
let npk_bytes = key_chain.nullifer_public_key.0; let npk_bytes = key_chain.nullifer_public_key.0;
// IPK is a compressed secp256k1 point (33 bytes) // VPK is a compressed secp256k1 point (33 bytes)
let ipk_bytes = key_chain.incoming_viewing_public_key.to_bytes(); let vpk_bytes = key_chain.viewing_public_key.to_bytes();
let ipk_len = ipk_bytes.len(); let vpk_len = vpk_bytes.len();
let ipk_vec = ipk_bytes.to_vec(); let vpk_vec = vpk_bytes.to_vec();
let ipk_boxed = ipk_vec.into_boxed_slice(); let vpk_boxed = vpk_vec.into_boxed_slice();
let ipk_ptr = Box::into_raw(ipk_boxed) as *const u8; let vpk_ptr = Box::into_raw(vpk_boxed) as *const u8;
unsafe { unsafe {
(*out_keys).nullifier_public_key.data = npk_bytes; (*out_keys).nullifier_public_key.data = npk_bytes;
(*out_keys).incoming_viewing_public_key = ipk_ptr; (*out_keys).viewing_public_key = vpk_ptr;
(*out_keys).incoming_viewing_public_key_len = ipk_len; (*out_keys).viewing_public_key_len = vpk_len;
} }
WalletFfiError::Success WalletFfiError::Success
@ -159,10 +159,10 @@ pub unsafe extern "C" fn wallet_ffi_free_private_account_keys(keys: *mut FfiPriv
unsafe { unsafe {
let keys = &*keys; 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( let slice = std::slice::from_raw_parts_mut(
keys.incoming_viewing_public_key as *mut u8, keys.viewing_public_key as *mut u8,
keys.incoming_viewing_public_key_len, keys.viewing_public_key_len,
); );
drop(Box::from_raw(slice as *mut [u8])); 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 from_id = AccountId::new(unsafe { (*from).data });
let to_npk = (*to_keys).npk(); let to_npk = (*to_keys).npk();
let to_ipk = match (*to_keys).ivk() { let to_vpk = match (*to_keys).vpk() {
Ok(ipk) => ipk, Ok(vpk) => vpk,
Err(e) => { Err(e) => {
print_error("Invalid viewing key"); print_error("Invalid viewing key");
return e; return e;
@ -162,7 +162,7 @@ pub unsafe extern "C" fn wallet_ffi_transfer_shielded(
let transfer = NativeTokenTransfer(&wallet); let transfer = NativeTokenTransfer(&wallet);
match block_on( 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))) => { Ok(Ok((response, _shared_key))) => {
let tx_hash = CString::new(response.tx_hash) 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 from_id = AccountId::new(unsafe { (*from).data });
let to_npk = (*to_keys).npk(); let to_npk = (*to_keys).npk();
let to_ipk = match (*to_keys).ivk() { let to_vpk = match (*to_keys).vpk() {
Ok(ipk) => ipk, Ok(vpk) => vpk,
Err(e) => { Err(e) => {
print_error("Invalid viewing key"); print_error("Invalid viewing key");
return e; return e;
@ -334,7 +334,7 @@ pub unsafe extern "C" fn wallet_ffi_transfer_private(
let transfer = NativeTokenTransfer(&wallet); 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))) => { Ok(Ok((response, _shared_key))) => {
let tx_hash = CString::new(response.tx_hash) let tx_hash = CString::new(response.tx_hash)

View File

@ -72,18 +72,18 @@ impl Default for FfiAccount {
pub struct FfiPrivateAccountKeys { pub struct FfiPrivateAccountKeys {
/// Nullifier public key (32 bytes) /// Nullifier public key (32 bytes)
pub nullifier_public_key: FfiBytes32, pub nullifier_public_key: FfiBytes32,
/// Incoming viewing public key (compressed secp256k1 point) /// viewing public key (compressed secp256k1 point)
pub incoming_viewing_public_key: *const u8, pub viewing_public_key: *const u8,
/// Length of incoming viewing public key (typically 33 bytes) /// Length of viewing public key (typically 33 bytes)
pub incoming_viewing_public_key_len: usize, pub viewing_public_key_len: usize,
} }
impl Default for FfiPrivateAccountKeys { impl Default for FfiPrivateAccountKeys {
fn default() -> Self { fn default() -> Self {
Self { Self {
nullifier_public_key: FfiBytes32::default(), nullifier_public_key: FfiBytes32::default(),
incoming_viewing_public_key: std::ptr::null(), viewing_public_key: std::ptr::null(),
incoming_viewing_public_key_len: 0, viewing_public_key_len: 0,
} }
} }
} }
@ -157,13 +157,10 @@ impl FfiPrivateAccountKeys {
nssa_core::NullifierPublicKey(self.nullifier_public_key.data) nssa_core::NullifierPublicKey(self.nullifier_public_key.data)
} }
pub fn ivk(&self) -> Result<nssa_core::encryption::IncomingViewingPublicKey, WalletFfiError> { pub fn vpk(&self) -> Result<nssa_core::encryption::ViewingPublicKey, WalletFfiError> {
if self.incoming_viewing_public_key_len == 33 { if self.viewing_public_key_len == 33 {
let slice = unsafe { let slice = unsafe {
slice::from_raw_parts( slice::from_raw_parts(self.viewing_public_key, self.viewing_public_key_len)
self.incoming_viewing_public_key,
self.incoming_viewing_public_key_len,
)
}; };
Ok(Secp256k1Point(slice.to_vec())) Ok(Secp256k1Point(slice.to_vec()))
} else { } 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": { "Private": {
"account_id": "3oCG8gqdKLMegw4rRfyaMQvuPHpcASt7xwttsmnZLSkw", "account_id": "2ECgkFTaXzwjJBXR7ZKmXYQtpHbvTTHK9Auma4NL9AUo",
"account": { "account": {
"program_owner": [ "program_owner": [
0, 0,
@ -103,219 +103,19 @@
"nonce": 0 "nonce": 0
}, },
"key_chain": { "key_chain": {
"secret_spending_key": [ "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],
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
],
"private_key_holder": { "private_key_holder": {
"nullifier_secret_key": [ "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],
29, "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]
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
]
}, },
"nullifer_public_key": [ "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],
63, "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]
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
]
} }
} }
}, },
{ {
"Private": { "Private": {
"account_id": "AKTcXgJ1xoynta1Ec7y6Jso1z1JQtHqd7aPQ1h9er6xX", "account_id": "E8HwiTyQe4H9HK7icTvn95HQMnzx49mP9A2ddtMLpNaN",
"account": { "account": {
"program_owner": [ "program_owner": [
0, 0,
@ -332,213 +132,13 @@
"nonce": 0 "nonce": 0
}, },
"key_chain": { "key_chain": {
"secret_spending_key": [ "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],
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
],
"private_key_holder": { "private_key_holder": {
"nullifier_secret_key": [ "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],
25, "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]
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
]
}, },
"nullifer_public_key": [ "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],
192, "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]
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
]
} }
} }
} }

View File

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

View File

@ -22,7 +22,7 @@ pub enum AuthTransferSubcommand {
}, },
/// Send native tokens from one account to another with variable privacy /// 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. /// patterns.
/// ///
/// First is used for owned accounts, second otherwise. /// First is used for owned accounts, second otherwise.
@ -36,9 +36,9 @@ pub enum AuthTransferSubcommand {
/// to_npk - valid 32 byte hex string /// to_npk - valid 32 byte hex string
#[arg(long)] #[arg(long)]
to_npk: Option<String>, to_npk: Option<String>,
/// to_ipk - valid 33 byte hex string /// to_vpk - valid 33 byte hex string
#[arg(long)] #[arg(long)]
to_ipk: Option<String>, to_vpk: Option<String>,
/// amount - amount of balance to move /// amount - amount of balance to move
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
@ -102,10 +102,10 @@ impl WalletSubcommand for AuthTransferSubcommand {
from, from,
to, to,
to_npk, to_npk,
to_ipk, to_vpk,
amount, amount,
} => { } => {
let underlying_subcommand = match (to, to_npk, to_ipk) { let underlying_subcommand = match (to, to_npk, to_vpk) {
(None, None, None) => { (None, None, None) => {
anyhow::bail!( anyhow::bail!(
"Provide either account account_id of receiver or their public keys" "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)?; let (from, from_privacy) = parse_addr_with_privacy_prefix(&from)?;
match from_privacy { match from_privacy {
@ -163,7 +163,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
NativeTokenTransferProgramSubcommandPrivate::PrivateForeign { NativeTokenTransferProgramSubcommandPrivate::PrivateForeign {
from, from,
to_npk, to_npk,
to_ipk, to_vpk,
amount, amount,
}, },
) )
@ -173,7 +173,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
NativeTokenTransferProgramSubcommandShielded::ShieldedForeign { NativeTokenTransferProgramSubcommandShielded::ShieldedForeign {
from, from,
to_npk, to_npk,
to_ipk, to_vpk,
amount, amount,
}, },
) )
@ -255,9 +255,9 @@ pub enum NativeTokenTransferProgramSubcommandShielded {
/// to_npk - valid 32 byte hex string /// to_npk - valid 32 byte hex string
#[arg(long)] #[arg(long)]
to_npk: String, to_npk: String,
/// to_ipk - valid 33 byte hex string /// to_vpk - valid 33 byte hex string
#[arg(long)] #[arg(long)]
to_ipk: String, to_vpk: String,
/// amount - amount of balance to move /// amount - amount of balance to move
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
@ -292,9 +292,9 @@ pub enum NativeTokenTransferProgramSubcommandPrivate {
/// to_npk - valid 32 byte hex string /// to_npk - valid 32 byte hex string
#[arg(long)] #[arg(long)]
to_npk: String, to_npk: String,
/// to_ipk - valid 33 byte hex string /// to_vpk - valid 33 byte hex string
#[arg(long)] #[arg(long)]
to_ipk: String, to_vpk: String,
/// amount - amount of balance to move /// amount - amount of balance to move
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
@ -336,7 +336,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate {
NativeTokenTransferProgramSubcommandPrivate::PrivateForeign { NativeTokenTransferProgramSubcommandPrivate::PrivateForeign {
from, from,
to_npk, to_npk,
to_ipk, to_vpk,
amount, amount,
} => { } => {
let from: AccountId = from.parse().unwrap(); let from: AccountId = from.parse().unwrap();
@ -345,14 +345,14 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate {
to_npk.copy_from_slice(&to_npk_res); to_npk.copy_from_slice(&to_npk_res);
let to_npk = nssa_core::NullifierPublicKey(to_npk); let to_npk = nssa_core::NullifierPublicKey(to_npk);
let to_ipk_res = hex::decode(to_ipk)?; let to_vpk_res = hex::decode(to_vpk)?;
let mut to_ipk = [0u8; 33]; let mut to_vpk = [0u8; 33];
to_ipk.copy_from_slice(&to_ipk_res); to_vpk.copy_from_slice(&to_vpk_res);
let to_ipk = let to_vpk =
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec()); nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_vpk.to_vec());
let (res, [secret_from, _]) = NativeTokenTransfer(wallet_core) 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?; .await?;
println!("Results of tx send are {res:#?}"); println!("Results of tx send are {res:#?}");
@ -412,7 +412,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
NativeTokenTransferProgramSubcommandShielded::ShieldedForeign { NativeTokenTransferProgramSubcommandShielded::ShieldedForeign {
from, from,
to_npk, to_npk,
to_ipk, to_vpk,
amount, amount,
} => { } => {
let from: AccountId = from.parse().unwrap(); let from: AccountId = from.parse().unwrap();
@ -422,14 +422,14 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
to_npk.copy_from_slice(&to_npk_res); to_npk.copy_from_slice(&to_npk_res);
let to_npk = nssa_core::NullifierPublicKey(to_npk); let to_npk = nssa_core::NullifierPublicKey(to_npk);
let to_ipk_res = hex::decode(to_ipk)?; let to_vpk_res = hex::decode(to_vpk)?;
let mut to_ipk = [0u8; 33]; let mut to_vpk = [0u8; 33];
to_ipk.copy_from_slice(&to_ipk_res); to_vpk.copy_from_slice(&to_vpk_res);
let to_ipk = let to_vpk =
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec()); nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_vpk.to_vec());
let (res, _) = NativeTokenTransfer(wallet_core) 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?; .await?;
println!("Results of tx send are {res:#?}"); 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 /// 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. /// patterns.
/// ///
/// First is used for owned accounts, second otherwise. /// First is used for owned accounts, second otherwise.
@ -43,9 +43,9 @@ pub enum TokenProgramAgnosticSubcommand {
/// to_npk - valid 32 byte hex string /// to_npk - valid 32 byte hex string
#[arg(long)] #[arg(long)]
to_npk: Option<String>, to_npk: Option<String>,
/// to_ipk - valid 33 byte hex string /// to_vpk - valid 33 byte hex string
#[arg(long)] #[arg(long)]
to_ipk: Option<String>, to_vpk: Option<String>,
/// amount - amount of balance to move /// amount - amount of balance to move
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
@ -71,7 +71,7 @@ pub enum TokenProgramAgnosticSubcommand {
/// ///
/// `definition` is owned /// `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. /// exclusive patterns.
/// ///
/// First is used for owned accounts, second otherwise. /// First is used for owned accounts, second otherwise.
@ -85,9 +85,9 @@ pub enum TokenProgramAgnosticSubcommand {
/// holder_npk - valid 32 byte hex string /// holder_npk - valid 32 byte hex string
#[arg(long)] #[arg(long)]
holder_npk: Option<String>, holder_npk: Option<String>,
/// to_ipk - valid 33 byte hex string /// to_vpk - valid 33 byte hex string
#[arg(long)] #[arg(long)]
holder_ipk: Option<String>, holder_vpk: Option<String>,
/// amount - amount of balance to mint /// amount - amount of balance to mint
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
@ -160,10 +160,10 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
from, from,
to, to,
to_npk, to_npk,
to_ipk, to_vpk,
amount, amount,
} => { } => {
let underlying_subcommand = match (to, to_npk, to_ipk) { let underlying_subcommand = match (to, to_npk, to_vpk) {
(None, None, None) => { (None, None, None) => {
anyhow::bail!( anyhow::bail!(
"Provide either account account_id of receiver or their public keys" "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)?; let (from, from_privacy) = parse_addr_with_privacy_prefix(&from)?;
match from_privacy { match from_privacy {
@ -228,7 +228,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
TokenProgramSubcommandPrivate::TransferTokenPrivateForeign { TokenProgramSubcommandPrivate::TransferTokenPrivateForeign {
sender_account_id: from, sender_account_id: from,
recipient_npk: to_npk, recipient_npk: to_npk,
recipient_ipk: to_ipk, recipient_vpk: to_vpk,
balance_to_move: amount, balance_to_move: amount,
}, },
), ),
@ -236,7 +236,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
TokenProgramSubcommandShielded::TransferTokenShieldedForeign { TokenProgramSubcommandShielded::TransferTokenShieldedForeign {
sender_account_id: from, sender_account_id: from,
recipient_npk: to_npk, recipient_npk: to_npk,
recipient_ipk: to_ipk, recipient_vpk: to_vpk,
balance_to_move: amount, balance_to_move: amount,
}, },
), ),
@ -302,10 +302,10 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
definition, definition,
holder, holder,
holder_npk, holder_npk,
holder_ipk, holder_vpk,
amount, amount,
} => { } => {
let underlying_subcommand = match (holder, holder_npk, holder_ipk) { let underlying_subcommand = match (holder, holder_npk, holder_vpk) {
(None, None, None) => { (None, None, None) => {
anyhow::bail!( anyhow::bail!(
"Provide either account account_id of holder or their public keys" "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) = let (definition, definition_privacy) =
parse_addr_with_privacy_prefix(&definition)?; parse_addr_with_privacy_prefix(&definition)?;
@ -372,7 +372,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
TokenProgramSubcommandPrivate::MintTokenPrivateForeign { TokenProgramSubcommandPrivate::MintTokenPrivateForeign {
definition_account_id: definition, definition_account_id: definition,
holder_npk, holder_npk,
holder_ipk, holder_vpk,
amount, amount,
}, },
), ),
@ -380,7 +380,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
TokenProgramSubcommandShielded::MintTokenShieldedForeign { TokenProgramSubcommandShielded::MintTokenShieldedForeign {
definition_account_id: definition, definition_account_id: definition,
holder_npk, holder_npk,
holder_ipk, holder_vpk,
amount, amount,
}, },
), ),
@ -465,9 +465,9 @@ pub enum TokenProgramSubcommandPrivate {
/// recipient_npk - valid 32 byte hex string /// recipient_npk - valid 32 byte hex string
#[arg(long)] #[arg(long)]
recipient_npk: String, recipient_npk: String,
/// recipient_ipk - valid 33 byte hex string /// recipient_vpk - valid 33 byte hex string
#[arg(long)] #[arg(long)]
recipient_ipk: String, recipient_vpk: String,
#[arg(short, long)] #[arg(short, long)]
balance_to_move: u128, balance_to_move: u128,
}, },
@ -496,7 +496,7 @@ pub enum TokenProgramSubcommandPrivate {
#[arg(short, long)] #[arg(short, long)]
holder_npk: String, holder_npk: String,
#[arg(short, long)] #[arg(short, long)]
holder_ipk: String, holder_vpk: String,
#[arg(short, long)] #[arg(short, long)]
amount: u128, amount: u128,
}, },
@ -553,9 +553,9 @@ pub enum TokenProgramSubcommandShielded {
/// recipient_npk - valid 32 byte hex string /// recipient_npk - valid 32 byte hex string
#[arg(long)] #[arg(long)]
recipient_npk: String, recipient_npk: String,
/// recipient_ipk - valid 33 byte hex string /// recipient_vpk - valid 33 byte hex string
#[arg(long)] #[arg(long)]
recipient_ipk: String, recipient_vpk: String,
#[arg(short, long)] #[arg(short, long)]
balance_to_move: u128, balance_to_move: u128,
}, },
@ -584,7 +584,7 @@ pub enum TokenProgramSubcommandShielded {
#[arg(short, long)] #[arg(short, long)]
holder_npk: String, holder_npk: String,
#[arg(short, long)] #[arg(short, long)]
holder_ipk: String, holder_vpk: String,
#[arg(short, long)] #[arg(short, long)]
amount: u128, amount: u128,
}, },
@ -745,7 +745,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
TokenProgramSubcommandPrivate::TransferTokenPrivateForeign { TokenProgramSubcommandPrivate::TransferTokenPrivateForeign {
sender_account_id, sender_account_id,
recipient_npk, recipient_npk,
recipient_ipk, recipient_vpk,
balance_to_move, balance_to_move,
} => { } => {
let sender_account_id: AccountId = sender_account_id.parse().unwrap(); 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); recipient_npk.copy_from_slice(&recipient_npk_res);
let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk); let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk);
let recipient_ipk_res = hex::decode(recipient_ipk)?; let recipient_vpk_res = hex::decode(recipient_vpk)?;
let mut recipient_ipk = [0u8; 33]; let mut recipient_vpk = [0u8; 33];
recipient_ipk.copy_from_slice(&recipient_ipk_res); recipient_vpk.copy_from_slice(&recipient_vpk_res);
let recipient_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point( let recipient_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
recipient_ipk.to_vec(), recipient_vpk.to_vec(),
); );
let (res, [secret_sender, _]) = Token(wallet_core) let (res, [secret_sender, _]) = Token(wallet_core)
.send_transfer_transaction_private_foreign_account( .send_transfer_transaction_private_foreign_account(
sender_account_id, sender_account_id,
recipient_npk, recipient_npk,
recipient_ipk, recipient_vpk,
balance_to_move, balance_to_move,
) )
.await?; .await?;
@ -865,7 +865,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
TokenProgramSubcommandPrivate::MintTokenPrivateForeign { TokenProgramSubcommandPrivate::MintTokenPrivateForeign {
definition_account_id, definition_account_id,
holder_npk, holder_npk,
holder_ipk, holder_vpk,
amount, amount,
} => { } => {
let definition_account_id: AccountId = definition_account_id.parse().unwrap(); 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); holder_npk.copy_from_slice(&holder_npk_res);
let holder_npk = nssa_core::NullifierPublicKey(holder_npk); let holder_npk = nssa_core::NullifierPublicKey(holder_npk);
let holder_ipk_res = hex::decode(holder_ipk)?; let holder_vpk_res = hex::decode(holder_vpk)?;
let mut holder_ipk = [0u8; 33]; let mut holder_vpk = [0u8; 33];
holder_ipk.copy_from_slice(&holder_ipk_res); holder_vpk.copy_from_slice(&holder_vpk_res);
let holder_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point( let holder_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
holder_ipk.to_vec(), holder_vpk.to_vec(),
); );
let (res, [secret_definition, _]) = Token(wallet_core) let (res, [secret_definition, _]) = Token(wallet_core)
.send_mint_transaction_private_foreign_account( .send_mint_transaction_private_foreign_account(
definition_account_id, definition_account_id,
holder_npk, holder_npk,
holder_ipk, holder_vpk,
amount, amount,
) )
.await?; .await?;
@ -1034,7 +1034,7 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
TokenProgramSubcommandShielded::TransferTokenShieldedForeign { TokenProgramSubcommandShielded::TransferTokenShieldedForeign {
sender_account_id, sender_account_id,
recipient_npk, recipient_npk,
recipient_ipk, recipient_vpk,
balance_to_move, balance_to_move,
} => { } => {
let sender_account_id: AccountId = sender_account_id.parse().unwrap(); 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); recipient_npk.copy_from_slice(&recipient_npk_res);
let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk); let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk);
let recipient_ipk_res = hex::decode(recipient_ipk)?; let recipient_vpk_res = hex::decode(recipient_vpk)?;
let mut recipient_ipk = [0u8; 33]; let mut recipient_vpk = [0u8; 33];
recipient_ipk.copy_from_slice(&recipient_ipk_res); recipient_vpk.copy_from_slice(&recipient_vpk_res);
let recipient_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point( let recipient_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
recipient_ipk.to_vec(), recipient_vpk.to_vec(),
); );
let (res, _) = Token(wallet_core) let (res, _) = Token(wallet_core)
.send_transfer_transaction_shielded_foreign_account( .send_transfer_transaction_shielded_foreign_account(
sender_account_id, sender_account_id,
recipient_npk, recipient_npk,
recipient_ipk, recipient_vpk,
balance_to_move, balance_to_move,
) )
.await?; .await?;
@ -1177,7 +1177,7 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
TokenProgramSubcommandShielded::MintTokenShieldedForeign { TokenProgramSubcommandShielded::MintTokenShieldedForeign {
definition_account_id, definition_account_id,
holder_npk, holder_npk,
holder_ipk, holder_vpk,
amount, amount,
} => { } => {
let definition_account_id: AccountId = definition_account_id.parse().unwrap(); 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); holder_npk.copy_from_slice(&holder_npk_res);
let holder_npk = nssa_core::NullifierPublicKey(holder_npk); let holder_npk = nssa_core::NullifierPublicKey(holder_npk);
let holder_ipk_res = hex::decode(holder_ipk)?; let holder_vpk_res = hex::decode(holder_vpk)?;
let mut holder_ipk = [0u8; 33]; let mut holder_vpk = [0u8; 33];
holder_ipk.copy_from_slice(&holder_ipk_res); holder_vpk.copy_from_slice(&holder_vpk_res);
let holder_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point( let holder_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
holder_ipk.to_vec(), holder_vpk.to_vec(),
); );
let (res, _) = Token(wallet_core) let (res, _) = Token(wallet_core)
.send_mint_transaction_shielded_foreign_account( .send_mint_transaction_shielded_foreign_account(
definition_account_id, definition_account_id,
holder_npk, holder_npk,
holder_ipk, holder_vpk,
amount, amount,
) )
.await?; .await?;

View File

@ -292,7 +292,7 @@ impl Default for WalletConfig {
}, },
{ {
"Private": { "Private": {
"account_id": "3oCG8gqdKLMegw4rRfyaMQvuPHpcASt7xwttsmnZLSkw", "account_id": "FpdcxBrMkHWqXCBQ6FG98eYfWGY6jWZRsKNSi1FwDMxy",
"account": { "account": {
"program_owner": [ "program_owner": [
0, 0,
@ -310,218 +310,151 @@ impl Default for WalletConfig {
}, },
"key_chain": { "key_chain": {
"secret_spending_key": [ "secret_spending_key": [
251, 239,
82, 27,
235, 159,
1, 83,
146, 199,
96, 194,
30, 132,
81,
162,
234,
33, 33,
15, 20,
123, 28,
129, 217,
116, 103,
0, 101,
57,
27,
125,
84, 84,
136, 57,
176, 19,
70, 86,
190, 98,
224, 135,
161, 161,
54, 221,
134, 108,
142, 125,
154, 152,
1, 174,
18, 161,
251, 64,
242, 16,
189 200
], ],
"private_key_holder": { "private_key_holder": {
"nullifier_secret_key": [ "nullifier_secret_key": [
29, 71,
250, 195,
10,
187,
35,
123,
180,
250,
246,
97,
216,
153,
44,
156,
16, 16,
93, 119,
241, 0,
26, 98,
174, 35,
219, 106,
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, 139,
113, 82,
214, 145,
12 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": [ "nullifer_public_key": [
63,
202,
178,
231,
183,
82,
237,
212,
216,
221,
215,
255,
153,
101,
177, 177,
161,
254,
210,
128,
122,
54,
190,
230,
151,
183,
64, 64,
225,
229,
113,
1, 1,
228, 11,
97 87,
], 38,
"incoming_viewing_public_key": [ 254,
3, 159,
235, 231,
139, 165,
131, 1,
237, 94,
177, 64,
122, 137,
189,
6,
177,
167,
178,
202,
117,
246,
58,
28,
65,
132,
79,
220,
139,
119,
243, 243,
187, 76,
160, 249,
212, 101,
121, 251,
61, 129,
247, 33,
116, 101,
72, 189,
205 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": { "Private": {
"account_id": "AKTcXgJ1xoynta1Ec7y6Jso1z1JQtHqd7aPQ1h9er6xX", "account_id": "E8HwiTyQe4H9HK7icTvn95HQMnzx49mP9A2ddtMLpNaN",
"account": { "account": {
"program_owner": [ "program_owner": [
0, 0,
@ -539,211 +472,20 @@ impl Default for WalletConfig {
}, },
"key_chain": { "key_chain": {
"secret_spending_key": [ "secret_spending_key": [
238, 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],
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
],
"private_key_holder": { "private_key_holder": {
"nullifier_secret_key": [ "nullifier_secret_key": [
25, 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
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": [ "viewing_secret_key": [
193, 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
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
] ]
}, },
"nullifer_public_key": [ "nullifer_public_key": [
192, 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
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": [ "viewing_public_key": [
2, 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
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
] ]
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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