mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-05 06:43:08 +00:00
Merge pull request #119 from vacp2p/schouhy/wallet-minor-improvements
Wallet improvements
This commit is contained in:
commit
e101a9311c
@ -17,12 +17,7 @@ log.workspace = true
|
||||
elliptic-curve.workspace = true
|
||||
hex.workspace = true
|
||||
nssa-core = { path = "../nssa/core", features = ["host"] }
|
||||
|
||||
borsh.workspace = true
|
||||
|
||||
[dependencies.secp256k1-zkp]
|
||||
workspace = true
|
||||
features = ["std", "rand-std", "rand", "serde", "global-context"]
|
||||
|
||||
[dependencies.nssa]
|
||||
path = "../nssa"
|
||||
|
||||
@ -54,7 +54,7 @@ pub struct GetAccountRequest {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct GetProofByCommitmentRequest {
|
||||
pub struct GetProofForCommitmentRequest {
|
||||
pub commitment: nssa_core::Commitment,
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ parse_request!(GetInitialTestnetAccountsRequest);
|
||||
parse_request!(GetAccountBalanceRequest);
|
||||
parse_request!(GetTransactionByHashRequest);
|
||||
parse_request!(GetAccountsNoncesRequest);
|
||||
parse_request!(GetProofByCommitmentRequest);
|
||||
parse_request!(GetProofForCommitmentRequest);
|
||||
parse_request!(GetAccountRequest);
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
@ -123,6 +123,6 @@ pub struct GetAccountResponse {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct GetProofByCommitmentResponse {
|
||||
pub struct GetProofForCommitmentResponse {
|
||||
pub membership_proof: Option<nssa_core::MembershipProof>,
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ use serde_json::Value;
|
||||
|
||||
use crate::rpc_primitives::requests::{
|
||||
GetAccountRequest, GetAccountResponse, GetAccountsNoncesRequest, GetAccountsNoncesResponse,
|
||||
GetProofByCommitmentRequest, GetProofByCommitmentResponse, GetTransactionByHashRequest,
|
||||
GetProofForCommitmentRequest, GetProofForCommitmentResponse, GetTransactionByHashRequest,
|
||||
GetTransactionByHashResponse,
|
||||
};
|
||||
use crate::sequencer_client::json::AccountInitialData;
|
||||
@ -222,7 +222,7 @@ impl SequencerClient {
|
||||
&self,
|
||||
commitment: nssa_core::Commitment,
|
||||
) -> Result<Option<nssa_core::MembershipProof>, SequencerClientError> {
|
||||
let acc_req = GetProofByCommitmentRequest { commitment };
|
||||
let acc_req = GetProofForCommitmentRequest { commitment };
|
||||
|
||||
let req = serde_json::to_value(acc_req).unwrap();
|
||||
|
||||
@ -231,7 +231,7 @@ impl SequencerClient {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let resp_deser = serde_json::from_value::<GetProofByCommitmentResponse>(resp)
|
||||
let resp_deser = serde_json::from_value::<GetProofForCommitmentResponse>(resp)
|
||||
.unwrap()
|
||||
.membership_proof;
|
||||
|
||||
|
||||
@ -8,12 +8,12 @@ anyhow.workspace = true
|
||||
env_logger.workspace = true
|
||||
log.workspace = true
|
||||
actix.workspace = true
|
||||
bytemuck = "1.23.2"
|
||||
|
||||
actix-web.workspace = true
|
||||
base64.workspace = true
|
||||
tokio.workspace = true
|
||||
hex.workspace = true
|
||||
tempfile.workspace = true
|
||||
borsh.workspace = true
|
||||
|
||||
nssa-core = { path = "../nssa/core", features = ["host"] }
|
||||
|
||||
|
||||
@ -8,11 +8,11 @@
|
||||
"port": 3040,
|
||||
"initial_accounts": [
|
||||
{
|
||||
"addr": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
|
||||
"addr": "0eee24287296ba55278f1e5403be014754866366388730303c2889be17ada065",
|
||||
"balance": 10000
|
||||
},
|
||||
{
|
||||
"addr": "4d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766",
|
||||
"addr": "9e3d8e654d440e95293aa2dceceb137899a59535e952f747068e7a0ee30965f2",
|
||||
"balance": 20000
|
||||
}
|
||||
],
|
||||
@ -154,4 +154,4 @@
|
||||
37,
|
||||
37
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
"initial_accounts": [
|
||||
{
|
||||
"Public": {
|
||||
"address": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
|
||||
"address": "0eee24287296ba55278f1e5403be014754866366388730303c2889be17ada065",
|
||||
"pub_sign_key": [
|
||||
1,
|
||||
1,
|
||||
@ -48,7 +48,7 @@
|
||||
},
|
||||
{
|
||||
"Public": {
|
||||
"address": "4d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766",
|
||||
"address": "9e3d8e654d440e95293aa2dceceb137899a59535e952f747068e7a0ee30965f2",
|
||||
"pub_sign_key": [
|
||||
2,
|
||||
2,
|
||||
@ -87,7 +87,7 @@
|
||||
},
|
||||
{
|
||||
"Private": {
|
||||
"address": "6ffe0893c4b2c956fdb769b11fe4e3b2dd36ac4bd0ad90c810844051747c8c04",
|
||||
"address": "9cb6b0035320266e430eac9d96745769e7efcf30d2b9cc21ff000b3f873dc2a8",
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
@ -316,7 +316,7 @@
|
||||
},
|
||||
{
|
||||
"Private": {
|
||||
"address": "4ee9de60e33da96fd72929f1485fb365bcc9c1634dd44e4ba55b1ab96692674b",
|
||||
"address": "a55f4f98d2f265c91d8a9868564242d8070b9bf7180a29363f52eb76988636fd",
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
@ -544,4 +544,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,18 @@
|
||||
use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
|
||||
use std::{path::PathBuf, time::Duration};
|
||||
|
||||
use actix_web::dev::ServerHandle;
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use common::sequencer_client::SequencerClient;
|
||||
use common::{
|
||||
sequencer_client::SequencerClient,
|
||||
transaction::{EncodedTransaction, NSSATransaction},
|
||||
};
|
||||
use log::{info, warn};
|
||||
use nssa::program::Program;
|
||||
use nssa_core::{NullifierPublicKey, encryption::shared_key_derivation::Secp256k1Point};
|
||||
use nssa::{Address, PrivacyPreservingTransaction, program::Program};
|
||||
use nssa_core::{
|
||||
Commitment, NullifierPublicKey, encryption::shared_key_derivation::Secp256k1Point,
|
||||
};
|
||||
use sequencer_core::config::SequencerConfig;
|
||||
use sequencer_runner::startup_sequencer;
|
||||
use tempfile::TempDir;
|
||||
@ -14,7 +20,7 @@ use tokio::task::JoinHandle;
|
||||
use wallet::{
|
||||
Command, SubcommandReturnValue, WalletCore,
|
||||
config::PersistentAccountData,
|
||||
helperfunctions::{fetch_config, fetch_persistent_accounts, produce_account_addr_from_hex},
|
||||
helperfunctions::{fetch_config, fetch_persistent_accounts},
|
||||
};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
@ -26,13 +32,13 @@ struct Args {
|
||||
test_name: String,
|
||||
}
|
||||
|
||||
pub const ACC_SENDER: &str = "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f";
|
||||
pub const ACC_RECEIVER: &str = "4d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766";
|
||||
pub const ACC_SENDER: &str = "0eee24287296ba55278f1e5403be014754866366388730303c2889be17ada065";
|
||||
pub const ACC_RECEIVER: &str = "9e3d8e654d440e95293aa2dceceb137899a59535e952f747068e7a0ee30965f2";
|
||||
|
||||
pub const ACC_SENDER_PRIVATE: &str =
|
||||
"6ffe0893c4b2c956fdb769b11fe4e3b2dd36ac4bd0ad90c810844051747c8c04";
|
||||
"9cb6b0035320266e430eac9d96745769e7efcf30d2b9cc21ff000b3f873dc2a8";
|
||||
pub const ACC_RECEIVER_PRIVATE: &str =
|
||||
"4ee9de60e33da96fd72929f1485fb365bcc9c1634dd44e4ba55b1ab96692674b";
|
||||
"a55f4f98d2f265c91d8a9868564242d8070b9bf7180a29363f52eb76988636fd";
|
||||
|
||||
pub const TIME_TO_WAIT_FOR_BLOCK_SECONDS: u64 = 12;
|
||||
|
||||
@ -389,10 +395,7 @@ pub async fn test_success_token_program() {
|
||||
// Bytes from 1 to 33 represent the id of the token this account is associated with.
|
||||
// In this example, this is a token account of the newly created token, so it is expected
|
||||
// to be equal to the address of the token definition account.
|
||||
assert_eq!(
|
||||
&supply_acc.data[1..33],
|
||||
nssa::AccountId::from(&definition_addr).to_bytes()
|
||||
);
|
||||
assert_eq!(&supply_acc.data[1..33], definition_addr.to_bytes());
|
||||
assert_eq!(
|
||||
u128::from_le_bytes(supply_acc.data[33..].try_into().unwrap()),
|
||||
37
|
||||
@ -419,10 +422,7 @@ pub async fn test_success_token_program() {
|
||||
// First byte equal to 1 means it's a token holding account
|
||||
assert_eq!(supply_acc.data[0], 1);
|
||||
// Bytes from 1 to 33 represent the id of the token this account is associated with.
|
||||
assert_eq!(
|
||||
&supply_acc.data[1..33],
|
||||
nssa::AccountId::from(&definition_addr).to_bytes()
|
||||
);
|
||||
assert_eq!(&supply_acc.data[1..33], definition_addr.to_bytes());
|
||||
assert_eq!(
|
||||
u128::from_le_bytes(supply_acc.data[33..].try_into().unwrap()),
|
||||
30
|
||||
@ -440,10 +440,7 @@ pub async fn test_success_token_program() {
|
||||
// First byte equal to 1 means it's a token holding account
|
||||
assert_eq!(recipient_acc.data[0], 1);
|
||||
// Bytes from 1 to 33 represent the id of the token this account is associated with.
|
||||
assert_eq!(
|
||||
&recipient_acc.data[1..33],
|
||||
nssa::AccountId::from(&definition_addr).to_bytes()
|
||||
);
|
||||
assert_eq!(&recipient_acc.data[1..33], definition_addr.to_bytes());
|
||||
assert_eq!(
|
||||
u128::from_le_bytes(recipient_acc.data[33..].try_into().unwrap()),
|
||||
7
|
||||
@ -452,159 +449,118 @@ pub async fn test_success_token_program() {
|
||||
|
||||
pub async fn test_success_private_transfer_to_another_owned_account() {
|
||||
info!("test_success_private_transfer_to_another_owned_account");
|
||||
let command = Command::SendNativeTokenTransferPrivate {
|
||||
from: ACC_SENDER_PRIVATE.to_string(),
|
||||
to: ACC_RECEIVER_PRIVATE.to_string(),
|
||||
let from: Address = ACC_SENDER_PRIVATE.parse().unwrap();
|
||||
let to: Address = ACC_RECEIVER_PRIVATE.parse().unwrap();
|
||||
|
||||
let command = Command::SendNativeTokenTransferPrivateOwnedAccount {
|
||||
from: from.to_string(),
|
||||
to: to.to_string(),
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
let from = produce_account_addr_from_hex(ACC_SENDER_PRIVATE.to_string()).unwrap();
|
||||
let to = produce_account_addr_from_hex(ACC_RECEIVER_PRIVATE.to_string()).unwrap();
|
||||
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
|
||||
let mut wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } =
|
||||
wallet::execute_subcommand(command).await.unwrap()
|
||||
else {
|
||||
panic!("invalid subcommand return value");
|
||||
};
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let new_commitment1 = {
|
||||
let from_acc = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.get_private_account_mut(&from)
|
||||
.unwrap();
|
||||
|
||||
from_acc.1.program_owner = nssa::program::Program::authenticated_transfer_program().id();
|
||||
from_acc.1.balance -= 100;
|
||||
from_acc.1.nonce += 1;
|
||||
|
||||
nssa_core::Commitment::new(&from_acc.0.nullifer_public_key, &from_acc.1)
|
||||
let command = Command::FetchPrivateAccount {
|
||||
tx_hash: tx_hash.clone(),
|
||||
acc_addr: from.to_string(),
|
||||
output_id: 0,
|
||||
};
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
let new_commitment2 = {
|
||||
let to_acc = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.get_private_account_mut(&to)
|
||||
.unwrap();
|
||||
|
||||
to_acc.1.program_owner = nssa::program::Program::authenticated_transfer_program().id();
|
||||
to_acc.1.balance += 100;
|
||||
to_acc.1.nonce += 1;
|
||||
|
||||
nssa_core::Commitment::new(&to_acc.0.nullifer_public_key, &to_acc.1)
|
||||
let command = Command::FetchPrivateAccount {
|
||||
tx_hash,
|
||||
acc_addr: to.to_string(),
|
||||
output_id: 1,
|
||||
};
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
let proof1 = seq_client
|
||||
.get_proof_for_commitment(new_commitment1)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let proof2 = seq_client
|
||||
.get_proof_for_commitment(new_commitment2)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
|
||||
println!("New proof is {proof1:#?}");
|
||||
println!("New proof is {proof2:#?}");
|
||||
let new_commitment1 = wallet_storage
|
||||
.get_private_account_commitment(&from)
|
||||
.unwrap();
|
||||
assert!(verify_commitment_is_in_state(new_commitment1, &seq_client).await);
|
||||
|
||||
let new_commitment2 = wallet_storage.get_private_account_commitment(&to).unwrap();
|
||||
assert!(verify_commitment_is_in_state(new_commitment2, &seq_client).await);
|
||||
|
||||
info!("Success!");
|
||||
}
|
||||
|
||||
pub async fn test_success_private_transfer_to_another_foreign_account() {
|
||||
info!("test_success_private_transfer_to_another_foreign_account");
|
||||
let to_npk_orig = NullifierPublicKey([42; 32]);
|
||||
let to_npk = hex::encode(to_npk_orig.0);
|
||||
let to_ipk = Secp256k1Point::from_scalar(to_npk_orig.0);
|
||||
let from: Address = ACC_SENDER_PRIVATE.parse().unwrap();
|
||||
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 command = Command::SendNativeTokenTransferPrivateForeignAccount {
|
||||
from: ACC_SENDER_PRIVATE.to_string(),
|
||||
to_npk,
|
||||
from: from.to_string(),
|
||||
to_npk: to_npk_string,
|
||||
to_ipk: hex::encode(to_ipk.0),
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
let from = produce_account_addr_from_hex(ACC_SENDER_PRIVATE.to_string()).unwrap();
|
||||
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
|
||||
let mut wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
|
||||
let sub_ret = wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
println!("SUB RET is {sub_ret:#?}");
|
||||
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } =
|
||||
wallet::execute_subcommand(command).await.unwrap()
|
||||
else {
|
||||
panic!("invalid subcommand return value");
|
||||
};
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let new_commitment1 = {
|
||||
let from_acc = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.get_private_account_mut(&from)
|
||||
.unwrap();
|
||||
|
||||
from_acc.1.program_owner = nssa::program::Program::authenticated_transfer_program().id();
|
||||
from_acc.1.balance -= 100;
|
||||
from_acc.1.nonce += 1;
|
||||
|
||||
nssa_core::Commitment::new(&from_acc.0.nullifer_public_key, &from_acc.1)
|
||||
let command = Command::FetchPrivateAccount {
|
||||
tx_hash: tx_hash.clone(),
|
||||
acc_addr: from.to_string(),
|
||||
output_id: 0,
|
||||
};
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
let new_commitment2 = {
|
||||
let to_acc = nssa_core::account::Account {
|
||||
program_owner: nssa::program::Program::authenticated_transfer_program().id(),
|
||||
balance: 100,
|
||||
data: vec![],
|
||||
nonce: 1,
|
||||
};
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
|
||||
nssa_core::Commitment::new(&to_npk_orig, &to_acc)
|
||||
};
|
||||
|
||||
let proof1 = seq_client
|
||||
.get_proof_for_commitment(new_commitment1)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let proof2 = seq_client
|
||||
.get_proof_for_commitment(new_commitment2)
|
||||
.await
|
||||
.unwrap()
|
||||
let new_commitment1 = wallet_storage
|
||||
.get_private_account_commitment(&from)
|
||||
.unwrap();
|
||||
|
||||
println!("New proof is {proof1:#?}");
|
||||
println!("New proof is {proof2:#?}");
|
||||
let tx = fetch_privacy_preserving_tx(&seq_client, tx_hash.clone()).await;
|
||||
assert_eq!(tx.message.new_commitments[0], new_commitment1);
|
||||
|
||||
assert_eq!(tx.message.new_commitments.len(), 2);
|
||||
for commitment in tx.message.new_commitments.into_iter() {
|
||||
assert!(verify_commitment_is_in_state(commitment, &seq_client).await);
|
||||
}
|
||||
|
||||
info!("Success!");
|
||||
}
|
||||
|
||||
pub async fn test_success_private_transfer_to_another_owned_account_claiming_path() {
|
||||
info!("test_success_private_transfer_to_another_owned_account_claiming_path");
|
||||
let from: Address = ACC_SENDER_PRIVATE.parse().unwrap();
|
||||
|
||||
let command = Command::RegisterAccountPrivate {};
|
||||
|
||||
let sub_ret = wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
let SubcommandReturnValue::RegisterAccount { addr: to_addr } = sub_ret else {
|
||||
panic!("FAILED TO REGISTER ACCOUNT");
|
||||
};
|
||||
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config.clone()).unwrap();
|
||||
|
||||
let mut wallet_storage =
|
||||
WalletCore::start_from_config_update_chain(wallet_config.clone()).unwrap();
|
||||
|
||||
let (to_keys, mut to_acc) = wallet_storage
|
||||
let (to_keys, _) = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.user_private_accounts
|
||||
@ -613,74 +569,38 @@ pub async fn test_success_private_transfer_to_another_owned_account_claiming_pat
|
||||
.unwrap();
|
||||
|
||||
let command = Command::SendNativeTokenTransferPrivateForeignAccount {
|
||||
from: ACC_SENDER_PRIVATE.to_string(),
|
||||
from: from.to_string(),
|
||||
to_npk: hex::encode(to_keys.nullifer_public_key.0),
|
||||
to_ipk: hex::encode(to_keys.incoming_viewing_public_key.0),
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
let from = produce_account_addr_from_hex(ACC_SENDER_PRIVATE.to_string()).unwrap();
|
||||
|
||||
let sub_ret = wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = sub_ret else {
|
||||
panic!("FAILED TO SEND TX");
|
||||
};
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
let tx = fetch_privacy_preserving_tx(&seq_client, tx_hash.clone()).await;
|
||||
|
||||
let new_commitment1 = {
|
||||
let from_acc = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.get_private_account_mut(&from)
|
||||
.unwrap();
|
||||
|
||||
from_acc.1.program_owner = nssa::program::Program::authenticated_transfer_program().id();
|
||||
from_acc.1.balance -= 100;
|
||||
from_acc.1.nonce += 1;
|
||||
|
||||
nssa_core::Commitment::new(&from_acc.0.nullifer_public_key, &from_acc.1)
|
||||
};
|
||||
|
||||
let new_commitment2 = {
|
||||
to_acc.program_owner = nssa::program::Program::authenticated_transfer_program().id();
|
||||
to_acc.balance = 100;
|
||||
to_acc.nonce = 1;
|
||||
|
||||
nssa_core::Commitment::new(&to_keys.nullifer_public_key, &to_acc)
|
||||
};
|
||||
|
||||
let proof1 = seq_client
|
||||
.get_proof_for_commitment(new_commitment1)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let proof2 = seq_client
|
||||
.get_proof_for_commitment(new_commitment2)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
println!("New proof is {proof1:#?}");
|
||||
println!("New proof is {proof2:#?}");
|
||||
|
||||
let command = Command::ClaimPrivateAccount {
|
||||
let command = Command::FetchPrivateAccount {
|
||||
tx_hash,
|
||||
acc_addr: hex::encode(to_addr),
|
||||
ciph_id: 1,
|
||||
acc_addr: to_addr.to_string(),
|
||||
output_id: 1,
|
||||
};
|
||||
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
|
||||
let (_, to_res_acc) = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.get_private_account(&to_addr)
|
||||
let new_commitment1 = wallet_storage
|
||||
.get_private_account_commitment(&from)
|
||||
.unwrap();
|
||||
assert_eq!(tx.message.new_commitments[0], new_commitment1);
|
||||
|
||||
assert_eq!(tx.message.new_commitments.len(), 2);
|
||||
for commitment in tx.message.new_commitments.into_iter() {
|
||||
assert!(verify_commitment_is_in_state(commitment, &seq_client).await);
|
||||
}
|
||||
|
||||
let to_res_acc = wallet_storage.get_account_private(&to_addr).unwrap();
|
||||
|
||||
assert_eq!(to_res_acc.balance, 100);
|
||||
|
||||
@ -689,51 +609,50 @@ pub async fn test_success_private_transfer_to_another_owned_account_claiming_pat
|
||||
|
||||
pub async fn test_success_deshielded_transfer_to_another_account() {
|
||||
info!("test_success_deshielded_transfer_to_another_account");
|
||||
let from: Address = ACC_SENDER_PRIVATE.parse().unwrap();
|
||||
let to: Address = ACC_RECEIVER.parse().unwrap();
|
||||
let command = Command::SendNativeTokenTransferDeshielded {
|
||||
from: ACC_SENDER_PRIVATE.to_string(),
|
||||
to: ACC_RECEIVER.to_string(),
|
||||
from: from.to_string(),
|
||||
to: to.to_string(),
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
let from = produce_account_addr_from_hex(ACC_SENDER_PRIVATE.to_string()).unwrap();
|
||||
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config.clone()).unwrap();
|
||||
|
||||
let mut wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
let from_acc = wallet_storage.get_account_private(&from).unwrap();
|
||||
assert_eq!(from_acc.balance, 10000);
|
||||
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } =
|
||||
wallet::execute_subcommand(command).await.unwrap()
|
||||
else {
|
||||
panic!("invalid subcommand return value");
|
||||
};
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let new_commitment1 = {
|
||||
let from_acc = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.get_private_account_mut(&from)
|
||||
.unwrap();
|
||||
|
||||
from_acc.1.program_owner = nssa::program::Program::authenticated_transfer_program().id();
|
||||
from_acc.1.balance -= 100;
|
||||
from_acc.1.nonce += 1;
|
||||
|
||||
nssa_core::Commitment::new(&from_acc.0.nullifer_public_key, &from_acc.1)
|
||||
let command = Command::FetchPrivateAccount {
|
||||
tx_hash,
|
||||
acc_addr: from.to_string(),
|
||||
output_id: 0,
|
||||
};
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
|
||||
let proof1 = seq_client
|
||||
.get_proof_for_commitment(new_commitment1)
|
||||
.await
|
||||
.unwrap()
|
||||
let from_acc = wallet_storage.get_account_private(&from).unwrap();
|
||||
let new_commitment = wallet_storage
|
||||
.get_private_account_commitment(&from)
|
||||
.unwrap();
|
||||
assert!(verify_commitment_is_in_state(new_commitment, &seq_client).await);
|
||||
|
||||
let acc_2_balance = seq_client
|
||||
.get_account_balance(ACC_RECEIVER.to_string())
|
||||
.get_account_balance(to.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("New proof is {proof1:#?}");
|
||||
assert_eq!(from_acc.balance, 10000 - 100);
|
||||
assert_eq!(acc_2_balance.balance, 20100);
|
||||
|
||||
info!("Success!");
|
||||
@ -741,66 +660,59 @@ pub async fn test_success_deshielded_transfer_to_another_account() {
|
||||
|
||||
pub async fn test_success_shielded_transfer_to_another_owned_account() {
|
||||
info!("test_success_shielded_transfer_to_another_owned_account");
|
||||
let from: Address = ACC_SENDER.parse().unwrap();
|
||||
let to: Address = ACC_RECEIVER_PRIVATE.parse().unwrap();
|
||||
let command = Command::SendNativeTokenTransferShielded {
|
||||
from: ACC_SENDER.to_string(),
|
||||
to: ACC_RECEIVER_PRIVATE.to_string(),
|
||||
from: from.to_string(),
|
||||
to: to.to_string(),
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
let to = produce_account_addr_from_hex(ACC_RECEIVER_PRIVATE.to_string()).unwrap();
|
||||
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
|
||||
let mut wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } =
|
||||
wallet::execute_subcommand(command).await.unwrap()
|
||||
else {
|
||||
panic!("invalid subcommand return value");
|
||||
};
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let new_commitment2 = {
|
||||
let to_acc = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.get_private_account_mut(&to)
|
||||
.unwrap();
|
||||
|
||||
to_acc.1.program_owner = nssa::program::Program::authenticated_transfer_program().id();
|
||||
to_acc.1.balance += 100;
|
||||
to_acc.1.nonce += 1;
|
||||
|
||||
nssa_core::Commitment::new(&to_acc.0.nullifer_public_key, &to_acc.1)
|
||||
let command = Command::FetchPrivateAccount {
|
||||
tx_hash,
|
||||
acc_addr: to.to_string(),
|
||||
output_id: 0,
|
||||
};
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
|
||||
let acc_1_balance = seq_client
|
||||
.get_account_balance(ACC_SENDER.to_string())
|
||||
let acc_to = wallet_storage.get_account_private(&to).unwrap();
|
||||
let new_commitment = wallet_storage.get_private_account_commitment(&to).unwrap();
|
||||
assert!(verify_commitment_is_in_state(new_commitment, &seq_client).await);
|
||||
|
||||
let acc_from_balance = seq_client
|
||||
.get_account_balance(from.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let proof2 = seq_client
|
||||
.get_proof_for_commitment(new_commitment2)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(acc_1_balance.balance, 9900);
|
||||
|
||||
println!("New proof is {proof2:#?}");
|
||||
assert_eq!(acc_from_balance.balance, 9900);
|
||||
assert_eq!(acc_to.balance, 20000 + 100);
|
||||
|
||||
info!("Success!");
|
||||
}
|
||||
|
||||
pub async fn test_success_shielded_transfer_to_another_foreign_account() {
|
||||
info!("test_success_shielded_transfer_to_another_foreign_account");
|
||||
let to_npk_orig = NullifierPublicKey([42; 32]);
|
||||
let to_npk = hex::encode(to_npk_orig.0);
|
||||
let to_ipk = Secp256k1Point::from_scalar(to_npk_orig.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 from: Address = ACC_SENDER.parse().unwrap();
|
||||
|
||||
let command = Command::SendNativeTokenTransferShieldedForeignAccount {
|
||||
from: ACC_SENDER.to_string(),
|
||||
to_npk,
|
||||
from: from.to_string(),
|
||||
to_npk: to_npk_string,
|
||||
to_ipk: hex::encode(to_ipk.0),
|
||||
amount: 100,
|
||||
};
|
||||
@ -809,118 +721,27 @@ pub async fn test_success_shielded_transfer_to_another_foreign_account() {
|
||||
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let new_commitment2 = {
|
||||
let to_acc = nssa_core::account::Account {
|
||||
program_owner: nssa::program::Program::authenticated_transfer_program().id(),
|
||||
balance: 100,
|
||||
data: vec![],
|
||||
nonce: 1,
|
||||
};
|
||||
|
||||
nssa_core::Commitment::new(&to_npk_orig, &to_acc)
|
||||
};
|
||||
|
||||
let acc_1_balance = seq_client
|
||||
.get_account_balance(ACC_SENDER.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let proof2 = seq_client
|
||||
.get_proof_for_commitment(new_commitment2)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(acc_1_balance.balance, 9900);
|
||||
println!("New proof is {proof2:#?}");
|
||||
|
||||
info!("Success!");
|
||||
}
|
||||
|
||||
pub async fn test_success_shielded_transfer_to_another_owned_account_claiming_path() {
|
||||
info!("test_success_shielded_transfer_to_another_owned_account_claiming_path");
|
||||
let command = Command::RegisterAccountPrivate {};
|
||||
|
||||
let sub_ret = wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
let SubcommandReturnValue::RegisterAccount { addr: to_addr } = sub_ret else {
|
||||
panic!("FAILED TO REGISTER ACCOUNT");
|
||||
};
|
||||
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
|
||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config.clone()).unwrap();
|
||||
|
||||
let (to_keys, mut to_acc) = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.user_private_accounts
|
||||
.get(&to_addr)
|
||||
.cloned()
|
||||
.unwrap();
|
||||
|
||||
let command = Command::SendNativeTokenTransferShieldedForeignAccount {
|
||||
from: ACC_SENDER.to_string(),
|
||||
to_npk: hex::encode(to_keys.nullifer_public_key.0),
|
||||
to_ipk: hex::encode(to_keys.incoming_viewing_public_key.0),
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
let sub_ret = wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } = sub_ret else {
|
||||
panic!("FAILED TO SEND TX");
|
||||
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } =
|
||||
wallet::execute_subcommand(command).await.unwrap()
|
||||
else {
|
||||
panic!("invalid subcommand return value");
|
||||
};
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let new_commitment2 = {
|
||||
to_acc.program_owner = nssa::program::Program::authenticated_transfer_program().id();
|
||||
to_acc.balance = 100;
|
||||
to_acc.nonce = 1;
|
||||
|
||||
nssa_core::Commitment::new(&to_keys.nullifer_public_key, &to_acc)
|
||||
};
|
||||
let tx = fetch_privacy_preserving_tx(&seq_client, tx_hash).await;
|
||||
|
||||
let acc_1_balance = seq_client
|
||||
.get_account_balance(ACC_SENDER.to_string())
|
||||
.get_account_balance(from.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let proof2 = seq_client
|
||||
.get_proof_for_commitment(new_commitment2)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert!(
|
||||
verify_commitment_is_in_state(tx.message.new_commitments[0].clone(), &seq_client).await
|
||||
);
|
||||
|
||||
assert_eq!(acc_1_balance.balance, 9900);
|
||||
println!("New proof is {proof2:#?}");
|
||||
|
||||
let command = Command::ClaimPrivateAccount {
|
||||
tx_hash,
|
||||
acc_addr: hex::encode(to_addr),
|
||||
ciph_id: 0,
|
||||
};
|
||||
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||
|
||||
let (_, to_res_acc) = wallet_storage
|
||||
.storage
|
||||
.user_data
|
||||
.get_private_account(&to_addr)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(to_res_acc.balance, 100);
|
||||
|
||||
info!("Success!");
|
||||
}
|
||||
@ -1047,12 +868,6 @@ pub async fn main_tests_runner() -> Result<()> {
|
||||
test_success_shielded_transfer_to_another_foreign_account
|
||||
);
|
||||
}
|
||||
"test_success_shielded_transfer_to_another_owned_account_claiming_path" => {
|
||||
test_cleanup_wrap!(
|
||||
home_dir,
|
||||
test_success_shielded_transfer_to_another_owned_account_claiming_path
|
||||
);
|
||||
}
|
||||
"test_pinata" => {
|
||||
test_cleanup_wrap!(home_dir, test_pinata);
|
||||
}
|
||||
@ -1086,11 +901,33 @@ pub async fn main_tests_runner() -> Result<()> {
|
||||
home_dir,
|
||||
test_success_private_transfer_to_another_owned_account_claiming_path
|
||||
);
|
||||
test_cleanup_wrap!(home_dir, test_pinata);
|
||||
}
|
||||
"all_private" => {
|
||||
test_cleanup_wrap!(
|
||||
home_dir,
|
||||
test_success_shielded_transfer_to_another_owned_account_claiming_path
|
||||
test_success_private_transfer_to_another_owned_account
|
||||
);
|
||||
test_cleanup_wrap!(
|
||||
home_dir,
|
||||
test_success_private_transfer_to_another_foreign_account
|
||||
);
|
||||
test_cleanup_wrap!(
|
||||
home_dir,
|
||||
test_success_deshielded_transfer_to_another_account
|
||||
);
|
||||
test_cleanup_wrap!(
|
||||
home_dir,
|
||||
test_success_shielded_transfer_to_another_owned_account
|
||||
);
|
||||
test_cleanup_wrap!(
|
||||
home_dir,
|
||||
test_success_shielded_transfer_to_another_foreign_account
|
||||
);
|
||||
test_cleanup_wrap!(
|
||||
home_dir,
|
||||
test_success_private_transfer_to_another_owned_account_claiming_path
|
||||
);
|
||||
test_cleanup_wrap!(home_dir, test_pinata);
|
||||
}
|
||||
_ => {
|
||||
anyhow::bail!("Unknown test name");
|
||||
@ -1099,3 +936,37 @@ pub async fn main_tests_runner() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn fetch_privacy_preserving_tx(
|
||||
seq_client: &SequencerClient,
|
||||
tx_hash: String,
|
||||
) -> PrivacyPreservingTransaction {
|
||||
let transaction_encoded = seq_client
|
||||
.get_transaction_by_hash(tx_hash.clone())
|
||||
.await
|
||||
.unwrap()
|
||||
.transaction
|
||||
.unwrap();
|
||||
|
||||
let tx_base64_decode = BASE64.decode(transaction_encoded).unwrap();
|
||||
match NSSATransaction::try_from(
|
||||
&borsh::from_slice::<EncodedTransaction>(&tx_base64_decode).unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
{
|
||||
NSSATransaction::PrivacyPreserving(privacy_preserving_transaction) => {
|
||||
privacy_preserving_transaction
|
||||
}
|
||||
_ => panic!("Invalid tx type"),
|
||||
}
|
||||
}
|
||||
|
||||
async fn verify_commitment_is_in_state(
|
||||
commitment: Commitment,
|
||||
seq_client: &SequencerClient,
|
||||
) -> bool {
|
||||
matches!(
|
||||
seq_client.get_proof_for_commitment(commitment).await,
|
||||
Ok(Some(_))
|
||||
)
|
||||
}
|
||||
|
||||
@ -10,10 +10,8 @@ serde.workspace = true
|
||||
k256.workspace = true
|
||||
sha2.workspace = true
|
||||
rand.workspace = true
|
||||
elliptic-curve.workspace = true
|
||||
hex.workspace = true
|
||||
aes-gcm.workspace = true
|
||||
lazy_static.workspace = true
|
||||
bip39.workspace = true
|
||||
hmac-sha512.workspace = true
|
||||
nssa-core = { path = "../nssa/core", features = ["host"] }
|
||||
|
||||
@ -5,8 +5,6 @@ use nssa_core::{
|
||||
use rand::{RngCore, rngs::OsRng};
|
||||
use sha2::Digest;
|
||||
|
||||
use crate::key_management::secret_holders::OutgoingViewingSecretKey;
|
||||
|
||||
#[derive(Debug)]
|
||||
///Ephemeral secret key holder. Non-clonable as intended for one-time use. Produces ephemeral public keys. Can produce shared secret for sender.
|
||||
pub struct EphemeralKeyHolder {
|
||||
@ -25,21 +23,12 @@ pub fn produce_one_sided_shared_secret_receiver(
|
||||
}
|
||||
|
||||
impl EphemeralKeyHolder {
|
||||
pub fn new(
|
||||
receiver_nullifier_public_key: NullifierPublicKey,
|
||||
sender_outgoing_viewing_secret_key: OutgoingViewingSecretKey,
|
||||
nonce: u64,
|
||||
) -> Self {
|
||||
pub fn new(receiver_nullifier_public_key: &NullifierPublicKey) -> Self {
|
||||
let mut nonce_bytes = [0; 16];
|
||||
OsRng.fill_bytes(&mut nonce_bytes);
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(receiver_nullifier_public_key);
|
||||
hasher.update(nonce.to_le_bytes());
|
||||
hasher.update([0; 24]);
|
||||
|
||||
let hash_recepient = hasher.finalize();
|
||||
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(sender_outgoing_viewing_secret_key);
|
||||
hasher.update(hash_recepient);
|
||||
hasher.update(nonce_bytes);
|
||||
|
||||
Self {
|
||||
ephemeral_secret_key: hasher.finalize().into(),
|
||||
@ -52,11 +41,11 @@ impl EphemeralKeyHolder {
|
||||
|
||||
pub fn calculate_shared_secret_sender(
|
||||
&self,
|
||||
receiver_incoming_viewing_public_key: IncomingViewingPublicKey,
|
||||
receiver_incoming_viewing_public_key: &IncomingViewingPublicKey,
|
||||
) -> SharedSecretKey {
|
||||
SharedSecretKey::new(
|
||||
&self.ephemeral_secret_key,
|
||||
&receiver_incoming_viewing_public_key,
|
||||
receiver_incoming_viewing_public_key,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
use common::TreeHashType;
|
||||
use nssa_core::{
|
||||
NullifierPublicKey, SharedSecretKey,
|
||||
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
|
||||
};
|
||||
use secret_holders::{PrivateKeyHolder, SecretSpendingKey, SeedHolder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, digest::FixedOutput};
|
||||
|
||||
pub type PublicAccountSigningKey = [u8; 32];
|
||||
|
||||
@ -21,18 +19,6 @@ pub struct KeyChain {
|
||||
pub incoming_viewing_public_key: IncomingViewingPublicKey,
|
||||
}
|
||||
|
||||
pub fn produce_user_address_foreign_account(
|
||||
npk: &NullifierPublicKey,
|
||||
ipk: &IncomingViewingPublicKey,
|
||||
) -> [u8; 32] {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
|
||||
hasher.update(npk);
|
||||
hasher.update(ipk.to_bytes());
|
||||
|
||||
<TreeHashType>::from(hasher.finalize_fixed())
|
||||
}
|
||||
|
||||
impl KeyChain {
|
||||
pub fn new_os_random() -> Self {
|
||||
//Currently dropping SeedHolder at the end of initialization.
|
||||
@ -53,15 +39,6 @@ impl KeyChain {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn produce_user_address(&self) -> [u8; 32] {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
|
||||
hasher.update(&self.nullifer_public_key);
|
||||
hasher.update(self.incoming_viewing_public_key.to_bytes());
|
||||
|
||||
<TreeHashType>::from(hasher.finalize_fixed())
|
||||
}
|
||||
|
||||
pub fn calculate_shared_secret_receiver(
|
||||
&self,
|
||||
ephemeral_public_key_sender: EphemeralPublicKey,
|
||||
|
||||
@ -22,7 +22,9 @@ impl NSSAUserData {
|
||||
) -> bool {
|
||||
let mut check_res = true;
|
||||
for (addr, key) in accounts_keys_map {
|
||||
if &nssa::Address::from(&nssa::PublicKey::new_from_private_key(key)) != addr {
|
||||
let expected_addr = nssa::Address::from(&nssa::PublicKey::new_from_private_key(key));
|
||||
if &expected_addr != addr {
|
||||
println!("{}, {}", expected_addr, addr);
|
||||
check_res = false;
|
||||
}
|
||||
}
|
||||
@ -34,7 +36,9 @@ impl NSSAUserData {
|
||||
) -> bool {
|
||||
let mut check_res = true;
|
||||
for (addr, (key, _)) in accounts_keys_map {
|
||||
if nssa::Address::new(key.produce_user_address()) != *addr {
|
||||
let expected_addr = nssa::Address::from(&key.nullifer_public_key);
|
||||
if expected_addr != *addr {
|
||||
println!("{}, {}", expected_addr, addr);
|
||||
check_res = false;
|
||||
}
|
||||
}
|
||||
@ -88,7 +92,7 @@ impl NSSAUserData {
|
||||
/// Returns the address of new account
|
||||
pub fn generate_new_privacy_preserving_transaction_key_chain(&mut self) -> nssa::Address {
|
||||
let key_chain = KeyChain::new_os_random();
|
||||
let address = nssa::Address::new(key_chain.produce_user_address());
|
||||
let address = nssa::Address::from(&key_chain.nullifer_public_key);
|
||||
|
||||
self.user_private_accounts
|
||||
.insert(address, (key_chain, nssa_core::account::Account::default()));
|
||||
|
||||
@ -14,7 +14,6 @@ secp256k1 = "0.31.1"
|
||||
rand = "0.8"
|
||||
borsh = "1.5.7"
|
||||
hex = "0.4.3"
|
||||
k256 = "0.13.3"
|
||||
|
||||
[dev-dependencies]
|
||||
test-program-methods = { path = "test_program_methods" }
|
||||
|
||||
@ -10,7 +10,8 @@ thiserror = { version = "2.0.12", optional = true }
|
||||
bytemuck = { version = "1.13", optional = true }
|
||||
chacha20 = { version = "0.9", default-features = false }
|
||||
k256 = { version = "0.13.3", optional = true }
|
||||
hex = { version = "0.4.3", optional = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
host = ["thiserror", "bytemuck", "k256"]
|
||||
host = ["thiserror", "bytemuck", "k256", "hex"]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::program::ProgramId;
|
||||
use crate::{address::Address, program::ProgramId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub type Nonce = u128;
|
||||
@ -14,16 +14,17 @@ pub struct Account {
|
||||
pub nonce: Nonce,
|
||||
}
|
||||
|
||||
/// A fingerprint of the owner of an account. This can be, for example, an `Address` in case the account
|
||||
/// is public, or a `NullifierPublicKey` in case the account is private.
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug))]
|
||||
pub struct AccountId(pub(super) [u8; 32]);
|
||||
impl AccountId {
|
||||
pub fn new(value: [u8; 32]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
// /// A fingerprint of the owner of an account. This can be, for example, an `Address` in case the account
|
||||
// /// is public, or a `NullifierPublicKey` in case the account is private.
|
||||
// #[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
// #[cfg_attr(any(feature = "host", test), derive(Debug))]
|
||||
// pub struct AccountId(pub(super) [u8; 32]);
|
||||
// impl AccountId {
|
||||
// pub fn new(value: [u8; 32]) -> Self {
|
||||
// Self(value)
|
||||
// }
|
||||
// }
|
||||
pub type AccountId = Address;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, PartialEq, Eq))]
|
||||
@ -88,8 +89,7 @@ mod tests {
|
||||
nonce: 0xdeadbeef,
|
||||
};
|
||||
let fingerprint = AccountId::new([8; 32]);
|
||||
let new_acc_with_metadata =
|
||||
AccountWithMetadata::new(account.clone(), true, fingerprint.clone());
|
||||
let new_acc_with_metadata = AccountWithMetadata::new(account.clone(), true, fingerprint);
|
||||
assert_eq!(new_acc_with_metadata.account, account);
|
||||
assert!(new_acc_with_metadata.is_authorized);
|
||||
assert_eq!(new_acc_with_metadata.account_id, fingerprint);
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
use std::{fmt::Display, str::FromStr};
|
||||
|
||||
use nssa_core::account::AccountId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
use crate::signature::PublicKey;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(
|
||||
any(feature = "host", test),
|
||||
derive(Debug, Copy, PartialOrd, Ord, Default)
|
||||
)]
|
||||
pub struct Address {
|
||||
value: [u8; 32],
|
||||
}
|
||||
@ -27,13 +28,7 @@ impl AsRef<[u8]> for Address {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&PublicKey> for Address {
|
||||
fn from(value: &PublicKey) -> Self {
|
||||
// TODO: Check specs
|
||||
Self::new(*value.value())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum AddressError {
|
||||
#[error("invalid hex")]
|
||||
@ -42,6 +37,7 @@ pub enum AddressError {
|
||||
InvalidLength(usize),
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
impl FromStr for Address {
|
||||
type Err = AddressError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
@ -55,50 +51,17 @@ impl FromStr for Address {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
impl Display for Address {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", hex::encode(self.value))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Address {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let hex_string = self.to_string();
|
||||
|
||||
hex_string.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Address {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let hex_string = String::deserialize(deserializer)?;
|
||||
|
||||
Address::from_str(&hex_string).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Address> for AccountId {
|
||||
fn from(address: &Address) -> Self {
|
||||
const PUBLIC_ACCOUNT_ID_PREFIX: &[u8; 32] = b"/NSSA/v0.1/AccountId/Public/\x00\x00\x00\x00";
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(PUBLIC_ACCOUNT_ID_PREFIX);
|
||||
hasher.update(address.value);
|
||||
AccountId::new(hasher.finalize().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nssa_core::account::AccountId;
|
||||
|
||||
use crate::{Address, address::AddressError};
|
||||
use super::{Address, AddressError};
|
||||
|
||||
#[test]
|
||||
fn parse_valid_address() {
|
||||
@ -127,17 +90,4 @@ mod tests {
|
||||
let result = hex_str.parse::<Address>().unwrap_err();
|
||||
assert!(matches!(result, AddressError::InvalidLength(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_account_id_from_address() {
|
||||
let address: Address = "37".repeat(32).parse().unwrap();
|
||||
let expected_account_id = AccountId::new([
|
||||
93, 223, 66, 245, 78, 230, 157, 188, 110, 161, 134, 255, 137, 177, 220, 88, 37, 44,
|
||||
243, 91, 236, 4, 36, 147, 185, 112, 21, 49, 234, 4, 107, 185,
|
||||
]);
|
||||
|
||||
let account_id = AccountId::from(&address);
|
||||
|
||||
assert_eq!(account_id, expected_account_id);
|
||||
}
|
||||
}
|
||||
@ -140,7 +140,7 @@ impl Secp256k1Point {
|
||||
|
||||
impl AccountId {
|
||||
pub fn to_bytes(&self) -> [u8; 32] {
|
||||
self.0
|
||||
*self.value()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ pub mod encryption;
|
||||
mod nullifier;
|
||||
pub mod program;
|
||||
|
||||
pub mod address;
|
||||
|
||||
pub use circuit_io::{PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput};
|
||||
pub use commitment::{Commitment, CommitmentSetDigest, MembershipProof, compute_digest_for_path};
|
||||
pub use encryption::{EncryptionScheme, SharedSecretKey};
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
pub mod address;
|
||||
pub mod encoding;
|
||||
pub mod error;
|
||||
mod merkle_tree;
|
||||
@ -8,8 +7,8 @@ pub mod public_transaction;
|
||||
mod signature;
|
||||
mod state;
|
||||
|
||||
pub use address::Address;
|
||||
pub use nssa_core::account::{Account, AccountId};
|
||||
pub use nssa_core::address::Address;
|
||||
pub use privacy_preserving_transaction::{
|
||||
PrivacyPreservingTransaction, circuit::execute_and_prove,
|
||||
};
|
||||
|
||||
@ -94,7 +94,7 @@ impl PrivacyPreservingTransaction {
|
||||
AccountWithMetadata::new(
|
||||
state.get_account_by_address(address),
|
||||
signer_addresses.contains(address),
|
||||
address,
|
||||
*address,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -2,13 +2,13 @@ use std::collections::{HashMap, HashSet};
|
||||
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata},
|
||||
address::Address,
|
||||
program::validate_execution,
|
||||
};
|
||||
use sha2::{Digest, digest::FixedOutput};
|
||||
|
||||
use crate::{
|
||||
V01State,
|
||||
address::Address,
|
||||
error::NssaError,
|
||||
public_transaction::{Message, WitnessSet},
|
||||
};
|
||||
@ -95,7 +95,7 @@ impl PublicTransaction {
|
||||
AccountWithMetadata::new(
|
||||
state.get_account_by_address(address),
|
||||
signer_addresses.contains(address),
|
||||
address,
|
||||
*address,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
@ -187,12 +187,12 @@ pub mod tests {
|
||||
let tx = transaction_for_tests();
|
||||
let expected_signer_addresses = vec![
|
||||
Address::new([
|
||||
27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30,
|
||||
24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143,
|
||||
14, 238, 36, 40, 114, 150, 186, 85, 39, 143, 30, 84, 3, 190, 1, 71, 84, 134, 99,
|
||||
102, 56, 135, 48, 48, 60, 40, 137, 190, 23, 173, 160, 101,
|
||||
]),
|
||||
Address::new([
|
||||
77, 75, 108, 209, 54, 16, 50, 202, 155, 210, 174, 185, 217, 0, 170, 77, 69, 217,
|
||||
234, 216, 10, 201, 66, 51, 116, 196, 81, 167, 37, 77, 7, 102,
|
||||
158, 61, 142, 101, 77, 68, 14, 149, 41, 58, 162, 220, 236, 235, 19, 120, 153, 165,
|
||||
149, 53, 233, 82, 247, 71, 6, 142, 122, 14, 227, 9, 101, 242,
|
||||
]),
|
||||
];
|
||||
let signer_addresses = tx.signer_addresses();
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
use nssa_core::address::Address;
|
||||
|
||||
use crate::{PrivateKey, error::NssaError};
|
||||
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct PublicKey([u8; 32]);
|
||||
|
||||
@ -27,6 +31,17 @@ impl PublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&PublicKey> for Address {
|
||||
fn from(key: &PublicKey) -> Self {
|
||||
const PUBLIC_ACCOUNT_ID_PREFIX: &[u8; 32] = b"/NSSA/v0.1/AccountId/Public/\x00\x00\x00\x00";
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(PUBLIC_ACCOUNT_ID_PREFIX);
|
||||
hasher.update(key.0);
|
||||
Self::new(hasher.finalize().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{PublicKey, error::NssaError, signature::bip340_test_vectors};
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
use crate::{
|
||||
address::Address, error::NssaError, merkle_tree::MerkleTree,
|
||||
error::NssaError, merkle_tree::MerkleTree,
|
||||
privacy_preserving_transaction::PrivacyPreservingTransaction, program::Program,
|
||||
public_transaction::PublicTransaction,
|
||||
};
|
||||
use nssa_core::{
|
||||
Commitment, CommitmentSetDigest, MembershipProof, Nullifier,
|
||||
account::Account,
|
||||
address::Address,
|
||||
program::{DEFAULT_PROGRAM_ID, ProgramId},
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
@ -810,7 +811,7 @@ pub mod tests {
|
||||
let sender = AccountWithMetadata::new(
|
||||
state.get_account_by_address(&sender_keys.address()),
|
||||
true,
|
||||
&sender_keys.address(),
|
||||
sender_keys.address(),
|
||||
);
|
||||
|
||||
let sender_nonce = sender.account.nonce;
|
||||
@ -915,7 +916,7 @@ pub mod tests {
|
||||
let recipient_pre = AccountWithMetadata::new(
|
||||
state.get_account_by_address(recipient_address),
|
||||
false,
|
||||
recipient_address,
|
||||
*recipient_address,
|
||||
);
|
||||
|
||||
let esk = [3; 32];
|
||||
|
||||
@ -231,13 +231,13 @@ mod tests {
|
||||
|
||||
fn setup_sequencer_config() -> SequencerConfig {
|
||||
let acc1_addr = vec![
|
||||
27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24,
|
||||
52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143,
|
||||
14, 238, 36, 40, 114, 150, 186, 85, 39, 143, 30, 84, 3, 190, 1, 71, 84, 134, 99, 102,
|
||||
56, 135, 48, 48, 60, 40, 137, 190, 23, 173, 160, 101,
|
||||
];
|
||||
|
||||
let acc2_addr = vec![
|
||||
77, 75, 108, 209, 54, 16, 50, 202, 155, 210, 174, 185, 217, 0, 170, 77, 69, 217, 234,
|
||||
216, 10, 201, 66, 51, 116, 196, 81, 167, 37, 77, 7, 102,
|
||||
158, 61, 142, 101, 77, 68, 14, 149, 41, 58, 162, 220, 236, 235, 19, 120, 153, 165, 149,
|
||||
53, 233, 82, 247, 71, 6, 142, 122, 14, 227, 9, 101, 242,
|
||||
];
|
||||
|
||||
let initial_acc1 = AccountInitialData {
|
||||
|
||||
@ -12,7 +12,6 @@ actix-cors.workspace = true
|
||||
futures.workspace = true
|
||||
hex.workspace = true
|
||||
tempfile.workspace = true
|
||||
nssa-core = { path = "../nssa/core", features = ["host"] }
|
||||
base64.workspace = true
|
||||
|
||||
actix-web.workspace = true
|
||||
|
||||
@ -14,8 +14,8 @@ use common::{
|
||||
requests::{
|
||||
GetAccountBalanceRequest, GetAccountBalanceResponse, GetAccountRequest,
|
||||
GetAccountResponse, GetAccountsNoncesRequest, GetAccountsNoncesResponse,
|
||||
GetInitialTestnetAccountsRequest, GetProofByCommitmentRequest,
|
||||
GetProofByCommitmentResponse, GetTransactionByHashRequest,
|
||||
GetInitialTestnetAccountsRequest, GetProofForCommitmentRequest,
|
||||
GetProofForCommitmentResponse, GetTransactionByHashRequest,
|
||||
GetTransactionByHashResponse,
|
||||
},
|
||||
},
|
||||
@ -254,7 +254,7 @@ impl JsonHandler {
|
||||
|
||||
/// Returns the commitment proof, corresponding to commitment
|
||||
async fn process_get_proof_by_commitment(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let get_proof_req = GetProofByCommitmentRequest::parse(Some(request.params))?;
|
||||
let get_proof_req = GetProofForCommitmentRequest::parse(Some(request.params))?;
|
||||
|
||||
let membership_proof = {
|
||||
let state = self.sequencer_state.lock().await;
|
||||
@ -263,7 +263,7 @@ impl JsonHandler {
|
||||
.state
|
||||
.get_proof_for_commitment(&get_proof_req.commitment)
|
||||
};
|
||||
let helperstruct = GetProofByCommitmentResponse { membership_proof };
|
||||
let helperstruct = GetProofForCommitmentResponse { membership_proof };
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
@ -308,13 +308,13 @@ mod tests {
|
||||
let tempdir = tempdir().unwrap();
|
||||
let home = tempdir.path().to_path_buf();
|
||||
let acc1_addr = vec![
|
||||
27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24,
|
||||
52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143,
|
||||
14, 238, 36, 40, 114, 150, 186, 85, 39, 143, 30, 84, 3, 190, 1, 71, 84, 134, 99, 102,
|
||||
56, 135, 48, 48, 60, 40, 137, 190, 23, 173, 160, 101,
|
||||
];
|
||||
|
||||
let acc2_addr = vec![
|
||||
77, 75, 108, 209, 54, 16, 50, 202, 155, 210, 174, 185, 217, 0, 170, 77, 69, 217, 234,
|
||||
216, 10, 201, 66, 51, 116, 196, 81, 167, 37, 77, 7, 102,
|
||||
158, 61, 142, 101, 77, 68, 14, 149, 41, 58, 162, 220, 236, 235, 19, 120, 153, 165, 149,
|
||||
53, 233, 82, 247, 71, 6, 142, 122, 14, 227, 9, 101, 242,
|
||||
];
|
||||
|
||||
let initial_acc1 = AccountInitialData {
|
||||
@ -352,8 +352,8 @@ mod tests {
|
||||
let balance_to_move = 10;
|
||||
let tx = common::test_utils::create_transaction_native_token_transfer(
|
||||
[
|
||||
27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30,
|
||||
24, 52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143,
|
||||
14, 238, 36, 40, 114, 150, 186, 85, 39, 143, 30, 84, 3, 190, 1, 71, 84, 134, 99,
|
||||
102, 56, 135, 48, 48, 60, 40, 137, 190, 23, 173, 160, 101,
|
||||
],
|
||||
0,
|
||||
[2; 32],
|
||||
|
||||
@ -8,12 +8,150 @@
|
||||
"port": 3040,
|
||||
"initial_accounts": [
|
||||
{
|
||||
"addr": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
|
||||
"addr": "0eee24287296ba55278f1e5403be014754866366388730303c2889be17ada065",
|
||||
"balance": 10000
|
||||
},
|
||||
{
|
||||
"addr": "4d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766",
|
||||
"addr": "9e3d8e654d440e95293aa2dceceb137899a59535e952f747068e7a0ee30965f2",
|
||||
"balance": 20000
|
||||
}
|
||||
],
|
||||
"initial_commitments": [
|
||||
{
|
||||
"npk": [
|
||||
193,
|
||||
209,
|
||||
150,
|
||||
113,
|
||||
47,
|
||||
241,
|
||||
48,
|
||||
145,
|
||||
250,
|
||||
79,
|
||||
235,
|
||||
51,
|
||||
119,
|
||||
40,
|
||||
184,
|
||||
232,
|
||||
5,
|
||||
221,
|
||||
36,
|
||||
21,
|
||||
201,
|
||||
106,
|
||||
90,
|
||||
210,
|
||||
129,
|
||||
106,
|
||||
71,
|
||||
99,
|
||||
208,
|
||||
153,
|
||||
75,
|
||||
215
|
||||
],
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"balance": 10000,
|
||||
"data": [],
|
||||
"nonce": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"npk": [
|
||||
27,
|
||||
250,
|
||||
136,
|
||||
142,
|
||||
88,
|
||||
128,
|
||||
138,
|
||||
21,
|
||||
49,
|
||||
183,
|
||||
118,
|
||||
160,
|
||||
117,
|
||||
114,
|
||||
110,
|
||||
47,
|
||||
136,
|
||||
87,
|
||||
60,
|
||||
70,
|
||||
59,
|
||||
60,
|
||||
18,
|
||||
223,
|
||||
23,
|
||||
147,
|
||||
241,
|
||||
5,
|
||||
184,
|
||||
103,
|
||||
225,
|
||||
105
|
||||
],
|
||||
"account": {
|
||||
"program_owner": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"balance": 20000,
|
||||
"data": [],
|
||||
"nonce": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"signing_key": [
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37
|
||||
]
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ k256 = { version = "0.13.3" }
|
||||
bytemuck = "1.23.2"
|
||||
borsh.workspace = true
|
||||
hex.workspace = true
|
||||
rand.workspace = true
|
||||
|
||||
[dependencies.key_protocol]
|
||||
path = "../key_protocol"
|
||||
|
||||
@ -2,6 +2,7 @@ use std::collections::HashMap;
|
||||
|
||||
use anyhow::Result;
|
||||
use key_protocol::key_protocol_core::NSSAUserData;
|
||||
use nssa::program::Program;
|
||||
|
||||
use crate::config::{InitialAccountData, PersistentAccountData, WalletConfig};
|
||||
|
||||
@ -18,10 +19,15 @@ impl WalletChainStore {
|
||||
for init_acc_data in config.initial_accounts.clone() {
|
||||
match init_acc_data {
|
||||
InitialAccountData::Public(data) => {
|
||||
public_init_acc_map.insert(data.address, data.pub_sign_key);
|
||||
public_init_acc_map.insert(data.address.parse()?, data.pub_sign_key);
|
||||
}
|
||||
InitialAccountData::Private(data) => {
|
||||
private_init_acc_map.insert(data.address, (data.key_chain, data.account));
|
||||
let mut account = data.account;
|
||||
// TODO: Program owner is only known after code is compiled and can't be set in
|
||||
// the config. Therefore we overwrite it here on startup. Fix this when program
|
||||
// id can be fetched from the node and queried from the wallet.
|
||||
account.program_owner = Program::authenticated_transfer_program().id();
|
||||
private_init_acc_map.insert(data.address.parse()?, (data.key_chain, account));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -37,6 +43,7 @@ impl WalletChainStore {
|
||||
addr: nssa::Address,
|
||||
account: nssa_core::account::Account,
|
||||
) {
|
||||
println!("inserting at addres {}, this account {:?}", addr, account);
|
||||
self.user_data
|
||||
.user_private_accounts
|
||||
.entry(addr)
|
||||
@ -70,14 +77,14 @@ mod tests {
|
||||
fn create_initial_accounts() -> Vec<InitialAccountData> {
|
||||
let initial_acc1 = serde_json::from_str(r#"{
|
||||
"Public": {
|
||||
"address": "1b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
|
||||
"address": "0eee24287296ba55278f1e5403be014754866366388730303c2889be17ada065",
|
||||
"pub_sign_key": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
}
|
||||
}"#).unwrap();
|
||||
|
||||
let initial_acc2 = serde_json::from_str(r#"{
|
||||
"Public": {
|
||||
"address": "4d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766",
|
||||
"address": "9e3d8e654d440e95293aa2dceceb137899a59535e952f747068e7a0ee30965f2",
|
||||
"pub_sign_key": [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
|
||||
}
|
||||
}"#).unwrap();
|
||||
|
||||
@ -4,7 +4,7 @@ use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct InitialAccountDataPublic {
|
||||
pub address: nssa::Address,
|
||||
pub address: String,
|
||||
pub pub_sign_key: nssa::PrivateKey,
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ pub struct PersistentAccountDataPublic {
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct InitialAccountDataPrivate {
|
||||
pub address: nssa::Address,
|
||||
pub address: String,
|
||||
pub account: nssa_core::account::Account,
|
||||
pub key_chain: KeyChain,
|
||||
}
|
||||
@ -49,8 +49,8 @@ pub enum PersistentAccountData {
|
||||
impl InitialAccountData {
|
||||
pub fn address(&self) -> nssa::Address {
|
||||
match &self {
|
||||
Self::Public(acc) => acc.address,
|
||||
Self::Private(acc) => acc.address,
|
||||
Self::Public(acc) => acc.address.parse().unwrap(),
|
||||
Self::Private(acc) => acc.address.parse().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
|
||||
use nssa_core::account::Nonce;
|
||||
use rand::{RngCore, rngs::OsRng};
|
||||
use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr};
|
||||
|
||||
use anyhow::Result;
|
||||
use key_protocol::key_protocol_core::NSSAUserData;
|
||||
use nssa::{Account, Address};
|
||||
use nssa::Account;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{
|
||||
@ -28,11 +30,6 @@ pub fn fetch_config() -> Result<WalletConfig> {
|
||||
Ok(serde_json::from_reader(reader)?)
|
||||
}
|
||||
|
||||
// ToDo: Replace with structures conversion in future
|
||||
pub fn produce_account_addr_from_hex(hex_str: String) -> Result<Address> {
|
||||
Ok(hex_str.parse()?)
|
||||
}
|
||||
|
||||
/// Fetch list of accounts stored at `NSSA_WALLET_HOME_DIR/curr_accounts.json`
|
||||
///
|
||||
/// If file not present, it is considered as empty list of persistent accounts
|
||||
@ -82,6 +79,12 @@ pub fn produce_data_for_storage(user_data: &NSSAUserData) -> Vec<PersistentAccou
|
||||
vec_for_storage
|
||||
}
|
||||
|
||||
pub(crate) fn produce_random_nonces(size: usize) -> Vec<Nonce> {
|
||||
let mut result = vec![[0; 16]; size];
|
||||
result.iter_mut().for_each(|bytes| OsRng.fill_bytes(bytes));
|
||||
result.into_iter().map(Nonce::from_le_bytes).collect()
|
||||
}
|
||||
|
||||
/// Human-readable representation of an account.
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct HumanReadableAccount {
|
||||
|
||||
@ -14,11 +14,12 @@ use log::info;
|
||||
use nssa::{Account, Address};
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use nssa_core::Commitment;
|
||||
|
||||
use crate::{
|
||||
helperfunctions::{
|
||||
HumanReadableAccount, fetch_config, fetch_persistent_accounts, get_home,
|
||||
produce_account_addr_from_hex, produce_data_for_storage,
|
||||
produce_data_for_storage,
|
||||
},
|
||||
poller::TxPoller,
|
||||
};
|
||||
@ -180,11 +181,24 @@ impl WalletCore {
|
||||
}
|
||||
|
||||
///Get account
|
||||
pub async fn get_account(&self, addr: Address) -> Result<Account> {
|
||||
pub async fn get_account_public(&self, addr: Address) -> Result<Account> {
|
||||
let response = self.sequencer_client.get_account(addr.to_string()).await?;
|
||||
Ok(response.account)
|
||||
}
|
||||
|
||||
pub fn get_account_private(&self, addr: &Address) -> Option<Account> {
|
||||
self.storage
|
||||
.user_data
|
||||
.user_private_accounts
|
||||
.get(addr)
|
||||
.map(|value| value.1.clone())
|
||||
}
|
||||
|
||||
pub fn get_private_account_commitment(&self, addr: &Address) -> Option<Commitment> {
|
||||
let (keys, account) = self.storage.user_data.user_private_accounts.get(addr)?;
|
||||
Some(Commitment::new(&keys.nullifer_public_key, account))
|
||||
}
|
||||
|
||||
///Poll transactions
|
||||
pub async fn poll_native_token_transfer(&self, hash: String) -> Result<NSSATransaction> {
|
||||
let transaction_encoded = self.poller.poll_tx(hash).await?;
|
||||
@ -216,7 +230,7 @@ pub enum Command {
|
||||
///Send native token transfer from `from` to `to` for `amount`
|
||||
///
|
||||
/// Private operation
|
||||
SendNativeTokenTransferPrivate {
|
||||
SendNativeTokenTransferPrivateOwnedAccount {
|
||||
///from - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
from: String,
|
||||
@ -290,16 +304,21 @@ pub enum Command {
|
||||
amount: u128,
|
||||
},
|
||||
///Claim account `acc_addr` generated in transaction `tx_hash`, using secret `sh_secret` at ciphertext id `ciph_id`
|
||||
ClaimPrivateAccount {
|
||||
FetchPrivateAccount {
|
||||
///tx_hash - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
tx_hash: String,
|
||||
///acc_addr - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
acc_addr: String,
|
||||
///ciph_id - id of cipher in transaction
|
||||
///output_id - id of the output in the transaction
|
||||
#[arg(long)]
|
||||
ciph_id: usize,
|
||||
output_id: usize,
|
||||
},
|
||||
///Get private account with `addr` from storage
|
||||
GetPrivateAccount {
|
||||
#[arg(short, long)]
|
||||
addr: String,
|
||||
},
|
||||
///Register new public account
|
||||
RegisterAccountPublic {},
|
||||
@ -311,17 +330,17 @@ pub enum Command {
|
||||
tx_hash: String,
|
||||
},
|
||||
///Get account `addr` balance
|
||||
GetAccountBalance {
|
||||
GetPublicAccountBalance {
|
||||
#[arg(short, long)]
|
||||
addr: String,
|
||||
},
|
||||
///Get account `addr` nonce
|
||||
GetAccountNonce {
|
||||
GetPublicAccountNonce {
|
||||
#[arg(short, long)]
|
||||
addr: String,
|
||||
},
|
||||
///Get account at address `addr`
|
||||
GetAccount {
|
||||
GetPublicAccount {
|
||||
#[arg(short, long)]
|
||||
addr: String,
|
||||
},
|
||||
@ -373,6 +392,7 @@ pub struct Args {
|
||||
pub enum SubcommandReturnValue {
|
||||
PrivacyPreservingTransfer { tx_hash: String },
|
||||
RegisterAccount { addr: nssa::Address },
|
||||
Account(nssa::Account),
|
||||
Empty,
|
||||
}
|
||||
|
||||
@ -382,8 +402,8 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
|
||||
let subcommand_ret = match command {
|
||||
Command::SendNativeTokenTransferPublic { from, to, amount } => {
|
||||
let from = produce_account_addr_from_hex(from)?;
|
||||
let to = produce_account_addr_from_hex(to)?;
|
||||
let from: Address = from.parse().unwrap();
|
||||
let to: Address = to.parse().unwrap();
|
||||
|
||||
let res = wallet_core
|
||||
.send_public_native_token_transfer(from, to, amount)
|
||||
@ -401,12 +421,12 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
|
||||
SubcommandReturnValue::Empty
|
||||
}
|
||||
Command::SendNativeTokenTransferPrivate { from, to, amount } => {
|
||||
let from = produce_account_addr_from_hex(from)?;
|
||||
let to = produce_account_addr_from_hex(to)?;
|
||||
Command::SendNativeTokenTransferPrivateOwnedAccount { from, to, amount } => {
|
||||
let from: Address = from.parse().unwrap();
|
||||
let to: Address = to.parse().unwrap();
|
||||
|
||||
let (res, secret) = wallet_core
|
||||
.send_private_native_token_transfer(from, to, amount)
|
||||
let (res, [secret_from, secret_to]) = wallet_core
|
||||
.send_private_native_token_transfer_owned_account(from, to, amount)
|
||||
.await?;
|
||||
|
||||
println!("Results of tx send is {res:#?}");
|
||||
@ -425,15 +445,19 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
|
||||
let res_acc_from = nssa_core::EncryptionScheme::decrypt(
|
||||
&from_ebc.ciphertext,
|
||||
&secret,
|
||||
&secret_from,
|
||||
&from_comm,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let res_acc_to =
|
||||
nssa_core::EncryptionScheme::decrypt(&to_ebc.ciphertext, &secret, &to_comm, 1)
|
||||
.unwrap();
|
||||
let res_acc_to = nssa_core::EncryptionScheme::decrypt(
|
||||
&to_ebc.ciphertext,
|
||||
&secret_to,
|
||||
&to_comm,
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
println!("Received new from acc {res_acc_from:#?}");
|
||||
println!("Received new to acc {res_acc_to:#?}");
|
||||
@ -460,7 +484,7 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
to_ipk,
|
||||
amount,
|
||||
} => {
|
||||
let from = produce_account_addr_from_hex(from)?;
|
||||
let from: Address = from.parse().unwrap();
|
||||
let to_npk_res = hex::decode(to_npk)?;
|
||||
let mut to_npk = [0; 32];
|
||||
to_npk.copy_from_slice(&to_npk_res);
|
||||
@ -472,7 +496,7 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
let to_ipk =
|
||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec());
|
||||
|
||||
let (res, secret) = wallet_core
|
||||
let (res, [secret_from, secret_to]) = wallet_core
|
||||
.send_private_native_token_transfer_outer_account(from, to_npk, to_ipk, amount)
|
||||
.await?;
|
||||
|
||||
@ -492,15 +516,19 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
|
||||
let res_acc_from = nssa_core::EncryptionScheme::decrypt(
|
||||
&from_ebc.ciphertext,
|
||||
&secret,
|
||||
&secret_from,
|
||||
&from_comm,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let res_acc_to =
|
||||
nssa_core::EncryptionScheme::decrypt(&to_ebc.ciphertext, &secret, &to_comm, 1)
|
||||
.unwrap();
|
||||
let res_acc_to = nssa_core::EncryptionScheme::decrypt(
|
||||
&to_ebc.ciphertext,
|
||||
&secret_to,
|
||||
&to_comm,
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
println!("RES acc {res_acc_from:#?}");
|
||||
println!("RES acc to {res_acc_to:#?}");
|
||||
@ -519,8 +547,8 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }
|
||||
}
|
||||
Command::SendNativeTokenTransferDeshielded { from, to, amount } => {
|
||||
let from = produce_account_addr_from_hex(from)?;
|
||||
let to = produce_account_addr_from_hex(to)?;
|
||||
let from: Address = from.parse().unwrap();
|
||||
let to: Address = to.parse().unwrap();
|
||||
|
||||
let (res, secret) = wallet_core
|
||||
.send_deshielded_native_token_transfer(from, to, amount)
|
||||
@ -561,11 +589,11 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }
|
||||
}
|
||||
Command::SendNativeTokenTransferShielded { from, to, amount } => {
|
||||
let from = produce_account_addr_from_hex(from)?;
|
||||
let to = produce_account_addr_from_hex(to)?;
|
||||
let from: Address = from.parse().unwrap();
|
||||
let to: Address = to.parse().unwrap();
|
||||
|
||||
let (res, secret) = wallet_core
|
||||
.send_shiedled_native_token_transfer(from, to, amount)
|
||||
.send_shielded_native_token_transfer(from, to, amount)
|
||||
.await?;
|
||||
|
||||
println!("Results of tx send is {res:#?}");
|
||||
@ -600,7 +628,7 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
to_ipk,
|
||||
amount,
|
||||
} => {
|
||||
let from = produce_account_addr_from_hex(from)?;
|
||||
let from: Address = from.parse().unwrap();
|
||||
|
||||
let to_npk_res = hex::decode(to_npk)?;
|
||||
let mut to_npk = [0; 32];
|
||||
@ -614,9 +642,7 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec());
|
||||
|
||||
let (res, secret) = wallet_core
|
||||
.send_shielded_native_token_transfer_maybe_outer_account(
|
||||
from, to_npk, to_ipk, amount,
|
||||
)
|
||||
.send_shielded_native_token_transfer_outer_account(from, to_npk, to_ipk, amount)
|
||||
.await?;
|
||||
|
||||
println!("Results of tx send is {res:#?}");
|
||||
@ -645,12 +671,12 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
|
||||
SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }
|
||||
}
|
||||
Command::ClaimPrivateAccount {
|
||||
Command::FetchPrivateAccount {
|
||||
tx_hash,
|
||||
acc_addr,
|
||||
ciph_id,
|
||||
output_id: ciph_id,
|
||||
} => {
|
||||
let acc_addr = produce_account_addr_from_hex(acc_addr)?;
|
||||
let acc_addr: Address = acc_addr.parse().unwrap();
|
||||
|
||||
let account_key_chain = wallet_core
|
||||
.storage
|
||||
@ -706,15 +732,18 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
Command::RegisterAccountPrivate {} => {
|
||||
let addr = wallet_core.create_new_account_private();
|
||||
|
||||
let (key, account) = wallet_core
|
||||
let (key, _) = wallet_core
|
||||
.storage
|
||||
.user_data
|
||||
.get_private_account(&addr)
|
||||
.unwrap();
|
||||
|
||||
println!("Generated new account with addr {addr:#?}");
|
||||
println!("With key {key:#?}");
|
||||
println!("With account {account:#?}");
|
||||
println!("Generated new account with addr {addr}");
|
||||
println!("With npk {}", hex::encode(&key.nullifer_public_key));
|
||||
println!(
|
||||
"With ipk {}",
|
||||
hex::encode(key.incoming_viewing_public_key.to_bytes())
|
||||
);
|
||||
|
||||
let path = wallet_core.store_persistent_accounts()?;
|
||||
|
||||
@ -732,7 +761,7 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
|
||||
SubcommandReturnValue::Empty
|
||||
}
|
||||
Command::GetAccountBalance { addr } => {
|
||||
Command::GetPublicAccountBalance { addr } => {
|
||||
let addr = Address::from_str(&addr)?;
|
||||
|
||||
let balance = wallet_core.get_account_balance(addr).await?;
|
||||
@ -740,7 +769,7 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
|
||||
SubcommandReturnValue::Empty
|
||||
}
|
||||
Command::GetAccountNonce { addr } => {
|
||||
Command::GetPublicAccountNonce { addr } => {
|
||||
let addr = Address::from_str(&addr)?;
|
||||
|
||||
let nonce = wallet_core.get_accounts_nonces(vec![addr]).await?[0];
|
||||
@ -748,11 +777,21 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
||||
|
||||
SubcommandReturnValue::Empty
|
||||
}
|
||||
Command::GetAccount { addr } => {
|
||||
Command::GetPublicAccount { addr } => {
|
||||
let addr: Address = addr.parse()?;
|
||||
let account: HumanReadableAccount = wallet_core.get_account(addr).await?.into();
|
||||
println!("{}", serde_json::to_string(&account).unwrap());
|
||||
let account = wallet_core.get_account_public(addr).await?;
|
||||
let account_hr: HumanReadableAccount = account.clone().into();
|
||||
println!("{}", serde_json::to_string(&account_hr).unwrap());
|
||||
|
||||
SubcommandReturnValue::Account(account)
|
||||
}
|
||||
Command::GetPrivateAccount { addr } => {
|
||||
let addr: Address = addr.parse()?;
|
||||
if let Some(account) = wallet_core.get_account_private(&addr) {
|
||||
println!("{}", serde_json::to_string(&account).unwrap());
|
||||
} else {
|
||||
println!("Private account not found.");
|
||||
}
|
||||
SubcommandReturnValue::Empty
|
||||
}
|
||||
Command::CreateNewToken {
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
use common::{ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||
use k256::elliptic_curve::rand_core::{OsRng, RngCore};
|
||||
use nssa::Address;
|
||||
use nssa_core::{SharedSecretKey, encryption::EphemeralPublicKey};
|
||||
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||
use nssa::{
|
||||
Address, PrivacyPreservingTransaction,
|
||||
privacy_preserving_transaction::{circuit, message::Message, witness_set::WitnessSet},
|
||||
program::Program,
|
||||
};
|
||||
use nssa_core::{Commitment, account::AccountWithMetadata};
|
||||
|
||||
use crate::WalletCore;
|
||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
||||
|
||||
impl WalletCore {
|
||||
pub async fn send_deshielded_native_token_transfer(
|
||||
@ -12,48 +16,36 @@ impl WalletCore {
|
||||
to: Address,
|
||||
balance_to_move: u128,
|
||||
) -> Result<(SendTxResponse, nssa_core::SharedSecretKey), ExecutionFailureKind> {
|
||||
let from_data = self.storage.user_data.get_private_account(&from).cloned();
|
||||
let to_data = self.get_account(to).await;
|
||||
|
||||
let Some((from_keys, mut from_acc)) = from_data else {
|
||||
let Some((from_keys, from_acc)) =
|
||||
self.storage.user_data.get_private_account(&from).cloned()
|
||||
else {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let Ok(to_acc) = to_data else {
|
||||
let Ok(to_acc) = self.get_account_public(to).await else {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
if from_acc.balance >= balance_to_move {
|
||||
let program = nssa::program::Program::authenticated_transfer_program();
|
||||
let program = Program::authenticated_transfer_program();
|
||||
|
||||
from_acc.program_owner = program.id();
|
||||
let npk_from = from_keys.nullifer_public_key;
|
||||
let ipk_from = from_keys.incoming_viewing_public_key;
|
||||
|
||||
let sender_commitment =
|
||||
nssa_core::Commitment::new(&from_keys.nullifer_public_key, &from_acc);
|
||||
let sender_commitment = Commitment::new(&npk_from, &from_acc);
|
||||
|
||||
let sender_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: from_acc.clone(),
|
||||
is_authorized: true,
|
||||
account_id: (&from_keys.nullifer_public_key).into(),
|
||||
};
|
||||
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: to_acc.clone(),
|
||||
is_authorized: false,
|
||||
account_id: (&to).into(),
|
||||
};
|
||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, &npk_from);
|
||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, to);
|
||||
|
||||
//Move into different function
|
||||
let mut esk = [0; 32];
|
||||
OsRng.fill_bytes(&mut esk);
|
||||
let shared_secret = SharedSecretKey::new(&esk, &from_keys.incoming_viewing_public_key);
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
let eph_holder = EphemeralKeyHolder::new(&npk_from);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&ipk_from);
|
||||
|
||||
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[1, 0],
|
||||
&[from_acc.nonce + 1],
|
||||
&[(from_keys.nullifer_public_key.clone(), shared_secret.clone())],
|
||||
&produce_random_nonces(1),
|
||||
&[(npk_from.clone(), shared_secret.clone())],
|
||||
&[(
|
||||
from_keys.private_key_holder.nullifier_secret_key,
|
||||
self.sequencer_client
|
||||
@ -66,30 +58,21 @@ impl WalletCore {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let message =
|
||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
||||
vec![to],
|
||||
vec![],
|
||||
vec![(
|
||||
from_keys.nullifer_public_key.clone(),
|
||||
from_keys.incoming_viewing_public_key.clone(),
|
||||
epk,
|
||||
)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![to],
|
||||
vec![],
|
||||
vec![(
|
||||
npk_from.clone(),
|
||||
ipk_from.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let witness_set =
|
||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||
&message,
|
||||
proof,
|
||||
&[],
|
||||
);
|
||||
let witness_set = WitnessSet::for_message(&message, proof, &[]);
|
||||
|
||||
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
||||
message,
|
||||
witness_set,
|
||||
);
|
||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||
|
||||
Ok((
|
||||
self.sequencer_client.send_tx_private(tx).await?,
|
||||
|
||||
@ -1,61 +1,58 @@
|
||||
use common::{ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||
use nssa::Address;
|
||||
use nssa::{
|
||||
Address, PrivacyPreservingTransaction,
|
||||
privacy_preserving_transaction::{circuit, message::Message, witness_set::WitnessSet},
|
||||
program::Program,
|
||||
};
|
||||
use nssa_core::{
|
||||
Commitment, NullifierPublicKey, SharedSecretKey, account::AccountWithMetadata,
|
||||
encryption::IncomingViewingPublicKey,
|
||||
};
|
||||
|
||||
use crate::WalletCore;
|
||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
||||
|
||||
impl WalletCore {
|
||||
pub async fn send_private_native_token_transfer_outer_account(
|
||||
&self,
|
||||
from: Address,
|
||||
to_npk: nssa_core::NullifierPublicKey,
|
||||
to_ipk: nssa_core::encryption::IncomingViewingPublicKey,
|
||||
to_npk: NullifierPublicKey,
|
||||
to_ipk: IncomingViewingPublicKey,
|
||||
balance_to_move: u128,
|
||||
) -> Result<(SendTxResponse, nssa_core::SharedSecretKey), ExecutionFailureKind> {
|
||||
let from_data = self.storage.user_data.get_private_account(&from).cloned();
|
||||
|
||||
let Some((from_keys, mut from_acc)) = from_data else {
|
||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||
let Some((from_keys, from_acc)) =
|
||||
self.storage.user_data.get_private_account(&from).cloned()
|
||||
else {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let to_acc = nssa_core::account::Account::default();
|
||||
|
||||
if from_acc.balance >= balance_to_move {
|
||||
let program = nssa::program::Program::authenticated_transfer_program();
|
||||
let program = Program::authenticated_transfer_program();
|
||||
|
||||
from_acc.program_owner = program.id();
|
||||
let from_npk = from_keys.nullifer_public_key;
|
||||
let from_ipk = from_keys.incoming_viewing_public_key;
|
||||
|
||||
let sender_commitment =
|
||||
nssa_core::Commitment::new(&from_keys.nullifer_public_key, &from_acc);
|
||||
let sender_commitment = Commitment::new(&from_npk, &from_acc);
|
||||
|
||||
let sender_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: from_acc.clone(),
|
||||
is_authorized: true,
|
||||
account_id: (&from_keys.nullifer_public_key).into(),
|
||||
};
|
||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, &from_npk);
|
||||
|
||||
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: to_acc.clone(),
|
||||
is_authorized: false,
|
||||
account_id: (&to_npk).into(),
|
||||
};
|
||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
|
||||
|
||||
let eph_holder = EphemeralKeyHolder::new(
|
||||
to_npk.clone(),
|
||||
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
||||
from_acc.nonce.try_into().unwrap(),
|
||||
);
|
||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
||||
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 (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[1, 2],
|
||||
&[from_acc.nonce + 1, to_acc.nonce + 1],
|
||||
&produce_random_nonces(2),
|
||||
&[
|
||||
(from_keys.nullifer_public_key.clone(), shared_secret.clone()),
|
||||
(to_npk.clone(), shared_secret.clone()),
|
||||
(from_npk.clone(), shared_secret_from.clone()),
|
||||
(to_npk.clone(), shared_secret_to.clone()),
|
||||
],
|
||||
&[(
|
||||
from_keys.private_key_holder.nullifier_secret_key,
|
||||
@ -69,105 +66,83 @@ impl WalletCore {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let message =
|
||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(
|
||||
from_keys.nullifer_public_key.clone(),
|
||||
from_keys.incoming_viewing_public_key.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
),
|
||||
(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
),
|
||||
],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(
|
||||
from_npk.clone(),
|
||||
from_ipk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
),
|
||||
(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
),
|
||||
],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let witness_set =
|
||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||
&message,
|
||||
proof,
|
||||
&[],
|
||||
);
|
||||
let witness_set = WitnessSet::for_message(&message, proof, &[]);
|
||||
|
||||
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
||||
message,
|
||||
witness_set,
|
||||
);
|
||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||
|
||||
Ok((
|
||||
self.sequencer_client.send_tx_private(tx).await?,
|
||||
shared_secret,
|
||||
[shared_secret_from, shared_secret_to],
|
||||
))
|
||||
} else {
|
||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_private_native_token_transfer(
|
||||
pub async fn send_private_native_token_transfer_owned_account(
|
||||
&self,
|
||||
from: Address,
|
||||
to: Address,
|
||||
balance_to_move: u128,
|
||||
) -> Result<(SendTxResponse, nssa_core::SharedSecretKey), ExecutionFailureKind> {
|
||||
let from_data = self.storage.user_data.get_private_account(&from).cloned();
|
||||
let to_data = self.storage.user_data.get_private_account(&to).cloned();
|
||||
|
||||
let Some((from_keys, mut from_acc)) = from_data else {
|
||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||
let Some((from_keys, from_acc)) =
|
||||
self.storage.user_data.get_private_account(&from).cloned()
|
||||
else {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let Some((to_keys, mut to_acc)) = to_data else {
|
||||
let Some((to_keys, to_acc)) = self.storage.user_data.get_private_account(&to).cloned()
|
||||
else {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let from_npk = from_keys.nullifer_public_key;
|
||||
let from_ipk = from_keys.incoming_viewing_public_key;
|
||||
let to_npk = to_keys.nullifer_public_key.clone();
|
||||
let to_ipk = to_keys.incoming_viewing_public_key.clone();
|
||||
|
||||
if from_acc.balance >= balance_to_move {
|
||||
let program = nssa::program::Program::authenticated_transfer_program();
|
||||
let program = Program::authenticated_transfer_program();
|
||||
|
||||
from_acc.program_owner = program.id();
|
||||
to_acc.program_owner = program.id();
|
||||
let sender_commitment = Commitment::new(&from_npk, &from_acc);
|
||||
let receiver_commitment = Commitment::new(&to_npk, &to_acc);
|
||||
|
||||
let sender_commitment =
|
||||
nssa_core::Commitment::new(&from_keys.nullifer_public_key, &from_acc);
|
||||
let receiver_commitment =
|
||||
nssa_core::Commitment::new(&to_keys.nullifer_public_key, &to_acc);
|
||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, &from_npk);
|
||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), true, &to_npk);
|
||||
|
||||
let sender_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: from_acc.clone(),
|
||||
is_authorized: true,
|
||||
account_id: (&from_keys.nullifer_public_key).into(),
|
||||
};
|
||||
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: to_acc.clone(),
|
||||
is_authorized: true,
|
||||
account_id: (&to_npk).into(),
|
||||
};
|
||||
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
|
||||
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
|
||||
|
||||
let eph_holder = EphemeralKeyHolder::new(
|
||||
to_npk.clone(),
|
||||
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
||||
from_acc.nonce.try_into().unwrap(),
|
||||
);
|
||||
let eph_holder_to = EphemeralKeyHolder::new(&to_npk);
|
||||
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_ipk);
|
||||
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
||||
|
||||
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[1, 1],
|
||||
&[from_acc.nonce + 1, to_acc.nonce + 1],
|
||||
&produce_random_nonces(2),
|
||||
&[
|
||||
(from_keys.nullifer_public_key.clone(), shared_secret.clone()),
|
||||
(to_npk.clone(), shared_secret.clone()),
|
||||
(from_npk.clone(), shared_secret_from.clone()),
|
||||
(to_npk.clone(), shared_secret_to.clone()),
|
||||
],
|
||||
&[
|
||||
(
|
||||
@ -191,41 +166,31 @@ impl WalletCore {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let message =
|
||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(
|
||||
from_keys.nullifer_public_key.clone(),
|
||||
from_keys.incoming_viewing_public_key.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
),
|
||||
(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
),
|
||||
],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(
|
||||
from_npk.clone(),
|
||||
from_ipk.clone(),
|
||||
eph_holder_from.generate_ephemeral_public_key(),
|
||||
),
|
||||
(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
eph_holder_to.generate_ephemeral_public_key(),
|
||||
),
|
||||
],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let witness_set =
|
||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||
&message,
|
||||
proof,
|
||||
&[],
|
||||
);
|
||||
|
||||
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
||||
message,
|
||||
witness_set,
|
||||
);
|
||||
let witness_set = WitnessSet::for_message(&message, proof, &[]);
|
||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||
|
||||
Ok((
|
||||
self.sequencer_client.send_tx_private(tx).await?,
|
||||
shared_secret,
|
||||
[shared_secret_from, shared_secret_to],
|
||||
))
|
||||
} else {
|
||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
use common::{ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||
use nssa::Address;
|
||||
use nssa::{
|
||||
Address, PublicTransaction,
|
||||
program::Program,
|
||||
public_transaction::{Message, WitnessSet},
|
||||
};
|
||||
|
||||
use crate::WalletCore;
|
||||
|
||||
@ -20,14 +24,8 @@ impl WalletCore {
|
||||
};
|
||||
|
||||
let addresses = vec![from, to];
|
||||
let program_id = nssa::program::Program::authenticated_transfer_program().id();
|
||||
let message = nssa::public_transaction::Message::try_new(
|
||||
program_id,
|
||||
addresses,
|
||||
nonces,
|
||||
balance_to_move,
|
||||
)
|
||||
.unwrap();
|
||||
let program_id = Program::authenticated_transfer_program().id();
|
||||
let message = Message::try_new(program_id, addresses, nonces, balance_to_move).unwrap();
|
||||
|
||||
let signing_key = self.storage.user_data.get_pub_account_signing_key(&from);
|
||||
|
||||
@ -35,10 +33,9 @@ impl WalletCore {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let witness_set =
|
||||
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]);
|
||||
let witness_set = WitnessSet::for_message(&message, &[signing_key]);
|
||||
|
||||
let tx = nssa::PublicTransaction::new(message, witness_set);
|
||||
let tx = PublicTransaction::new(message, witness_set);
|
||||
|
||||
Ok(self.sequencer_client.send_tx_public(tx).await?)
|
||||
} else {
|
||||
|
||||
@ -1,24 +1,30 @@
|
||||
use common::{ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||
use key_protocol::key_management::ephemeral_key_holder::produce_one_sided_shared_secret_receiver;
|
||||
use nssa::Address;
|
||||
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||
use nssa::{
|
||||
Account, Address, PrivacyPreservingTransaction,
|
||||
privacy_preserving_transaction::{circuit, message::Message, witness_set::WitnessSet},
|
||||
program::Program,
|
||||
};
|
||||
use nssa_core::{
|
||||
Commitment, NullifierPublicKey, SharedSecretKey, account::AccountWithMetadata,
|
||||
encryption::IncomingViewingPublicKey,
|
||||
};
|
||||
|
||||
use crate::WalletCore;
|
||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
||||
|
||||
impl WalletCore {
|
||||
pub async fn send_shiedled_native_token_transfer(
|
||||
pub async fn send_shielded_native_token_transfer(
|
||||
&self,
|
||||
from: Address,
|
||||
to: Address,
|
||||
balance_to_move: u128,
|
||||
) -> Result<(SendTxResponse, nssa_core::SharedSecretKey), ExecutionFailureKind> {
|
||||
let from_data = self.get_account(from).await;
|
||||
let to_data = self.storage.user_data.get_private_account(&to).cloned();
|
||||
|
||||
let Ok(from_acc) = from_data else {
|
||||
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||
let Ok(from_acc) = self.get_account_public(from).await else {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let Some((to_keys, mut to_acc)) = to_data else {
|
||||
let Some((to_keys, to_acc)) = self.storage.user_data.get_private_account(&to).cloned()
|
||||
else {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
@ -26,31 +32,21 @@ impl WalletCore {
|
||||
let to_ipk = to_keys.incoming_viewing_public_key.clone();
|
||||
|
||||
if from_acc.balance >= balance_to_move {
|
||||
let program = nssa::program::Program::authenticated_transfer_program();
|
||||
let program = Program::authenticated_transfer_program();
|
||||
|
||||
to_acc.program_owner = program.id();
|
||||
let receiver_commitment = Commitment::new(&to_npk, &to_acc);
|
||||
|
||||
let receiver_commitment =
|
||||
nssa_core::Commitment::new(&to_keys.nullifer_public_key, &to_acc);
|
||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), true, &to_npk);
|
||||
|
||||
let sender_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: from_acc.clone(),
|
||||
is_authorized: true,
|
||||
account_id: (&from).into(),
|
||||
};
|
||||
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: to_acc.clone(),
|
||||
is_authorized: true,
|
||||
account_id: (&to_npk).into(),
|
||||
};
|
||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||
|
||||
let (shared_secret, epk) = produce_one_sided_shared_secret_receiver(&to_ipk);
|
||||
|
||||
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[0, 1],
|
||||
&[to_acc.nonce + 1],
|
||||
&produce_random_nonces(1),
|
||||
&[(to_npk.clone(), shared_secret.clone())],
|
||||
&[(
|
||||
to_keys.private_key_holder.nullifier_secret_key,
|
||||
@ -64,14 +60,17 @@ impl WalletCore {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let message =
|
||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
||||
vec![from],
|
||||
vec![from_acc.nonce],
|
||||
vec![(to_npk.clone(), to_ipk.clone(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![from],
|
||||
vec![from_acc.nonce],
|
||||
vec![(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let signing_key = self.storage.user_data.get_pub_account_signing_key(&from);
|
||||
|
||||
@ -79,17 +78,9 @@ impl WalletCore {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let witness_set =
|
||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||
&message,
|
||||
proof,
|
||||
&[signing_key],
|
||||
);
|
||||
let witness_set = WitnessSet::for_message(&message, proof, &[signing_key]);
|
||||
|
||||
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
||||
message,
|
||||
witness_set,
|
||||
);
|
||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||
|
||||
Ok((
|
||||
self.sequencer_client.send_tx_private(tx).await?,
|
||||
@ -100,57 +91,50 @@ impl WalletCore {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_shielded_native_token_transfer_maybe_outer_account(
|
||||
pub async fn send_shielded_native_token_transfer_outer_account(
|
||||
&self,
|
||||
from: Address,
|
||||
to_npk: nssa_core::NullifierPublicKey,
|
||||
to_ipk: nssa_core::encryption::IncomingViewingPublicKey,
|
||||
to_npk: NullifierPublicKey,
|
||||
to_ipk: IncomingViewingPublicKey,
|
||||
balance_to_move: u128,
|
||||
) -> Result<(SendTxResponse, nssa_core::SharedSecretKey), ExecutionFailureKind> {
|
||||
let from_data = self.get_account(from).await;
|
||||
|
||||
let Ok(from_acc) = from_data else {
|
||||
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||
let Ok(from_acc) = self.get_account_public(from).await else {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let to_acc = nssa_core::account::Account::default();
|
||||
let to_acc = Account::default();
|
||||
|
||||
if from_acc.balance >= balance_to_move {
|
||||
let program = nssa::program::Program::authenticated_transfer_program();
|
||||
let program = Program::authenticated_transfer_program();
|
||||
|
||||
let sender_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: from_acc.clone(),
|
||||
is_authorized: true,
|
||||
account_id: (&from).into(),
|
||||
};
|
||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
|
||||
|
||||
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||
account: to_acc.clone(),
|
||||
is_authorized: false,
|
||||
account_id: (&to_npk).into(),
|
||||
};
|
||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||
|
||||
let (shared_secret, epk) = produce_one_sided_shared_secret_receiver(&to_ipk);
|
||||
|
||||
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
&[sender_pre, recipient_pre],
|
||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[0, 2],
|
||||
&[to_acc.nonce + 1],
|
||||
&produce_random_nonces(1),
|
||||
&[(to_npk.clone(), shared_secret.clone())],
|
||||
&[],
|
||||
&program,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let message =
|
||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
||||
vec![from],
|
||||
vec![from_acc.nonce],
|
||||
vec![(to_npk.clone(), to_ipk.clone(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![from],
|
||||
vec![from_acc.nonce],
|
||||
vec![(
|
||||
to_npk.clone(),
|
||||
to_ipk.clone(),
|
||||
eph_holder.generate_ephemeral_public_key(),
|
||||
)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let signing_key = self.storage.user_data.get_pub_account_signing_key(&from);
|
||||
|
||||
@ -158,17 +142,8 @@ impl WalletCore {
|
||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||
};
|
||||
|
||||
let witness_set =
|
||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||
&message,
|
||||
proof,
|
||||
&[signing_key],
|
||||
);
|
||||
|
||||
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
||||
message,
|
||||
witness_set,
|
||||
);
|
||||
let witness_set = WitnessSet::for_message(&message, proof, &[signing_key]);
|
||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||
|
||||
Ok((
|
||||
self.sequencer_client.send_tx_private(tx).await?,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user