mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-02-18 20:33:13 +00:00
Merge branch 'main' into Pravdyvy/indexer-state-management
This commit is contained in:
commit
f11d374ae7
11
.deny.toml
11
.deny.toml
@ -12,6 +12,7 @@ ignore = [
|
||||
{ id = "RUSTSEC-2024-0436", reason = "`paste` has a security vulnerability; consider using an alternative. Use `cargo tree -p paste -i > tmp.txt` to check the dependency tree." },
|
||||
{ id = "RUSTSEC-2025-0055", reason = "`tracing-subscriber` v0.2.25 pulled in by ark-relations v0.4.0 - will be addressed before mainnet" },
|
||||
{ id = "RUSTSEC-2025-0141", reason = "`bincode` is unmaintained but continuing to use it." },
|
||||
{ id = "RUSTSEC-2023-0089", reason = "atomic-polyfill is pulled transitively via risc0-zkvm; waiting on upstream fix (see https://github.com/risc0/risc0/issues/3453)" },
|
||||
]
|
||||
yanked = "deny"
|
||||
unused-ignored-advisory = "deny"
|
||||
@ -35,6 +36,16 @@ allow = [
|
||||
"Unicode-3.0",
|
||||
"Zlib",
|
||||
]
|
||||
exceptions = [
|
||||
# TEMP: Pending legal review. Pulled transitively via `risc0-zkvm`
|
||||
{ name = "downloader", version = "0.2.8", allow = ["LGPL-3.0-or-later"] },
|
||||
{ name = "malachite", version = "0.4.22", allow = ["LGPL-3.0-only"] },
|
||||
{ name = "malachite-base", version = "0.4.22", allow = ["LGPL-3.0-only"] },
|
||||
{ name = "malachite-float", version = "0.4.22", allow = ["LGPL-3.0-only"] },
|
||||
{ name = "malachite-nz", version = "0.4.22", allow = ["LGPL-3.0-only"] },
|
||||
{ name = "malachite-q", version = "0.4.22", allow = ["LGPL-3.0-only"] },
|
||||
{ name = "managed", version = "0.8.0", allow = ["0BSD"] },
|
||||
]
|
||||
private = { ignore = false }
|
||||
unused-allowed-license = "deny"
|
||||
|
||||
|
||||
1428
Cargo.lock
generated
1428
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -67,8 +67,8 @@ tokio = { version = "1.28.2", features = [
|
||||
"fs",
|
||||
] }
|
||||
tokio-util = "0.7.18"
|
||||
risc0-zkvm = { version = "3.0.3", features = ['std'] }
|
||||
risc0-build = "3.0.3"
|
||||
risc0-zkvm = { version = "3.0.5", features = ['std'] }
|
||||
risc0-build = "3.0.5"
|
||||
anyhow = "1.0.98"
|
||||
num_cpus = "1.13.1"
|
||||
openssl = { version = "0.10", features = ["vendored"] }
|
||||
|
||||
@ -92,7 +92,7 @@ wallet account new private
|
||||
# Output:
|
||||
Generated new account with account_id Private/HMRHZdPw4pbyPVZHNGrV6K5AA95wACFsHTRST84fr3CF
|
||||
With npk 6a2dfe433cf28e525aa0196d719be3c16146f7ee358ca39595323f94fde38f93
|
||||
With ipk 03d59abf4bee974cc12ddb44641c19f0b5441fef39191f047c988c29a77252a577
|
||||
With vpk 03d59abf4bee974cc12ddb44641c19f0b5441fef39191f047c988c29a77252a577
|
||||
```
|
||||
|
||||
2. Create the token (Token B):
|
||||
|
||||
@ -154,11 +154,11 @@ wallet account new private
|
||||
# Output:
|
||||
Generated new account with account_id Private/HacPU3hakLYzWtSqUPw6TUr8fqoMieVWovsUR6sJf7cL
|
||||
With npk e6366f79d026c8bd64ae6b3d601f0506832ec682ab54897f205fffe64ec0d951
|
||||
With ipk 02ddc96d0eb56e00ce14994cfdaec5ae1f76244180a919545983156e3519940a17
|
||||
With vpk 02ddc96d0eb56e00ce14994cfdaec5ae1f76244180a919545983156e3519940a17
|
||||
```
|
||||
|
||||
> [!Tip]
|
||||
> Focus on the account ID for now. The `npk` and `ipk` values are stored locally and used to build privacy-preserving transactions. The private account ID is derived from `npk`.
|
||||
> Focus on the account ID for now. The `npk` and `vpk` values are stored locally and used to build privacy-preserving transactions. The private account ID is derived from `npk`.
|
||||
|
||||
Just like public accounts, new private accounts start out uninitialized:
|
||||
|
||||
@ -228,17 +228,17 @@ wallet account new private
|
||||
# Output:
|
||||
Generated new account with account_id Private/AukXPRBmrYVqoqEW2HTs7N3hvTn3qdNFDcxDHVr5hMm5
|
||||
With npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e
|
||||
With ipk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72
|
||||
With vpk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72
|
||||
```
|
||||
|
||||
> [!Tip]
|
||||
> Ignore the private account ID here and use the `npk` and `ipk` values to send to a foreign private account.
|
||||
> Ignore the private account ID here and use the `npk` and `vpk` values to send to a foreign private account.
|
||||
|
||||
```bash
|
||||
wallet auth-transfer send \
|
||||
--from Public/Ev1JprP9BmhbFVQyBcbznU8bAXcwrzwRoPTetXdQPAWS \
|
||||
--to-npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e \
|
||||
--to-ipk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72 \
|
||||
--to-vpk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72 \
|
||||
--amount 3
|
||||
```
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -97,7 +97,7 @@ _wallet_auth_transfer() {
|
||||
'--from[Source account ID]:from_account:_wallet_account_ids' \
|
||||
'--to[Destination account ID (for owned accounts)]:to_account:_wallet_account_ids' \
|
||||
'--to-npk[Destination nullifier public key (for foreign private accounts)]:npk:' \
|
||||
'--to-ipk[Destination viewing public key (for foreign private accounts)]:ipk:' \
|
||||
'--to-vpk[Destination viewing public key (for foreign private accounts)]:vpk:' \
|
||||
'--amount[Amount of native tokens to send]:amount:'
|
||||
;;
|
||||
esac
|
||||
@ -164,7 +164,7 @@ _wallet_account() {
|
||||
get)
|
||||
_arguments \
|
||||
'(-r --raw)'{-r,--raw}'[Get raw account data]' \
|
||||
'(-k --keys)'{-k,--keys}'[Display keys (pk for public accounts, npk/ipk for private accounts)]' \
|
||||
'(-k --keys)'{-k,--keys}'[Display keys (pk for public accounts, npk/vpk for private accounts)]' \
|
||||
'(-a --account-id)'{-a,--account-id}'[Account ID to query]:account_id:_wallet_account_ids'
|
||||
;;
|
||||
list|ls)
|
||||
@ -255,7 +255,7 @@ _wallet_token() {
|
||||
'--from[Source holding account ID]:from_account:_wallet_account_ids' \
|
||||
'--to[Destination holding account ID (for owned accounts)]:to_account:_wallet_account_ids' \
|
||||
'--to-npk[Destination nullifier public key (for foreign private accounts)]:npk:' \
|
||||
'--to-ipk[Destination viewing public key (for foreign private accounts)]:ipk:' \
|
||||
'--to-vpk[Destination viewing public key (for foreign private accounts)]:vpk:' \
|
||||
'--amount[Amount of tokens to send]:amount:'
|
||||
;;
|
||||
burn)
|
||||
@ -269,7 +269,7 @@ _wallet_token() {
|
||||
'--definition[Definition account ID]:definition_account:_wallet_account_ids' \
|
||||
'--holder[Holder account ID (for owned accounts)]:holder_account:_wallet_account_ids' \
|
||||
'--holder-npk[Holder nullifier public key (for foreign private accounts)]:npk:' \
|
||||
'--holder-ipk[Holder viewing public key (for foreign private accounts)]:ipk:' \
|
||||
'--holder-vpk[Holder viewing public key (for foreign private accounts)]:vpk:' \
|
||||
'--amount[Amount of tokens to mint]:amount:'
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -29,40 +29,7 @@
|
||||
],
|
||||
"initial_commitments": [
|
||||
{
|
||||
"npk": [
|
||||
63,
|
||||
202,
|
||||
178,
|
||||
231,
|
||||
183,
|
||||
82,
|
||||
237,
|
||||
212,
|
||||
216,
|
||||
221,
|
||||
215,
|
||||
255,
|
||||
153,
|
||||
101,
|
||||
177,
|
||||
161,
|
||||
254,
|
||||
210,
|
||||
128,
|
||||
122,
|
||||
54,
|
||||
190,
|
||||
230,
|
||||
151,
|
||||
183,
|
||||
64,
|
||||
225,
|
||||
229,
|
||||
113,
|
||||
1,
|
||||
228,
|
||||
97
|
||||
],
|
||||
"npk": [13, 25, 40, 5, 198, 248, 210, 248, 237, 121, 124, 145, 186, 142, 253, 216, 236, 69, 193, 32, 166, 167, 49, 133, 172, 111, 159, 46, 84, 17, 157, 23],
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
@ -80,40 +47,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"npk": [
|
||||
192,
|
||||
251,
|
||||
166,
|
||||
243,
|
||||
167,
|
||||
236,
|
||||
84,
|
||||
249,
|
||||
35,
|
||||
136,
|
||||
130,
|
||||
172,
|
||||
219,
|
||||
225,
|
||||
161,
|
||||
139,
|
||||
229,
|
||||
89,
|
||||
243,
|
||||
125,
|
||||
194,
|
||||
213,
|
||||
209,
|
||||
30,
|
||||
23,
|
||||
174,
|
||||
100,
|
||||
244,
|
||||
124,
|
||||
74,
|
||||
140,
|
||||
47
|
||||
],
|
||||
"npk": [32, 67, 72, 164, 106, 53, 66, 239, 141, 15, 52, 230, 136, 177, 2, 236, 207, 243, 134, 135, 210, 143, 87, 232, 215, 128, 194, 120, 113, 224, 4, 165],
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
|
||||
@ -263,7 +263,7 @@ impl indexer_service_rpc::RpcServer for MockIndexerService {
|
||||
.collect();
|
||||
|
||||
// Sort by block ID descending (most recent first)
|
||||
account_txs.sort_by(|a, b| b.1.cmp(&a.1));
|
||||
account_txs.sort_by_key(|b| std::cmp::Reverse(b.1));
|
||||
|
||||
let start = offset as usize;
|
||||
if start >= account_txs.len() {
|
||||
|
||||
@ -102,7 +102,7 @@ async fn amm_public() -> Result<()> {
|
||||
from: format_public_account_id(supply_account_id_1),
|
||||
to: Some(format_public_account_id(recipient_account_id_1)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 7,
|
||||
};
|
||||
|
||||
@ -126,7 +126,7 @@ async fn amm_public() -> Result<()> {
|
||||
from: format_public_account_id(supply_account_id_2),
|
||||
to: Some(format_public_account_id(recipient_account_id_2)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 7,
|
||||
};
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ async fn private_transfer_to_owned_account() -> Result<()> {
|
||||
from: format_private_account_id(from),
|
||||
to: Some(format_private_account_id(to)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -59,13 +59,13 @@ async fn private_transfer_to_foreign_account() -> Result<()> {
|
||||
let from: AccountId = ctx.existing_private_accounts()[0];
|
||||
let to_npk = NullifierPublicKey([42; 32]);
|
||||
let to_npk_string = hex::encode(to_npk.0);
|
||||
let to_ipk = Secp256k1Point::from_scalar(to_npk.0);
|
||||
let to_vpk = Secp256k1Point::from_scalar(to_npk.0);
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: format_private_account_id(from),
|
||||
to: None,
|
||||
to_npk: Some(to_npk_string),
|
||||
to_ipk: Some(hex::encode(to_ipk.0)),
|
||||
to_vpk: Some(hex::encode(to_vpk.0)),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -113,7 +113,7 @@ async fn deshielded_transfer_to_public_account() -> Result<()> {
|
||||
from: format_private_account_id(from),
|
||||
to: Some(format_public_account_id(to)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -168,12 +168,12 @@ async fn private_transfer_to_owned_account_using_claiming_path() -> Result<()> {
|
||||
.cloned()
|
||||
.context("Failed to get private account")?;
|
||||
|
||||
// Send to this account using claiming path (using npk and ipk instead of account ID)
|
||||
// Send to this account using claiming path (using npk and vpk instead of account ID)
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: format_private_account_id(from),
|
||||
to: None,
|
||||
to_npk: Some(hex::encode(to_keys.nullifer_public_key.0)),
|
||||
to_ipk: Some(hex::encode(to_keys.incoming_viewing_public_key.0)),
|
||||
to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -221,7 +221,7 @@ async fn shielded_transfer_to_owned_private_account() -> Result<()> {
|
||||
from: format_public_account_id(from),
|
||||
to: Some(format_private_account_id(to)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -256,14 +256,14 @@ async fn shielded_transfer_to_foreign_account() -> Result<()> {
|
||||
|
||||
let to_npk = NullifierPublicKey([42; 32]);
|
||||
let to_npk_string = hex::encode(to_npk.0);
|
||||
let to_ipk = Secp256k1Point::from_scalar(to_npk.0);
|
||||
let to_vpk = Secp256k1Point::from_scalar(to_npk.0);
|
||||
let from: AccountId = ctx.existing_public_accounts()[0];
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: format_public_account_id(from),
|
||||
to: None,
|
||||
to_npk: Some(to_npk_string),
|
||||
to_ipk: Some(hex::encode(to_ipk.0)),
|
||||
to_vpk: Some(hex::encode(to_vpk.0)),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -325,12 +325,12 @@ async fn private_transfer_to_owned_account_continuous_run_path() -> Result<()> {
|
||||
.cloned()
|
||||
.context("Failed to get private account")?;
|
||||
|
||||
// Send transfer using nullifier and incoming viewing public keys
|
||||
// Send transfer using nullifier and viewing public keys
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: format_private_account_id(from),
|
||||
to: None,
|
||||
to_npk: Some(hex::encode(to_keys.nullifer_public_key.0)),
|
||||
to_ipk: Some(hex::encode(to_keys.incoming_viewing_public_key.0)),
|
||||
to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ async fn successful_transfer_to_existing_account() -> Result<()> {
|
||||
from: format_public_account_id(ctx.existing_public_accounts()[0]),
|
||||
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -72,7 +72,7 @@ pub async fn successful_transfer_to_new_account() -> Result<()> {
|
||||
from: format_public_account_id(ctx.existing_public_accounts()[0]),
|
||||
to: Some(format_public_account_id(new_persistent_account_id)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -108,7 +108,7 @@ async fn failed_transfer_with_insufficient_balance() -> Result<()> {
|
||||
from: format_public_account_id(ctx.existing_public_accounts()[0]),
|
||||
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 1000000,
|
||||
});
|
||||
|
||||
@ -146,7 +146,7 @@ async fn two_consecutive_successful_transfers() -> Result<()> {
|
||||
from: format_public_account_id(ctx.existing_public_accounts()[0]),
|
||||
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -178,7 +178,7 @@ async fn two_consecutive_successful_transfers() -> Result<()> {
|
||||
from: format_public_account_id(ctx.existing_public_accounts()[0]),
|
||||
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ use tokio::test;
|
||||
use wallet::cli::{Command, programs::native_token_transfer::AuthTransferSubcommand};
|
||||
|
||||
/// Timeout in milliseconds to reliably await for block finalization
|
||||
const L2_TO_L1_TIMEOUT_MILLIS: u64 = 220000;
|
||||
const L2_TO_L1_TIMEOUT_MILLIS: u64 = 300000;
|
||||
|
||||
#[test]
|
||||
async fn indexer_test_run() -> Result<()> {
|
||||
@ -45,6 +45,7 @@ async fn indexer_test_run() -> Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Not reliable with current bedrock node"]
|
||||
async fn indexer_block_batching() -> Result<()> {
|
||||
let ctx = TestContext::new().await?;
|
||||
|
||||
@ -80,6 +81,7 @@ async fn indexer_block_batching() -> Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Not reliable with current bedrock node"]
|
||||
async fn indexer_state_consistency() -> Result<()> {
|
||||
let mut ctx = TestContext::new().await?;
|
||||
|
||||
@ -87,7 +89,7 @@ async fn indexer_state_consistency() -> Result<()> {
|
||||
from: format_public_account_id(ctx.existing_public_accounts()[0]),
|
||||
to: Some(format_public_account_id(ctx.existing_public_accounts()[1])),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
@ -119,7 +121,7 @@ async fn indexer_state_consistency() -> Result<()> {
|
||||
from: format_private_account_id(from),
|
||||
to: Some(format_private_account_id(to)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ async fn restore_keys_from_seed() -> Result<()> {
|
||||
from: format_private_account_id(from),
|
||||
to: Some(format_private_account_id(to_account_id1)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
@ -60,7 +60,7 @@ async fn restore_keys_from_seed() -> Result<()> {
|
||||
from: format_private_account_id(from),
|
||||
to: Some(format_private_account_id(to_account_id2)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 101,
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
@ -96,7 +96,7 @@ async fn restore_keys_from_seed() -> Result<()> {
|
||||
from: format_public_account_id(from),
|
||||
to: Some(format_public_account_id(to_account_id3)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 102,
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
@ -106,7 +106,7 @@ async fn restore_keys_from_seed() -> Result<()> {
|
||||
from: format_public_account_id(from),
|
||||
to: Some(format_public_account_id(to_account_id4)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 103,
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
@ -169,7 +169,7 @@ async fn restore_keys_from_seed() -> Result<()> {
|
||||
from: format_private_account_id(to_account_id1),
|
||||
to: Some(format_private_account_id(to_account_id2)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 10,
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
@ -178,7 +178,7 @@ async fn restore_keys_from_seed() -> Result<()> {
|
||||
from: format_public_account_id(to_account_id3),
|
||||
to: Some(format_public_account_id(to_account_id4)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: 11,
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
|
||||
@ -115,7 +115,7 @@ async fn create_and_transfer_public_token() -> Result<()> {
|
||||
from: format_public_account_id(supply_account_id),
|
||||
to: Some(format_public_account_id(recipient_account_id)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: transfer_amount,
|
||||
};
|
||||
|
||||
@ -208,7 +208,7 @@ async fn create_and_transfer_public_token() -> Result<()> {
|
||||
definition: format_public_account_id(definition_account_id),
|
||||
holder: Some(format_public_account_id(recipient_account_id)),
|
||||
holder_npk: None,
|
||||
holder_ipk: None,
|
||||
holder_vpk: None,
|
||||
amount: mint_amount,
|
||||
};
|
||||
|
||||
@ -343,7 +343,7 @@ async fn create_and_transfer_token_with_private_supply() -> Result<()> {
|
||||
from: format_private_account_id(supply_account_id),
|
||||
to: Some(format_private_account_id(recipient_account_id)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: transfer_amount,
|
||||
};
|
||||
|
||||
@ -525,7 +525,7 @@ async fn create_token_with_private_definition() -> Result<()> {
|
||||
definition: format_private_account_id(definition_account_id),
|
||||
holder: Some(format_public_account_id(recipient_account_id_public)),
|
||||
holder_npk: None,
|
||||
holder_ipk: None,
|
||||
holder_vpk: None,
|
||||
amount: mint_amount_public,
|
||||
};
|
||||
|
||||
@ -572,7 +572,7 @@ async fn create_token_with_private_definition() -> Result<()> {
|
||||
definition: format_private_account_id(definition_account_id),
|
||||
holder: Some(format_private_account_id(recipient_account_id_private)),
|
||||
holder_npk: None,
|
||||
holder_ipk: None,
|
||||
holder_vpk: None,
|
||||
amount: mint_amount_private,
|
||||
};
|
||||
|
||||
@ -701,7 +701,7 @@ async fn create_token_with_private_definition_and_supply() -> Result<()> {
|
||||
from: format_private_account_id(supply_account_id),
|
||||
to: Some(format_private_account_id(recipient_account_id)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: transfer_amount,
|
||||
};
|
||||
|
||||
@ -819,7 +819,7 @@ async fn shielded_token_transfer() -> Result<()> {
|
||||
from: format_public_account_id(supply_account_id),
|
||||
to: Some(format_private_account_id(recipient_account_id)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: transfer_amount,
|
||||
};
|
||||
|
||||
@ -933,7 +933,7 @@ async fn deshielded_token_transfer() -> Result<()> {
|
||||
from: format_private_account_id(supply_account_id),
|
||||
to: Some(format_public_account_id(recipient_account_id)),
|
||||
to_npk: None,
|
||||
to_ipk: None,
|
||||
to_vpk: None,
|
||||
amount: transfer_amount,
|
||||
};
|
||||
|
||||
@ -1056,7 +1056,7 @@ async fn token_claiming_path_with_private_accounts() -> Result<()> {
|
||||
definition: format_private_account_id(definition_account_id),
|
||||
holder: None,
|
||||
holder_npk: Some(hex::encode(holder_keys.nullifer_public_key.0)),
|
||||
holder_ipk: Some(hex::encode(holder_keys.incoming_viewing_public_key.0)),
|
||||
holder_vpk: Some(hex::encode(holder_keys.viewing_public_key.0)),
|
||||
amount: mint_amount,
|
||||
};
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ use nssa::{
|
||||
use nssa_core::{
|
||||
MembershipProof, NullifierPublicKey,
|
||||
account::{AccountWithMetadata, data::Data},
|
||||
encryption::IncomingViewingPublicKey,
|
||||
encryption::ViewingPublicKey,
|
||||
};
|
||||
use tokio::test;
|
||||
|
||||
@ -192,8 +192,8 @@ impl TpsTestManager {
|
||||
fn build_privacy_transaction() -> PrivacyPreservingTransaction {
|
||||
let program = Program::authenticated_transfer_program();
|
||||
let sender_nsk = [1; 32];
|
||||
let sender_isk = [99; 32];
|
||||
let sender_ipk = IncomingViewingPublicKey::from_scalar(sender_isk);
|
||||
let sender_vsk = [99; 32];
|
||||
let sender_vpk = ViewingPublicKey::from_scalar(sender_vsk);
|
||||
let sender_npk = NullifierPublicKey::from(&sender_nsk);
|
||||
let sender_pre = AccountWithMetadata::new(
|
||||
Account {
|
||||
@ -206,18 +206,18 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
|
||||
AccountId::from(&sender_npk),
|
||||
);
|
||||
let recipient_nsk = [2; 32];
|
||||
let recipient_isk = [99; 32];
|
||||
let recipient_ipk = IncomingViewingPublicKey::from_scalar(recipient_isk);
|
||||
let recipient_vsk = [99; 32];
|
||||
let recipient_vpk = ViewingPublicKey::from_scalar(recipient_vsk);
|
||||
let recipient_npk = NullifierPublicKey::from(&recipient_nsk);
|
||||
let recipient_pre =
|
||||
AccountWithMetadata::new(Account::default(), false, AccountId::from(&recipient_npk));
|
||||
|
||||
let eph_holder_from = EphemeralKeyHolder::new(&sender_npk);
|
||||
let sender_ss = eph_holder_from.calculate_shared_secret_sender(&sender_ipk);
|
||||
let sender_ss = eph_holder_from.calculate_shared_secret_sender(&sender_vpk);
|
||||
let sender_epk = eph_holder_from.generate_ephemeral_public_key();
|
||||
|
||||
let eph_holder_to = EphemeralKeyHolder::new(&recipient_npk);
|
||||
let recipient_ss = eph_holder_to.calculate_shared_secret_sender(&recipient_ipk);
|
||||
let recipient_ss = eph_holder_to.calculate_shared_secret_sender(&recipient_vpk);
|
||||
let recipient_epk = eph_holder_from.generate_ephemeral_public_key();
|
||||
|
||||
let balance_to_move: u128 = 1;
|
||||
@ -246,8 +246,8 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(sender_npk, sender_ipk, sender_epk),
|
||||
(recipient_npk, recipient_ipk, recipient_epk),
|
||||
(sender_npk, sender_vpk, sender_epk),
|
||||
(recipient_npk, recipient_vpk, recipient_epk),
|
||||
],
|
||||
output,
|
||||
)
|
||||
|
||||
@ -2,6 +2,7 @@ use std::{
|
||||
collections::HashSet,
|
||||
ffi::{CStr, CString, c_char},
|
||||
io::Write,
|
||||
path::Path,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
@ -24,6 +25,11 @@ unsafe extern "C" {
|
||||
password: *const c_char,
|
||||
) -> *mut WalletHandle;
|
||||
|
||||
fn wallet_ffi_open(
|
||||
config_path: *const c_char,
|
||||
storage_path: *const c_char,
|
||||
) -> *mut WalletHandle;
|
||||
|
||||
fn wallet_ffi_destroy(handle: *mut WalletHandle);
|
||||
|
||||
fn wallet_ffi_create_account_public(
|
||||
@ -56,6 +62,12 @@ unsafe extern "C" {
|
||||
out_account: *mut FfiAccount,
|
||||
) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_get_account_private(
|
||||
handle: *mut WalletHandle,
|
||||
account_id: *const FfiBytes32,
|
||||
out_account: *mut FfiAccount,
|
||||
) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_free_account_data(account: *mut FfiAccount);
|
||||
|
||||
fn wallet_ffi_get_public_account_key(
|
||||
@ -89,6 +101,30 @@ unsafe extern "C" {
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_transfer_shielded(
|
||||
handle: *mut WalletHandle,
|
||||
from: *const FfiBytes32,
|
||||
to_keys: *const FfiPrivateAccountKeys,
|
||||
amount: *const [u8; 16],
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_transfer_deshielded(
|
||||
handle: *mut WalletHandle,
|
||||
from: *const FfiBytes32,
|
||||
to: *const FfiBytes32,
|
||||
amount: *const [u8; 16],
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_transfer_private(
|
||||
handle: *mut WalletHandle,
|
||||
from: *const FfiBytes32,
|
||||
to_keys: *const FfiPrivateAccountKeys,
|
||||
amount: *const [u8; 16],
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_free_transfer_result(result: *mut FfiTransferResult);
|
||||
|
||||
fn wallet_ffi_register_public_account(
|
||||
@ -96,12 +132,29 @@ unsafe extern "C" {
|
||||
account_id: *const FfiBytes32,
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_register_private_account(
|
||||
handle: *mut WalletHandle,
|
||||
account_id: *const FfiBytes32,
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_save(handle: *mut WalletHandle) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_sync_to_block(handle: *mut WalletHandle, block_id: u64) -> error::WalletFfiError;
|
||||
|
||||
fn wallet_ffi_get_current_block_height(
|
||||
handle: *mut WalletHandle,
|
||||
out_block_height: *mut u64,
|
||||
) -> error::WalletFfiError;
|
||||
}
|
||||
|
||||
fn new_wallet_ffi_with_test_context_config(ctx: &BlockingTestContext) -> *mut WalletHandle {
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let config_path = tempdir.path().join("wallet_config.json");
|
||||
let storage_path = tempdir.path().join("storage.json");
|
||||
fn new_wallet_ffi_with_test_context_config(
|
||||
ctx: &BlockingTestContext,
|
||||
home: &Path,
|
||||
) -> *mut WalletHandle {
|
||||
let config_path = home.join("wallet_config.json");
|
||||
let storage_path = home.join("storage.json");
|
||||
let mut config = ctx.ctx().wallet().config().to_owned();
|
||||
if let Some(config_overrides) = ctx.ctx().wallet().config_overrides().clone() {
|
||||
config.apply_overrides(config_overrides);
|
||||
@ -161,6 +214,15 @@ fn new_wallet_rust_with_default_config(password: &str) -> WalletCore {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn load_existing_ffi_wallet(home: &Path) -> *mut WalletHandle {
|
||||
let config_path = home.join("wallet_config.json");
|
||||
let storage_path = home.join("storage.json");
|
||||
let config_path = CString::new(config_path.to_str().unwrap()).unwrap();
|
||||
let storage_path = CString::new(storage_path.to_str().unwrap()).unwrap();
|
||||
|
||||
unsafe { wallet_ffi_open(config_path.as_ptr(), storage_path.as_ptr()) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_create_public_accounts() {
|
||||
let password = "password_for_tests";
|
||||
@ -232,6 +294,56 @@ fn test_wallet_ffi_create_private_accounts() {
|
||||
|
||||
assert_eq!(new_private_account_ids_ffi, new_private_account_ids_rust)
|
||||
}
|
||||
#[test]
|
||||
fn test_wallet_ffi_save_and_load_persistent_storage() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new()?;
|
||||
let mut out_private_account_id = FfiBytes32::from_bytes([0; 32]);
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
|
||||
// Create a private account with the wallet FFI and save it
|
||||
unsafe {
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
wallet_ffi_create_account_private(
|
||||
wallet_ffi_handle,
|
||||
(&mut out_private_account_id) as *mut FfiBytes32,
|
||||
);
|
||||
|
||||
wallet_ffi_save(wallet_ffi_handle);
|
||||
wallet_ffi_destroy(wallet_ffi_handle);
|
||||
}
|
||||
|
||||
let private_account_keys = unsafe {
|
||||
let wallet_ffi_handle = load_existing_ffi_wallet(home.path());
|
||||
|
||||
let mut private_account = FfiAccount::default();
|
||||
|
||||
let result = wallet_ffi_get_account_private(
|
||||
wallet_ffi_handle,
|
||||
(&out_private_account_id) as *const FfiBytes32,
|
||||
(&mut private_account) as *mut FfiAccount,
|
||||
);
|
||||
assert_eq!(result, error::WalletFfiError::Success);
|
||||
|
||||
let mut out_keys = FfiPrivateAccountKeys::default();
|
||||
let result = wallet_ffi_get_private_account_keys(
|
||||
wallet_ffi_handle,
|
||||
(&out_private_account_id) as *const FfiBytes32,
|
||||
(&mut out_keys) as *mut FfiPrivateAccountKeys,
|
||||
);
|
||||
assert_eq!(result, error::WalletFfiError::Success);
|
||||
|
||||
wallet_ffi_destroy(wallet_ffi_handle);
|
||||
|
||||
out_keys
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
nssa::AccountId::from(&private_account_keys.npk()),
|
||||
out_private_account_id.into()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_list_accounts() {
|
||||
@ -326,7 +438,8 @@ fn test_wallet_ffi_list_accounts() {
|
||||
fn test_wallet_ffi_get_balance_public() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new()?;
|
||||
let account_id: AccountId = ctx.ctx().existing_public_accounts()[0];
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx);
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
|
||||
let balance = unsafe {
|
||||
let mut out_balance: [u8; 16] = [0; 16];
|
||||
@ -354,7 +467,8 @@ fn test_wallet_ffi_get_balance_public() -> Result<()> {
|
||||
fn test_wallet_ffi_get_account_public() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new()?;
|
||||
let account_id: AccountId = ctx.ctx().existing_public_accounts()[0];
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx);
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
let mut out_account = FfiAccount::default();
|
||||
|
||||
let account: Account = unsafe {
|
||||
@ -385,11 +499,48 @@ fn test_wallet_ffi_get_account_public() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_get_account_private() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new()?;
|
||||
let account_id: AccountId = ctx.ctx().existing_private_accounts()[0];
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
let mut out_account = FfiAccount::default();
|
||||
|
||||
let account: Account = unsafe {
|
||||
let ffi_account_id = FfiBytes32::from(&account_id);
|
||||
let _result = wallet_ffi_get_account_private(
|
||||
wallet_ffi_handle,
|
||||
(&ffi_account_id) as *const FfiBytes32,
|
||||
(&mut out_account) as *mut FfiAccount,
|
||||
);
|
||||
(&out_account).try_into().unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
account.program_owner,
|
||||
Program::authenticated_transfer_program().id()
|
||||
);
|
||||
assert_eq!(account.balance, 10000);
|
||||
assert!(account.data.is_empty());
|
||||
assert_eq!(account.nonce, 0);
|
||||
|
||||
unsafe {
|
||||
wallet_ffi_free_account_data((&mut out_account) as *mut FfiAccount);
|
||||
wallet_ffi_destroy(wallet_ffi_handle);
|
||||
}
|
||||
|
||||
info!("Successfully retrieved account with correct details");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_get_public_account_keys() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new()?;
|
||||
let account_id: AccountId = ctx.ctx().existing_public_accounts()[0];
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx);
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
let mut out_key = FfiPublicAccountKey::default();
|
||||
|
||||
let key: PublicKey = unsafe {
|
||||
@ -426,7 +577,8 @@ fn test_wallet_ffi_get_public_account_keys() -> Result<()> {
|
||||
fn test_wallet_ffi_get_private_account_keys() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new()?;
|
||||
let account_id: AccountId = ctx.ctx().existing_private_accounts()[0];
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx);
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
let mut keys = FfiPrivateAccountKeys::default();
|
||||
|
||||
unsafe {
|
||||
@ -448,10 +600,10 @@ fn test_wallet_ffi_get_private_account_keys() -> Result<()> {
|
||||
.0;
|
||||
|
||||
let expected_npk = &key_chain.nullifer_public_key;
|
||||
let expected_ivk = &key_chain.incoming_viewing_public_key;
|
||||
let expected_vpk = &key_chain.viewing_public_key;
|
||||
|
||||
assert_eq!(&keys.npk(), expected_npk);
|
||||
assert_eq!(&keys.ivk().unwrap(), expected_ivk);
|
||||
assert_eq!(&keys.vpk().unwrap(), expected_vpk);
|
||||
|
||||
unsafe {
|
||||
wallet_ffi_free_private_account_keys((&mut keys) as *mut FfiPrivateAccountKeys);
|
||||
@ -504,7 +656,8 @@ fn test_wallet_ffi_base58_to_account_id() {
|
||||
#[test]
|
||||
fn test_wallet_ffi_init_public_account_auth_transfer() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx);
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
|
||||
// Create a new uninitialized public account
|
||||
let mut out_account_id = FfiBytes32::from_bytes([0; 32]);
|
||||
@ -563,10 +716,81 @@ fn test_wallet_ffi_init_public_account_auth_transfer() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_init_private_account_auth_transfer() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new().unwrap();
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
|
||||
// Create a new uninitialized public account
|
||||
let mut out_account_id = FfiBytes32::from_bytes([0; 32]);
|
||||
unsafe {
|
||||
wallet_ffi_create_account_private(
|
||||
wallet_ffi_handle,
|
||||
(&mut out_account_id) as *mut FfiBytes32,
|
||||
);
|
||||
}
|
||||
|
||||
// Check its program owner is the default program id
|
||||
let account: Account = unsafe {
|
||||
let mut out_account = FfiAccount::default();
|
||||
wallet_ffi_get_account_private(
|
||||
wallet_ffi_handle,
|
||||
(&out_account_id) as *const FfiBytes32,
|
||||
(&mut out_account) as *mut FfiAccount,
|
||||
);
|
||||
(&out_account).try_into().unwrap()
|
||||
};
|
||||
assert_eq!(account.program_owner, DEFAULT_PROGRAM_ID);
|
||||
|
||||
// Call the init funciton
|
||||
let mut transfer_result = FfiTransferResult::default();
|
||||
unsafe {
|
||||
wallet_ffi_register_private_account(
|
||||
wallet_ffi_handle,
|
||||
(&out_account_id) as *const FfiBytes32,
|
||||
(&mut transfer_result) as *mut FfiTransferResult,
|
||||
);
|
||||
}
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS));
|
||||
|
||||
// Sync private account local storage with onchain encrypted state
|
||||
unsafe {
|
||||
let mut current_height = 0;
|
||||
wallet_ffi_get_current_block_height(wallet_ffi_handle, (&mut current_height) as *mut u64);
|
||||
wallet_ffi_sync_to_block(wallet_ffi_handle, current_height);
|
||||
};
|
||||
|
||||
// Check that the program owner is now the authenticated transfer program
|
||||
let account: Account = unsafe {
|
||||
let mut out_account = FfiAccount::default();
|
||||
let _result = wallet_ffi_get_account_private(
|
||||
wallet_ffi_handle,
|
||||
(&out_account_id) as *const FfiBytes32,
|
||||
(&mut out_account) as *mut FfiAccount,
|
||||
);
|
||||
(&out_account).try_into().unwrap()
|
||||
};
|
||||
assert_eq!(
|
||||
account.program_owner,
|
||||
Program::authenticated_transfer_program().id()
|
||||
);
|
||||
|
||||
unsafe {
|
||||
wallet_ffi_free_transfer_result((&mut transfer_result) as *mut FfiTransferResult);
|
||||
wallet_ffi_destroy(wallet_ffi_handle);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_transfer_public() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx);
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
let from: FfiBytes32 = (&ctx.ctx().existing_public_accounts()[0]).into();
|
||||
let to: FfiBytes32 = (&ctx.ctx().existing_public_accounts()[1]).into();
|
||||
let amount: [u8; 16] = 100u128.to_le_bytes();
|
||||
@ -617,3 +841,220 @@ fn test_wallet_ffi_transfer_public() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_transfer_shielded() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new().unwrap();
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
let from: FfiBytes32 = (&ctx.ctx().existing_public_accounts()[0]).into();
|
||||
let (to, to_keys) = unsafe {
|
||||
let mut out_account_id = FfiBytes32::default();
|
||||
let mut out_keys = FfiPrivateAccountKeys::default();
|
||||
wallet_ffi_create_account_private(
|
||||
wallet_ffi_handle,
|
||||
(&mut out_account_id) as *mut FfiBytes32,
|
||||
);
|
||||
wallet_ffi_get_private_account_keys(
|
||||
wallet_ffi_handle,
|
||||
(&out_account_id) as *const FfiBytes32,
|
||||
(&mut out_keys) as *mut FfiPrivateAccountKeys,
|
||||
);
|
||||
(out_account_id, out_keys)
|
||||
};
|
||||
let amount: [u8; 16] = 100u128.to_le_bytes();
|
||||
|
||||
let mut transfer_result = FfiTransferResult::default();
|
||||
unsafe {
|
||||
wallet_ffi_transfer_shielded(
|
||||
wallet_ffi_handle,
|
||||
(&from) as *const FfiBytes32,
|
||||
(&to_keys) as *const FfiPrivateAccountKeys,
|
||||
(&amount) as *const [u8; 16],
|
||||
(&mut transfer_result) as *mut FfiTransferResult,
|
||||
);
|
||||
}
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS));
|
||||
|
||||
// Sync private account local storage with onchain encrypted state
|
||||
unsafe {
|
||||
let mut current_height = 0;
|
||||
wallet_ffi_get_current_block_height(wallet_ffi_handle, (&mut current_height) as *mut u64);
|
||||
wallet_ffi_sync_to_block(wallet_ffi_handle, current_height);
|
||||
};
|
||||
|
||||
let from_balance = unsafe {
|
||||
let mut out_balance: [u8; 16] = [0; 16];
|
||||
let _result = wallet_ffi_get_balance(
|
||||
wallet_ffi_handle,
|
||||
(&from) as *const FfiBytes32,
|
||||
true,
|
||||
(&mut out_balance) as *mut [u8; 16],
|
||||
);
|
||||
u128::from_le_bytes(out_balance)
|
||||
};
|
||||
|
||||
let to_balance = unsafe {
|
||||
let mut out_balance: [u8; 16] = [0; 16];
|
||||
let _result = wallet_ffi_get_balance(
|
||||
wallet_ffi_handle,
|
||||
(&to) as *const FfiBytes32,
|
||||
false,
|
||||
(&mut out_balance) as *mut [u8; 16],
|
||||
);
|
||||
u128::from_le_bytes(out_balance)
|
||||
};
|
||||
|
||||
assert_eq!(from_balance, 9900);
|
||||
assert_eq!(to_balance, 100);
|
||||
|
||||
unsafe {
|
||||
wallet_ffi_free_transfer_result((&mut transfer_result) as *mut FfiTransferResult);
|
||||
wallet_ffi_destroy(wallet_ffi_handle);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_transfer_deshielded() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new().unwrap();
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
let from: FfiBytes32 = (&ctx.ctx().existing_private_accounts()[0]).into();
|
||||
let to = FfiBytes32::from_bytes([37; 32]);
|
||||
let amount: [u8; 16] = 100u128.to_le_bytes();
|
||||
|
||||
let mut transfer_result = FfiTransferResult::default();
|
||||
unsafe {
|
||||
wallet_ffi_transfer_deshielded(
|
||||
wallet_ffi_handle,
|
||||
(&from) as *const FfiBytes32,
|
||||
(&to) as *const FfiBytes32,
|
||||
(&amount) as *const [u8; 16],
|
||||
(&mut transfer_result) as *mut FfiTransferResult,
|
||||
);
|
||||
}
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS));
|
||||
|
||||
// Sync private account local storage with onchain encrypted state
|
||||
unsafe {
|
||||
let mut current_height = 0;
|
||||
wallet_ffi_get_current_block_height(wallet_ffi_handle, (&mut current_height) as *mut u64);
|
||||
wallet_ffi_sync_to_block(wallet_ffi_handle, current_height);
|
||||
};
|
||||
|
||||
let from_balance = unsafe {
|
||||
let mut out_balance: [u8; 16] = [0; 16];
|
||||
let _result = wallet_ffi_get_balance(
|
||||
wallet_ffi_handle,
|
||||
(&from) as *const FfiBytes32,
|
||||
false,
|
||||
(&mut out_balance) as *mut [u8; 16],
|
||||
);
|
||||
u128::from_le_bytes(out_balance)
|
||||
};
|
||||
|
||||
let to_balance = unsafe {
|
||||
let mut out_balance: [u8; 16] = [0; 16];
|
||||
let _result = wallet_ffi_get_balance(
|
||||
wallet_ffi_handle,
|
||||
(&to) as *const FfiBytes32,
|
||||
true,
|
||||
(&mut out_balance) as *mut [u8; 16],
|
||||
);
|
||||
u128::from_le_bytes(out_balance)
|
||||
};
|
||||
|
||||
assert_eq!(from_balance, 9900);
|
||||
assert_eq!(to_balance, 100);
|
||||
|
||||
unsafe {
|
||||
wallet_ffi_free_transfer_result((&mut transfer_result) as *mut FfiTransferResult);
|
||||
wallet_ffi_destroy(wallet_ffi_handle);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_ffi_transfer_private() -> Result<()> {
|
||||
let ctx = BlockingTestContext::new().unwrap();
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx, home.path());
|
||||
|
||||
let from: FfiBytes32 = (&ctx.ctx().existing_private_accounts()[0]).into();
|
||||
let (to, to_keys) = unsafe {
|
||||
let mut out_account_id = FfiBytes32::default();
|
||||
let mut out_keys = FfiPrivateAccountKeys::default();
|
||||
wallet_ffi_create_account_private(
|
||||
wallet_ffi_handle,
|
||||
(&mut out_account_id) as *mut FfiBytes32,
|
||||
);
|
||||
wallet_ffi_get_private_account_keys(
|
||||
wallet_ffi_handle,
|
||||
(&out_account_id) as *const FfiBytes32,
|
||||
(&mut out_keys) as *mut FfiPrivateAccountKeys,
|
||||
);
|
||||
(out_account_id, out_keys)
|
||||
};
|
||||
|
||||
let amount: [u8; 16] = 100u128.to_le_bytes();
|
||||
|
||||
let mut transfer_result = FfiTransferResult::default();
|
||||
unsafe {
|
||||
wallet_ffi_transfer_private(
|
||||
wallet_ffi_handle,
|
||||
(&from) as *const FfiBytes32,
|
||||
(&to_keys) as *const FfiPrivateAccountKeys,
|
||||
(&amount) as *const [u8; 16],
|
||||
(&mut transfer_result) as *mut FfiTransferResult,
|
||||
);
|
||||
}
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS));
|
||||
|
||||
// Sync private account local storage with onchain encrypted state
|
||||
unsafe {
|
||||
let mut current_height = 0;
|
||||
wallet_ffi_get_current_block_height(wallet_ffi_handle, (&mut current_height) as *mut u64);
|
||||
wallet_ffi_sync_to_block(wallet_ffi_handle, current_height);
|
||||
};
|
||||
|
||||
let from_balance = unsafe {
|
||||
let mut out_balance: [u8; 16] = [0; 16];
|
||||
let _result = wallet_ffi_get_balance(
|
||||
wallet_ffi_handle,
|
||||
(&from) as *const FfiBytes32,
|
||||
false,
|
||||
(&mut out_balance) as *mut [u8; 16],
|
||||
);
|
||||
u128::from_le_bytes(out_balance)
|
||||
};
|
||||
|
||||
let to_balance = unsafe {
|
||||
let mut out_balance: [u8; 16] = [0; 16];
|
||||
let _result = wallet_ffi_get_balance(
|
||||
wallet_ffi_handle,
|
||||
(&to) as *const FfiBytes32,
|
||||
false,
|
||||
(&mut out_balance) as *mut [u8; 16],
|
||||
);
|
||||
u128::from_le_bytes(out_balance)
|
||||
};
|
||||
|
||||
assert_eq!(from_balance, 9900);
|
||||
assert_eq!(to_balance, 100);
|
||||
|
||||
unsafe {
|
||||
wallet_ffi_free_transfer_result((&mut transfer_result) as *mut FfiTransferResult);
|
||||
wallet_ffi_destroy(wallet_ffi_handle);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use nssa_core::{
|
||||
NullifierPublicKey, SharedSecretKey,
|
||||
encryption::{EphemeralPublicKey, EphemeralSecretKey, IncomingViewingPublicKey},
|
||||
encryption::{EphemeralPublicKey, EphemeralSecretKey, ViewingPublicKey},
|
||||
};
|
||||
use rand::{RngCore, rngs::OsRng};
|
||||
use sha2::Digest;
|
||||
@ -13,12 +13,12 @@ pub struct EphemeralKeyHolder {
|
||||
}
|
||||
|
||||
pub fn produce_one_sided_shared_secret_receiver(
|
||||
ipk: &IncomingViewingPublicKey,
|
||||
vpk: &ViewingPublicKey,
|
||||
) -> (SharedSecretKey, EphemeralPublicKey) {
|
||||
let mut esk = [0; 32];
|
||||
OsRng.fill_bytes(&mut esk);
|
||||
(
|
||||
SharedSecretKey::new(&esk, ipk),
|
||||
SharedSecretKey::new(&esk, vpk),
|
||||
EphemeralPublicKey::from_scalar(esk),
|
||||
)
|
||||
}
|
||||
@ -42,11 +42,8 @@ impl EphemeralKeyHolder {
|
||||
|
||||
pub fn calculate_shared_secret_sender(
|
||||
&self,
|
||||
receiver_incoming_viewing_public_key: &IncomingViewingPublicKey,
|
||||
receiver_viewing_public_key: &ViewingPublicKey,
|
||||
) -> SharedSecretKey {
|
||||
SharedSecretKey::new(
|
||||
&self.ephemeral_secret_key,
|
||||
receiver_incoming_viewing_public_key,
|
||||
)
|
||||
SharedSecretKey::new(&self.ephemeral_secret_key, receiver_viewing_public_key)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use k256::{Scalar, elliptic_curve::PrimeField};
|
||||
use nssa_core::encryption::IncomingViewingPublicKey;
|
||||
use nssa_core::{NullifierPublicKey, encryption::ViewingPublicKey};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::key_management::{
|
||||
@ -18,7 +18,7 @@ pub struct ChildKeysPrivate {
|
||||
|
||||
impl KeyNode for ChildKeysPrivate {
|
||||
fn root(seed: [u8; 64]) -> Self {
|
||||
let hash_value = hmac_sha512::HMAC::mac(seed, "NSSA_master_priv");
|
||||
let hash_value = hmac_sha512::HMAC::mac(seed, b"LEE_master_priv");
|
||||
|
||||
let ssk = SecretSpendingKey(
|
||||
*hash_value
|
||||
@ -29,23 +29,21 @@ impl KeyNode for ChildKeysPrivate {
|
||||
.last_chunk::<32>()
|
||||
.expect("hash_value is 64 bytes, must be safe to get last 32");
|
||||
|
||||
let nsk = ssk.generate_nullifier_secret_key();
|
||||
let isk = ssk.generate_incoming_viewing_secret_key();
|
||||
let ovk = ssk.generate_outgoing_viewing_secret_key();
|
||||
let nsk = ssk.generate_nullifier_secret_key(None);
|
||||
let vsk = ssk.generate_viewing_secret_key(None);
|
||||
|
||||
let npk = (&nsk).into();
|
||||
let ipk = IncomingViewingPublicKey::from_scalar(isk);
|
||||
let npk = NullifierPublicKey::from(&nsk);
|
||||
let vpk = ViewingPublicKey::from_scalar(vsk);
|
||||
|
||||
Self {
|
||||
value: (
|
||||
KeyChain {
|
||||
secret_spending_key: ssk,
|
||||
nullifer_public_key: npk,
|
||||
incoming_viewing_public_key: ipk,
|
||||
viewing_public_key: vpk,
|
||||
private_key_holder: PrivateKeyHolder {
|
||||
nullifier_secret_key: nsk,
|
||||
incoming_viewing_secret_key: isk,
|
||||
outgoing_viewing_secret_key: ovk,
|
||||
viewing_secret_key: vsk,
|
||||
},
|
||||
},
|
||||
nssa::Account::default(),
|
||||
@ -56,27 +54,14 @@ impl KeyNode for ChildKeysPrivate {
|
||||
}
|
||||
|
||||
fn nth_child(&self, cci: u32) -> Self {
|
||||
let parent_pt = Scalar::from_repr(
|
||||
self.value
|
||||
.0
|
||||
.private_key_holder
|
||||
.outgoing_viewing_secret_key
|
||||
.into(),
|
||||
)
|
||||
.expect("Key generated as scalar, must be valid representation")
|
||||
+ Scalar::from_repr(self.value.0.private_key_holder.nullifier_secret_key.into())
|
||||
let parent_pt =
|
||||
Scalar::from_repr(self.value.0.private_key_holder.nullifier_secret_key.into())
|
||||
.expect("Key generated as scalar, must be valid representation")
|
||||
* Scalar::from_repr(
|
||||
self.value
|
||||
.0
|
||||
.private_key_holder
|
||||
.incoming_viewing_secret_key
|
||||
.into(),
|
||||
)
|
||||
.expect("Key generated as scalar, must be valid representation");
|
||||
* Scalar::from_repr(self.value.0.private_key_holder.viewing_secret_key.into())
|
||||
.expect("Key generated as scalar, must be valid representation");
|
||||
let mut input = vec![];
|
||||
|
||||
input.extend_from_slice(b"NSSA_seed_priv");
|
||||
input.extend_from_slice(b"LEE_seed_priv");
|
||||
input.extend_from_slice(&parent_pt.to_bytes());
|
||||
input.extend_from_slice(&cci.to_le_bytes());
|
||||
|
||||
@ -91,23 +76,21 @@ impl KeyNode for ChildKeysPrivate {
|
||||
.last_chunk::<32>()
|
||||
.expect("hash_value is 64 bytes, must be safe to get last 32");
|
||||
|
||||
let nsk = ssk.generate_nullifier_secret_key();
|
||||
let isk = ssk.generate_incoming_viewing_secret_key();
|
||||
let ovk = ssk.generate_outgoing_viewing_secret_key();
|
||||
let nsk = ssk.generate_nullifier_secret_key(Some(cci));
|
||||
let vsk = ssk.generate_viewing_secret_key(Some(cci));
|
||||
|
||||
let npk = (&nsk).into();
|
||||
let ipk = IncomingViewingPublicKey::from_scalar(isk);
|
||||
let npk = NullifierPublicKey::from(&nsk);
|
||||
let vpk = ViewingPublicKey::from_scalar(vsk);
|
||||
|
||||
Self {
|
||||
value: (
|
||||
KeyChain {
|
||||
secret_spending_key: ssk,
|
||||
nullifer_public_key: npk,
|
||||
incoming_viewing_public_key: ipk,
|
||||
viewing_public_key: vpk,
|
||||
private_key_holder: PrivateKeyHolder {
|
||||
nullifier_secret_key: nsk,
|
||||
incoming_viewing_secret_key: isk,
|
||||
outgoing_viewing_secret_key: ovk,
|
||||
viewing_secret_key: vsk,
|
||||
},
|
||||
},
|
||||
nssa::Account::default(),
|
||||
@ -144,120 +127,98 @@ impl<'a> From<&'a mut ChildKeysPrivate> for &'a mut (KeyChain, nssa::Account) {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nssa_core::{NullifierPublicKey, NullifierSecretKey};
|
||||
|
||||
use super::*;
|
||||
use crate::key_management::{self, secret_holders::ViewingSecretKey};
|
||||
|
||||
#[test]
|
||||
fn test_keys_deterministic_generation() {
|
||||
let root_keys = ChildKeysPrivate::root([42; 64]);
|
||||
let child_keys = root_keys.nth_child(5);
|
||||
fn test_master_key_generation() {
|
||||
let seed: [u8; 64] = [
|
||||
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
|
||||
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
|
||||
129, 223, 176, 198, 5, 150, 157, 70, 210, 254, 14, 105, 89, 191, 246, 27, 52, 170, 56,
|
||||
114, 39, 38, 118, 197, 205, 225,
|
||||
];
|
||||
|
||||
assert_eq!(root_keys.cci, None);
|
||||
assert_eq!(child_keys.cci, Some(5));
|
||||
let keys = ChildKeysPrivate::root(seed);
|
||||
|
||||
assert_eq!(
|
||||
root_keys.value.0.secret_spending_key.0,
|
||||
[
|
||||
249, 83, 253, 32, 174, 204, 185, 44, 253, 167, 61, 92, 128, 5, 152, 4, 220, 21, 88,
|
||||
84, 167, 180, 154, 249, 44, 77, 33, 136, 59, 131, 203, 152
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
child_keys.value.0.secret_spending_key.0,
|
||||
[
|
||||
16, 242, 229, 242, 252, 158, 153, 210, 234, 120, 70, 85, 83, 196, 5, 53, 28, 26,
|
||||
187, 230, 22, 193, 146, 232, 237, 3, 166, 184, 122, 1, 233, 93
|
||||
]
|
||||
);
|
||||
let expected_ssk: SecretSpendingKey = key_management::secret_holders::SecretSpendingKey([
|
||||
246, 79, 26, 124, 135, 95, 52, 51, 201, 27, 48, 194, 2, 144, 51, 219, 245, 128, 139,
|
||||
222, 42, 195, 105, 33, 115, 97, 186, 0, 97, 14, 218, 191,
|
||||
]);
|
||||
|
||||
assert_eq!(
|
||||
root_keys.value.0.private_key_holder.nullifier_secret_key,
|
||||
[
|
||||
38, 195, 52, 182, 16, 66, 167, 156, 9, 14, 65, 100, 17, 93, 166, 71, 27, 148, 93,
|
||||
85, 116, 109, 130, 8, 195, 222, 159, 214, 141, 41, 124, 57
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
child_keys.value.0.private_key_holder.nullifier_secret_key,
|
||||
[
|
||||
215, 46, 2, 151, 174, 60, 86, 154, 5, 3, 175, 245, 12, 176, 220, 58, 250, 118, 236,
|
||||
49, 254, 221, 229, 58, 40, 1, 170, 145, 175, 108, 23, 170
|
||||
]
|
||||
);
|
||||
let expected_ccc = [
|
||||
56, 114, 70, 249, 67, 169, 206, 9, 192, 11, 180, 168, 149, 129, 42, 95, 43, 157, 130,
|
||||
111, 13, 5, 195, 75, 20, 255, 162, 85, 40, 251, 8, 168,
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
root_keys
|
||||
.value
|
||||
.0
|
||||
.private_key_holder
|
||||
.incoming_viewing_secret_key,
|
||||
[
|
||||
153, 161, 15, 34, 96, 184, 165, 165, 27, 244, 155, 40, 70, 5, 241, 133, 78, 40, 61,
|
||||
118, 48, 148, 226, 5, 97, 18, 201, 128, 82, 248, 163, 72
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
child_keys
|
||||
.value
|
||||
.0
|
||||
.private_key_holder
|
||||
.incoming_viewing_secret_key,
|
||||
[
|
||||
192, 155, 55, 43, 164, 115, 71, 145, 227, 225, 21, 57, 55, 12, 226, 44, 10, 103,
|
||||
39, 73, 230, 173, 60, 69, 69, 122, 110, 241, 164, 3, 192, 57
|
||||
]
|
||||
);
|
||||
let expected_nsk: NullifierSecretKey = [
|
||||
154, 102, 103, 5, 34, 235, 227, 13, 22, 182, 226, 11, 7, 67, 110, 162, 99, 193, 174,
|
||||
34, 234, 19, 222, 2, 22, 12, 163, 252, 88, 11, 0, 163,
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
root_keys
|
||||
.value
|
||||
.0
|
||||
.private_key_holder
|
||||
.outgoing_viewing_secret_key,
|
||||
[
|
||||
205, 87, 71, 129, 90, 242, 217, 200, 140, 252, 124, 46, 207, 7, 33, 156, 83, 166,
|
||||
150, 81, 98, 131, 182, 156, 110, 92, 78, 140, 125, 218, 152, 154
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
child_keys
|
||||
.value
|
||||
.0
|
||||
.private_key_holder
|
||||
.outgoing_viewing_secret_key,
|
||||
[
|
||||
131, 202, 219, 172, 219, 29, 48, 120, 226, 209, 209, 10, 216, 173, 48, 167, 233,
|
||||
17, 35, 155, 30, 217, 176, 120, 72, 146, 250, 226, 165, 178, 255, 90
|
||||
]
|
||||
);
|
||||
let expected_npk: NullifierPublicKey = nssa_core::NullifierPublicKey([
|
||||
7, 123, 125, 191, 233, 183, 201, 4, 20, 214, 155, 210, 45, 234, 27, 240, 194, 111, 97,
|
||||
247, 155, 113, 122, 246, 192, 0, 70, 61, 76, 71, 70, 2,
|
||||
]);
|
||||
let expected_vsk: ViewingSecretKey = [
|
||||
155, 90, 54, 75, 228, 130, 68, 201, 129, 251, 180, 195, 250, 64, 34, 230, 241, 204,
|
||||
216, 50, 149, 156, 10, 67, 208, 74, 9, 10, 47, 59, 50, 202,
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
root_keys.value.0.nullifer_public_key.0,
|
||||
[
|
||||
65, 176, 149, 243, 192, 45, 216, 177, 169, 56, 229, 7, 28, 66, 204, 87, 109, 83,
|
||||
152, 64, 14, 188, 179, 210, 147, 60, 22, 251, 203, 70, 89, 215
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
child_keys.value.0.nullifer_public_key.0,
|
||||
[
|
||||
69, 104, 130, 115, 48, 134, 19, 188, 67, 148, 163, 54, 155, 237, 57, 27, 136, 228,
|
||||
111, 233, 205, 158, 149, 31, 84, 11, 241, 176, 243, 12, 138, 249
|
||||
]
|
||||
);
|
||||
let expected_vpk_as_bytes: [u8; 33] = [
|
||||
2, 191, 99, 102, 114, 40, 131, 109, 166, 8, 222, 186, 107, 29, 156, 106, 206, 96, 127,
|
||||
80, 170, 66, 217, 79, 38, 80, 11, 74, 147, 123, 221, 159, 166,
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
root_keys.value.0.incoming_viewing_public_key.0,
|
||||
&[
|
||||
3, 174, 56, 136, 244, 179, 18, 122, 38, 220, 36, 50, 200, 41, 104, 167, 70, 18, 60,
|
||||
202, 93, 193, 29, 16, 125, 252, 96, 51, 199, 152, 47, 233, 178
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
child_keys.value.0.incoming_viewing_public_key.0,
|
||||
&[
|
||||
3, 18, 202, 246, 79, 141, 169, 51, 55, 202, 120, 169, 244, 201, 156, 162, 216, 115,
|
||||
126, 53, 46, 94, 235, 125, 114, 178, 215, 81, 171, 93, 93, 88, 117
|
||||
]
|
||||
);
|
||||
assert!(expected_ssk == keys.value.0.secret_spending_key);
|
||||
assert!(expected_ccc == keys.ccc);
|
||||
assert!(expected_nsk == keys.value.0.private_key_holder.nullifier_secret_key);
|
||||
assert!(expected_npk == keys.value.0.nullifer_public_key);
|
||||
assert!(expected_vsk == keys.value.0.private_key_holder.viewing_secret_key);
|
||||
assert!(expected_vpk_as_bytes == keys.value.0.viewing_public_key.to_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_child_keys_generation() {
|
||||
let seed: [u8; 64] = [
|
||||
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
|
||||
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
|
||||
129, 223, 176, 198, 5, 150, 157, 70, 210, 254, 14, 105, 89, 191, 246, 27, 52, 170, 56,
|
||||
114, 39, 38, 118, 197, 205, 225,
|
||||
];
|
||||
|
||||
let root_node = ChildKeysPrivate::root(seed);
|
||||
let child_node = ChildKeysPrivate::nth_child(&root_node, 42u32);
|
||||
|
||||
let expected_ccc: [u8; 32] = [
|
||||
145, 59, 225, 32, 54, 168, 14, 45, 60, 253, 57, 202, 31, 86, 142, 234, 51, 57, 154, 88,
|
||||
132, 200, 92, 191, 220, 144, 42, 184, 108, 35, 226, 146,
|
||||
];
|
||||
|
||||
let expected_nsk: NullifierSecretKey = [
|
||||
19, 100, 119, 73, 191, 225, 234, 219, 129, 88, 40, 229, 63, 225, 189, 136, 69, 172,
|
||||
221, 186, 147, 83, 150, 207, 70, 17, 228, 70, 113, 87, 227, 31,
|
||||
];
|
||||
let expected_npk: NullifierPublicKey = nssa_core::NullifierPublicKey([
|
||||
133, 235, 223, 151, 12, 69, 26, 222, 60, 125, 235, 125, 167, 212, 201, 168, 101, 242,
|
||||
111, 239, 1, 228, 12, 252, 146, 53, 75, 17, 187, 255, 122, 181,
|
||||
]);
|
||||
|
||||
let expected_vsk: ViewingSecretKey = [
|
||||
218, 219, 193, 132, 160, 6, 178, 194, 139, 248, 199, 81, 17, 133, 37, 201, 58, 104, 49,
|
||||
222, 187, 46, 156, 93, 14, 118, 209, 243, 38, 101, 77, 45,
|
||||
];
|
||||
let expected_vpk_as_bytes: [u8; 33] = [
|
||||
3, 164, 65, 167, 88, 167, 179, 51, 159, 27, 241, 174, 77, 174, 142, 106, 128, 96, 69,
|
||||
74, 117, 231, 42, 193, 235, 153, 206, 116, 102, 7, 101, 192, 45,
|
||||
];
|
||||
|
||||
assert!(expected_ccc == child_node.ccc);
|
||||
assert!(expected_nsk == child_node.value.0.private_key_holder.nullifier_secret_key);
|
||||
assert!(expected_npk == child_node.value.0.nullifer_public_key);
|
||||
assert!(expected_vsk == child_node.value.0.private_key_holder.viewing_secret_key);
|
||||
assert!(expected_vpk_as_bytes == child_node.value.0.viewing_public_key.to_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use nssa_core::{
|
||||
NullifierPublicKey, SharedSecretKey,
|
||||
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
|
||||
encryption::{EphemeralPublicKey, ViewingPublicKey},
|
||||
};
|
||||
use secret_holders::{PrivateKeyHolder, SecretSpendingKey, SeedHolder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -17,7 +17,7 @@ pub struct KeyChain {
|
||||
pub secret_spending_key: SecretSpendingKey,
|
||||
pub private_key_holder: PrivateKeyHolder,
|
||||
pub nullifer_public_key: NullifierPublicKey,
|
||||
pub incoming_viewing_public_key: IncomingViewingPublicKey,
|
||||
pub viewing_public_key: ViewingPublicKey,
|
||||
}
|
||||
|
||||
impl KeyChain {
|
||||
@ -27,16 +27,16 @@ impl KeyChain {
|
||||
let seed_holder = SeedHolder::new_os_random();
|
||||
let secret_spending_key = seed_holder.produce_top_secret_key_holder();
|
||||
|
||||
let private_key_holder = secret_spending_key.produce_private_key_holder();
|
||||
let private_key_holder = secret_spending_key.produce_private_key_holder(None);
|
||||
|
||||
let nullifer_public_key = private_key_holder.generate_nullifier_public_key();
|
||||
let incoming_viewing_public_key = private_key_holder.generate_incoming_viewing_public_key();
|
||||
let viewing_public_key = private_key_holder.generate_viewing_public_key();
|
||||
|
||||
Self {
|
||||
secret_spending_key,
|
||||
private_key_holder,
|
||||
nullifer_public_key,
|
||||
incoming_viewing_public_key,
|
||||
viewing_public_key,
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,16 +46,16 @@ impl KeyChain {
|
||||
let seed_holder = SeedHolder::new_mnemonic(passphrase);
|
||||
let secret_spending_key = seed_holder.produce_top_secret_key_holder();
|
||||
|
||||
let private_key_holder = secret_spending_key.produce_private_key_holder();
|
||||
let private_key_holder = secret_spending_key.produce_private_key_holder(None);
|
||||
|
||||
let nullifer_public_key = private_key_holder.generate_nullifier_public_key();
|
||||
let incoming_viewing_public_key = private_key_holder.generate_incoming_viewing_public_key();
|
||||
let viewing_public_key = private_key_holder.generate_viewing_public_key();
|
||||
|
||||
Self {
|
||||
secret_spending_key,
|
||||
private_key_holder,
|
||||
nullifer_public_key,
|
||||
incoming_viewing_public_key,
|
||||
viewing_public_key,
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,9 +64,7 @@ impl KeyChain {
|
||||
ephemeral_public_key_sender: EphemeralPublicKey,
|
||||
) -> SharedSecretKey {
|
||||
SharedSecretKey::new(
|
||||
&self
|
||||
.secret_spending_key
|
||||
.generate_incoming_viewing_secret_key(),
|
||||
&self.secret_spending_key.generate_viewing_secret_key(None),
|
||||
&ephemeral_public_key_sender,
|
||||
)
|
||||
}
|
||||
@ -112,10 +110,10 @@ mod tests {
|
||||
let seed_holder = SeedHolder::new_os_random();
|
||||
let top_secret_key_holder = seed_holder.produce_top_secret_key_holder();
|
||||
|
||||
let utxo_secret_key_holder = top_secret_key_holder.produce_private_key_holder();
|
||||
let utxo_secret_key_holder = top_secret_key_holder.produce_private_key_holder(None);
|
||||
|
||||
let nullifer_public_key = utxo_secret_key_holder.generate_nullifier_public_key();
|
||||
let viewing_public_key = utxo_secret_key_holder.generate_incoming_viewing_public_key();
|
||||
let viewing_public_key = utxo_secret_key_holder.generate_viewing_public_key();
|
||||
|
||||
let pub_account_signing_key = nssa::PrivateKey::new_os_random();
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ use bip39::Mnemonic;
|
||||
use common::HashType;
|
||||
use nssa_core::{
|
||||
NullifierPublicKey, NullifierSecretKey,
|
||||
encryption::{IncomingViewingPublicKey, Scalar},
|
||||
encryption::{Scalar, ViewingPublicKey},
|
||||
};
|
||||
use rand::{RngCore, rngs::OsRng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -18,20 +18,18 @@ pub struct SeedHolder {
|
||||
pub(crate) seed: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
/// Secret spending key object. Can produce `PrivateKeyHolder` objects.
|
||||
pub struct SecretSpendingKey(pub(crate) [u8; 32]);
|
||||
|
||||
pub type IncomingViewingSecretKey = Scalar;
|
||||
pub type OutgoingViewingSecretKey = Scalar;
|
||||
pub type ViewingSecretKey = Scalar;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
/// Private key holder. Produces public keys. Can produce account_id. Can produce shared secret for
|
||||
/// recepient.
|
||||
pub struct PrivateKeyHolder {
|
||||
pub nullifier_secret_key: NullifierSecretKey,
|
||||
pub(crate) incoming_viewing_secret_key: IncomingViewingSecretKey,
|
||||
pub outgoing_viewing_secret_key: OutgoingViewingSecretKey,
|
||||
pub(crate) viewing_secret_key: ViewingSecretKey,
|
||||
}
|
||||
|
||||
impl SeedHolder {
|
||||
@ -75,44 +73,49 @@ impl SeedHolder {
|
||||
}
|
||||
|
||||
impl SecretSpendingKey {
|
||||
pub fn generate_nullifier_secret_key(&self) -> NullifierSecretKey {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
pub fn generate_nullifier_secret_key(&self, index: Option<u32>) -> NullifierSecretKey {
|
||||
let index = match index {
|
||||
None => 0u32,
|
||||
_ => index.expect("Expect a valid u32"),
|
||||
};
|
||||
|
||||
hasher.update("NSSA_keys");
|
||||
const PREFIX: &[u8; 8] = b"LEE/keys";
|
||||
const SUFFIX_1: &[u8; 1] = &[1];
|
||||
const SUFFIX_2: &[u8; 19] = &[0; 19];
|
||||
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(PREFIX);
|
||||
hasher.update(self.0);
|
||||
hasher.update([1u8]);
|
||||
hasher.update([0u8; 22]);
|
||||
hasher.update(SUFFIX_1);
|
||||
hasher.update(index.to_le_bytes());
|
||||
hasher.update(SUFFIX_2);
|
||||
|
||||
<NullifierSecretKey>::from(hasher.finalize_fixed())
|
||||
}
|
||||
|
||||
pub fn generate_incoming_viewing_secret_key(&self) -> IncomingViewingSecretKey {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
pub fn generate_viewing_secret_key(&self, index: Option<u32>) -> ViewingSecretKey {
|
||||
let index = match index {
|
||||
None => 0u32,
|
||||
_ => index.expect("Expect a valid u32"),
|
||||
};
|
||||
const PREFIX: &[u8; 8] = b"LEE/keys";
|
||||
const SUFFIX_1: &[u8; 1] = &[2];
|
||||
const SUFFIX_2: &[u8; 19] = &[0; 19];
|
||||
|
||||
hasher.update("NSSA_keys");
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(PREFIX);
|
||||
hasher.update(self.0);
|
||||
hasher.update([2u8]);
|
||||
hasher.update([0u8; 22]);
|
||||
hasher.update(SUFFIX_1);
|
||||
hasher.update(index.to_le_bytes());
|
||||
hasher.update(SUFFIX_2);
|
||||
|
||||
hasher.finalize_fixed().into()
|
||||
}
|
||||
|
||||
pub fn generate_outgoing_viewing_secret_key(&self) -> OutgoingViewingSecretKey {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
|
||||
hasher.update("NSSA_keys");
|
||||
hasher.update(self.0);
|
||||
hasher.update([3u8]);
|
||||
hasher.update([0u8; 22]);
|
||||
|
||||
hasher.finalize_fixed().into()
|
||||
}
|
||||
|
||||
pub fn produce_private_key_holder(&self) -> PrivateKeyHolder {
|
||||
pub fn produce_private_key_holder(&self, index: Option<u32>) -> PrivateKeyHolder {
|
||||
PrivateKeyHolder {
|
||||
nullifier_secret_key: self.generate_nullifier_secret_key(),
|
||||
incoming_viewing_secret_key: self.generate_incoming_viewing_secret_key(),
|
||||
outgoing_viewing_secret_key: self.generate_outgoing_viewing_secret_key(),
|
||||
nullifier_secret_key: self.generate_nullifier_secret_key(index),
|
||||
viewing_secret_key: self.generate_viewing_secret_key(index),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,8 +125,8 @@ impl PrivateKeyHolder {
|
||||
(&self.nullifier_secret_key).into()
|
||||
}
|
||||
|
||||
pub fn generate_incoming_viewing_public_key(&self) -> IncomingViewingPublicKey {
|
||||
IncomingViewingPublicKey::from_scalar(self.incoming_viewing_secret_key)
|
||||
pub fn generate_viewing_public_key(&self) -> ViewingPublicKey {
|
||||
ViewingPublicKey::from_scalar(self.viewing_secret_key)
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,6 +134,7 @@ impl PrivateKeyHolder {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// TODO? are these necessary?
|
||||
#[test]
|
||||
fn seed_generation_test() {
|
||||
let seed_holder = SeedHolder::new_os_random();
|
||||
@ -155,18 +159,7 @@ mod tests {
|
||||
|
||||
let top_secret_key_holder = seed_holder.produce_top_secret_key_holder();
|
||||
|
||||
let _ = top_secret_key_holder.generate_incoming_viewing_secret_key();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ovs_generation_test() {
|
||||
let seed_holder = SeedHolder::new_os_random();
|
||||
|
||||
assert_eq!(seed_holder.seed.len(), 64);
|
||||
|
||||
let top_secret_key_holder = seed_holder.produce_top_secret_key_holder();
|
||||
|
||||
let _ = top_secret_key_holder.generate_outgoing_viewing_secret_key();
|
||||
let _ = top_secret_key_holder.generate_viewing_secret_key(None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -33,3 +33,4 @@ test-case = "3.3.1"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
prove = ["risc0-zkvm/prove"]
|
||||
|
||||
@ -159,6 +159,7 @@ mod tests {
|
||||
assert_eq!(new_acc_with_metadata.account_id, fingerprint);
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
#[test]
|
||||
fn parse_valid_account_id() {
|
||||
let base58_str = "11111111111111111111111111111111";
|
||||
@ -166,6 +167,7 @@ mod tests {
|
||||
assert_eq!(account_id.value, [0u8; 32]);
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
#[test]
|
||||
fn parse_invalid_base58() {
|
||||
let base58_str = "00".repeat(32); // invalid base58 chars
|
||||
@ -173,6 +175,7 @@ mod tests {
|
||||
assert!(matches!(result, AccountIdError::InvalidBase58(_)));
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
#[test]
|
||||
fn parse_wrong_length_short() {
|
||||
let base58_str = "11".repeat(31); // 62 chars = 31 bytes
|
||||
@ -180,6 +183,7 @@ mod tests {
|
||||
assert!(matches!(result, AccountIdError::InvalidLength(_)));
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
#[test]
|
||||
fn parse_wrong_length_long() {
|
||||
let base58_str = "11".repeat(33); // 66 chars = 33 bytes
|
||||
|
||||
@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
|
||||
pub mod shared_key_derivation;
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub use shared_key_derivation::{EphemeralPublicKey, EphemeralSecretKey, IncomingViewingPublicKey};
|
||||
pub use shared_key_derivation::{EphemeralPublicKey, EphemeralSecretKey, ViewingPublicKey};
|
||||
|
||||
use crate::{Commitment, account::Account};
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ impl Secp256k1Point {
|
||||
|
||||
pub type EphemeralSecretKey = Scalar;
|
||||
pub type EphemeralPublicKey = Secp256k1Point;
|
||||
pub type IncomingViewingPublicKey = Secp256k1Point;
|
||||
pub type ViewingPublicKey = Secp256k1Point;
|
||||
impl From<&EphemeralSecretKey> for EphemeralPublicKey {
|
||||
fn from(value: &EphemeralSecretKey) -> Self {
|
||||
Secp256k1Point::from_scalar(*value)
|
||||
|
||||
@ -10,7 +10,8 @@ pub struct NullifierPublicKey(pub [u8; 32]);
|
||||
|
||||
impl From<&NullifierPublicKey> for AccountId {
|
||||
fn from(value: &NullifierPublicKey) -> Self {
|
||||
const PRIVATE_ACCOUNT_ID_PREFIX: &[u8; 32] = b"/NSSA/v0.2/AccountId/Private/\x00\x00\x00";
|
||||
const PRIVATE_ACCOUNT_ID_PREFIX: &[u8; 32] =
|
||||
b"/LEE/v0.3/AccountId/Private/\x00\x00\x00\x00";
|
||||
|
||||
let mut bytes = [0; 64];
|
||||
bytes[0..32].copy_from_slice(PRIVATE_ACCOUNT_ID_PREFIX);
|
||||
@ -28,9 +29,9 @@ impl AsRef<[u8]> for NullifierPublicKey {
|
||||
impl From<&NullifierSecretKey> for NullifierPublicKey {
|
||||
fn from(value: &NullifierSecretKey) -> Self {
|
||||
let mut bytes = Vec::new();
|
||||
const PREFIX: &[u8; 9] = b"NSSA_keys";
|
||||
const PREFIX: &[u8; 8] = b"LEE/keys";
|
||||
const SUFFIX_1: &[u8; 1] = &[7];
|
||||
const SUFFIX_2: &[u8; 22] = &[0; 22];
|
||||
const SUFFIX_2: &[u8; 23] = &[0; 23];
|
||||
bytes.extend_from_slice(PREFIX);
|
||||
bytes.extend_from_slice(value);
|
||||
bytes.extend_from_slice(SUFFIX_1);
|
||||
@ -102,8 +103,8 @@ mod tests {
|
||||
196, 134, 22, 224, 211, 237, 120, 136, 225, 188, 220, 249, 28,
|
||||
];
|
||||
let expected_npk = NullifierPublicKey([
|
||||
202, 120, 42, 189, 194, 218, 78, 244, 31, 6, 108, 169, 29, 61, 22, 221, 69, 138, 197,
|
||||
161, 241, 39, 142, 242, 242, 50, 188, 201, 99, 28, 176, 238,
|
||||
78, 20, 20, 5, 177, 198, 233, 100, 175, 134, 174, 200, 24, 205, 68, 215, 130, 74, 35,
|
||||
54, 154, 184, 219, 42, 168, 106, 126, 147, 133, 244, 18, 218,
|
||||
]);
|
||||
let npk = NullifierPublicKey::from(&nsk);
|
||||
assert_eq!(npk, expected_npk);
|
||||
@ -117,8 +118,8 @@ mod tests {
|
||||
];
|
||||
let npk = NullifierPublicKey::from(&nsk);
|
||||
let expected_account_id = AccountId::new([
|
||||
18, 153, 225, 78, 35, 214, 212, 205, 152, 83, 18, 246, 69, 41, 20, 217, 85, 1, 108, 7,
|
||||
87, 133, 181, 53, 247, 221, 174, 12, 112, 194, 34, 121,
|
||||
139, 72, 194, 222, 215, 187, 147, 56, 55, 35, 222, 205, 156, 12, 204, 227, 166, 44, 30,
|
||||
81, 186, 14, 167, 234, 28, 236, 32, 213, 125, 251, 193, 233,
|
||||
]);
|
||||
|
||||
let account_id = AccountId::from(&npk);
|
||||
|
||||
@ -223,7 +223,7 @@ mod tests {
|
||||
let expected_sender_pre = sender.clone();
|
||||
|
||||
let esk = [3; 32];
|
||||
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
|
||||
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.vpk());
|
||||
|
||||
let (output, proof) = execute_and_prove(
|
||||
vec![sender, recipient],
|
||||
@ -316,10 +316,10 @@ mod tests {
|
||||
];
|
||||
|
||||
let esk_1 = [3; 32];
|
||||
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.ivk());
|
||||
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.vpk());
|
||||
|
||||
let esk_2 = [5; 32];
|
||||
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
|
||||
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.vpk());
|
||||
|
||||
let (output, proof) = execute_and_prove(
|
||||
vec![sender_pre.clone(), recipient],
|
||||
|
||||
@ -2,7 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use nssa_core::{
|
||||
Commitment, CommitmentSetDigest, Nullifier, NullifierPublicKey, PrivacyPreservingCircuitOutput,
|
||||
account::{Account, Nonce},
|
||||
encryption::{Ciphertext, EphemeralPublicKey, IncomingViewingPublicKey},
|
||||
encryption::{Ciphertext, EphemeralPublicKey, ViewingPublicKey},
|
||||
};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
@ -21,10 +21,10 @@ impl EncryptedAccountData {
|
||||
fn new(
|
||||
ciphertext: Ciphertext,
|
||||
npk: NullifierPublicKey,
|
||||
ivk: IncomingViewingPublicKey,
|
||||
vpk: ViewingPublicKey,
|
||||
epk: EphemeralPublicKey,
|
||||
) -> Self {
|
||||
let view_tag = Self::compute_view_tag(npk, ivk);
|
||||
let view_tag = Self::compute_view_tag(npk, vpk);
|
||||
Self {
|
||||
ciphertext,
|
||||
epk,
|
||||
@ -32,12 +32,12 @@ impl EncryptedAccountData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the tag as the first byte of SHA256("/NSSA/v0.2/ViewTag/" || Npk || Ivk)
|
||||
pub fn compute_view_tag(npk: NullifierPublicKey, ivk: IncomingViewingPublicKey) -> ViewTag {
|
||||
/// Computes the tag as the first byte of SHA256("/NSSA/v0.2/ViewTag/" || Npk || vpk)
|
||||
pub fn compute_view_tag(npk: NullifierPublicKey, vpk: ViewingPublicKey) -> ViewTag {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(b"/NSSA/v0.2/ViewTag/");
|
||||
hasher.update(npk.to_byte_array());
|
||||
hasher.update(ivk.to_bytes());
|
||||
hasher.update(vpk.to_bytes());
|
||||
let digest: [u8; 32] = hasher.finalize().into();
|
||||
digest[0]
|
||||
}
|
||||
@ -57,11 +57,7 @@ impl Message {
|
||||
pub fn try_from_circuit_output(
|
||||
public_account_ids: Vec<AccountId>,
|
||||
nonces: Vec<Nonce>,
|
||||
public_keys: Vec<(
|
||||
NullifierPublicKey,
|
||||
IncomingViewingPublicKey,
|
||||
EphemeralPublicKey,
|
||||
)>,
|
||||
public_keys: Vec<(NullifierPublicKey, ViewingPublicKey, EphemeralPublicKey)>,
|
||||
output: PrivacyPreservingCircuitOutput,
|
||||
) -> Result<Self, NssaError> {
|
||||
if public_keys.len() != output.ciphertexts.len() {
|
||||
@ -74,8 +70,8 @@ impl Message {
|
||||
.ciphertexts
|
||||
.into_iter()
|
||||
.zip(public_keys)
|
||||
.map(|(ciphertext, (npk, ivk, epk))| {
|
||||
EncryptedAccountData::new(ciphertext, npk, ivk, epk)
|
||||
.map(|(ciphertext, (npk, vpk, epk))| {
|
||||
EncryptedAccountData::new(ciphertext, npk, vpk, epk)
|
||||
})
|
||||
.collect();
|
||||
Ok(Self {
|
||||
@ -94,7 +90,7 @@ pub mod tests {
|
||||
use nssa_core::{
|
||||
Commitment, EncryptionScheme, Nullifier, NullifierPublicKey, SharedSecretKey,
|
||||
account::Account,
|
||||
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
|
||||
encryption::{EphemeralPublicKey, ViewingPublicKey},
|
||||
};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
@ -142,21 +138,21 @@ pub mod tests {
|
||||
#[test]
|
||||
fn test_encrypted_account_data_constructor() {
|
||||
let npk = NullifierPublicKey::from(&[1; 32]);
|
||||
let ivk = IncomingViewingPublicKey::from_scalar([2; 32]);
|
||||
let vpk = ViewingPublicKey::from_scalar([2; 32]);
|
||||
let account = Account::default();
|
||||
let commitment = Commitment::new(&npk, &account);
|
||||
let esk = [3; 32];
|
||||
let shared_secret = SharedSecretKey::new(&esk, &ivk);
|
||||
let shared_secret = SharedSecretKey::new(&esk, &vpk);
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
let ciphertext = EncryptionScheme::encrypt(&account, &shared_secret, &commitment, 2);
|
||||
let encrypted_account_data =
|
||||
EncryptedAccountData::new(ciphertext.clone(), npk.clone(), ivk.clone(), epk.clone());
|
||||
EncryptedAccountData::new(ciphertext.clone(), npk.clone(), vpk.clone(), epk.clone());
|
||||
|
||||
let expected_view_tag = {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(b"/NSSA/v0.2/ViewTag/");
|
||||
hasher.update(npk.to_byte_array());
|
||||
hasher.update(ivk.to_bytes());
|
||||
hasher.update(vpk.to_bytes());
|
||||
let digest: [u8; 32] = hasher.finalize().into();
|
||||
digest[0]
|
||||
};
|
||||
@ -165,7 +161,7 @@ pub mod tests {
|
||||
assert_eq!(encrypted_account_data.epk, epk);
|
||||
assert_eq!(
|
||||
encrypted_account_data.view_tag,
|
||||
EncryptedAccountData::compute_view_tag(npk, ivk)
|
||||
EncryptedAccountData::compute_view_tag(npk, vpk)
|
||||
);
|
||||
assert_eq!(encrypted_account_data.view_tag, expected_view_tag);
|
||||
}
|
||||
|
||||
@ -315,7 +315,7 @@ pub mod tests {
|
||||
use nssa_core::{
|
||||
Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
|
||||
account::{Account, AccountId, AccountWithMetadata, Nonce, data::Data},
|
||||
encryption::{EphemeralPublicKey, IncomingViewingPublicKey, Scalar},
|
||||
encryption::{EphemeralPublicKey, Scalar, ViewingPublicKey},
|
||||
program::{PdaSeed, ProgramId},
|
||||
};
|
||||
use token_core::{TokenDefinition, TokenHolding};
|
||||
@ -864,7 +864,7 @@ pub mod tests {
|
||||
|
||||
pub struct TestPrivateKeys {
|
||||
pub nsk: NullifierSecretKey,
|
||||
pub isk: Scalar,
|
||||
pub vsk: Scalar,
|
||||
}
|
||||
|
||||
impl TestPrivateKeys {
|
||||
@ -872,22 +872,22 @@ pub mod tests {
|
||||
NullifierPublicKey::from(&self.nsk)
|
||||
}
|
||||
|
||||
pub fn ivk(&self) -> IncomingViewingPublicKey {
|
||||
IncomingViewingPublicKey::from_scalar(self.isk)
|
||||
pub fn vpk(&self) -> ViewingPublicKey {
|
||||
ViewingPublicKey::from_scalar(self.vsk)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_private_account_keys_1() -> TestPrivateKeys {
|
||||
TestPrivateKeys {
|
||||
nsk: [13; 32],
|
||||
isk: [31; 32],
|
||||
vsk: [31; 32],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_private_account_keys_2() -> TestPrivateKeys {
|
||||
TestPrivateKeys {
|
||||
nsk: [38; 32],
|
||||
isk: [83; 32],
|
||||
vsk: [83; 32],
|
||||
}
|
||||
}
|
||||
|
||||
@ -908,7 +908,7 @@ pub mod tests {
|
||||
let recipient = AccountWithMetadata::new(Account::default(), false, &recipient_keys.npk());
|
||||
|
||||
let esk = [3; 32];
|
||||
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
|
||||
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.vpk());
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
@ -926,7 +926,7 @@ pub mod tests {
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![sender_keys.account_id()],
|
||||
vec![sender_nonce],
|
||||
vec![(recipient_keys.npk(), recipient_keys.ivk(), epk)],
|
||||
vec![(recipient_keys.npk(), recipient_keys.vpk(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
@ -951,11 +951,11 @@ pub mod tests {
|
||||
AccountWithMetadata::new(Account::default(), false, &recipient_keys.npk());
|
||||
|
||||
let esk_1 = [3; 32];
|
||||
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.ivk());
|
||||
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.vpk());
|
||||
let epk_1 = EphemeralPublicKey::from_scalar(esk_1);
|
||||
|
||||
let esk_2 = [3; 32];
|
||||
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
|
||||
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.vpk());
|
||||
let epk_2 = EphemeralPublicKey::from_scalar(esk_2);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
@ -977,8 +977,8 @@ pub mod tests {
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(sender_keys.npk(), sender_keys.ivk(), epk_1),
|
||||
(recipient_keys.npk(), recipient_keys.ivk(), epk_2),
|
||||
(sender_keys.npk(), sender_keys.vpk(), epk_1),
|
||||
(recipient_keys.npk(), recipient_keys.vpk(), epk_2),
|
||||
],
|
||||
output,
|
||||
)
|
||||
@ -1008,7 +1008,7 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let esk = [3; 32];
|
||||
let shared_secret = SharedSecretKey::new(&esk, &sender_keys.ivk());
|
||||
let shared_secret = SharedSecretKey::new(&esk, &sender_keys.vpk());
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
@ -1026,7 +1026,7 @@ pub mod tests {
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![*recipient_account_id],
|
||||
vec![],
|
||||
vec![(sender_keys.npk(), sender_keys.ivk(), epk)],
|
||||
vec![(sender_keys.npk(), sender_keys.vpk(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
@ -1538,11 +1538,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
vec![sender_keys.nsk],
|
||||
@ -1572,7 +1572,7 @@ pub mod tests {
|
||||
// Setting only one key for an execution with two private accounts.
|
||||
let private_account_keys = [(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
)];
|
||||
let result = execute_and_prove(
|
||||
vec![private_account_1, private_account_2],
|
||||
@ -1615,11 +1615,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
vec![sender_keys.nsk],
|
||||
@ -1657,11 +1657,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
private_account_nsks.to_vec(),
|
||||
@ -1693,12 +1693,12 @@ pub mod tests {
|
||||
// First private account is the sender
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
// Second private account is the recipient
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
];
|
||||
|
||||
@ -1753,11 +1753,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
vec![sender_keys.nsk],
|
||||
@ -1801,11 +1801,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
vec![sender_keys.nsk],
|
||||
@ -1848,11 +1848,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
vec![sender_keys.nsk],
|
||||
@ -1895,11 +1895,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
vec![sender_keys.nsk],
|
||||
@ -1940,11 +1940,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
vec![sender_keys.nsk],
|
||||
@ -2013,11 +2013,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
vec![sender_keys.nsk],
|
||||
@ -2050,15 +2050,15 @@ pub mod tests {
|
||||
let private_account_keys = [
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[57; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[57; 32], &sender_keys.vpk()),
|
||||
),
|
||||
];
|
||||
let result = execute_and_prove(
|
||||
@ -2105,11 +2105,11 @@ pub mod tests {
|
||||
vec![
|
||||
(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[55; 32], &sender_keys.vpk()),
|
||||
),
|
||||
(
|
||||
recipient_keys.npk(),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.ivk()),
|
||||
SharedSecretKey::new(&[56; 32], &recipient_keys.vpk()),
|
||||
),
|
||||
],
|
||||
private_account_nsks.to_vec(),
|
||||
@ -2192,7 +2192,7 @@ pub mod tests {
|
||||
let visibility_mask = [1, 1];
|
||||
let private_account_nsks = [sender_keys.nsk, sender_keys.nsk];
|
||||
let private_account_membership_proofs = [Some((1, vec![])), Some((1, vec![]))];
|
||||
let shared_secret = SharedSecretKey::new(&[55; 32], &sender_keys.ivk());
|
||||
let shared_secret = SharedSecretKey::new(&[55; 32], &sender_keys.vpk());
|
||||
let result = execute_and_prove(
|
||||
vec![private_account_1.clone(), private_account_1],
|
||||
Program::serialize_instruction(100u128).unwrap(),
|
||||
@ -3809,11 +3809,11 @@ pub mod tests {
|
||||
);
|
||||
|
||||
let from_esk = [3; 32];
|
||||
let from_ss = SharedSecretKey::new(&from_esk, &from_keys.ivk());
|
||||
let from_ss = SharedSecretKey::new(&from_esk, &from_keys.vpk());
|
||||
let from_epk = EphemeralPublicKey::from_scalar(from_esk);
|
||||
|
||||
let to_esk = [3; 32];
|
||||
let to_ss = SharedSecretKey::new(&to_esk, &to_keys.ivk());
|
||||
let to_ss = SharedSecretKey::new(&to_esk, &to_keys.vpk());
|
||||
let to_epk = EphemeralPublicKey::from_scalar(to_esk);
|
||||
|
||||
let mut dependencies = HashMap::new();
|
||||
@ -3858,8 +3858,8 @@ pub mod tests {
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(to_keys.npk(), to_keys.ivk(), to_epk),
|
||||
(from_keys.npk(), from_keys.ivk(), from_epk),
|
||||
(to_keys.npk(), to_keys.vpk(), to_epk),
|
||||
(from_keys.npk(), from_keys.vpk(), from_epk),
|
||||
],
|
||||
output,
|
||||
)
|
||||
@ -4069,7 +4069,7 @@ pub mod tests {
|
||||
|
||||
// Set up parameters for the new account
|
||||
let esk = [3; 32];
|
||||
let shared_secret = SharedSecretKey::new(&esk, &private_keys.ivk());
|
||||
let shared_secret = SharedSecretKey::new(&esk, &private_keys.vpk());
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
|
||||
// Balance to initialize the account with (0 for a new account)
|
||||
@ -4094,7 +4094,7 @@ pub mod tests {
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![(private_keys.npk(), private_keys.ivk(), epk)],
|
||||
vec![(private_keys.npk(), private_keys.vpk(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
@ -4124,7 +4124,7 @@ pub mod tests {
|
||||
|
||||
// Set up parameters for claiming the new account
|
||||
let esk = [3; 32];
|
||||
let shared_secret = SharedSecretKey::new(&esk, &private_keys.ivk());
|
||||
let shared_secret = SharedSecretKey::new(&esk, &private_keys.vpk());
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
|
||||
let balance: u128 = 0;
|
||||
@ -4146,7 +4146,7 @@ pub mod tests {
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![(private_keys.npk(), private_keys.ivk(), epk)],
|
||||
vec![(private_keys.npk(), private_keys.vpk(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
@ -4174,7 +4174,7 @@ pub mod tests {
|
||||
|
||||
let noop_program = Program::noop();
|
||||
let esk2 = [4; 32];
|
||||
let shared_secret2 = SharedSecretKey::new(&esk2, &private_keys.ivk());
|
||||
let shared_secret2 = SharedSecretKey::new(&esk2, &private_keys.vpk());
|
||||
|
||||
let nonce2 = 0xdeadbeef2;
|
||||
|
||||
@ -4256,7 +4256,7 @@ pub mod tests {
|
||||
vec![2],
|
||||
vec![(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[3; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[3; 32], &sender_keys.vpk()),
|
||||
)],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
@ -4284,7 +4284,7 @@ pub mod tests {
|
||||
vec![2],
|
||||
vec![(
|
||||
sender_keys.npk(),
|
||||
SharedSecretKey::new(&[3; 32], &sender_keys.ivk()),
|
||||
SharedSecretKey::new(&[3; 32], &sender_keys.vpk()),
|
||||
)],
|
||||
vec![sender_keys.nsk],
|
||||
vec![Some((0, vec![]))],
|
||||
@ -4327,7 +4327,7 @@ pub mod tests {
|
||||
let instruction = (balance_to_transfer, auth_transfers.id());
|
||||
|
||||
let recipient_esk = [3; 32];
|
||||
let recipient = SharedSecretKey::new(&recipient_esk, &recipient_keys.ivk());
|
||||
let recipient = SharedSecretKey::new(&recipient_esk, &recipient_keys.vpk());
|
||||
|
||||
let mut dependencies = HashMap::new();
|
||||
dependencies.insert(auth_transfers.id(), auth_transfers);
|
||||
|
||||
@ -118,7 +118,7 @@ pub fn add_liquidity(
|
||||
assert!(delta_lp != 0, "Payable LP must be nonzero");
|
||||
|
||||
assert!(
|
||||
delta_lp >= min_amount_liquidity.into(),
|
||||
delta_lp >= min_amount_liquidity.get(),
|
||||
"Payable LP is less than provided minimum LP amount"
|
||||
);
|
||||
|
||||
|
||||
@ -870,15 +870,15 @@ mod tests {
|
||||
|
||||
fn acc1() -> AccountId {
|
||||
AccountId::new([
|
||||
208, 122, 210, 232, 75, 39, 250, 0, 194, 98, 240, 161, 238, 160, 255, 53, 202, 9, 115,
|
||||
84, 126, 106, 16, 111, 114, 241, 147, 194, 220, 131, 139, 68,
|
||||
148, 179, 206, 253, 199, 51, 82, 86, 232, 2, 152, 122, 80, 243, 54, 207, 237, 112, 83,
|
||||
153, 44, 59, 204, 49, 128, 84, 160, 227, 216, 149, 97, 102,
|
||||
])
|
||||
}
|
||||
|
||||
fn acc2() -> AccountId {
|
||||
AccountId::new([
|
||||
231, 174, 119, 197, 239, 26, 5, 153, 147, 68, 175, 73, 159, 199, 138, 23, 5, 57, 141,
|
||||
98, 237, 6, 207, 46, 20, 121, 246, 222, 248, 154, 57, 188,
|
||||
30, 145, 107, 3, 207, 73, 192, 230, 160, 63, 238, 207, 18, 69, 54, 216, 103, 244, 92,
|
||||
94, 124, 248, 42, 16, 141, 19, 119, 18, 14, 226, 140, 204,
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
@ -19,3 +19,7 @@ cbindgen = "0.29"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
prove = ["nssa/prove"]
|
||||
|
||||
@ -354,6 +354,61 @@ pub unsafe extern "C" fn wallet_ffi_get_account_public(
|
||||
WalletFfiError::Success
|
||||
}
|
||||
|
||||
/// Get full private account data from the local storage.
|
||||
///
|
||||
/// # 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
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_get_account_private(
|
||||
handle: *mut WalletHandle,
|
||||
account_id: *const FfiBytes32,
|
||||
out_account: *mut FfiAccount,
|
||||
) -> WalletFfiError {
|
||||
let wrapper = match get_wallet(handle) {
|
||||
Ok(w) => w,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
||||
if account_id.is_null() || out_account.is_null() {
|
||||
print_error("Null pointer argument");
|
||||
return WalletFfiError::NullPointer;
|
||||
}
|
||||
|
||||
let wallet = match wrapper.core.lock() {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to lock wallet: {}", e));
|
||||
return WalletFfiError::InternalError;
|
||||
}
|
||||
};
|
||||
|
||||
let account_id = AccountId::new(unsafe { (*account_id).data });
|
||||
|
||||
let Some(account) = wallet.get_account_private(account_id) else {
|
||||
return WalletFfiError::AccountNotFound;
|
||||
};
|
||||
|
||||
unsafe {
|
||||
*out_account = account.into();
|
||||
}
|
||||
|
||||
WalletFfiError::Success
|
||||
}
|
||||
|
||||
/// Free account data returned by `wallet_ffi_get_account_public`.
|
||||
///
|
||||
/// # Safety
|
||||
|
||||
@ -73,7 +73,7 @@ pub unsafe extern "C" fn wallet_ffi_get_public_account_key(
|
||||
|
||||
/// Get keys for a private account.
|
||||
///
|
||||
/// Returns the nullifier public key (NPK) and incoming viewing public key (IPK)
|
||||
/// Returns the nullifier public key (NPK) and viewing public key (VPK)
|
||||
/// for the specified private account. These keys are safe to share publicly.
|
||||
///
|
||||
/// # Parameters
|
||||
@ -130,17 +130,17 @@ pub unsafe extern "C" fn wallet_ffi_get_private_account_keys(
|
||||
// NPK is a 32-byte array
|
||||
let npk_bytes = key_chain.nullifer_public_key.0;
|
||||
|
||||
// IPK is a compressed secp256k1 point (33 bytes)
|
||||
let ipk_bytes = key_chain.incoming_viewing_public_key.to_bytes();
|
||||
let ipk_len = ipk_bytes.len();
|
||||
let ipk_vec = ipk_bytes.to_vec();
|
||||
let ipk_boxed = ipk_vec.into_boxed_slice();
|
||||
let ipk_ptr = Box::into_raw(ipk_boxed) as *const u8;
|
||||
// VPK is a compressed secp256k1 point (33 bytes)
|
||||
let vpk_bytes = key_chain.viewing_public_key.to_bytes();
|
||||
let vpk_len = vpk_bytes.len();
|
||||
let vpk_vec = vpk_bytes.to_vec();
|
||||
let vpk_boxed = vpk_vec.into_boxed_slice();
|
||||
let vpk_ptr = Box::into_raw(vpk_boxed) as *const u8;
|
||||
|
||||
unsafe {
|
||||
(*out_keys).nullifier_public_key.data = npk_bytes;
|
||||
(*out_keys).incoming_viewing_public_key = ipk_ptr;
|
||||
(*out_keys).incoming_viewing_public_key_len = ipk_len;
|
||||
(*out_keys).viewing_public_key = vpk_ptr;
|
||||
(*out_keys).viewing_public_key_len = vpk_len;
|
||||
}
|
||||
|
||||
WalletFfiError::Success
|
||||
@ -159,10 +159,10 @@ pub unsafe extern "C" fn wallet_ffi_free_private_account_keys(keys: *mut FfiPriv
|
||||
|
||||
unsafe {
|
||||
let keys = &*keys;
|
||||
if !keys.incoming_viewing_public_key.is_null() && keys.incoming_viewing_public_key_len > 0 {
|
||||
if !keys.viewing_public_key.is_null() && keys.viewing_public_key_len > 0 {
|
||||
let slice = std::slice::from_raw_parts_mut(
|
||||
keys.incoming_viewing_public_key as *mut u8,
|
||||
keys.incoming_viewing_public_key_len,
|
||||
keys.viewing_public_key as *mut u8,
|
||||
keys.viewing_public_key_len,
|
||||
);
|
||||
drop(Box::from_raw(slice as *mut [u8]));
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ use crate::{
|
||||
error::{print_error, WalletFfiError},
|
||||
types::{FfiBytes32, FfiTransferResult, WalletHandle},
|
||||
wallet::get_wallet,
|
||||
FfiPrivateAccountKeys,
|
||||
};
|
||||
|
||||
/// Send a public token transfer.
|
||||
@ -89,13 +90,270 @@ pub unsafe extern "C" fn wallet_ffi_transfer_public(
|
||||
(*out_result).tx_hash = ptr::null_mut();
|
||||
(*out_result).success = false;
|
||||
}
|
||||
match e {
|
||||
ExecutionFailureKind::InsufficientFundsError => WalletFfiError::InsufficientFunds,
|
||||
ExecutionFailureKind::KeyNotFoundError => WalletFfiError::KeyNotFound,
|
||||
ExecutionFailureKind::SequencerError => WalletFfiError::NetworkError,
|
||||
ExecutionFailureKind::SequencerClientError(_) => WalletFfiError::NetworkError,
|
||||
_ => WalletFfiError::InternalError,
|
||||
map_execution_error(e)
|
||||
}
|
||||
Err(e) => e,
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a shielded token transfer.
|
||||
///
|
||||
/// Transfers tokens from a public account to a private account.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `handle`: Valid wallet handle
|
||||
/// - `from`: Source account ID (must be owned by this wallet)
|
||||
/// - `to_keys`: Destination account keys
|
||||
/// - `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_keys` must be a valid pointer to a `FfiPrivateAccountKeys` struct
|
||||
/// - `amount` must be a valid pointer to a `[u8; 16]` array
|
||||
/// - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_transfer_shielded(
|
||||
handle: *mut WalletHandle,
|
||||
from: *const FfiBytes32,
|
||||
to_keys: *const FfiPrivateAccountKeys,
|
||||
amount: *const [u8; 16],
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> WalletFfiError {
|
||||
let wrapper = match get_wallet(handle) {
|
||||
Ok(w) => w,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
||||
if from.is_null() || to_keys.is_null() || amount.is_null() || out_result.is_null() {
|
||||
print_error("Null pointer argument");
|
||||
return WalletFfiError::NullPointer;
|
||||
}
|
||||
|
||||
let wallet = match wrapper.core.lock() {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to lock wallet: {}", e));
|
||||
return WalletFfiError::InternalError;
|
||||
}
|
||||
};
|
||||
|
||||
let from_id = AccountId::new(unsafe { (*from).data });
|
||||
let to_npk = (*to_keys).npk();
|
||||
let to_vpk = match (*to_keys).vpk() {
|
||||
Ok(vpk) => vpk,
|
||||
Err(e) => {
|
||||
print_error("Invalid viewing key");
|
||||
return e;
|
||||
}
|
||||
};
|
||||
let amount = u128::from_le_bytes(unsafe { *amount });
|
||||
|
||||
let transfer = NativeTokenTransfer(&wallet);
|
||||
|
||||
match block_on(
|
||||
transfer.send_shielded_transfer_to_outer_account(from_id, to_npk, to_vpk, amount),
|
||||
) {
|
||||
Ok(Ok((response, _shared_key))) => {
|
||||
let tx_hash = CString::new(response.tx_hash)
|
||||
.map(|s| s.into_raw())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
|
||||
unsafe {
|
||||
(*out_result).tx_hash = tx_hash;
|
||||
(*out_result).success = true;
|
||||
}
|
||||
WalletFfiError::Success
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
print_error(format!("Transfer failed: {:?}", e));
|
||||
unsafe {
|
||||
(*out_result).tx_hash = ptr::null_mut();
|
||||
(*out_result).success = false;
|
||||
}
|
||||
map_execution_error(e)
|
||||
}
|
||||
Err(e) => e,
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a deshielded token transfer.
|
||||
///
|
||||
/// Transfers tokens from a private account to a public account.
|
||||
///
|
||||
/// # 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
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_transfer_deshielded(
|
||||
handle: *mut WalletHandle,
|
||||
from: *const FfiBytes32,
|
||||
to: *const FfiBytes32,
|
||||
amount: *const [u8; 16],
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> WalletFfiError {
|
||||
let wrapper = match get_wallet(handle) {
|
||||
Ok(w) => w,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
||||
if from.is_null() || to.is_null() || amount.is_null() || out_result.is_null() {
|
||||
print_error("Null pointer argument");
|
||||
return WalletFfiError::NullPointer;
|
||||
}
|
||||
|
||||
let wallet = match wrapper.core.lock() {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to lock wallet: {}", e));
|
||||
return WalletFfiError::InternalError;
|
||||
}
|
||||
};
|
||||
|
||||
let from_id = AccountId::new(unsafe { (*from).data });
|
||||
let to_id = AccountId::new(unsafe { (*to).data });
|
||||
let amount = u128::from_le_bytes(unsafe { *amount });
|
||||
|
||||
let transfer = NativeTokenTransfer(&wallet);
|
||||
|
||||
match block_on(transfer.send_deshielded_transfer(from_id, to_id, amount)) {
|
||||
Ok(Ok((response, _shared_key))) => {
|
||||
let tx_hash = CString::new(response.tx_hash)
|
||||
.map(|s| s.into_raw())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
|
||||
unsafe {
|
||||
(*out_result).tx_hash = tx_hash;
|
||||
(*out_result).success = true;
|
||||
}
|
||||
WalletFfiError::Success
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
print_error(format!("Transfer failed: {:?}", e));
|
||||
unsafe {
|
||||
(*out_result).tx_hash = ptr::null_mut();
|
||||
(*out_result).success = false;
|
||||
}
|
||||
map_execution_error(e)
|
||||
}
|
||||
Err(e) => e,
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a private token transfer.
|
||||
///
|
||||
/// Transfers tokens from a private account to another private account.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `handle`: Valid wallet handle
|
||||
/// - `from`: Source account ID (must be owned by this wallet)
|
||||
/// - `to_keys`: Destination account keys
|
||||
/// - `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_keys` must be a valid pointer to a `FfiPrivateAccountKeys` struct
|
||||
/// - `amount` must be a valid pointer to a `[u8; 16]` array
|
||||
/// - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_transfer_private(
|
||||
handle: *mut WalletHandle,
|
||||
from: *const FfiBytes32,
|
||||
to_keys: *const FfiPrivateAccountKeys,
|
||||
amount: *const [u8; 16],
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> WalletFfiError {
|
||||
let wrapper = match get_wallet(handle) {
|
||||
Ok(w) => w,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
||||
if from.is_null() || to_keys.is_null() || amount.is_null() || out_result.is_null() {
|
||||
print_error("Null pointer argument");
|
||||
return WalletFfiError::NullPointer;
|
||||
}
|
||||
|
||||
let wallet = match wrapper.core.lock() {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to lock wallet: {}", e));
|
||||
return WalletFfiError::InternalError;
|
||||
}
|
||||
};
|
||||
|
||||
let from_id = AccountId::new(unsafe { (*from).data });
|
||||
let to_npk = (*to_keys).npk();
|
||||
let to_vpk = match (*to_keys).vpk() {
|
||||
Ok(vpk) => vpk,
|
||||
Err(e) => {
|
||||
print_error("Invalid viewing key");
|
||||
return e;
|
||||
}
|
||||
};
|
||||
let amount = u128::from_le_bytes(unsafe { *amount });
|
||||
|
||||
let transfer = NativeTokenTransfer(&wallet);
|
||||
|
||||
match block_on(transfer.send_private_transfer_to_outer_account(from_id, to_npk, to_vpk, amount))
|
||||
{
|
||||
Ok(Ok((response, _shared_key))) => {
|
||||
let tx_hash = CString::new(response.tx_hash)
|
||||
.map(|s| s.into_raw())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
|
||||
unsafe {
|
||||
(*out_result).tx_hash = tx_hash;
|
||||
(*out_result).success = true;
|
||||
}
|
||||
WalletFfiError::Success
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
print_error(format!("Transfer failed: {:?}", e));
|
||||
unsafe {
|
||||
(*out_result).tx_hash = ptr::null_mut();
|
||||
(*out_result).success = false;
|
||||
}
|
||||
map_execution_error(e)
|
||||
}
|
||||
Err(e) => e,
|
||||
}
|
||||
@ -168,12 +426,80 @@ pub unsafe extern "C" fn wallet_ffi_register_public_account(
|
||||
(*out_result).tx_hash = ptr::null_mut();
|
||||
(*out_result).success = false;
|
||||
}
|
||||
match e {
|
||||
ExecutionFailureKind::KeyNotFoundError => WalletFfiError::KeyNotFound,
|
||||
ExecutionFailureKind::SequencerError => WalletFfiError::NetworkError,
|
||||
ExecutionFailureKind::SequencerClientError(_) => WalletFfiError::NetworkError,
|
||||
_ => WalletFfiError::InternalError,
|
||||
map_execution_error(e)
|
||||
}
|
||||
Err(e) => e,
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a private account on the network.
|
||||
///
|
||||
/// This initializes a private account. 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
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_register_private_account(
|
||||
handle: *mut WalletHandle,
|
||||
account_id: *const FfiBytes32,
|
||||
out_result: *mut FfiTransferResult,
|
||||
) -> WalletFfiError {
|
||||
let wrapper = match get_wallet(handle) {
|
||||
Ok(w) => w,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
||||
if account_id.is_null() || out_result.is_null() {
|
||||
print_error("Null pointer argument");
|
||||
return WalletFfiError::NullPointer;
|
||||
}
|
||||
|
||||
let wallet = match wrapper.core.lock() {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to lock wallet: {}", e));
|
||||
return WalletFfiError::InternalError;
|
||||
}
|
||||
};
|
||||
|
||||
let account_id = AccountId::new(unsafe { (*account_id).data });
|
||||
|
||||
let transfer = NativeTokenTransfer(&wallet);
|
||||
|
||||
match block_on(transfer.register_account_private(account_id)) {
|
||||
Ok(Ok((res, _secret))) => {
|
||||
let tx_hash = CString::new(res.tx_hash)
|
||||
.map(|s| s.into_raw())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
|
||||
unsafe {
|
||||
(*out_result).tx_hash = tx_hash;
|
||||
(*out_result).success = true;
|
||||
}
|
||||
WalletFfiError::Success
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
print_error(format!("Registration failed: {:?}", e));
|
||||
unsafe {
|
||||
(*out_result).tx_hash = ptr::null_mut();
|
||||
(*out_result).success = false;
|
||||
}
|
||||
map_execution_error(e)
|
||||
}
|
||||
Err(e) => e,
|
||||
}
|
||||
@ -197,3 +523,13 @@ pub unsafe extern "C" fn wallet_ffi_free_transfer_result(result: *mut FfiTransfe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn map_execution_error(e: ExecutionFailureKind) -> WalletFfiError {
|
||||
match e {
|
||||
ExecutionFailureKind::InsufficientFundsError => WalletFfiError::InsufficientFunds,
|
||||
ExecutionFailureKind::KeyNotFoundError => WalletFfiError::KeyNotFound,
|
||||
ExecutionFailureKind::SequencerError => WalletFfiError::NetworkError,
|
||||
ExecutionFailureKind::SequencerClientError(_) => WalletFfiError::NetworkError,
|
||||
_ => WalletFfiError::InternalError,
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,18 +72,18 @@ impl Default for FfiAccount {
|
||||
pub struct FfiPrivateAccountKeys {
|
||||
/// Nullifier public key (32 bytes)
|
||||
pub nullifier_public_key: FfiBytes32,
|
||||
/// Incoming viewing public key (compressed secp256k1 point)
|
||||
pub incoming_viewing_public_key: *const u8,
|
||||
/// Length of incoming viewing public key (typically 33 bytes)
|
||||
pub incoming_viewing_public_key_len: usize,
|
||||
/// viewing public key (compressed secp256k1 point)
|
||||
pub viewing_public_key: *const u8,
|
||||
/// Length of viewing public key (typically 33 bytes)
|
||||
pub viewing_public_key_len: usize,
|
||||
}
|
||||
|
||||
impl Default for FfiPrivateAccountKeys {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
nullifier_public_key: FfiBytes32::default(),
|
||||
incoming_viewing_public_key: std::ptr::null(),
|
||||
incoming_viewing_public_key_len: 0,
|
||||
viewing_public_key: std::ptr::null(),
|
||||
viewing_public_key_len: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,13 +157,10 @@ impl FfiPrivateAccountKeys {
|
||||
nssa_core::NullifierPublicKey(self.nullifier_public_key.data)
|
||||
}
|
||||
|
||||
pub fn ivk(&self) -> Result<nssa_core::encryption::IncomingViewingPublicKey, WalletFfiError> {
|
||||
if self.incoming_viewing_public_key_len == 33 {
|
||||
pub fn vpk(&self) -> Result<nssa_core::encryption::ViewingPublicKey, WalletFfiError> {
|
||||
if self.viewing_public_key_len == 33 {
|
||||
let slice = unsafe {
|
||||
slice::from_raw_parts(
|
||||
self.incoming_viewing_public_key,
|
||||
self.incoming_viewing_public_key_len,
|
||||
)
|
||||
slice::from_raw_parts(self.viewing_public_key, self.viewing_public_key_len)
|
||||
};
|
||||
Ok(Secp256k1Point(slice.to_vec()))
|
||||
} else {
|
||||
|
||||
@ -198,13 +198,13 @@ typedef struct FfiPrivateAccountKeys {
|
||||
*/
|
||||
struct FfiBytes32 nullifier_public_key;
|
||||
/**
|
||||
* Incoming viewing public key (compressed secp256k1 point)
|
||||
* viewing public key (compressed secp256k1 point)
|
||||
*/
|
||||
const uint8_t *incoming_viewing_public_key;
|
||||
const uint8_t *viewing_public_key;
|
||||
/**
|
||||
* Length of incoming viewing public key (typically 33 bytes)
|
||||
* Length of viewing public key (typically 33 bytes)
|
||||
*/
|
||||
uintptr_t incoming_viewing_public_key_len;
|
||||
uintptr_t viewing_public_key_len;
|
||||
} FfiPrivateAccountKeys;
|
||||
|
||||
/**
|
||||
@ -344,6 +344,30 @@ enum WalletFfiError wallet_ffi_get_account_public(struct WalletHandle *handle,
|
||||
const struct FfiBytes32 *account_id,
|
||||
struct FfiAccount *out_account);
|
||||
|
||||
/**
|
||||
* Get full private account data from the local storage.
|
||||
*
|
||||
* # 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_private(struct WalletHandle *handle,
|
||||
const struct FfiBytes32 *account_id,
|
||||
struct FfiAccount *out_account);
|
||||
|
||||
/**
|
||||
* Free account data returned by `wallet_ffi_get_account_public`.
|
||||
*
|
||||
@ -380,7 +404,7 @@ enum WalletFfiError wallet_ffi_get_public_account_key(struct WalletHandle *handl
|
||||
/**
|
||||
* Get keys for a private account.
|
||||
*
|
||||
* Returns the nullifier public key (NPK) and incoming viewing public key (IPK)
|
||||
* Returns the nullifier public key (NPK) and viewing public key (VPK)
|
||||
* for the specified private account. These keys are safe to share publicly.
|
||||
*
|
||||
* # Parameters
|
||||
@ -546,6 +570,108 @@ enum WalletFfiError wallet_ffi_transfer_public(struct WalletHandle *handle,
|
||||
const uint8_t (*amount)[16],
|
||||
struct FfiTransferResult *out_result);
|
||||
|
||||
/**
|
||||
* Send a shielded token transfer.
|
||||
*
|
||||
* Transfers tokens from a public account to a private account.
|
||||
*
|
||||
* # Parameters
|
||||
* - `handle`: Valid wallet handle
|
||||
* - `from`: Source account ID (must be owned by this wallet)
|
||||
* - `to_keys`: Destination account keys
|
||||
* - `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_keys` must be a valid pointer to a `FfiPrivateAccountKeys` 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_shielded(struct WalletHandle *handle,
|
||||
const struct FfiBytes32 *from,
|
||||
const struct FfiPrivateAccountKeys *to_keys,
|
||||
const uint8_t (*amount)[16],
|
||||
struct FfiTransferResult *out_result);
|
||||
|
||||
/**
|
||||
* Send a deshielded token transfer.
|
||||
*
|
||||
* Transfers tokens from a private account to a public account.
|
||||
*
|
||||
* # 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_deshielded(struct WalletHandle *handle,
|
||||
const struct FfiBytes32 *from,
|
||||
const struct FfiBytes32 *to,
|
||||
const uint8_t (*amount)[16],
|
||||
struct FfiTransferResult *out_result);
|
||||
|
||||
/**
|
||||
* Send a private token transfer.
|
||||
*
|
||||
* Transfers tokens from a private account to another private account.
|
||||
*
|
||||
* # Parameters
|
||||
* - `handle`: Valid wallet handle
|
||||
* - `from`: Source account ID (must be owned by this wallet)
|
||||
* - `to_keys`: Destination account keys
|
||||
* - `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_keys` must be a valid pointer to a `FfiPrivateAccountKeys` 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_private(struct WalletHandle *handle,
|
||||
const struct FfiBytes32 *from,
|
||||
const struct FfiPrivateAccountKeys *to_keys,
|
||||
const uint8_t (*amount)[16],
|
||||
struct FfiTransferResult *out_result);
|
||||
|
||||
/**
|
||||
* Register a public account on the network.
|
||||
*
|
||||
@ -573,6 +699,33 @@ enum WalletFfiError wallet_ffi_register_public_account(struct WalletHandle *hand
|
||||
const struct FfiBytes32 *account_id,
|
||||
struct FfiTransferResult *out_result);
|
||||
|
||||
/**
|
||||
* Register a private account on the network.
|
||||
*
|
||||
* This initializes a private account. 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_private_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`.
|
||||
|
||||
@ -84,9 +84,9 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
"Private": {
|
||||
"account_id": "3oCG8gqdKLMegw4rRfyaMQvuPHpcASt7xwttsmnZLSkw",
|
||||
"account_id": "2ECgkFTaXzwjJBXR7ZKmXYQtpHbvTTHK9Auma4NL9AUo",
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
@ -103,219 +103,19 @@
|
||||
"nonce": 0
|
||||
},
|
||||
"key_chain": {
|
||||
"secret_spending_key": [
|
||||
251,
|
||||
82,
|
||||
235,
|
||||
1,
|
||||
146,
|
||||
96,
|
||||
30,
|
||||
81,
|
||||
162,
|
||||
234,
|
||||
33,
|
||||
15,
|
||||
123,
|
||||
129,
|
||||
116,
|
||||
0,
|
||||
84,
|
||||
136,
|
||||
176,
|
||||
70,
|
||||
190,
|
||||
224,
|
||||
161,
|
||||
54,
|
||||
134,
|
||||
142,
|
||||
154,
|
||||
1,
|
||||
18,
|
||||
251,
|
||||
242,
|
||||
189
|
||||
],
|
||||
"secret_spending_key": [112, 17, 152, 192, 217, 201, 142, 92, 111, 68, 85, 222, 107, 73, 78, 196, 118, 226, 37, 17, 185, 177, 149, 182, 9, 85, 187, 152, 163, 144, 68, 121],
|
||||
"private_key_holder": {
|
||||
"nullifier_secret_key": [
|
||||
29,
|
||||
250,
|
||||
10,
|
||||
187,
|
||||
35,
|
||||
123,
|
||||
180,
|
||||
250,
|
||||
246,
|
||||
97,
|
||||
216,
|
||||
153,
|
||||
44,
|
||||
156,
|
||||
16,
|
||||
93,
|
||||
241,
|
||||
26,
|
||||
174,
|
||||
219,
|
||||
72,
|
||||
84,
|
||||
34,
|
||||
247,
|
||||
112,
|
||||
101,
|
||||
217,
|
||||
243,
|
||||
189,
|
||||
173,
|
||||
75,
|
||||
20
|
||||
],
|
||||
"incoming_viewing_secret_key": [
|
||||
251,
|
||||
201,
|
||||
22,
|
||||
154,
|
||||
100,
|
||||
165,
|
||||
218,
|
||||
108,
|
||||
163,
|
||||
190,
|
||||
135,
|
||||
91,
|
||||
145,
|
||||
84,
|
||||
69,
|
||||
241,
|
||||
46,
|
||||
117,
|
||||
217,
|
||||
110,
|
||||
197,
|
||||
248,
|
||||
91,
|
||||
193,
|
||||
14,
|
||||
104,
|
||||
88,
|
||||
103,
|
||||
67,
|
||||
153,
|
||||
182,
|
||||
158
|
||||
],
|
||||
"outgoing_viewing_secret_key": [
|
||||
25,
|
||||
67,
|
||||
121,
|
||||
76,
|
||||
175,
|
||||
100,
|
||||
30,
|
||||
198,
|
||||
105,
|
||||
123,
|
||||
49,
|
||||
169,
|
||||
75,
|
||||
178,
|
||||
75,
|
||||
210,
|
||||
100,
|
||||
143,
|
||||
210,
|
||||
243,
|
||||
228,
|
||||
243,
|
||||
21,
|
||||
18,
|
||||
36,
|
||||
84,
|
||||
164,
|
||||
186,
|
||||
139,
|
||||
113,
|
||||
214,
|
||||
12
|
||||
]
|
||||
"nullifier_secret_key": [52, 33, 235, 245, 42, 132, 163, 182, 114, 56, 144, 187, 147, 23, 184, 227, 128, 12, 180, 142, 217, 110, 188, 177, 155, 141, 23, 127, 216, 185, 33, 126],
|
||||
"viewing_secret_key": [44, 81, 165, 166, 34, 188, 192, 240, 40, 9, 83, 189, 215, 184, 246, 154, 247, 227, 155, 16, 121, 238, 4, 245, 63, 135, 192, 213, 222, 247, 120, 86]
|
||||
},
|
||||
"nullifer_public_key": [
|
||||
63,
|
||||
202,
|
||||
178,
|
||||
231,
|
||||
183,
|
||||
82,
|
||||
237,
|
||||
212,
|
||||
216,
|
||||
221,
|
||||
215,
|
||||
255,
|
||||
153,
|
||||
101,
|
||||
177,
|
||||
161,
|
||||
254,
|
||||
210,
|
||||
128,
|
||||
122,
|
||||
54,
|
||||
190,
|
||||
230,
|
||||
151,
|
||||
183,
|
||||
64,
|
||||
225,
|
||||
229,
|
||||
113,
|
||||
1,
|
||||
228,
|
||||
97
|
||||
],
|
||||
"incoming_viewing_public_key": [
|
||||
3,
|
||||
235,
|
||||
139,
|
||||
131,
|
||||
237,
|
||||
177,
|
||||
122,
|
||||
189,
|
||||
6,
|
||||
177,
|
||||
167,
|
||||
178,
|
||||
202,
|
||||
117,
|
||||
246,
|
||||
58,
|
||||
28,
|
||||
65,
|
||||
132,
|
||||
79,
|
||||
220,
|
||||
139,
|
||||
119,
|
||||
243,
|
||||
187,
|
||||
160,
|
||||
212,
|
||||
121,
|
||||
61,
|
||||
247,
|
||||
116,
|
||||
72,
|
||||
205
|
||||
]
|
||||
"nullifer_public_key": [13, 25, 40, 5, 198, 248, 210, 248, 237, 121, 124, 145, 186, 142, 253, 216, 236, 69, 193, 32, 166, 167, 49, 133, 172, 111, 159, 46, 84, 17, 157, 23],
|
||||
"viewing_public_key": [3, 43, 116, 165, 161, 27, 150, 158, 175, 198, 215, 27, 121, 126, 158, 224, 249, 92, 168, 163, 173, 115, 120, 122, 89, 173, 133, 94, 39, 238, 62, 52, 193]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Private": {
|
||||
"account_id": "AKTcXgJ1xoynta1Ec7y6Jso1z1JQtHqd7aPQ1h9er6xX",
|
||||
"account_id": "E8HwiTyQe4H9HK7icTvn95HQMnzx49mP9A2ddtMLpNaN",
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
@ -332,213 +132,13 @@
|
||||
"nonce": 0
|
||||
},
|
||||
"key_chain": {
|
||||
"secret_spending_key": [
|
||||
238,
|
||||
171,
|
||||
241,
|
||||
69,
|
||||
111,
|
||||
217,
|
||||
85,
|
||||
64,
|
||||
19,
|
||||
82,
|
||||
18,
|
||||
189,
|
||||
32,
|
||||
91,
|
||||
78,
|
||||
175,
|
||||
107,
|
||||
7,
|
||||
109,
|
||||
60,
|
||||
52,
|
||||
44,
|
||||
243,
|
||||
230,
|
||||
72,
|
||||
244,
|
||||
192,
|
||||
92,
|
||||
137,
|
||||
33,
|
||||
118,
|
||||
254
|
||||
],
|
||||
"secret_spending_key": [48, 175, 124, 10, 230, 240, 166, 14, 249, 254, 157, 226, 208, 124, 122, 177, 203, 139, 192, 180, 43, 120, 55, 151, 50, 21, 113, 22, 254, 83, 148, 56],
|
||||
"private_key_holder": {
|
||||
"nullifier_secret_key": [
|
||||
25,
|
||||
211,
|
||||
215,
|
||||
119,
|
||||
57,
|
||||
223,
|
||||
247,
|
||||
37,
|
||||
245,
|
||||
144,
|
||||
122,
|
||||
29,
|
||||
118,
|
||||
245,
|
||||
83,
|
||||
228,
|
||||
23,
|
||||
9,
|
||||
101,
|
||||
120,
|
||||
88,
|
||||
33,
|
||||
238,
|
||||
207,
|
||||
128,
|
||||
61,
|
||||
110,
|
||||
2,
|
||||
89,
|
||||
62,
|
||||
164,
|
||||
13
|
||||
],
|
||||
"incoming_viewing_secret_key": [
|
||||
193,
|
||||
181,
|
||||
14,
|
||||
196,
|
||||
142,
|
||||
84,
|
||||
15,
|
||||
65,
|
||||
128,
|
||||
101,
|
||||
70,
|
||||
196,
|
||||
241,
|
||||
47,
|
||||
130,
|
||||
221,
|
||||
23,
|
||||
146,
|
||||
161,
|
||||
237,
|
||||
221,
|
||||
40,
|
||||
19,
|
||||
126,
|
||||
59,
|
||||
15,
|
||||
169,
|
||||
236,
|
||||
25,
|
||||
105,
|
||||
104,
|
||||
231
|
||||
],
|
||||
"outgoing_viewing_secret_key": [
|
||||
20,
|
||||
170,
|
||||
220,
|
||||
108,
|
||||
41,
|
||||
23,
|
||||
155,
|
||||
217,
|
||||
247,
|
||||
190,
|
||||
175,
|
||||
168,
|
||||
247,
|
||||
34,
|
||||
105,
|
||||
134,
|
||||
114,
|
||||
74,
|
||||
104,
|
||||
91,
|
||||
211,
|
||||
62,
|
||||
126,
|
||||
13,
|
||||
130,
|
||||
100,
|
||||
241,
|
||||
214,
|
||||
250,
|
||||
236,
|
||||
38,
|
||||
150
|
||||
]
|
||||
"nullifier_secret_key": [99, 82, 190, 140, 234, 10, 61, 163, 15, 211, 179, 54, 70, 166, 87, 5, 182, 68, 117, 244, 217, 23, 99, 9, 4, 177, 230, 125, 109, 91, 160, 30],
|
||||
"viewing_secret_key": [205, 32, 76, 251, 255, 236, 96, 119, 61, 111, 65, 100, 75, 218, 12, 22, 17, 170, 55, 226, 21, 154, 161, 34, 208, 74, 27, 1, 119, 13, 88, 128]
|
||||
},
|
||||
"nullifer_public_key": [
|
||||
192,
|
||||
251,
|
||||
166,
|
||||
243,
|
||||
167,
|
||||
236,
|
||||
84,
|
||||
249,
|
||||
35,
|
||||
136,
|
||||
130,
|
||||
172,
|
||||
219,
|
||||
225,
|
||||
161,
|
||||
139,
|
||||
229,
|
||||
89,
|
||||
243,
|
||||
125,
|
||||
194,
|
||||
213,
|
||||
209,
|
||||
30,
|
||||
23,
|
||||
174,
|
||||
100,
|
||||
244,
|
||||
124,
|
||||
74,
|
||||
140,
|
||||
47
|
||||
],
|
||||
"incoming_viewing_public_key": [
|
||||
2,
|
||||
181,
|
||||
98,
|
||||
93,
|
||||
216,
|
||||
241,
|
||||
241,
|
||||
110,
|
||||
58,
|
||||
198,
|
||||
119,
|
||||
174,
|
||||
250,
|
||||
184,
|
||||
1,
|
||||
204,
|
||||
200,
|
||||
173,
|
||||
44,
|
||||
238,
|
||||
37,
|
||||
247,
|
||||
170,
|
||||
156,
|
||||
100,
|
||||
254,
|
||||
116,
|
||||
242,
|
||||
28,
|
||||
183,
|
||||
187,
|
||||
77,
|
||||
255
|
||||
]
|
||||
"nullifer_public_key": [32, 67, 72, 164, 106, 53, 66, 239, 141, 15, 52, 230, 136, 177, 2, 236, 207, 243, 134, 135, 210, 143, 87, 232, 215, 128, 194, 120, 113, 224, 4, 165],
|
||||
"viewing_public_key": [2, 79, 110, 46, 203, 29, 206, 205, 18, 86, 27, 189, 104, 103, 113, 181, 110, 53, 78, 172, 11, 171, 190, 18, 126, 214, 81, 77, 192, 154, 58, 195, 238]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ pub enum AccountSubcommand {
|
||||
/// Flag to get raw account data
|
||||
#[arg(short, long)]
|
||||
raw: bool,
|
||||
/// Display keys (pk for public accounts, npk/ipk for private accounts)
|
||||
/// Display keys (pk for public accounts, npk/vpk for private accounts)
|
||||
#[arg(short, long)]
|
||||
keys: bool,
|
||||
/// Valid 32 byte base58 string with privacy prefix
|
||||
@ -107,8 +107,8 @@ impl WalletSubcommand for NewSubcommand {
|
||||
);
|
||||
println!("With npk {}", hex::encode(key.nullifer_public_key.0));
|
||||
println!(
|
||||
"With ipk {}",
|
||||
hex::encode(key.incoming_viewing_public_key.to_bytes())
|
||||
"With vpk {}",
|
||||
hex::encode(key.viewing_public_key.to_bytes())
|
||||
);
|
||||
|
||||
wallet_core.store_persistent_data().await?;
|
||||
@ -207,10 +207,7 @@ impl WalletSubcommand for AccountSubcommand {
|
||||
.ok_or(anyhow::anyhow!("Private account not found in storage"))?;
|
||||
|
||||
println!("npk {}", hex::encode(key.nullifer_public_key.0));
|
||||
println!(
|
||||
"ipk {}",
|
||||
hex::encode(key.incoming_viewing_public_key.to_bytes())
|
||||
);
|
||||
println!("vpk {}", hex::encode(key.viewing_public_key.to_bytes()));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@ -22,7 +22,7 @@ pub enum AuthTransferSubcommand {
|
||||
},
|
||||
/// Send native tokens from one account to another with variable privacy
|
||||
///
|
||||
/// If receiver is private, then `to` and (`to_npk` , `to_ipk`) is a mutually exclusive
|
||||
/// If receiver is private, then `to` and (`to_npk` , `to_vpk`) is a mutually exclusive
|
||||
/// patterns.
|
||||
///
|
||||
/// First is used for owned accounts, second otherwise.
|
||||
@ -36,9 +36,9 @@ pub enum AuthTransferSubcommand {
|
||||
/// to_npk - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
to_npk: Option<String>,
|
||||
/// to_ipk - valid 33 byte hex string
|
||||
/// to_vpk - valid 33 byte hex string
|
||||
#[arg(long)]
|
||||
to_ipk: Option<String>,
|
||||
to_vpk: Option<String>,
|
||||
/// amount - amount of balance to move
|
||||
#[arg(long)]
|
||||
amount: u128,
|
||||
@ -102,10 +102,10 @@ impl WalletSubcommand for AuthTransferSubcommand {
|
||||
from,
|
||||
to,
|
||||
to_npk,
|
||||
to_ipk,
|
||||
to_vpk,
|
||||
amount,
|
||||
} => {
|
||||
let underlying_subcommand = match (to, to_npk, to_ipk) {
|
||||
let underlying_subcommand = match (to, to_npk, to_vpk) {
|
||||
(None, None, None) => {
|
||||
anyhow::bail!(
|
||||
"Provide either account account_id of receiver or their public keys"
|
||||
@ -154,7 +154,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
|
||||
}
|
||||
}
|
||||
}
|
||||
(None, Some(to_npk), Some(to_ipk)) => {
|
||||
(None, Some(to_npk), Some(to_vpk)) => {
|
||||
let (from, from_privacy) = parse_addr_with_privacy_prefix(&from)?;
|
||||
|
||||
match from_privacy {
|
||||
@ -163,7 +163,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
|
||||
NativeTokenTransferProgramSubcommandPrivate::PrivateForeign {
|
||||
from,
|
||||
to_npk,
|
||||
to_ipk,
|
||||
to_vpk,
|
||||
amount,
|
||||
},
|
||||
)
|
||||
@ -173,7 +173,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
|
||||
NativeTokenTransferProgramSubcommandShielded::ShieldedForeign {
|
||||
from,
|
||||
to_npk,
|
||||
to_ipk,
|
||||
to_vpk,
|
||||
amount,
|
||||
},
|
||||
)
|
||||
@ -255,9 +255,9 @@ pub enum NativeTokenTransferProgramSubcommandShielded {
|
||||
/// to_npk - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
to_npk: String,
|
||||
/// to_ipk - valid 33 byte hex string
|
||||
/// to_vpk - valid 33 byte hex string
|
||||
#[arg(long)]
|
||||
to_ipk: String,
|
||||
to_vpk: String,
|
||||
/// amount - amount of balance to move
|
||||
#[arg(long)]
|
||||
amount: u128,
|
||||
@ -292,9 +292,9 @@ pub enum NativeTokenTransferProgramSubcommandPrivate {
|
||||
/// to_npk - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
to_npk: String,
|
||||
/// to_ipk - valid 33 byte hex string
|
||||
/// to_vpk - valid 33 byte hex string
|
||||
#[arg(long)]
|
||||
to_ipk: String,
|
||||
to_vpk: String,
|
||||
/// amount - amount of balance to move
|
||||
#[arg(long)]
|
||||
amount: u128,
|
||||
@ -336,7 +336,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate {
|
||||
NativeTokenTransferProgramSubcommandPrivate::PrivateForeign {
|
||||
from,
|
||||
to_npk,
|
||||
to_ipk,
|
||||
to_vpk,
|
||||
amount,
|
||||
} => {
|
||||
let from: AccountId = from.parse().unwrap();
|
||||
@ -345,14 +345,14 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate {
|
||||
to_npk.copy_from_slice(&to_npk_res);
|
||||
let to_npk = nssa_core::NullifierPublicKey(to_npk);
|
||||
|
||||
let to_ipk_res = hex::decode(to_ipk)?;
|
||||
let mut to_ipk = [0u8; 33];
|
||||
to_ipk.copy_from_slice(&to_ipk_res);
|
||||
let to_ipk =
|
||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec());
|
||||
let to_vpk_res = hex::decode(to_vpk)?;
|
||||
let mut to_vpk = [0u8; 33];
|
||||
to_vpk.copy_from_slice(&to_vpk_res);
|
||||
let to_vpk =
|
||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_vpk.to_vec());
|
||||
|
||||
let (res, [secret_from, _]) = NativeTokenTransfer(wallet_core)
|
||||
.send_private_transfer_to_outer_account(from, to_npk, to_ipk, amount)
|
||||
.send_private_transfer_to_outer_account(from, to_npk, to_vpk, amount)
|
||||
.await?;
|
||||
|
||||
println!("Results of tx send are {res:#?}");
|
||||
@ -412,7 +412,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
|
||||
NativeTokenTransferProgramSubcommandShielded::ShieldedForeign {
|
||||
from,
|
||||
to_npk,
|
||||
to_ipk,
|
||||
to_vpk,
|
||||
amount,
|
||||
} => {
|
||||
let from: AccountId = from.parse().unwrap();
|
||||
@ -422,14 +422,14 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
|
||||
to_npk.copy_from_slice(&to_npk_res);
|
||||
let to_npk = nssa_core::NullifierPublicKey(to_npk);
|
||||
|
||||
let to_ipk_res = hex::decode(to_ipk)?;
|
||||
let mut to_ipk = [0u8; 33];
|
||||
to_ipk.copy_from_slice(&to_ipk_res);
|
||||
let to_ipk =
|
||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec());
|
||||
let to_vpk_res = hex::decode(to_vpk)?;
|
||||
let mut to_vpk = [0u8; 33];
|
||||
to_vpk.copy_from_slice(&to_vpk_res);
|
||||
let to_vpk =
|
||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_vpk.to_vec());
|
||||
|
||||
let (res, _) = NativeTokenTransfer(wallet_core)
|
||||
.send_shielded_transfer_to_outer_account(from, to_npk, to_ipk, amount)
|
||||
.send_shielded_transfer_to_outer_account(from, to_npk, to_vpk, amount)
|
||||
.await?;
|
||||
|
||||
println!("Results of tx send are {res:#?}");
|
||||
|
||||
@ -29,7 +29,7 @@ pub enum TokenProgramAgnosticSubcommand {
|
||||
},
|
||||
/// Send tokens from one account to another with variable privacy
|
||||
///
|
||||
/// If receiver is private, then `to` and (`to_npk` , `to_ipk`) is a mutually exclusive
|
||||
/// If receiver is private, then `to` and (`to_npk` , `to_vpk`) is a mutually exclusive
|
||||
/// patterns.
|
||||
///
|
||||
/// First is used for owned accounts, second otherwise.
|
||||
@ -43,9 +43,9 @@ pub enum TokenProgramAgnosticSubcommand {
|
||||
/// to_npk - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
to_npk: Option<String>,
|
||||
/// to_ipk - valid 33 byte hex string
|
||||
/// to_vpk - valid 33 byte hex string
|
||||
#[arg(long)]
|
||||
to_ipk: Option<String>,
|
||||
to_vpk: Option<String>,
|
||||
/// amount - amount of balance to move
|
||||
#[arg(long)]
|
||||
amount: u128,
|
||||
@ -71,7 +71,7 @@ pub enum TokenProgramAgnosticSubcommand {
|
||||
///
|
||||
/// `definition` is owned
|
||||
///
|
||||
/// If `holder` is private, then `holder` and (`holder_npk` , `holder_ipk`) is a mutually
|
||||
/// If `holder` is private, then `holder` and (`holder_npk` , `holder_vpk`) is a mutually
|
||||
/// exclusive patterns.
|
||||
///
|
||||
/// First is used for owned accounts, second otherwise.
|
||||
@ -85,9 +85,9 @@ pub enum TokenProgramAgnosticSubcommand {
|
||||
/// holder_npk - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
holder_npk: Option<String>,
|
||||
/// to_ipk - valid 33 byte hex string
|
||||
/// to_vpk - valid 33 byte hex string
|
||||
#[arg(long)]
|
||||
holder_ipk: Option<String>,
|
||||
holder_vpk: Option<String>,
|
||||
/// amount - amount of balance to mint
|
||||
#[arg(long)]
|
||||
amount: u128,
|
||||
@ -160,10 +160,10 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
||||
from,
|
||||
to,
|
||||
to_npk,
|
||||
to_ipk,
|
||||
to_vpk,
|
||||
amount,
|
||||
} => {
|
||||
let underlying_subcommand = match (to, to_npk, to_ipk) {
|
||||
let underlying_subcommand = match (to, to_npk, to_vpk) {
|
||||
(None, None, None) => {
|
||||
anyhow::bail!(
|
||||
"Provide either account account_id of receiver or their public keys"
|
||||
@ -220,7 +220,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
||||
}
|
||||
}
|
||||
}
|
||||
(None, Some(to_npk), Some(to_ipk)) => {
|
||||
(None, Some(to_npk), Some(to_vpk)) => {
|
||||
let (from, from_privacy) = parse_addr_with_privacy_prefix(&from)?;
|
||||
|
||||
match from_privacy {
|
||||
@ -228,7 +228,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
||||
TokenProgramSubcommandPrivate::TransferTokenPrivateForeign {
|
||||
sender_account_id: from,
|
||||
recipient_npk: to_npk,
|
||||
recipient_ipk: to_ipk,
|
||||
recipient_vpk: to_vpk,
|
||||
balance_to_move: amount,
|
||||
},
|
||||
),
|
||||
@ -236,7 +236,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
||||
TokenProgramSubcommandShielded::TransferTokenShieldedForeign {
|
||||
sender_account_id: from,
|
||||
recipient_npk: to_npk,
|
||||
recipient_ipk: to_ipk,
|
||||
recipient_vpk: to_vpk,
|
||||
balance_to_move: amount,
|
||||
},
|
||||
),
|
||||
@ -302,10 +302,10 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
||||
definition,
|
||||
holder,
|
||||
holder_npk,
|
||||
holder_ipk,
|
||||
holder_vpk,
|
||||
amount,
|
||||
} => {
|
||||
let underlying_subcommand = match (holder, holder_npk, holder_ipk) {
|
||||
let underlying_subcommand = match (holder, holder_npk, holder_vpk) {
|
||||
(None, None, None) => {
|
||||
anyhow::bail!(
|
||||
"Provide either account account_id of holder or their public keys"
|
||||
@ -363,7 +363,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
||||
}
|
||||
}
|
||||
}
|
||||
(None, Some(holder_npk), Some(holder_ipk)) => {
|
||||
(None, Some(holder_npk), Some(holder_vpk)) => {
|
||||
let (definition, definition_privacy) =
|
||||
parse_addr_with_privacy_prefix(&definition)?;
|
||||
|
||||
@ -372,7 +372,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
||||
TokenProgramSubcommandPrivate::MintTokenPrivateForeign {
|
||||
definition_account_id: definition,
|
||||
holder_npk,
|
||||
holder_ipk,
|
||||
holder_vpk,
|
||||
amount,
|
||||
},
|
||||
),
|
||||
@ -380,7 +380,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
||||
TokenProgramSubcommandShielded::MintTokenShieldedForeign {
|
||||
definition_account_id: definition,
|
||||
holder_npk,
|
||||
holder_ipk,
|
||||
holder_vpk,
|
||||
amount,
|
||||
},
|
||||
),
|
||||
@ -465,9 +465,9 @@ pub enum TokenProgramSubcommandPrivate {
|
||||
/// recipient_npk - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
recipient_npk: String,
|
||||
/// recipient_ipk - valid 33 byte hex string
|
||||
/// recipient_vpk - valid 33 byte hex string
|
||||
#[arg(long)]
|
||||
recipient_ipk: String,
|
||||
recipient_vpk: String,
|
||||
#[arg(short, long)]
|
||||
balance_to_move: u128,
|
||||
},
|
||||
@ -496,7 +496,7 @@ pub enum TokenProgramSubcommandPrivate {
|
||||
#[arg(short, long)]
|
||||
holder_npk: String,
|
||||
#[arg(short, long)]
|
||||
holder_ipk: String,
|
||||
holder_vpk: String,
|
||||
#[arg(short, long)]
|
||||
amount: u128,
|
||||
},
|
||||
@ -553,9 +553,9 @@ pub enum TokenProgramSubcommandShielded {
|
||||
/// recipient_npk - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
recipient_npk: String,
|
||||
/// recipient_ipk - valid 33 byte hex string
|
||||
/// recipient_vpk - valid 33 byte hex string
|
||||
#[arg(long)]
|
||||
recipient_ipk: String,
|
||||
recipient_vpk: String,
|
||||
#[arg(short, long)]
|
||||
balance_to_move: u128,
|
||||
},
|
||||
@ -584,7 +584,7 @@ pub enum TokenProgramSubcommandShielded {
|
||||
#[arg(short, long)]
|
||||
holder_npk: String,
|
||||
#[arg(short, long)]
|
||||
holder_ipk: String,
|
||||
holder_vpk: String,
|
||||
#[arg(short, long)]
|
||||
amount: u128,
|
||||
},
|
||||
@ -745,7 +745,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
|
||||
TokenProgramSubcommandPrivate::TransferTokenPrivateForeign {
|
||||
sender_account_id,
|
||||
recipient_npk,
|
||||
recipient_ipk,
|
||||
recipient_vpk,
|
||||
balance_to_move,
|
||||
} => {
|
||||
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
|
||||
@ -754,18 +754,18 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
|
||||
recipient_npk.copy_from_slice(&recipient_npk_res);
|
||||
let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk);
|
||||
|
||||
let recipient_ipk_res = hex::decode(recipient_ipk)?;
|
||||
let mut recipient_ipk = [0u8; 33];
|
||||
recipient_ipk.copy_from_slice(&recipient_ipk_res);
|
||||
let recipient_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
|
||||
recipient_ipk.to_vec(),
|
||||
let recipient_vpk_res = hex::decode(recipient_vpk)?;
|
||||
let mut recipient_vpk = [0u8; 33];
|
||||
recipient_vpk.copy_from_slice(&recipient_vpk_res);
|
||||
let recipient_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
|
||||
recipient_vpk.to_vec(),
|
||||
);
|
||||
|
||||
let (res, [secret_sender, _]) = Token(wallet_core)
|
||||
.send_transfer_transaction_private_foreign_account(
|
||||
sender_account_id,
|
||||
recipient_npk,
|
||||
recipient_ipk,
|
||||
recipient_vpk,
|
||||
balance_to_move,
|
||||
)
|
||||
.await?;
|
||||
@ -865,7 +865,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
|
||||
TokenProgramSubcommandPrivate::MintTokenPrivateForeign {
|
||||
definition_account_id,
|
||||
holder_npk,
|
||||
holder_ipk,
|
||||
holder_vpk,
|
||||
amount,
|
||||
} => {
|
||||
let definition_account_id: AccountId = definition_account_id.parse().unwrap();
|
||||
@ -875,18 +875,18 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
|
||||
holder_npk.copy_from_slice(&holder_npk_res);
|
||||
let holder_npk = nssa_core::NullifierPublicKey(holder_npk);
|
||||
|
||||
let holder_ipk_res = hex::decode(holder_ipk)?;
|
||||
let mut holder_ipk = [0u8; 33];
|
||||
holder_ipk.copy_from_slice(&holder_ipk_res);
|
||||
let holder_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
|
||||
holder_ipk.to_vec(),
|
||||
let holder_vpk_res = hex::decode(holder_vpk)?;
|
||||
let mut holder_vpk = [0u8; 33];
|
||||
holder_vpk.copy_from_slice(&holder_vpk_res);
|
||||
let holder_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
|
||||
holder_vpk.to_vec(),
|
||||
);
|
||||
|
||||
let (res, [secret_definition, _]) = Token(wallet_core)
|
||||
.send_mint_transaction_private_foreign_account(
|
||||
definition_account_id,
|
||||
holder_npk,
|
||||
holder_ipk,
|
||||
holder_vpk,
|
||||
amount,
|
||||
)
|
||||
.await?;
|
||||
@ -1034,7 +1034,7 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
|
||||
TokenProgramSubcommandShielded::TransferTokenShieldedForeign {
|
||||
sender_account_id,
|
||||
recipient_npk,
|
||||
recipient_ipk,
|
||||
recipient_vpk,
|
||||
balance_to_move,
|
||||
} => {
|
||||
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
|
||||
@ -1043,18 +1043,18 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
|
||||
recipient_npk.copy_from_slice(&recipient_npk_res);
|
||||
let recipient_npk = nssa_core::NullifierPublicKey(recipient_npk);
|
||||
|
||||
let recipient_ipk_res = hex::decode(recipient_ipk)?;
|
||||
let mut recipient_ipk = [0u8; 33];
|
||||
recipient_ipk.copy_from_slice(&recipient_ipk_res);
|
||||
let recipient_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
|
||||
recipient_ipk.to_vec(),
|
||||
let recipient_vpk_res = hex::decode(recipient_vpk)?;
|
||||
let mut recipient_vpk = [0u8; 33];
|
||||
recipient_vpk.copy_from_slice(&recipient_vpk_res);
|
||||
let recipient_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
|
||||
recipient_vpk.to_vec(),
|
||||
);
|
||||
|
||||
let (res, _) = Token(wallet_core)
|
||||
.send_transfer_transaction_shielded_foreign_account(
|
||||
sender_account_id,
|
||||
recipient_npk,
|
||||
recipient_ipk,
|
||||
recipient_vpk,
|
||||
balance_to_move,
|
||||
)
|
||||
.await?;
|
||||
@ -1177,7 +1177,7 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
|
||||
TokenProgramSubcommandShielded::MintTokenShieldedForeign {
|
||||
definition_account_id,
|
||||
holder_npk,
|
||||
holder_ipk,
|
||||
holder_vpk,
|
||||
amount,
|
||||
} => {
|
||||
let definition_account_id: AccountId = definition_account_id.parse().unwrap();
|
||||
@ -1187,18 +1187,18 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
|
||||
holder_npk.copy_from_slice(&holder_npk_res);
|
||||
let holder_npk = nssa_core::NullifierPublicKey(holder_npk);
|
||||
|
||||
let holder_ipk_res = hex::decode(holder_ipk)?;
|
||||
let mut holder_ipk = [0u8; 33];
|
||||
holder_ipk.copy_from_slice(&holder_ipk_res);
|
||||
let holder_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
|
||||
holder_ipk.to_vec(),
|
||||
let holder_vpk_res = hex::decode(holder_vpk)?;
|
||||
let mut holder_vpk = [0u8; 33];
|
||||
holder_vpk.copy_from_slice(&holder_vpk_res);
|
||||
let holder_vpk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(
|
||||
holder_vpk.to_vec(),
|
||||
);
|
||||
|
||||
let (res, _) = Token(wallet_core)
|
||||
.send_mint_transaction_shielded_foreign_account(
|
||||
definition_account_id,
|
||||
holder_npk,
|
||||
holder_ipk,
|
||||
holder_vpk,
|
||||
amount,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -292,7 +292,7 @@ impl Default for WalletConfig {
|
||||
},
|
||||
{
|
||||
"Private": {
|
||||
"account_id": "3oCG8gqdKLMegw4rRfyaMQvuPHpcASt7xwttsmnZLSkw",
|
||||
"account_id": "FpdcxBrMkHWqXCBQ6FG98eYfWGY6jWZRsKNSi1FwDMxy",
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
@ -310,218 +310,151 @@ impl Default for WalletConfig {
|
||||
},
|
||||
"key_chain": {
|
||||
"secret_spending_key": [
|
||||
251,
|
||||
82,
|
||||
235,
|
||||
1,
|
||||
146,
|
||||
96,
|
||||
30,
|
||||
81,
|
||||
162,
|
||||
234,
|
||||
239,
|
||||
27,
|
||||
159,
|
||||
83,
|
||||
199,
|
||||
194,
|
||||
132,
|
||||
33,
|
||||
15,
|
||||
123,
|
||||
129,
|
||||
116,
|
||||
0,
|
||||
20,
|
||||
28,
|
||||
217,
|
||||
103,
|
||||
101,
|
||||
57,
|
||||
27,
|
||||
125,
|
||||
84,
|
||||
136,
|
||||
176,
|
||||
70,
|
||||
190,
|
||||
224,
|
||||
57,
|
||||
19,
|
||||
86,
|
||||
98,
|
||||
135,
|
||||
161,
|
||||
54,
|
||||
134,
|
||||
142,
|
||||
154,
|
||||
1,
|
||||
18,
|
||||
251,
|
||||
242,
|
||||
189
|
||||
221,
|
||||
108,
|
||||
125,
|
||||
152,
|
||||
174,
|
||||
161,
|
||||
64,
|
||||
16,
|
||||
200
|
||||
],
|
||||
"private_key_holder": {
|
||||
"nullifier_secret_key": [
|
||||
29,
|
||||
250,
|
||||
10,
|
||||
187,
|
||||
35,
|
||||
123,
|
||||
180,
|
||||
250,
|
||||
246,
|
||||
97,
|
||||
216,
|
||||
153,
|
||||
44,
|
||||
156,
|
||||
71,
|
||||
195,
|
||||
16,
|
||||
93,
|
||||
241,
|
||||
26,
|
||||
174,
|
||||
219,
|
||||
72,
|
||||
84,
|
||||
34,
|
||||
247,
|
||||
112,
|
||||
101,
|
||||
217,
|
||||
243,
|
||||
189,
|
||||
173,
|
||||
75,
|
||||
20
|
||||
],
|
||||
"incoming_viewing_secret_key": [
|
||||
251,
|
||||
201,
|
||||
22,
|
||||
154,
|
||||
100,
|
||||
165,
|
||||
218,
|
||||
108,
|
||||
163,
|
||||
190,
|
||||
135,
|
||||
91,
|
||||
145,
|
||||
84,
|
||||
69,
|
||||
241,
|
||||
46,
|
||||
117,
|
||||
217,
|
||||
110,
|
||||
197,
|
||||
248,
|
||||
91,
|
||||
193,
|
||||
14,
|
||||
104,
|
||||
88,
|
||||
103,
|
||||
67,
|
||||
153,
|
||||
182,
|
||||
158
|
||||
],
|
||||
"outgoing_viewing_secret_key": [
|
||||
25,
|
||||
67,
|
||||
121,
|
||||
76,
|
||||
175,
|
||||
100,
|
||||
30,
|
||||
198,
|
||||
105,
|
||||
123,
|
||||
49,
|
||||
169,
|
||||
75,
|
||||
178,
|
||||
75,
|
||||
210,
|
||||
100,
|
||||
143,
|
||||
210,
|
||||
243,
|
||||
228,
|
||||
243,
|
||||
21,
|
||||
18,
|
||||
36,
|
||||
84,
|
||||
164,
|
||||
186,
|
||||
119,
|
||||
0,
|
||||
98,
|
||||
35,
|
||||
106,
|
||||
139,
|
||||
113,
|
||||
214,
|
||||
12
|
||||
82,
|
||||
145,
|
||||
50,
|
||||
27,
|
||||
140,
|
||||
206,
|
||||
19,
|
||||
53,
|
||||
122,
|
||||
166,
|
||||
76,
|
||||
195,
|
||||
0,
|
||||
16,
|
||||
19,
|
||||
21,
|
||||
143,
|
||||
155,
|
||||
119,
|
||||
9,
|
||||
200,
|
||||
81,
|
||||
105
|
||||
],
|
||||
"viewing_secret_key": [
|
||||
5,
|
||||
117,
|
||||
221,
|
||||
27,
|
||||
236,
|
||||
199,
|
||||
53,
|
||||
22,
|
||||
249,
|
||||
231,
|
||||
98,
|
||||
147,
|
||||
213,
|
||||
116,
|
||||
191,
|
||||
82,
|
||||
188,
|
||||
148,
|
||||
175,
|
||||
98,
|
||||
139,
|
||||
52,
|
||||
232,
|
||||
249,
|
||||
220,
|
||||
217,
|
||||
83,
|
||||
58,
|
||||
112,
|
||||
155,
|
||||
197,
|
||||
196
|
||||
]
|
||||
},
|
||||
"nullifer_public_key": [
|
||||
63,
|
||||
202,
|
||||
178,
|
||||
231,
|
||||
183,
|
||||
82,
|
||||
237,
|
||||
212,
|
||||
216,
|
||||
221,
|
||||
215,
|
||||
255,
|
||||
153,
|
||||
101,
|
||||
177,
|
||||
161,
|
||||
254,
|
||||
210,
|
||||
128,
|
||||
122,
|
||||
54,
|
||||
190,
|
||||
230,
|
||||
151,
|
||||
183,
|
||||
64,
|
||||
225,
|
||||
229,
|
||||
113,
|
||||
1,
|
||||
228,
|
||||
97
|
||||
],
|
||||
"incoming_viewing_public_key": [
|
||||
3,
|
||||
235,
|
||||
139,
|
||||
131,
|
||||
237,
|
||||
177,
|
||||
122,
|
||||
189,
|
||||
6,
|
||||
177,
|
||||
167,
|
||||
178,
|
||||
202,
|
||||
117,
|
||||
246,
|
||||
58,
|
||||
28,
|
||||
65,
|
||||
132,
|
||||
79,
|
||||
220,
|
||||
139,
|
||||
119,
|
||||
11,
|
||||
87,
|
||||
38,
|
||||
254,
|
||||
159,
|
||||
231,
|
||||
165,
|
||||
1,
|
||||
94,
|
||||
64,
|
||||
137,
|
||||
243,
|
||||
187,
|
||||
160,
|
||||
212,
|
||||
121,
|
||||
61,
|
||||
247,
|
||||
116,
|
||||
72,
|
||||
205
|
||||
]
|
||||
76,
|
||||
249,
|
||||
101,
|
||||
251,
|
||||
129,
|
||||
33,
|
||||
101,
|
||||
189,
|
||||
30,
|
||||
42,
|
||||
11,
|
||||
191,
|
||||
34,
|
||||
103,
|
||||
186,
|
||||
227,
|
||||
230
|
||||
],
|
||||
"viewing_public_key": [
|
||||
2, 69, 126, 43, 158, 209, 172, 144, 23, 185, 208, 25, 163, 166, 176, 200, 225, 251, 106, 211, 4, 199, 112, 243, 207, 144, 135, 56, 157, 167, 32, 219, 38]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Private": {
|
||||
"account_id": "AKTcXgJ1xoynta1Ec7y6Jso1z1JQtHqd7aPQ1h9er6xX",
|
||||
"account_id": "E8HwiTyQe4H9HK7icTvn95HQMnzx49mP9A2ddtMLpNaN",
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
@ -539,211 +472,20 @@ impl Default for WalletConfig {
|
||||
},
|
||||
"key_chain": {
|
||||
"secret_spending_key": [
|
||||
238,
|
||||
171,
|
||||
241,
|
||||
69,
|
||||
111,
|
||||
217,
|
||||
85,
|
||||
64,
|
||||
19,
|
||||
82,
|
||||
18,
|
||||
189,
|
||||
32,
|
||||
91,
|
||||
78,
|
||||
175,
|
||||
107,
|
||||
7,
|
||||
109,
|
||||
60,
|
||||
52,
|
||||
44,
|
||||
243,
|
||||
230,
|
||||
72,
|
||||
244,
|
||||
192,
|
||||
92,
|
||||
137,
|
||||
33,
|
||||
118,
|
||||
254
|
||||
],
|
||||
48, 175, 124, 10, 230, 240, 166, 14, 249, 254, 157, 226, 208, 124, 122, 177, 203, 139, 192, 180, 43, 120, 55, 151, 50, 21, 113, 22, 254, 83, 148, 56],
|
||||
"private_key_holder": {
|
||||
"nullifier_secret_key": [
|
||||
25,
|
||||
211,
|
||||
215,
|
||||
119,
|
||||
57,
|
||||
223,
|
||||
247,
|
||||
37,
|
||||
245,
|
||||
144,
|
||||
122,
|
||||
29,
|
||||
118,
|
||||
245,
|
||||
83,
|
||||
228,
|
||||
23,
|
||||
9,
|
||||
101,
|
||||
120,
|
||||
88,
|
||||
33,
|
||||
238,
|
||||
207,
|
||||
128,
|
||||
61,
|
||||
110,
|
||||
2,
|
||||
89,
|
||||
62,
|
||||
164,
|
||||
13
|
||||
99, 82, 190, 140, 234, 10, 61, 163, 15, 211, 179, 54, 70, 166, 87, 5, 182, 68, 117, 244, 217, 23, 99, 9, 4, 177, 230, 125, 109, 91, 160, 30
|
||||
],
|
||||
"incoming_viewing_secret_key": [
|
||||
193,
|
||||
181,
|
||||
14,
|
||||
196,
|
||||
142,
|
||||
84,
|
||||
15,
|
||||
65,
|
||||
128,
|
||||
101,
|
||||
70,
|
||||
196,
|
||||
241,
|
||||
47,
|
||||
130,
|
||||
221,
|
||||
23,
|
||||
146,
|
||||
161,
|
||||
237,
|
||||
221,
|
||||
40,
|
||||
19,
|
||||
126,
|
||||
59,
|
||||
15,
|
||||
169,
|
||||
236,
|
||||
25,
|
||||
105,
|
||||
104,
|
||||
231
|
||||
],
|
||||
"outgoing_viewing_secret_key": [
|
||||
20,
|
||||
170,
|
||||
220,
|
||||
108,
|
||||
41,
|
||||
23,
|
||||
155,
|
||||
217,
|
||||
247,
|
||||
190,
|
||||
175,
|
||||
168,
|
||||
247,
|
||||
34,
|
||||
105,
|
||||
134,
|
||||
114,
|
||||
74,
|
||||
104,
|
||||
91,
|
||||
211,
|
||||
62,
|
||||
126,
|
||||
13,
|
||||
130,
|
||||
100,
|
||||
241,
|
||||
214,
|
||||
250,
|
||||
236,
|
||||
38,
|
||||
150
|
||||
"viewing_secret_key": [
|
||||
205, 32, 76, 251, 255, 236, 96, 119, 61, 111, 65, 100, 75, 218, 12, 22, 17, 170, 55, 226, 21, 154, 161, 34, 208, 74, 27, 1, 119, 13, 88, 128
|
||||
]
|
||||
},
|
||||
"nullifer_public_key": [
|
||||
192,
|
||||
251,
|
||||
166,
|
||||
243,
|
||||
167,
|
||||
236,
|
||||
84,
|
||||
249,
|
||||
35,
|
||||
136,
|
||||
130,
|
||||
172,
|
||||
219,
|
||||
225,
|
||||
161,
|
||||
139,
|
||||
229,
|
||||
89,
|
||||
243,
|
||||
125,
|
||||
194,
|
||||
213,
|
||||
209,
|
||||
30,
|
||||
23,
|
||||
174,
|
||||
100,
|
||||
244,
|
||||
124,
|
||||
74,
|
||||
140,
|
||||
47
|
||||
32, 67, 72, 164, 106, 53, 66, 239, 141, 15, 52, 230, 136, 177, 2, 236, 207, 243, 134, 135, 210, 143, 87, 232, 215, 128, 194, 120, 113, 224, 4, 165
|
||||
],
|
||||
"incoming_viewing_public_key": [
|
||||
2,
|
||||
181,
|
||||
98,
|
||||
93,
|
||||
216,
|
||||
241,
|
||||
241,
|
||||
110,
|
||||
58,
|
||||
198,
|
||||
119,
|
||||
174,
|
||||
250,
|
||||
184,
|
||||
1,
|
||||
204,
|
||||
200,
|
||||
173,
|
||||
44,
|
||||
238,
|
||||
37,
|
||||
247,
|
||||
170,
|
||||
156,
|
||||
100,
|
||||
254,
|
||||
116,
|
||||
242,
|
||||
28,
|
||||
183,
|
||||
187,
|
||||
77,
|
||||
255
|
||||
"viewing_public_key": [
|
||||
2, 79, 110, 46, 203, 29, 206, 205, 18, 86, 27, 189, 104, 103, 113, 181, 110, 53, 78, 172, 11, 171, 190, 18, 126, 214, 81, 77, 192, 154, 58, 195, 238
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,6 +298,8 @@ impl WalletCore {
|
||||
instruction_data: InstructionData,
|
||||
program: &ProgramWithDependencies,
|
||||
) -> Result<(SendTxResponse, Vec<SharedSecretKey>), ExecutionFailureKind> {
|
||||
// TODO: handle large Err-variant properly
|
||||
#[allow(clippy::result_large_err)]
|
||||
self.send_privacy_preserving_tx_with_pre_check(accounts, instruction_data, program, |_| {
|
||||
Ok(())
|
||||
})
|
||||
@ -343,7 +345,7 @@ impl WalletCore {
|
||||
Vec::from_iter(acc_manager.public_account_nonces()),
|
||||
private_account_keys
|
||||
.iter()
|
||||
.map(|keys| (keys.npk.clone(), keys.ipk.clone(), keys.epk.clone()))
|
||||
.map(|keys| (keys.npk.clone(), keys.vpk.clone(), keys.epk.clone()))
|
||||
.collect(),
|
||||
output,
|
||||
)
|
||||
@ -427,7 +429,7 @@ impl WalletCore {
|
||||
.flat_map(|(acc_account_id, key_chain)| {
|
||||
let view_tag = EncryptedAccountData::compute_view_tag(
|
||||
key_chain.nullifer_public_key.clone(),
|
||||
key_chain.incoming_viewing_public_key.clone(),
|
||||
key_chain.viewing_public_key.clone(),
|
||||
);
|
||||
|
||||
tx.message()
|
||||
|
||||
@ -36,7 +36,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: winner_nsk,
|
||||
npk: winner_npk,
|
||||
ipk: winner_ipk,
|
||||
vpk: winner_vpk,
|
||||
auth_acc: winner_pre,
|
||||
proof: _,
|
||||
} = self
|
||||
@ -50,7 +50,7 @@ impl WalletCore {
|
||||
let pinata_pre = AccountWithMetadata::new(pinata_acc.clone(), false, pinata_account_id);
|
||||
|
||||
let eph_holder_winner = EphemeralKeyHolder::new(&winner_npk);
|
||||
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_ipk);
|
||||
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_vpk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[pinata_pre, winner_pre],
|
||||
@ -70,7 +70,7 @@ impl WalletCore {
|
||||
vec![],
|
||||
vec![(
|
||||
winner_npk.clone(),
|
||||
winner_ipk.clone(),
|
||||
winner_vpk.clone(),
|
||||
eph_holder_winner.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
@ -103,7 +103,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: _,
|
||||
npk: winner_npk,
|
||||
ipk: winner_ipk,
|
||||
vpk: winner_vpk,
|
||||
auth_acc: winner_pre,
|
||||
proof: _,
|
||||
} = self
|
||||
@ -117,7 +117,7 @@ impl WalletCore {
|
||||
let pinata_pre = AccountWithMetadata::new(pinata_acc.clone(), false, pinata_account_id);
|
||||
|
||||
let eph_holder_winner = EphemeralKeyHolder::new(&winner_npk);
|
||||
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_ipk);
|
||||
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_vpk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[pinata_pre, winner_pre],
|
||||
@ -137,7 +137,7 @@ impl WalletCore {
|
||||
vec![],
|
||||
vec![(
|
||||
winner_npk.clone(),
|
||||
winner_ipk.clone(),
|
||||
winner_vpk.clone(),
|
||||
eph_holder_winner.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
|
||||
@ -5,7 +5,7 @@ use nssa::{AccountId, PrivateKey};
|
||||
use nssa_core::{
|
||||
MembershipProof, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
|
||||
account::{AccountWithMetadata, Nonce},
|
||||
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
|
||||
encryption::{EphemeralPublicKey, ViewingPublicKey},
|
||||
};
|
||||
|
||||
use crate::WalletCore;
|
||||
@ -16,7 +16,7 @@ pub enum PrivacyPreservingAccount {
|
||||
PrivateOwned(AccountId),
|
||||
PrivateForeign {
|
||||
npk: NullifierPublicKey,
|
||||
ipk: IncomingViewingPublicKey,
|
||||
vpk: ViewingPublicKey,
|
||||
},
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ impl PrivacyPreservingAccount {
|
||||
pub fn is_private(&self) -> bool {
|
||||
matches!(
|
||||
&self,
|
||||
Self::PrivateOwned(_) | Self::PrivateForeign { npk: _, ipk: _ }
|
||||
Self::PrivateOwned(_) | Self::PrivateForeign { npk: _, vpk: _ }
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,7 @@ impl PrivacyPreservingAccount {
|
||||
pub struct PrivateAccountKeys {
|
||||
pub npk: NullifierPublicKey,
|
||||
pub ssk: SharedSecretKey,
|
||||
pub ipk: IncomingViewingPublicKey,
|
||||
pub vpk: ViewingPublicKey,
|
||||
pub epk: EphemeralPublicKey,
|
||||
}
|
||||
|
||||
@ -80,13 +80,13 @@ impl AccountManager {
|
||||
|
||||
(State::Private(pre), mask)
|
||||
}
|
||||
PrivacyPreservingAccount::PrivateForeign { npk, ipk } => {
|
||||
PrivacyPreservingAccount::PrivateForeign { npk, vpk } => {
|
||||
let acc = nssa_core::account::Account::default();
|
||||
let auth_acc = AccountWithMetadata::new(acc, false, &npk);
|
||||
let pre = AccountPreparedData {
|
||||
nsk: None,
|
||||
npk,
|
||||
ipk,
|
||||
vpk,
|
||||
pre_state: auth_acc,
|
||||
proof: None,
|
||||
};
|
||||
@ -138,8 +138,8 @@ impl AccountManager {
|
||||
|
||||
Some(PrivateAccountKeys {
|
||||
npk: pre.npk.clone(),
|
||||
ssk: eph_holder.calculate_shared_secret_sender(&pre.ipk),
|
||||
ipk: pre.ipk.clone(),
|
||||
ssk: eph_holder.calculate_shared_secret_sender(&pre.vpk),
|
||||
vpk: pre.vpk.clone(),
|
||||
epk: eph_holder.generate_ephemeral_public_key(),
|
||||
})
|
||||
}
|
||||
@ -192,7 +192,7 @@ impl AccountManager {
|
||||
struct AccountPreparedData {
|
||||
nsk: Option<NullifierSecretKey>,
|
||||
npk: NullifierPublicKey,
|
||||
ipk: IncomingViewingPublicKey,
|
||||
vpk: ViewingPublicKey,
|
||||
pre_state: AccountWithMetadata,
|
||||
proof: Option<MembershipProof>,
|
||||
}
|
||||
@ -213,7 +213,7 @@ async fn private_acc_preparation(
|
||||
let nsk = from_keys.private_key_holder.nullifier_secret_key;
|
||||
|
||||
let from_npk = from_keys.nullifer_public_key;
|
||||
let from_ipk = from_keys.incoming_viewing_public_key;
|
||||
let from_vpk = from_keys.viewing_public_key;
|
||||
|
||||
// TODO: Remove this unwrap, error types must be compatible
|
||||
let proof = wallet
|
||||
@ -228,7 +228,7 @@ async fn private_acc_preparation(
|
||||
Ok(AccountPreparedData {
|
||||
nsk: Some(nsk),
|
||||
npk: from_npk,
|
||||
ipk: from_ipk,
|
||||
vpk: from_vpk,
|
||||
pre_state: sender_pre,
|
||||
proof,
|
||||
})
|
||||
|
||||
@ -20,6 +20,9 @@ fn auth_transfer_preparation(
|
||||
) {
|
||||
let instruction_data = Program::serialize_instruction(balance_to_move).unwrap();
|
||||
let program = Program::authenticated_transfer_program();
|
||||
|
||||
// TODO: handle large Err-variant properly
|
||||
#[allow(clippy::result_large_err)]
|
||||
let tx_pre_check = move |accounts: &[&Account]| {
|
||||
let from = accounts[0];
|
||||
if from.balance >= balance_to_move {
|
||||
|
||||
@ -2,7 +2,7 @@ use std::vec;
|
||||
|
||||
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
|
||||
use nssa::{AccountId, program::Program};
|
||||
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey};
|
||||
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
|
||||
|
||||
use super::{NativeTokenTransfer, auth_transfer_preparation};
|
||||
use crate::PrivacyPreservingAccount;
|
||||
@ -32,7 +32,7 @@ impl NativeTokenTransfer<'_> {
|
||||
&self,
|
||||
from: AccountId,
|
||||
to_npk: NullifierPublicKey,
|
||||
to_ipk: IncomingViewingPublicKey,
|
||||
to_vpk: ViewingPublicKey,
|
||||
balance_to_move: u128,
|
||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||
let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move);
|
||||
@ -43,7 +43,7 @@ impl NativeTokenTransfer<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(from),
|
||||
PrivacyPreservingAccount::PrivateForeign {
|
||||
npk: to_npk,
|
||||
ipk: to_ipk,
|
||||
vpk: to_vpk,
|
||||
},
|
||||
],
|
||||
instruction_data,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
|
||||
use nssa::AccountId;
|
||||
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey};
|
||||
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
|
||||
|
||||
use super::{NativeTokenTransfer, auth_transfer_preparation};
|
||||
use crate::PrivacyPreservingAccount;
|
||||
@ -38,7 +38,7 @@ impl NativeTokenTransfer<'_> {
|
||||
&self,
|
||||
from: AccountId,
|
||||
to_npk: NullifierPublicKey,
|
||||
to_ipk: IncomingViewingPublicKey,
|
||||
to_vpk: ViewingPublicKey,
|
||||
balance_to_move: u128,
|
||||
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||
let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move);
|
||||
@ -49,7 +49,7 @@ impl NativeTokenTransfer<'_> {
|
||||
PrivacyPreservingAccount::Public(from),
|
||||
PrivacyPreservingAccount::PrivateForeign {
|
||||
npk: to_npk,
|
||||
ipk: to_ipk,
|
||||
vpk: to_vpk,
|
||||
},
|
||||
],
|
||||
instruction_data,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
|
||||
use nssa::{AccountId, program::Program};
|
||||
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey};
|
||||
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
|
||||
use token_core::Instruction;
|
||||
|
||||
use crate::{PrivacyPreservingAccount, WalletCore};
|
||||
@ -194,7 +194,7 @@ impl Token<'_> {
|
||||
&self,
|
||||
sender_account_id: AccountId,
|
||||
recipient_npk: NullifierPublicKey,
|
||||
recipient_ipk: IncomingViewingPublicKey,
|
||||
recipient_vpk: ViewingPublicKey,
|
||||
amount: u128,
|
||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||
let instruction = Instruction::Transfer {
|
||||
@ -209,7 +209,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(sender_account_id),
|
||||
PrivacyPreservingAccount::PrivateForeign {
|
||||
npk: recipient_npk,
|
||||
ipk: recipient_ipk,
|
||||
vpk: recipient_vpk,
|
||||
},
|
||||
],
|
||||
instruction_data,
|
||||
@ -290,7 +290,7 @@ impl Token<'_> {
|
||||
&self,
|
||||
sender_account_id: AccountId,
|
||||
recipient_npk: NullifierPublicKey,
|
||||
recipient_ipk: IncomingViewingPublicKey,
|
||||
recipient_vpk: ViewingPublicKey,
|
||||
amount: u128,
|
||||
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||
let instruction = Instruction::Transfer {
|
||||
@ -305,7 +305,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::Public(sender_account_id),
|
||||
PrivacyPreservingAccount::PrivateForeign {
|
||||
npk: recipient_npk,
|
||||
ipk: recipient_ipk,
|
||||
vpk: recipient_vpk,
|
||||
},
|
||||
],
|
||||
instruction_data,
|
||||
@ -525,7 +525,7 @@ impl Token<'_> {
|
||||
&self,
|
||||
definition_account_id: AccountId,
|
||||
holder_npk: NullifierPublicKey,
|
||||
holder_ipk: IncomingViewingPublicKey,
|
||||
holder_vpk: ViewingPublicKey,
|
||||
amount: u128,
|
||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||
let instruction = Instruction::Mint {
|
||||
@ -540,7 +540,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
|
||||
PrivacyPreservingAccount::PrivateForeign {
|
||||
npk: holder_npk,
|
||||
ipk: holder_ipk,
|
||||
vpk: holder_vpk,
|
||||
},
|
||||
],
|
||||
instruction_data,
|
||||
@ -621,7 +621,7 @@ impl Token<'_> {
|
||||
&self,
|
||||
definition_account_id: AccountId,
|
||||
holder_npk: NullifierPublicKey,
|
||||
holder_ipk: IncomingViewingPublicKey,
|
||||
holder_vpk: ViewingPublicKey,
|
||||
amount: u128,
|
||||
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||
let instruction = Instruction::Mint {
|
||||
@ -636,7 +636,7 @@ impl Token<'_> {
|
||||
PrivacyPreservingAccount::Public(definition_account_id),
|
||||
PrivacyPreservingAccount::PrivateForeign {
|
||||
npk: holder_npk,
|
||||
ipk: holder_ipk,
|
||||
vpk: holder_vpk,
|
||||
},
|
||||
],
|
||||
instruction_data,
|
||||
|
||||
@ -7,7 +7,7 @@ use nssa::{
|
||||
};
|
||||
use nssa_core::{
|
||||
Commitment, MembershipProof, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
|
||||
account::AccountWithMetadata, encryption::IncomingViewingPublicKey, program::InstructionData,
|
||||
account::AccountWithMetadata, encryption::ViewingPublicKey, program::InstructionData,
|
||||
};
|
||||
|
||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
||||
@ -15,7 +15,7 @@ use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
||||
pub(crate) struct AccountPreparedData {
|
||||
pub nsk: Option<NullifierSecretKey>,
|
||||
pub npk: NullifierPublicKey,
|
||||
pub ipk: IncomingViewingPublicKey,
|
||||
pub vpk: ViewingPublicKey,
|
||||
pub auth_acc: AccountWithMetadata,
|
||||
pub proof: Option<MembershipProof>,
|
||||
}
|
||||
@ -40,7 +40,7 @@ impl WalletCore {
|
||||
let mut proof = None;
|
||||
|
||||
let from_npk = from_keys.nullifer_public_key;
|
||||
let from_ipk = from_keys.incoming_viewing_public_key;
|
||||
let from_vpk = from_keys.viewing_public_key;
|
||||
|
||||
let sender_commitment = Commitment::new(&from_npk, &from_acc);
|
||||
|
||||
@ -61,7 +61,7 @@ impl WalletCore {
|
||||
Ok(AccountPreparedData {
|
||||
nsk,
|
||||
npk: from_npk,
|
||||
ipk: from_ipk,
|
||||
vpk: from_vpk,
|
||||
auth_acc: sender_pre,
|
||||
proof,
|
||||
})
|
||||
@ -79,7 +79,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: from_nsk,
|
||||
npk: from_npk,
|
||||
ipk: from_ipk,
|
||||
vpk: from_vpk,
|
||||
auth_acc: sender_pre,
|
||||
proof: from_proof,
|
||||
} = self.private_acc_preparation(from, true, true).await?;
|
||||
@ -87,7 +87,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: to_nsk,
|
||||
npk: to_npk,
|
||||
ipk: to_ipk,
|
||||
vpk: to_vpk,
|
||||
auth_acc: recipient_pre,
|
||||
proof: _,
|
||||
} = self.private_acc_preparation(to, true, false).await?;
|
||||
@ -95,10 +95,10 @@ impl WalletCore {
|
||||
tx_pre_check(&sender_pre.account, &recipient_pre.account)?;
|
||||
|
||||
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
|
||||
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
|
||||
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_vpk);
|
||||
|
||||
let eph_holder_to = EphemeralKeyHolder::new(&to_npk);
|
||||
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_ipk);
|
||||
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_vpk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
@ -123,12 +123,12 @@ impl WalletCore {
|
||||
vec![
|
||||
(
|
||||
from_npk.clone(),
|
||||
from_ipk.clone(),
|
||||
from_vpk.clone(),
|
||||
eph_holder_from.generate_ephemeral_public_key(),
|
||||
),
|
||||
(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
to_vpk.clone(),
|
||||
eph_holder_to.generate_ephemeral_public_key(),
|
||||
),
|
||||
],
|
||||
@ -156,7 +156,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: from_nsk,
|
||||
npk: from_npk,
|
||||
ipk: from_ipk,
|
||||
vpk: from_vpk,
|
||||
auth_acc: sender_pre,
|
||||
proof: from_proof,
|
||||
} = self.private_acc_preparation(from, true, true).await?;
|
||||
@ -164,7 +164,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: _,
|
||||
npk: to_npk,
|
||||
ipk: to_ipk,
|
||||
vpk: to_vpk,
|
||||
auth_acc: recipient_pre,
|
||||
proof: _,
|
||||
} = self.private_acc_preparation(to, false, false).await?;
|
||||
@ -172,10 +172,10 @@ impl WalletCore {
|
||||
tx_pre_check(&sender_pre.account, &recipient_pre.account)?;
|
||||
|
||||
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
|
||||
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
|
||||
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_vpk);
|
||||
|
||||
let eph_holder_to = EphemeralKeyHolder::new(&to_npk);
|
||||
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_ipk);
|
||||
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_vpk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
@ -197,12 +197,12 @@ impl WalletCore {
|
||||
vec![
|
||||
(
|
||||
from_npk.clone(),
|
||||
from_ipk.clone(),
|
||||
from_vpk.clone(),
|
||||
eph_holder_from.generate_ephemeral_public_key(),
|
||||
),
|
||||
(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
to_vpk.clone(),
|
||||
eph_holder_to.generate_ephemeral_public_key(),
|
||||
),
|
||||
],
|
||||
@ -223,7 +223,7 @@ impl WalletCore {
|
||||
&self,
|
||||
from: AccountId,
|
||||
to_npk: NullifierPublicKey,
|
||||
to_ipk: IncomingViewingPublicKey,
|
||||
to_vpk: ViewingPublicKey,
|
||||
instruction_data: InstructionData,
|
||||
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||
program: Program,
|
||||
@ -231,7 +231,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: from_nsk,
|
||||
npk: from_npk,
|
||||
ipk: from_ipk,
|
||||
vpk: from_vpk,
|
||||
auth_acc: sender_pre,
|
||||
proof: from_proof,
|
||||
} = self.private_acc_preparation(from, true, true).await?;
|
||||
@ -244,8 +244,8 @@ impl WalletCore {
|
||||
|
||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||
|
||||
let shared_secret_from = eph_holder.calculate_shared_secret_sender(&from_ipk);
|
||||
let shared_secret_to = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||
let shared_secret_from = eph_holder.calculate_shared_secret_sender(&from_vpk);
|
||||
let shared_secret_to = eph_holder.calculate_shared_secret_sender(&to_vpk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
@ -267,12 +267,12 @@ impl WalletCore {
|
||||
vec![
|
||||
(
|
||||
from_npk.clone(),
|
||||
from_ipk.clone(),
|
||||
from_vpk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
),
|
||||
(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
to_vpk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
),
|
||||
],
|
||||
@ -301,7 +301,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: from_nsk,
|
||||
npk: from_npk,
|
||||
ipk: from_ipk,
|
||||
vpk: from_vpk,
|
||||
auth_acc: sender_pre,
|
||||
proof: from_proof,
|
||||
} = self.private_acc_preparation(from, true, true).await?;
|
||||
@ -315,7 +315,7 @@ impl WalletCore {
|
||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, to);
|
||||
|
||||
let eph_holder = EphemeralKeyHolder::new(&from_npk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&from_ipk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&from_vpk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
@ -333,7 +333,7 @@ impl WalletCore {
|
||||
vec![],
|
||||
vec![(
|
||||
from_npk.clone(),
|
||||
from_ipk.clone(),
|
||||
from_vpk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
@ -366,7 +366,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: to_nsk,
|
||||
npk: to_npk,
|
||||
ipk: to_ipk,
|
||||
vpk: to_vpk,
|
||||
auth_acc: recipient_pre,
|
||||
proof: _,
|
||||
} = self.private_acc_preparation(to, true, false).await?;
|
||||
@ -376,7 +376,7 @@ impl WalletCore {
|
||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
||||
|
||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_vpk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
@ -394,7 +394,7 @@ impl WalletCore {
|
||||
vec![from_acc.nonce],
|
||||
vec![(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
to_vpk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
@ -432,7 +432,7 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: _,
|
||||
npk: to_npk,
|
||||
ipk: to_ipk,
|
||||
vpk: to_vpk,
|
||||
auth_acc: recipient_pre,
|
||||
proof: _,
|
||||
} = self.private_acc_preparation(to, false, false).await?;
|
||||
@ -442,7 +442,7 @@ impl WalletCore {
|
||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
||||
|
||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_vpk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
@ -460,7 +460,7 @@ impl WalletCore {
|
||||
vec![from_acc.nonce],
|
||||
vec![(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
to_vpk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
@ -487,7 +487,7 @@ impl WalletCore {
|
||||
&self,
|
||||
from: AccountId,
|
||||
to_npk: NullifierPublicKey,
|
||||
to_ipk: IncomingViewingPublicKey,
|
||||
to_vpk: ViewingPublicKey,
|
||||
instruction_data: InstructionData,
|
||||
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||
program: Program,
|
||||
@ -504,7 +504,7 @@ impl WalletCore {
|
||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
|
||||
|
||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_vpk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
@ -522,7 +522,7 @@ impl WalletCore {
|
||||
vec![from_acc.nonce],
|
||||
vec![(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
to_vpk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
@ -548,13 +548,13 @@ impl WalletCore {
|
||||
let AccountPreparedData {
|
||||
nsk: _,
|
||||
npk: from_npk,
|
||||
ipk: from_ipk,
|
||||
vpk: from_vpk,
|
||||
auth_acc: sender_pre,
|
||||
proof: _,
|
||||
} = self.private_acc_preparation(from, false, false).await?;
|
||||
|
||||
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
|
||||
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
|
||||
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_vpk);
|
||||
|
||||
let instruction: u128 = 0;
|
||||
|
||||
@ -574,7 +574,7 @@ impl WalletCore {
|
||||
vec![],
|
||||
vec![(
|
||||
from_npk.clone(),
|
||||
from_ipk.clone(),
|
||||
from_vpk.clone(),
|
||||
eph_holder_from.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user