mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-03 22:03:06 +00:00
Merge branch 'main' into schouhy/add-sequencer-tps-test
This commit is contained in:
commit
ad9ad8d1d3
@ -11,6 +11,7 @@ members = [
|
|||||||
"sequencer_core",
|
"sequencer_core",
|
||||||
"common",
|
"common",
|
||||||
"nssa",
|
"nssa",
|
||||||
|
"integration_tests/proc_macro_test_attribute",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
|||||||
@ -17,6 +17,8 @@ borsh.workspace = true
|
|||||||
|
|
||||||
nssa-core = { path = "../nssa/core", features = ["host"] }
|
nssa-core = { path = "../nssa/core", features = ["host"] }
|
||||||
|
|
||||||
|
proc_macro_test_attribute = { path = "./proc_macro_test_attribute" }
|
||||||
|
|
||||||
[dependencies.clap]
|
[dependencies.clap]
|
||||||
features = ["derive", "env"]
|
features = ["derive", "env"]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|||||||
9
integration_tests/proc_macro_test_attribute/Cargo.toml
Normal file
9
integration_tests/proc_macro_test_attribute/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "proc_macro_test_attribute"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
49
integration_tests/proc_macro_test_attribute/src/lib.rs
Normal file
49
integration_tests/proc_macro_test_attribute/src/lib.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use proc_macro::*;
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn nssa_integration_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let input = item.to_string();
|
||||||
|
|
||||||
|
let fn_keyword = "fn ";
|
||||||
|
let fn_keyword_alternative = "fn\n";
|
||||||
|
|
||||||
|
let mut start_opt = None;
|
||||||
|
let mut fn_name = String::new();
|
||||||
|
|
||||||
|
if let Some(start) = input.find(fn_keyword) {
|
||||||
|
start_opt = Some(start);
|
||||||
|
} else if let Some(start) = input.find(fn_keyword_alternative) {
|
||||||
|
start_opt = Some(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(start) = start_opt {
|
||||||
|
let rest = &input[start + fn_keyword.len()..];
|
||||||
|
if let Some(end) = rest.find(|c: char| c == '(' || c.is_whitespace()) {
|
||||||
|
let name = &rest[..end];
|
||||||
|
fn_name = name.to_string();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("ERROR: keyword fn not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
let extension = format!(
|
||||||
|
r#"
|
||||||
|
{input}
|
||||||
|
|
||||||
|
function_map.insert("{fn_name}".to_string(), |home_dir: PathBuf| Box::pin(async {{
|
||||||
|
let res = pre_test(home_dir).await.unwrap();
|
||||||
|
|
||||||
|
info!("Waiting for first block creation");
|
||||||
|
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||||
|
|
||||||
|
{fn_name}().await;
|
||||||
|
|
||||||
|
post_test(res).await;
|
||||||
|
}}));
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
|
||||||
|
extension.parse().unwrap()
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
1655
integration_tests/src/test_suite_map.rs
Normal file
1655
integration_tests/src/test_suite_map.rs
Normal file
File diff suppressed because it is too large
Load Diff
3618
nssa/program_methods/guest/Cargo.lock
generated
Normal file
3618
nssa/program_methods/guest/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -224,7 +224,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
|
|||||||
|
|
||||||
let to_initialization = wallet_core.check_private_account_initialized(&to).await?;
|
let to_initialization = wallet_core.check_private_account_initialized(&to).await?;
|
||||||
|
|
||||||
let (res, secret) = if let Some(to_proof) = to_initialization {
|
let (res, [secret]) = if let Some(to_proof) = to_initialization {
|
||||||
wallet_core
|
wallet_core
|
||||||
.send_shielded_native_token_transfer_already_initialized(
|
.send_shielded_native_token_transfer_already_initialized(
|
||||||
from, to, amount, to_proof,
|
from, to, amount, to_proof,
|
||||||
@ -277,7 +277,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
|
|||||||
let to_ipk =
|
let to_ipk =
|
||||||
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec());
|
nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec());
|
||||||
|
|
||||||
let (res, _) = wallet_core
|
let res = wallet_core
|
||||||
.send_shielded_native_token_transfer_outer_account(from, to_npk, to_ipk, amount)
|
.send_shielded_native_token_transfer_outer_account(from, to_npk, to_ipk, amount)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommand {
|
|||||||
let from: Address = from.parse().unwrap();
|
let from: Address = from.parse().unwrap();
|
||||||
let to: Address = to.parse().unwrap();
|
let to: Address = to.parse().unwrap();
|
||||||
|
|
||||||
let (res, secret) = wallet_core
|
let (res, [secret]) = wallet_core
|
||||||
.send_deshielded_native_token_transfer(from, to, amount)
|
.send_deshielded_native_token_transfer(from, to, amount)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,7 @@ pub mod pinata_interactions;
|
|||||||
pub mod poller;
|
pub mod poller;
|
||||||
pub mod token_program_interactions;
|
pub mod token_program_interactions;
|
||||||
pub mod token_transfers;
|
pub mod token_transfers;
|
||||||
|
pub mod transaction_utils;
|
||||||
|
|
||||||
pub struct WalletCore {
|
pub struct WalletCore {
|
||||||
pub storage: WalletChainStore,
|
pub storage: WalletChainStore,
|
||||||
|
|||||||
@ -3,7 +3,9 @@ use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
|||||||
use nssa::{Address, privacy_preserving_transaction::circuit};
|
use nssa::{Address, privacy_preserving_transaction::circuit};
|
||||||
use nssa_core::{MembershipProof, SharedSecretKey, account::AccountWithMetadata};
|
use nssa_core::{MembershipProof, SharedSecretKey, account::AccountWithMetadata};
|
||||||
|
|
||||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
use crate::{
|
||||||
|
WalletCore, helperfunctions::produce_random_nonces, transaction_utils::AccountPreparedData,
|
||||||
|
};
|
||||||
|
|
||||||
impl WalletCore {
|
impl WalletCore {
|
||||||
pub async fn claim_pinata(
|
pub async fn claim_pinata(
|
||||||
@ -31,24 +33,21 @@ impl WalletCore {
|
|||||||
solution: u128,
|
solution: u128,
|
||||||
winner_proof: MembershipProof,
|
winner_proof: MembershipProof,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
let Some((winner_keys, winner_acc)) = self
|
let AccountPreparedData {
|
||||||
.storage
|
nsk: winner_nsk,
|
||||||
.user_data
|
npk: winner_npk,
|
||||||
.get_private_account(&winner_addr)
|
ipk: winner_ipk,
|
||||||
.cloned()
|
auth_acc: winner_pre,
|
||||||
else {
|
proof: _,
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
} = self
|
||||||
};
|
.private_acc_preparation(winner_addr, true, false)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let pinata_acc = self.get_account_public(pinata_addr).await.unwrap();
|
let pinata_acc = self.get_account_public(pinata_addr).await.unwrap();
|
||||||
|
|
||||||
let winner_npk = winner_keys.nullifer_public_key;
|
|
||||||
let winner_ipk = winner_keys.incoming_viewing_public_key;
|
|
||||||
|
|
||||||
let program = nssa::program::Program::pinata();
|
let program = nssa::program::Program::pinata();
|
||||||
|
|
||||||
let pinata_pre = AccountWithMetadata::new(pinata_acc.clone(), false, pinata_addr);
|
let pinata_pre = AccountWithMetadata::new(pinata_acc.clone(), false, pinata_addr);
|
||||||
let winner_pre = AccountWithMetadata::new(winner_acc.clone(), true, &winner_npk);
|
|
||||||
|
|
||||||
let eph_holder_winner = EphemeralKeyHolder::new(&winner_npk);
|
let eph_holder_winner = EphemeralKeyHolder::new(&winner_npk);
|
||||||
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_ipk);
|
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_ipk);
|
||||||
@ -59,10 +58,7 @@ impl WalletCore {
|
|||||||
&[0, 1],
|
&[0, 1],
|
||||||
&produce_random_nonces(1),
|
&produce_random_nonces(1),
|
||||||
&[(winner_npk.clone(), shared_secret_winner.clone())],
|
&[(winner_npk.clone(), shared_secret_winner.clone())],
|
||||||
&[(
|
&[(winner_nsk.unwrap(), winner_proof)],
|
||||||
winner_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
winner_proof,
|
|
||||||
)],
|
|
||||||
&program,
|
&program,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -103,24 +99,21 @@ impl WalletCore {
|
|||||||
winner_addr: Address,
|
winner_addr: Address,
|
||||||
solution: u128,
|
solution: u128,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
let Some((winner_keys, winner_acc)) = self
|
let AccountPreparedData {
|
||||||
.storage
|
nsk: _,
|
||||||
.user_data
|
npk: winner_npk,
|
||||||
.get_private_account(&winner_addr)
|
ipk: winner_ipk,
|
||||||
.cloned()
|
auth_acc: winner_pre,
|
||||||
else {
|
proof: _,
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
} = self
|
||||||
};
|
.private_acc_preparation(winner_addr, false, false)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let pinata_acc = self.get_account_public(pinata_addr).await.unwrap();
|
let pinata_acc = self.get_account_public(pinata_addr).await.unwrap();
|
||||||
|
|
||||||
let winner_npk = winner_keys.nullifer_public_key;
|
|
||||||
let winner_ipk = winner_keys.incoming_viewing_public_key;
|
|
||||||
|
|
||||||
let program = nssa::program::Program::pinata();
|
let program = nssa::program::Program::pinata();
|
||||||
|
|
||||||
let pinata_pre = AccountWithMetadata::new(pinata_acc.clone(), false, pinata_addr);
|
let pinata_pre = AccountWithMetadata::new(pinata_acc.clone(), false, pinata_addr);
|
||||||
let winner_pre = AccountWithMetadata::new(winner_acc.clone(), false, &winner_npk);
|
|
||||||
|
|
||||||
let eph_holder_winner = EphemeralKeyHolder::new(&winner_npk);
|
let eph_holder_winner = EphemeralKeyHolder::new(&winner_npk);
|
||||||
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_ipk);
|
let shared_secret_winner = eph_holder_winner.calculate_shared_secret_sender(&winner_ipk);
|
||||||
|
|||||||
@ -1,14 +1,50 @@
|
|||||||
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
use nssa::{Account, Address, program::Program};
|
||||||
use nssa::{Address, privacy_preserving_transaction::circuit, program::Program};
|
|
||||||
use nssa_core::{
|
use nssa_core::{
|
||||||
Commitment, MembershipProof, NullifierPublicKey, SharedSecretKey, account::AccountWithMetadata,
|
MembershipProof, NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey,
|
||||||
encryption::IncomingViewingPublicKey,
|
program::InstructionData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
use crate::WalletCore;
|
||||||
|
|
||||||
impl WalletCore {
|
impl WalletCore {
|
||||||
|
pub fn token_program_preparation_transfer(
|
||||||
|
amount: u128,
|
||||||
|
) -> (
|
||||||
|
InstructionData,
|
||||||
|
Program,
|
||||||
|
impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
) {
|
||||||
|
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 || 0x00 || 0x00 || 0x00].
|
||||||
|
let mut instruction = [0; 23];
|
||||||
|
instruction[0] = 0x01;
|
||||||
|
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
||||||
|
let instruction_data = Program::serialize_instruction(instruction).unwrap();
|
||||||
|
let program = Program::token();
|
||||||
|
let tx_pre_check = |_: &Account, _: &Account| Ok(());
|
||||||
|
|
||||||
|
(instruction_data, program, tx_pre_check)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn token_program_preparation_definition(
|
||||||
|
name: [u8; 6],
|
||||||
|
total_supply: u128,
|
||||||
|
) -> (
|
||||||
|
InstructionData,
|
||||||
|
Program,
|
||||||
|
impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
) {
|
||||||
|
// Instruction must be: [0x00 || total_supply (little-endian 16 bytes) || name (6 bytes)]
|
||||||
|
let mut instruction = [0; 23];
|
||||||
|
instruction[1..17].copy_from_slice(&total_supply.to_le_bytes());
|
||||||
|
instruction[17..].copy_from_slice(&name);
|
||||||
|
let instruction_data = Program::serialize_instruction(instruction).unwrap();
|
||||||
|
let program = Program::token();
|
||||||
|
let tx_pre_check = |_: &Account, _: &Account| Ok(());
|
||||||
|
|
||||||
|
(instruction_data, program, tx_pre_check)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn send_new_token_definition(
|
pub async fn send_new_token_definition(
|
||||||
&self,
|
&self,
|
||||||
definition_address: Address,
|
definition_address: Address,
|
||||||
@ -40,71 +76,19 @@ impl WalletCore {
|
|||||||
name: [u8; 6],
|
name: [u8; 6],
|
||||||
total_supply: u128,
|
total_supply: u128,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
let Some((supply_keys, supply_acc)) = self
|
let (instruction_data, program, tx_pre_check) =
|
||||||
.storage
|
WalletCore::token_program_preparation_definition(name, total_supply);
|
||||||
.user_data
|
|
||||||
.get_private_account(&supply_addr)
|
|
||||||
.cloned()
|
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
//It makes more sence to have definition acc as public
|
// Kind of non-obvious naming
|
||||||
let definition_acc = self.get_account_public(definition_addr).await.unwrap();
|
// Basically this funtion is called because authentication mask is [0, 2]
|
||||||
|
self.shielded_two_accs_receiver_uninit(
|
||||||
let supply_npk = supply_keys.nullifer_public_key;
|
definition_addr,
|
||||||
let supply_ipk = supply_keys.incoming_viewing_public_key;
|
supply_addr,
|
||||||
|
instruction_data,
|
||||||
let program = nssa::program::Program::token();
|
tx_pre_check,
|
||||||
|
program,
|
||||||
let definition_pre =
|
|
||||||
AccountWithMetadata::new(definition_acc.clone(), false, definition_addr);
|
|
||||||
let supply_pre = AccountWithMetadata::new(supply_acc.clone(), false, &supply_npk);
|
|
||||||
|
|
||||||
let eph_holder_supply = EphemeralKeyHolder::new(&supply_npk);
|
|
||||||
let shared_secret_supply = eph_holder_supply.calculate_shared_secret_sender(&supply_ipk);
|
|
||||||
|
|
||||||
// Instruction must be: [0x00 || total_supply (little-endian 16 bytes) || name (6 bytes)]
|
|
||||||
let mut instruction = [0; 23];
|
|
||||||
instruction[1..17].copy_from_slice(&total_supply.to_le_bytes());
|
|
||||||
instruction[17..].copy_from_slice(&name);
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[definition_pre, supply_pre],
|
|
||||||
&nssa::program::Program::serialize_instruction(instruction).unwrap(),
|
|
||||||
&[0, 2],
|
|
||||||
&produce_random_nonces(1),
|
|
||||||
&[(supply_npk.clone(), shared_secret_supply.clone())],
|
|
||||||
&[],
|
|
||||||
&program,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.await
|
||||||
|
|
||||||
let message =
|
|
||||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
|
||||||
vec![definition_addr],
|
|
||||||
vec![],
|
|
||||||
vec![(
|
|
||||||
supply_npk.clone(),
|
|
||||||
supply_ipk.clone(),
|
|
||||||
eph_holder_supply.generate_ephemeral_public_key(),
|
|
||||||
)],
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
let tx = nssa::PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_supply],
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction(
|
pub async fn send_transfer_token_transaction(
|
||||||
@ -148,107 +132,18 @@ impl WalletCore {
|
|||||||
amount: u128,
|
amount: u128,
|
||||||
recipient_proof: MembershipProof,
|
recipient_proof: MembershipProof,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||||
let Some((sender_keys, sender_acc)) = self
|
let (instruction_data, program, tx_pre_check) =
|
||||||
.storage
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
.user_data
|
|
||||||
.get_private_account(&sender_address)
|
|
||||||
.cloned()
|
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some((recipient_keys, recipient_acc)) = self
|
self.private_tx_two_accs_all_init(
|
||||||
.storage
|
sender_address,
|
||||||
.user_data
|
recipient_address,
|
||||||
.get_private_account(&recipient_address)
|
instruction_data,
|
||||||
.cloned()
|
tx_pre_check,
|
||||||
else {
|
program,
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
recipient_proof,
|
||||||
};
|
|
||||||
|
|
||||||
let sender_npk = sender_keys.nullifer_public_key;
|
|
||||||
let sender_ipk = sender_keys.incoming_viewing_public_key;
|
|
||||||
let recipient_npk = recipient_keys.nullifer_public_key.clone();
|
|
||||||
let recipient_ipk = recipient_keys.incoming_viewing_public_key.clone();
|
|
||||||
|
|
||||||
let program = Program::token();
|
|
||||||
|
|
||||||
let sender_commitment = Commitment::new(&sender_npk, &sender_acc);
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(sender_acc.clone(), true, &sender_npk);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(recipient_acc.clone(), true, &recipient_npk);
|
|
||||||
|
|
||||||
let eph_holder_sender = EphemeralKeyHolder::new(&sender_npk);
|
|
||||||
let shared_secret_sender = eph_holder_sender.calculate_shared_secret_sender(&sender_ipk);
|
|
||||||
|
|
||||||
let eph_holder_recipient = EphemeralKeyHolder::new(&recipient_npk);
|
|
||||||
let shared_secret_recipient =
|
|
||||||
eph_holder_recipient.calculate_shared_secret_sender(&recipient_ipk);
|
|
||||||
|
|
||||||
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 || 0x00 || 0x00 || 0x00].
|
|
||||||
let mut instruction = [0; 23];
|
|
||||||
instruction[0] = 0x01;
|
|
||||||
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(instruction).unwrap(),
|
|
||||||
&[1, 1],
|
|
||||||
&produce_random_nonces(2),
|
|
||||||
&[
|
|
||||||
(sender_npk.clone(), shared_secret_sender.clone()),
|
|
||||||
(recipient_npk.clone(), shared_secret_recipient.clone()),
|
|
||||||
],
|
|
||||||
&[
|
|
||||||
(
|
|
||||||
sender_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
recipient_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
recipient_proof,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
&program,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.await
|
||||||
|
|
||||||
let message =
|
|
||||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
|
||||||
vec![],
|
|
||||||
vec![],
|
|
||||||
vec![
|
|
||||||
(
|
|
||||||
sender_npk.clone(),
|
|
||||||
sender_ipk.clone(),
|
|
||||||
eph_holder_sender.generate_ephemeral_public_key(),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
recipient_npk.clone(),
|
|
||||||
recipient_ipk.clone(),
|
|
||||||
eph_holder_recipient.generate_ephemeral_public_key(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
let tx = nssa::PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_sender, shared_secret_recipient],
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_private_owned_account_not_initialized(
|
pub async fn send_transfer_token_transaction_private_owned_account_not_initialized(
|
||||||
@ -257,101 +152,17 @@ impl WalletCore {
|
|||||||
recipient_address: Address,
|
recipient_address: Address,
|
||||||
amount: u128,
|
amount: u128,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||||
let Some((sender_keys, sender_acc)) = self
|
let (instruction_data, program, tx_pre_check) =
|
||||||
.storage
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
.user_data
|
|
||||||
.get_private_account(&sender_address)
|
|
||||||
.cloned()
|
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some((recipient_keys, recipient_acc)) = self
|
self.private_tx_two_accs_receiver_uninit(
|
||||||
.storage
|
sender_address,
|
||||||
.user_data
|
recipient_address,
|
||||||
.get_private_account(&recipient_address)
|
instruction_data,
|
||||||
.cloned()
|
tx_pre_check,
|
||||||
else {
|
program,
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let sender_npk = sender_keys.nullifer_public_key;
|
|
||||||
let sender_ipk = sender_keys.incoming_viewing_public_key;
|
|
||||||
let recipient_npk = recipient_keys.nullifer_public_key.clone();
|
|
||||||
let recipient_ipk = recipient_keys.incoming_viewing_public_key.clone();
|
|
||||||
|
|
||||||
let program = Program::token();
|
|
||||||
|
|
||||||
let sender_commitment = Commitment::new(&sender_npk, &sender_acc);
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(sender_acc.clone(), true, &sender_npk);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(recipient_acc.clone(), false, &recipient_npk);
|
|
||||||
|
|
||||||
let eph_holder_sender = EphemeralKeyHolder::new(&sender_npk);
|
|
||||||
let shared_secret_sender = eph_holder_sender.calculate_shared_secret_sender(&sender_ipk);
|
|
||||||
|
|
||||||
let eph_holder_recipient = EphemeralKeyHolder::new(&recipient_npk);
|
|
||||||
let shared_secret_recipient =
|
|
||||||
eph_holder_recipient.calculate_shared_secret_sender(&recipient_ipk);
|
|
||||||
|
|
||||||
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 || 0x00 || 0x00 || 0x00].
|
|
||||||
let mut instruction = [0; 23];
|
|
||||||
instruction[0] = 0x01;
|
|
||||||
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(instruction).unwrap(),
|
|
||||||
&[1, 2],
|
|
||||||
&produce_random_nonces(2),
|
|
||||||
&[
|
|
||||||
(sender_npk.clone(), shared_secret_sender.clone()),
|
|
||||||
(recipient_npk.clone(), shared_secret_recipient.clone()),
|
|
||||||
],
|
|
||||||
&[(
|
|
||||||
sender_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
)],
|
|
||||||
&program,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.await
|
||||||
|
|
||||||
let message =
|
|
||||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
|
||||||
vec![],
|
|
||||||
vec![],
|
|
||||||
vec![
|
|
||||||
(
|
|
||||||
sender_npk.clone(),
|
|
||||||
sender_ipk.clone(),
|
|
||||||
eph_holder_sender.generate_ephemeral_public_key(),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
recipient_npk.clone(),
|
|
||||||
recipient_ipk.clone(),
|
|
||||||
eph_holder_recipient.generate_ephemeral_public_key(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
let tx = nssa::PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_sender, shared_secret_recipient],
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_private_foreign_account(
|
pub async fn send_transfer_token_transaction_private_foreign_account(
|
||||||
@ -361,92 +172,18 @@ impl WalletCore {
|
|||||||
recipient_ipk: IncomingViewingPublicKey,
|
recipient_ipk: IncomingViewingPublicKey,
|
||||||
amount: u128,
|
amount: u128,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||||
let Some((sender_keys, sender_acc)) = self
|
let (instruction_data, program, tx_pre_check) =
|
||||||
.storage
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
.user_data
|
|
||||||
.get_private_account(&sender_address)
|
|
||||||
.cloned()
|
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let recipient_acc = nssa_core::account::Account::default();
|
self.private_tx_two_accs_receiver_outer(
|
||||||
|
sender_address,
|
||||||
let sender_npk = sender_keys.nullifer_public_key;
|
recipient_npk,
|
||||||
let sender_ipk = sender_keys.incoming_viewing_public_key;
|
recipient_ipk,
|
||||||
|
instruction_data,
|
||||||
let program = Program::token();
|
tx_pre_check,
|
||||||
|
program,
|
||||||
let sender_commitment = Commitment::new(&sender_npk, &sender_acc);
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(sender_acc.clone(), true, &sender_npk);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(recipient_acc.clone(), false, &recipient_npk);
|
|
||||||
|
|
||||||
let eph_holder_sender = EphemeralKeyHolder::new(&sender_npk);
|
|
||||||
let shared_secret_sender = eph_holder_sender.calculate_shared_secret_sender(&sender_ipk);
|
|
||||||
|
|
||||||
let eph_holder_recipient = EphemeralKeyHolder::new(&recipient_npk);
|
|
||||||
let shared_secret_recipient =
|
|
||||||
eph_holder_recipient.calculate_shared_secret_sender(&recipient_ipk);
|
|
||||||
|
|
||||||
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 || 0x00 || 0x00 || 0x00].
|
|
||||||
let mut instruction = [0; 23];
|
|
||||||
instruction[0] = 0x01;
|
|
||||||
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(instruction).unwrap(),
|
|
||||||
&[1, 2],
|
|
||||||
&produce_random_nonces(2),
|
|
||||||
&[
|
|
||||||
(sender_npk.clone(), shared_secret_sender.clone()),
|
|
||||||
(recipient_npk.clone(), shared_secret_recipient.clone()),
|
|
||||||
],
|
|
||||||
&[(
|
|
||||||
sender_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
)],
|
|
||||||
&program,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.await
|
||||||
|
|
||||||
let message =
|
|
||||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
|
||||||
vec![],
|
|
||||||
vec![],
|
|
||||||
vec![
|
|
||||||
(
|
|
||||||
sender_npk.clone(),
|
|
||||||
sender_ipk.clone(),
|
|
||||||
eph_holder_sender.generate_ephemeral_public_key(),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
recipient_npk.clone(),
|
|
||||||
recipient_ipk.clone(),
|
|
||||||
eph_holder_recipient.generate_ephemeral_public_key(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
let tx = nssa::PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_sender, shared_secret_recipient],
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_deshielded(
|
pub async fn send_transfer_token_transaction_deshielded(
|
||||||
@ -455,81 +192,17 @@ impl WalletCore {
|
|||||||
recipient_address: Address,
|
recipient_address: Address,
|
||||||
amount: u128,
|
amount: u128,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
let Some((sender_keys, sender_acc)) = self
|
let (instruction_data, program, tx_pre_check) =
|
||||||
.storage
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
.user_data
|
|
||||||
.get_private_account(&sender_address)
|
|
||||||
.cloned()
|
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Ok(recipient_acc) = self.get_account_public(recipient_address).await else {
|
self.deshielded_tx_two_accs(
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
sender_address,
|
||||||
};
|
recipient_address,
|
||||||
|
instruction_data,
|
||||||
let sender_npk = sender_keys.nullifer_public_key;
|
tx_pre_check,
|
||||||
let sender_ipk = sender_keys.incoming_viewing_public_key;
|
program,
|
||||||
|
|
||||||
let program = Program::token();
|
|
||||||
|
|
||||||
let sender_commitment = Commitment::new(&sender_npk, &sender_acc);
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(sender_acc.clone(), true, &sender_npk);
|
|
||||||
let recipient_pre =
|
|
||||||
AccountWithMetadata::new(recipient_acc.clone(), false, recipient_address);
|
|
||||||
|
|
||||||
let eph_holder_sender = EphemeralKeyHolder::new(&sender_npk);
|
|
||||||
let shared_secret_sender = eph_holder_sender.calculate_shared_secret_sender(&sender_ipk);
|
|
||||||
|
|
||||||
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 || 0x00 || 0x00 || 0x00].
|
|
||||||
let mut instruction = [0; 23];
|
|
||||||
instruction[0] = 0x01;
|
|
||||||
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(instruction).unwrap(),
|
|
||||||
&[1, 0],
|
|
||||||
&produce_random_nonces(1),
|
|
||||||
&[(sender_npk.clone(), shared_secret_sender.clone())],
|
|
||||||
&[(
|
|
||||||
sender_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
)],
|
|
||||||
&program,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.await
|
||||||
|
|
||||||
let message =
|
|
||||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
|
||||||
vec![recipient_address],
|
|
||||||
vec![],
|
|
||||||
vec![(
|
|
||||||
sender_npk.clone(),
|
|
||||||
sender_ipk.clone(),
|
|
||||||
eph_holder_sender.generate_ephemeral_public_key(),
|
|
||||||
)],
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
let tx = nssa::PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_sender],
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_shielded_owned_account_already_initialized(
|
pub async fn send_transfer_token_transaction_shielded_owned_account_already_initialized(
|
||||||
@ -539,83 +212,18 @@ impl WalletCore {
|
|||||||
amount: u128,
|
amount: u128,
|
||||||
recipient_proof: MembershipProof,
|
recipient_proof: MembershipProof,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
let Ok(sender_acc) = self.get_account_public(sender_address).await else {
|
let (instruction_data, program, tx_pre_check) =
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
};
|
|
||||||
|
|
||||||
let Some(sender_priv_key) = self
|
self.shielded_two_accs_all_init(
|
||||||
.storage
|
sender_address,
|
||||||
.user_data
|
recipient_address,
|
||||||
.get_pub_account_signing_key(&sender_address)
|
instruction_data,
|
||||||
else {
|
tx_pre_check,
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
program,
|
||||||
};
|
recipient_proof,
|
||||||
|
|
||||||
let Some((recipient_keys, recipient_acc)) = self
|
|
||||||
.storage
|
|
||||||
.user_data
|
|
||||||
.get_private_account(&recipient_address)
|
|
||||||
.cloned()
|
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let recipient_npk = recipient_keys.nullifer_public_key.clone();
|
|
||||||
let recipient_ipk = recipient_keys.incoming_viewing_public_key.clone();
|
|
||||||
|
|
||||||
let program = Program::token();
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(sender_acc.clone(), true, sender_address);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(recipient_acc.clone(), true, &recipient_npk);
|
|
||||||
|
|
||||||
let eph_holder_recipient = EphemeralKeyHolder::new(&recipient_npk);
|
|
||||||
let shared_secret_recipient =
|
|
||||||
eph_holder_recipient.calculate_shared_secret_sender(&recipient_ipk);
|
|
||||||
|
|
||||||
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 || 0x00 || 0x00 || 0x00].
|
|
||||||
let mut instruction = [0; 23];
|
|
||||||
instruction[0] = 0x01;
|
|
||||||
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(instruction).unwrap(),
|
|
||||||
&[0, 1],
|
|
||||||
&produce_random_nonces(1),
|
|
||||||
&[(recipient_npk.clone(), shared_secret_recipient.clone())],
|
|
||||||
&[(
|
|
||||||
recipient_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
recipient_proof,
|
|
||||||
)],
|
|
||||||
&program,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.await
|
||||||
|
|
||||||
let message =
|
|
||||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
|
||||||
vec![sender_address],
|
|
||||||
vec![sender_acc.nonce],
|
|
||||||
vec![(
|
|
||||||
recipient_npk.clone(),
|
|
||||||
recipient_ipk.clone(),
|
|
||||||
eph_holder_recipient.generate_ephemeral_public_key(),
|
|
||||||
)],
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[sender_priv_key],
|
|
||||||
);
|
|
||||||
let tx = nssa::PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_recipient],
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_shielded_owned_account_not_initialized(
|
pub async fn send_transfer_token_transaction_shielded_owned_account_not_initialized(
|
||||||
@ -624,80 +232,17 @@ impl WalletCore {
|
|||||||
recipient_address: Address,
|
recipient_address: Address,
|
||||||
amount: u128,
|
amount: u128,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
let Ok(sender_acc) = self.get_account_public(sender_address).await else {
|
let (instruction_data, program, tx_pre_check) =
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
};
|
|
||||||
|
|
||||||
let Some(sender_priv_key) = self
|
self.shielded_two_accs_receiver_uninit(
|
||||||
.storage
|
sender_address,
|
||||||
.user_data
|
recipient_address,
|
||||||
.get_pub_account_signing_key(&sender_address)
|
instruction_data,
|
||||||
else {
|
tx_pre_check,
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
program,
|
||||||
};
|
|
||||||
|
|
||||||
let Some((recipient_keys, recipient_acc)) = self
|
|
||||||
.storage
|
|
||||||
.user_data
|
|
||||||
.get_private_account(&recipient_address)
|
|
||||||
.cloned()
|
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let recipient_npk = recipient_keys.nullifer_public_key.clone();
|
|
||||||
let recipient_ipk = recipient_keys.incoming_viewing_public_key.clone();
|
|
||||||
|
|
||||||
let program = Program::token();
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(sender_acc.clone(), true, sender_address);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(recipient_acc.clone(), false, &recipient_npk);
|
|
||||||
|
|
||||||
let eph_holder_recipient = EphemeralKeyHolder::new(&recipient_npk);
|
|
||||||
let shared_secret_recipient =
|
|
||||||
eph_holder_recipient.calculate_shared_secret_sender(&recipient_ipk);
|
|
||||||
|
|
||||||
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 || 0x00 || 0x00 || 0x00].
|
|
||||||
let mut instruction = [0; 23];
|
|
||||||
instruction[0] = 0x01;
|
|
||||||
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(instruction).unwrap(),
|
|
||||||
&[0, 2],
|
|
||||||
&produce_random_nonces(1),
|
|
||||||
&[(recipient_npk.clone(), shared_secret_recipient.clone())],
|
|
||||||
&[],
|
|
||||||
&program,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.await
|
||||||
|
|
||||||
let message =
|
|
||||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
|
||||||
vec![sender_address],
|
|
||||||
vec![sender_acc.nonce],
|
|
||||||
vec![(
|
|
||||||
recipient_npk.clone(),
|
|
||||||
recipient_ipk.clone(),
|
|
||||||
eph_holder_recipient.generate_ephemeral_public_key(),
|
|
||||||
)],
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[sender_priv_key],
|
|
||||||
);
|
|
||||||
let tx = nssa::PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_recipient],
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_shielded_foreign_account(
|
pub async fn send_transfer_token_transaction_shielded_foreign_account(
|
||||||
@ -707,66 +252,17 @@ impl WalletCore {
|
|||||||
recipient_ipk: IncomingViewingPublicKey,
|
recipient_ipk: IncomingViewingPublicKey,
|
||||||
amount: u128,
|
amount: u128,
|
||||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||||
let Ok(sender_acc) = self.get_account_public(sender_address).await else {
|
let (instruction_data, program, tx_pre_check) =
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
};
|
|
||||||
|
|
||||||
let Some(sender_priv_key) = self
|
self.shielded_two_accs_receiver_outer(
|
||||||
.storage
|
sender_address,
|
||||||
.user_data
|
recipient_npk,
|
||||||
.get_pub_account_signing_key(&sender_address)
|
recipient_ipk,
|
||||||
else {
|
instruction_data,
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
tx_pre_check,
|
||||||
};
|
program,
|
||||||
|
|
||||||
let recipient_acc = nssa_core::account::Account::default();
|
|
||||||
|
|
||||||
let program = Program::token();
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(sender_acc.clone(), true, sender_address);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(recipient_acc.clone(), false, &recipient_npk);
|
|
||||||
|
|
||||||
let eph_holder_recipient = EphemeralKeyHolder::new(&recipient_npk);
|
|
||||||
let shared_secret_recipient =
|
|
||||||
eph_holder_recipient.calculate_shared_secret_sender(&recipient_ipk);
|
|
||||||
|
|
||||||
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 || 0x00 || 0x00 || 0x00].
|
|
||||||
let mut instruction = [0; 23];
|
|
||||||
instruction[0] = 0x01;
|
|
||||||
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(instruction).unwrap(),
|
|
||||||
&[0, 2],
|
|
||||||
&produce_random_nonces(1),
|
|
||||||
&[(recipient_npk.clone(), shared_secret_recipient.clone())],
|
|
||||||
&[],
|
|
||||||
&program,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.await
|
||||||
|
|
||||||
let message =
|
|
||||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
|
||||||
vec![sender_address],
|
|
||||||
vec![sender_acc.nonce],
|
|
||||||
vec![(
|
|
||||||
recipient_npk.clone(),
|
|
||||||
recipient_ipk.clone(),
|
|
||||||
eph_holder_recipient.generate_ephemeral_public_key(),
|
|
||||||
)],
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[sender_priv_key],
|
|
||||||
);
|
|
||||||
let tx = nssa::PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok(self.sequencer_client.send_tx_private(tx).await?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,7 @@
|
|||||||
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
use common::{error::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, account::AccountWithMetadata};
|
|
||||||
|
|
||||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
use crate::WalletCore;
|
||||||
|
|
||||||
impl WalletCore {
|
impl WalletCore {
|
||||||
pub async fn send_deshielded_native_token_transfer(
|
pub async fn send_deshielded_native_token_transfer(
|
||||||
@ -15,71 +9,11 @@ impl WalletCore {
|
|||||||
from: Address,
|
from: Address,
|
||||||
to: Address,
|
to: Address,
|
||||||
balance_to_move: u128,
|
balance_to_move: u128,
|
||||||
) -> Result<(SendTxResponse, nssa_core::SharedSecretKey), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [nssa_core::SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
let Some((from_keys, from_acc)) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
self.storage.user_data.get_private_account(&from).cloned()
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Ok(to_acc) = self.get_account_public(to).await else {
|
self.deshielded_tx_two_accs(from, to, instruction_data, tx_pre_check, program)
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
.await
|
||||||
};
|
|
||||||
|
|
||||||
if from_acc.balance >= balance_to_move {
|
|
||||||
let program = Program::authenticated_transfer_program();
|
|
||||||
|
|
||||||
let npk_from = from_keys.nullifer_public_key;
|
|
||||||
let ipk_from = from_keys.incoming_viewing_public_key;
|
|
||||||
|
|
||||||
let sender_commitment = Commitment::new(&npk_from, &from_acc);
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, &npk_from);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, to);
|
|
||||||
|
|
||||||
let eph_holder = EphemeralKeyHolder::new(&npk_from);
|
|
||||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&ipk_from);
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[1, 0],
|
|
||||||
&produce_random_nonces(1),
|
|
||||||
&[(npk_from.clone(), shared_secret.clone())],
|
|
||||||
&[(
|
|
||||||
from_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
)],
|
|
||||||
&program,
|
|
||||||
)
|
|
||||||
.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 = WitnessSet::for_message(&message, proof, &[]);
|
|
||||||
|
|
||||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
shared_secret,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,32 @@
|
|||||||
|
use common::error::ExecutionFailureKind;
|
||||||
|
use nssa::{Account, program::Program};
|
||||||
|
use nssa_core::program::InstructionData;
|
||||||
|
|
||||||
|
use crate::WalletCore;
|
||||||
|
|
||||||
pub mod deshielded;
|
pub mod deshielded;
|
||||||
pub mod private;
|
pub mod private;
|
||||||
pub mod public;
|
pub mod public;
|
||||||
pub mod shielded;
|
pub mod shielded;
|
||||||
|
|
||||||
|
impl WalletCore {
|
||||||
|
pub fn auth_transfer_preparation(
|
||||||
|
balance_to_move: u128,
|
||||||
|
) -> (
|
||||||
|
InstructionData,
|
||||||
|
Program,
|
||||||
|
impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
) {
|
||||||
|
let instruction_data = Program::serialize_instruction(balance_to_move).unwrap();
|
||||||
|
let program = Program::authenticated_transfer_program();
|
||||||
|
let tx_pre_check = move |from: &Account, _: &Account| {
|
||||||
|
if from.balance >= balance_to_move {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(instruction_data, program, tx_pre_check)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,16 +1,10 @@
|
|||||||
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
use common::{error::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::{
|
use nssa_core::{
|
||||||
Commitment, MembershipProof, NullifierPublicKey, SharedSecretKey, account::AccountWithMetadata,
|
MembershipProof, NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey,
|
||||||
encryption::IncomingViewingPublicKey,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
use crate::WalletCore;
|
||||||
|
|
||||||
impl WalletCore {
|
impl WalletCore {
|
||||||
pub async fn send_private_native_token_transfer_outer_account(
|
pub async fn send_private_native_token_transfer_outer_account(
|
||||||
@ -20,82 +14,31 @@ impl WalletCore {
|
|||||||
to_ipk: IncomingViewingPublicKey,
|
to_ipk: IncomingViewingPublicKey,
|
||||||
balance_to_move: u128,
|
balance_to_move: u128,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||||
let Some((from_keys, from_acc)) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
self.storage.user_data.get_private_account(&from).cloned()
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let to_acc = nssa_core::account::Account::default();
|
self.private_tx_two_accs_receiver_outer(
|
||||||
|
from,
|
||||||
|
to_npk,
|
||||||
|
to_ipk,
|
||||||
|
instruction_data,
|
||||||
|
tx_pre_check,
|
||||||
|
program,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
if from_acc.balance >= balance_to_move {
|
pub async fn send_private_native_token_transfer_owned_account_not_initialized(
|
||||||
let program = Program::authenticated_transfer_program();
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
balance_to_move: u128,
|
||||||
|
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||||
|
let (instruction_data, program, tx_pre_check) =
|
||||||
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
|
|
||||||
let from_npk = from_keys.nullifer_public_key;
|
self.private_tx_two_accs_receiver_uninit(from, to, instruction_data, tx_pre_check, program)
|
||||||
let from_ipk = from_keys.incoming_viewing_public_key;
|
.await
|
||||||
|
|
||||||
let sender_commitment = Commitment::new(&from_npk, &from_acc);
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, &from_npk);
|
|
||||||
|
|
||||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
|
|
||||||
|
|
||||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
|
||||||
|
|
||||||
let shared_secret_from = eph_holder.calculate_shared_secret_sender(&from_ipk);
|
|
||||||
let shared_secret_to = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[1, 2],
|
|
||||||
&produce_random_nonces(2),
|
|
||||||
&[
|
|
||||||
(from_npk.clone(), shared_secret_from.clone()),
|
|
||||||
(to_npk.clone(), shared_secret_to.clone()),
|
|
||||||
],
|
|
||||||
&[(
|
|
||||||
from_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
)],
|
|
||||||
&program,
|
|
||||||
)
|
|
||||||
.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 = WitnessSet::for_message(&message, proof, &[]);
|
|
||||||
|
|
||||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_from, shared_secret_to],
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_private_native_token_transfer_owned_account_already_initialized(
|
pub async fn send_private_native_token_transfer_owned_account_already_initialized(
|
||||||
@ -105,176 +48,17 @@ impl WalletCore {
|
|||||||
balance_to_move: u128,
|
balance_to_move: u128,
|
||||||
to_proof: MembershipProof,
|
to_proof: MembershipProof,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||||
let Some((from_keys, from_acc)) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
self.storage.user_data.get_private_account(&from).cloned()
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some((to_keys, to_acc)) = self.storage.user_data.get_private_account(&to).cloned()
|
self.private_tx_two_accs_all_init(
|
||||||
else {
|
from,
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
to,
|
||||||
};
|
instruction_data,
|
||||||
|
tx_pre_check,
|
||||||
let from_npk = from_keys.nullifer_public_key;
|
program,
|
||||||
let from_ipk = from_keys.incoming_viewing_public_key;
|
to_proof,
|
||||||
let to_npk = to_keys.nullifer_public_key.clone();
|
)
|
||||||
let to_ipk = to_keys.incoming_viewing_public_key.clone();
|
.await
|
||||||
|
|
||||||
if from_acc.balance >= balance_to_move {
|
|
||||||
let program = Program::authenticated_transfer_program();
|
|
||||||
|
|
||||||
let sender_commitment = Commitment::new(&from_npk, &from_acc);
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, &from_npk);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), true, &to_npk);
|
|
||||||
|
|
||||||
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
|
|
||||||
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
|
|
||||||
|
|
||||||
let eph_holder_to = EphemeralKeyHolder::new(&to_npk);
|
|
||||||
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_ipk);
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[1, 1],
|
|
||||||
&produce_random_nonces(2),
|
|
||||||
&[
|
|
||||||
(from_npk.clone(), shared_secret_from.clone()),
|
|
||||||
(to_npk.clone(), shared_secret_to.clone()),
|
|
||||||
],
|
|
||||||
&[
|
|
||||||
(
|
|
||||||
from_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
(to_keys.private_key_holder.nullifier_secret_key, to_proof),
|
|
||||||
],
|
|
||||||
&program,
|
|
||||||
)
|
|
||||||
.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 = WitnessSet::for_message(&message, proof, &[]);
|
|
||||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_from, shared_secret_to],
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_private_native_token_transfer_owned_account_not_initialized(
|
|
||||||
&self,
|
|
||||||
from: Address,
|
|
||||||
to: Address,
|
|
||||||
balance_to_move: u128,
|
|
||||||
) -> 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, 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 = Program::authenticated_transfer_program();
|
|
||||||
|
|
||||||
let sender_commitment = Commitment::new(&from_npk, &from_acc);
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, &from_npk);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
|
|
||||||
|
|
||||||
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
|
|
||||||
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
|
|
||||||
|
|
||||||
let eph_holder_to = EphemeralKeyHolder::new(&to_npk);
|
|
||||||
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_ipk);
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[1, 2],
|
|
||||||
&produce_random_nonces(2),
|
|
||||||
&[
|
|
||||||
(from_npk.clone(), shared_secret_from.clone()),
|
|
||||||
(to_npk.clone(), shared_secret_to.clone()),
|
|
||||||
],
|
|
||||||
&[(
|
|
||||||
from_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
)],
|
|
||||||
&program,
|
|
||||||
)
|
|
||||||
.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 = WitnessSet::for_message(&message, proof, &[]);
|
|
||||||
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
[shared_secret_from, shared_secret_to],
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,10 @@
|
|||||||
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
use nssa::Address;
|
||||||
use nssa::{
|
|
||||||
Account, Address, PrivacyPreservingTransaction,
|
|
||||||
privacy_preserving_transaction::{circuit, message::Message, witness_set::WitnessSet},
|
|
||||||
program::Program,
|
|
||||||
};
|
|
||||||
use nssa_core::{
|
use nssa_core::{
|
||||||
MembershipProof, NullifierPublicKey, SharedSecretKey, account::AccountWithMetadata,
|
MembershipProof, NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey,
|
||||||
encryption::IncomingViewingPublicKey,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
use crate::WalletCore;
|
||||||
|
|
||||||
impl WalletCore {
|
impl WalletCore {
|
||||||
pub async fn send_shielded_native_token_transfer_already_initialized(
|
pub async fn send_shielded_native_token_transfer_already_initialized(
|
||||||
@ -19,68 +13,12 @@ impl WalletCore {
|
|||||||
to: Address,
|
to: Address,
|
||||||
balance_to_move: u128,
|
balance_to_move: u128,
|
||||||
to_proof: MembershipProof,
|
to_proof: MembershipProof,
|
||||||
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
let Ok(from_acc) = self.get_account_public(from).await else {
|
let (instruction_data, program, tx_pre_check) =
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
};
|
|
||||||
|
|
||||||
let Some((to_keys, to_acc)) = self.storage.user_data.get_private_account(&to).cloned()
|
self.shielded_two_accs_all_init(from, to, instruction_data, tx_pre_check, program, to_proof)
|
||||||
else {
|
.await
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
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 = Program::authenticated_transfer_program();
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), true, &to_npk);
|
|
||||||
|
|
||||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
|
||||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[0, 1],
|
|
||||||
&produce_random_nonces(1),
|
|
||||||
&[(to_npk.clone(), shared_secret.clone())],
|
|
||||||
&[(to_keys.private_key_holder.nullifier_secret_key, to_proof)],
|
|
||||||
&program,
|
|
||||||
)
|
|
||||||
.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);
|
|
||||||
|
|
||||||
let Some(signing_key) = signing_key else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
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?,
|
|
||||||
shared_secret,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_shielded_native_token_transfer_not_initialized(
|
pub async fn send_shielded_native_token_transfer_not_initialized(
|
||||||
@ -88,68 +26,12 @@ impl WalletCore {
|
|||||||
from: Address,
|
from: Address,
|
||||||
to: Address,
|
to: Address,
|
||||||
balance_to_move: u128,
|
balance_to_move: u128,
|
||||||
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
let Ok(from_acc) = self.get_account_public(from).await else {
|
let (instruction_data, program, tx_pre_check) =
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
};
|
|
||||||
|
|
||||||
let Some((to_keys, to_acc)) = self.storage.user_data.get_private_account(&to).cloned()
|
self.shielded_two_accs_receiver_uninit(from, to, instruction_data, tx_pre_check, program)
|
||||||
else {
|
.await
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
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 = Program::authenticated_transfer_program();
|
|
||||||
|
|
||||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
|
||||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
|
|
||||||
|
|
||||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
|
||||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[0, 2],
|
|
||||||
&produce_random_nonces(1),
|
|
||||||
&[(to_npk.clone(), shared_secret.clone())],
|
|
||||||
&[],
|
|
||||||
&program,
|
|
||||||
)
|
|
||||||
.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);
|
|
||||||
|
|
||||||
let Some(signing_key) = signing_key else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
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?,
|
|
||||||
shared_secret,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_shielded_native_token_transfer_outer_account(
|
pub async fn send_shielded_native_token_transfer_outer_account(
|
||||||
@ -158,60 +40,18 @@ impl WalletCore {
|
|||||||
to_npk: NullifierPublicKey,
|
to_npk: NullifierPublicKey,
|
||||||
to_ipk: IncomingViewingPublicKey,
|
to_ipk: IncomingViewingPublicKey,
|
||||||
balance_to_move: u128,
|
balance_to_move: u128,
|
||||||
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||||
let Ok(from_acc) = self.get_account_public(from).await else {
|
let (instruction_data, program, tx_pre_check) =
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
};
|
|
||||||
|
|
||||||
let to_acc = Account::default();
|
self.shielded_two_accs_receiver_outer(
|
||||||
|
from,
|
||||||
if from_acc.balance >= balance_to_move {
|
to_npk,
|
||||||
let program = Program::authenticated_transfer_program();
|
to_ipk,
|
||||||
|
instruction_data,
|
||||||
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
tx_pre_check,
|
||||||
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
|
program,
|
||||||
|
)
|
||||||
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
.await
|
||||||
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
|
||||||
|
|
||||||
let (output, proof) = circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[0, 2],
|
|
||||||
&produce_random_nonces(1),
|
|
||||||
&[(to_npk.clone(), shared_secret.clone())],
|
|
||||||
&[],
|
|
||||||
&program,
|
|
||||||
)
|
|
||||||
.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);
|
|
||||||
|
|
||||||
let Some(signing_key) = signing_key else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
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?,
|
|
||||||
shared_secret,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
540
wallet/src/transaction_utils.rs
Normal file
540
wallet/src/transaction_utils.rs
Normal file
@ -0,0 +1,540 @@
|
|||||||
|
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
|
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, MembershipProof, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
|
||||||
|
account::AccountWithMetadata, encryption::IncomingViewingPublicKey, program::InstructionData,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
||||||
|
|
||||||
|
pub(crate) struct AccountPreparedData {
|
||||||
|
pub nsk: Option<NullifierSecretKey>,
|
||||||
|
pub npk: NullifierPublicKey,
|
||||||
|
pub ipk: IncomingViewingPublicKey,
|
||||||
|
pub auth_acc: AccountWithMetadata,
|
||||||
|
pub proof: Option<MembershipProof>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WalletCore {
|
||||||
|
pub(crate) async fn private_acc_preparation(
|
||||||
|
&self,
|
||||||
|
addr: Address,
|
||||||
|
is_authorized: bool,
|
||||||
|
needs_proof: bool,
|
||||||
|
) -> Result<AccountPreparedData, ExecutionFailureKind> {
|
||||||
|
let Some((from_keys, from_acc)) =
|
||||||
|
self.storage.user_data.get_private_account(&addr).cloned()
|
||||||
|
else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut nsk = None;
|
||||||
|
let mut proof = None;
|
||||||
|
|
||||||
|
let from_npk = from_keys.nullifer_public_key;
|
||||||
|
let from_ipk = from_keys.incoming_viewing_public_key;
|
||||||
|
|
||||||
|
let sender_commitment = Commitment::new(&from_npk, &from_acc);
|
||||||
|
|
||||||
|
let sender_pre = AccountWithMetadata::new(from_acc.clone(), is_authorized, &from_npk);
|
||||||
|
|
||||||
|
if is_authorized {
|
||||||
|
nsk = Some(from_keys.private_key_holder.nullifier_secret_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if needs_proof {
|
||||||
|
proof = self
|
||||||
|
.sequencer_client
|
||||||
|
.get_proof_for_commitment(sender_commitment)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(AccountPreparedData {
|
||||||
|
nsk,
|
||||||
|
npk: from_npk,
|
||||||
|
ipk: from_ipk,
|
||||||
|
auth_acc: sender_pre,
|
||||||
|
proof,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn private_tx_two_accs_all_init(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
instruction_data: InstructionData,
|
||||||
|
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
program: Program,
|
||||||
|
to_proof: MembershipProof,
|
||||||
|
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||||
|
let AccountPreparedData {
|
||||||
|
nsk: from_nsk,
|
||||||
|
npk: from_npk,
|
||||||
|
ipk: from_ipk,
|
||||||
|
auth_acc: sender_pre,
|
||||||
|
proof: from_proof,
|
||||||
|
} = self.private_acc_preparation(from, true, true).await?;
|
||||||
|
|
||||||
|
let AccountPreparedData {
|
||||||
|
nsk: to_nsk,
|
||||||
|
npk: to_npk,
|
||||||
|
ipk: to_ipk,
|
||||||
|
auth_acc: recipient_pre,
|
||||||
|
proof: _,
|
||||||
|
} = self.private_acc_preparation(to, true, false).await?;
|
||||||
|
|
||||||
|
tx_pre_check(&sender_pre.account, &recipient_pre.account)?;
|
||||||
|
|
||||||
|
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
|
||||||
|
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
|
||||||
|
|
||||||
|
let eph_holder_to = EphemeralKeyHolder::new(&to_npk);
|
||||||
|
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_ipk);
|
||||||
|
|
||||||
|
let (output, proof) = circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&instruction_data,
|
||||||
|
&[1, 1],
|
||||||
|
&produce_random_nonces(2),
|
||||||
|
&[
|
||||||
|
(from_npk.clone(), shared_secret_from.clone()),
|
||||||
|
(to_npk.clone(), shared_secret_to.clone()),
|
||||||
|
],
|
||||||
|
&[
|
||||||
|
(from_nsk.unwrap(), from_proof.unwrap()),
|
||||||
|
(to_nsk.unwrap(), to_proof),
|
||||||
|
],
|
||||||
|
&program,
|
||||||
|
)
|
||||||
|
.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 = WitnessSet::for_message(&message, proof, &[]);
|
||||||
|
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
self.sequencer_client.send_tx_private(tx).await?,
|
||||||
|
[shared_secret_from, shared_secret_to],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn private_tx_two_accs_receiver_uninit(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
instruction_data: InstructionData,
|
||||||
|
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
program: Program,
|
||||||
|
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||||
|
let AccountPreparedData {
|
||||||
|
nsk: from_nsk,
|
||||||
|
npk: from_npk,
|
||||||
|
ipk: from_ipk,
|
||||||
|
auth_acc: sender_pre,
|
||||||
|
proof: from_proof,
|
||||||
|
} = self.private_acc_preparation(from, true, true).await?;
|
||||||
|
|
||||||
|
let AccountPreparedData {
|
||||||
|
nsk: _,
|
||||||
|
npk: to_npk,
|
||||||
|
ipk: to_ipk,
|
||||||
|
auth_acc: recipient_pre,
|
||||||
|
proof: _,
|
||||||
|
} = self.private_acc_preparation(to, false, false).await?;
|
||||||
|
|
||||||
|
tx_pre_check(&sender_pre.account, &recipient_pre.account)?;
|
||||||
|
|
||||||
|
let eph_holder_from = EphemeralKeyHolder::new(&from_npk);
|
||||||
|
let shared_secret_from = eph_holder_from.calculate_shared_secret_sender(&from_ipk);
|
||||||
|
|
||||||
|
let eph_holder_to = EphemeralKeyHolder::new(&to_npk);
|
||||||
|
let shared_secret_to = eph_holder_to.calculate_shared_secret_sender(&to_ipk);
|
||||||
|
|
||||||
|
let (output, proof) = circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&instruction_data,
|
||||||
|
&[1, 2],
|
||||||
|
&produce_random_nonces(2),
|
||||||
|
&[
|
||||||
|
(from_npk.clone(), shared_secret_from.clone()),
|
||||||
|
(to_npk.clone(), shared_secret_to.clone()),
|
||||||
|
],
|
||||||
|
&[(from_nsk.unwrap(), from_proof.unwrap())],
|
||||||
|
&program,
|
||||||
|
)
|
||||||
|
.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 = WitnessSet::for_message(&message, proof, &[]);
|
||||||
|
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
self.sequencer_client.send_tx_private(tx).await?,
|
||||||
|
[shared_secret_from, shared_secret_to],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn private_tx_two_accs_receiver_outer(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to_npk: NullifierPublicKey,
|
||||||
|
to_ipk: IncomingViewingPublicKey,
|
||||||
|
instruction_data: InstructionData,
|
||||||
|
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
program: Program,
|
||||||
|
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
||||||
|
let AccountPreparedData {
|
||||||
|
nsk: from_nsk,
|
||||||
|
npk: from_npk,
|
||||||
|
ipk: from_ipk,
|
||||||
|
auth_acc: sender_pre,
|
||||||
|
proof: from_proof,
|
||||||
|
} = self.private_acc_preparation(from, true, true).await?;
|
||||||
|
|
||||||
|
let to_acc = nssa_core::account::Account::default();
|
||||||
|
|
||||||
|
tx_pre_check(&sender_pre.account, &to_acc)?;
|
||||||
|
|
||||||
|
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||||
|
|
||||||
|
let shared_secret_from = eph_holder.calculate_shared_secret_sender(&from_ipk);
|
||||||
|
let shared_secret_to = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||||
|
|
||||||
|
let (output, proof) = circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&instruction_data,
|
||||||
|
&[1, 2],
|
||||||
|
&produce_random_nonces(2),
|
||||||
|
&[
|
||||||
|
(from_npk.clone(), shared_secret_from.clone()),
|
||||||
|
(to_npk.clone(), shared_secret_to.clone()),
|
||||||
|
],
|
||||||
|
&[(from_nsk.unwrap(), from_proof.unwrap())],
|
||||||
|
&program,
|
||||||
|
)
|
||||||
|
.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 = WitnessSet::for_message(&message, proof, &[]);
|
||||||
|
|
||||||
|
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
self.sequencer_client.send_tx_private(tx).await?,
|
||||||
|
[shared_secret_from, shared_secret_to],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn deshielded_tx_two_accs(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
instruction_data: InstructionData,
|
||||||
|
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
program: Program,
|
||||||
|
) -> Result<(SendTxResponse, [nssa_core::SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
|
let AccountPreparedData {
|
||||||
|
nsk: from_nsk,
|
||||||
|
npk: from_npk,
|
||||||
|
ipk: from_ipk,
|
||||||
|
auth_acc: sender_pre,
|
||||||
|
proof: from_proof,
|
||||||
|
} = self.private_acc_preparation(from, true, true).await?;
|
||||||
|
|
||||||
|
let Ok(to_acc) = self.get_account_public(to).await else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
tx_pre_check(&sender_pre.account, &to_acc)?;
|
||||||
|
|
||||||
|
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, to);
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(&from_npk);
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(&from_ipk);
|
||||||
|
|
||||||
|
let (output, proof) = circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&instruction_data,
|
||||||
|
&[1, 0],
|
||||||
|
&produce_random_nonces(1),
|
||||||
|
&[(from_npk.clone(), shared_secret.clone())],
|
||||||
|
&[(from_nsk.unwrap(), from_proof.unwrap())],
|
||||||
|
&program,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let message = Message::try_from_circuit_output(
|
||||||
|
vec![to],
|
||||||
|
vec![],
|
||||||
|
vec![(
|
||||||
|
from_npk.clone(),
|
||||||
|
from_ipk.clone(),
|
||||||
|
eph_holder.generate_ephemeral_public_key(),
|
||||||
|
)],
|
||||||
|
output,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
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],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn shielded_two_accs_all_init(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
instruction_data: InstructionData,
|
||||||
|
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
program: Program,
|
||||||
|
to_proof: MembershipProof,
|
||||||
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
|
let Ok(from_acc) = self.get_account_public(from).await else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
let AccountPreparedData {
|
||||||
|
nsk: to_nsk,
|
||||||
|
npk: to_npk,
|
||||||
|
ipk: to_ipk,
|
||||||
|
auth_acc: recipient_pre,
|
||||||
|
proof: _,
|
||||||
|
} = self.private_acc_preparation(to, true, false).await?;
|
||||||
|
|
||||||
|
tx_pre_check(&from_acc, &recipient_pre.account)?;
|
||||||
|
|
||||||
|
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||||
|
|
||||||
|
let (output, proof) = circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&instruction_data,
|
||||||
|
&[0, 1],
|
||||||
|
&produce_random_nonces(1),
|
||||||
|
&[(to_npk.clone(), shared_secret.clone())],
|
||||||
|
&[(to_nsk.unwrap(), to_proof)],
|
||||||
|
&program,
|
||||||
|
)
|
||||||
|
.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);
|
||||||
|
|
||||||
|
let Some(signing_key) = signing_key else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
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?,
|
||||||
|
[shared_secret],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn shielded_two_accs_receiver_uninit(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
instruction_data: InstructionData,
|
||||||
|
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
program: Program,
|
||||||
|
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
||||||
|
let Ok(from_acc) = self.get_account_public(from).await else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
let AccountPreparedData {
|
||||||
|
nsk: _,
|
||||||
|
npk: to_npk,
|
||||||
|
ipk: to_ipk,
|
||||||
|
auth_acc: recipient_pre,
|
||||||
|
proof: _,
|
||||||
|
} = self.private_acc_preparation(to, false, false).await?;
|
||||||
|
|
||||||
|
tx_pre_check(&from_acc, &recipient_pre.account)?;
|
||||||
|
|
||||||
|
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||||
|
|
||||||
|
let (output, proof) = circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&instruction_data,
|
||||||
|
&[0, 2],
|
||||||
|
&produce_random_nonces(1),
|
||||||
|
&[(to_npk.clone(), shared_secret.clone())],
|
||||||
|
&[],
|
||||||
|
&program,
|
||||||
|
)
|
||||||
|
.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);
|
||||||
|
|
||||||
|
let Some(signing_key) = signing_key else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
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?,
|
||||||
|
[shared_secret],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn shielded_two_accs_receiver_outer(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to_npk: NullifierPublicKey,
|
||||||
|
to_ipk: IncomingViewingPublicKey,
|
||||||
|
instruction_data: InstructionData,
|
||||||
|
tx_pre_check: impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
||||||
|
program: Program,
|
||||||
|
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||||
|
let Ok(from_acc) = self.get_account_public(from).await else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
let to_acc = Account::default();
|
||||||
|
|
||||||
|
tx_pre_check(&from_acc, &to_acc)?;
|
||||||
|
|
||||||
|
let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, from);
|
||||||
|
let recipient_pre = AccountWithMetadata::new(to_acc.clone(), false, &to_npk);
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(&to_npk);
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(&to_ipk);
|
||||||
|
|
||||||
|
let (output, proof) = circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&instruction_data,
|
||||||
|
&[0, 2],
|
||||||
|
&produce_random_nonces(1),
|
||||||
|
&[(to_npk.clone(), shared_secret.clone())],
|
||||||
|
&[],
|
||||||
|
&program,
|
||||||
|
)
|
||||||
|
.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);
|
||||||
|
|
||||||
|
let Some(signing_key) = signing_key else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
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