mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-04-22 01:13:22 +00:00
fix: more integration tests
This commit is contained in:
parent
c204915e1d
commit
d3742867ed
@ -324,29 +324,6 @@ pub async fn test_success_private_transfer_to_another_owned_account() {
|
|||||||
|
|
||||||
let mut wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
let mut wallet_storage = WalletCore::start_from_config_update_chain(wallet_config).unwrap();
|
||||||
|
|
||||||
let old_commitment1 = {
|
|
||||||
let from_acc = wallet_storage
|
|
||||||
.storage
|
|
||||||
.user_data
|
|
||||||
.get_private_account_mut(&from)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
nssa_core::Commitment::new(&from_acc.0.nullifer_public_key, &from_acc.1)
|
|
||||||
};
|
|
||||||
|
|
||||||
let old_commitment2 = {
|
|
||||||
let to_acc = wallet_storage
|
|
||||||
.storage
|
|
||||||
.user_data
|
|
||||||
.get_private_account_mut(&to)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
nssa_core::Commitment::new(&to_acc.0.nullifer_public_key, &to_acc.1)
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("Old commitment {old_commitment1:?}");
|
|
||||||
println!("Old commitment {old_commitment2:?}");
|
|
||||||
|
|
||||||
wallet::execute_subcommand(command).await.unwrap();
|
wallet::execute_subcommand(command).await.unwrap();
|
||||||
|
|
||||||
info!("Waiting for next block creation");
|
info!("Waiting for next block creation");
|
||||||
@ -378,8 +355,69 @@ pub async fn test_success_private_transfer_to_another_owned_account() {
|
|||||||
nssa_core::Commitment::new(&to_acc.0.nullifer_public_key, &to_acc.1)
|
nssa_core::Commitment::new(&to_acc.0.nullifer_public_key, &to_acc.1)
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("New commitment {new_commitment1:?}");
|
let proof1 = seq_client
|
||||||
println!("New commitment {new_commitment2:?}");
|
.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:#?}");
|
||||||
|
|
||||||
|
info!("Success!");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn test_success_private_transfer_to_another_foreign_account() {
|
||||||
|
let command = Command::SendNativeTokenTransferPrivate {
|
||||||
|
from: ACC_SENDER_PRIVATE.to_string(),
|
||||||
|
to: ACC_RECEIVER_PRIVATE.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();
|
||||||
|
|
||||||
|
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.balance -= 100;
|
||||||
|
from_acc.1.nonce += 1;
|
||||||
|
|
||||||
|
nssa_core::Commitment::new(&from_acc.0.nullifer_public_key, &from_acc.1)
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_commitment2 = {
|
||||||
|
let to_acc = wallet_storage
|
||||||
|
.storage
|
||||||
|
.user_data
|
||||||
|
.get_private_account_mut(&to)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
to_acc.1.balance += 100;
|
||||||
|
to_acc.1.nonce += 1;
|
||||||
|
|
||||||
|
nssa_core::Commitment::new(&to_acc.0.nullifer_public_key, &to_acc.1)
|
||||||
|
};
|
||||||
|
|
||||||
let proof1 = seq_client
|
let proof1 = seq_client
|
||||||
.get_proof_for_commitment(new_commitment1)
|
.get_proof_for_commitment(new_commitment1)
|
||||||
|
|||||||
@ -149,6 +149,23 @@ pub enum Command {
|
|||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
amount: u128,
|
amount: u128,
|
||||||
},
|
},
|
||||||
|
///Send native token transfer from `from` to `to` for `amount`
|
||||||
|
///
|
||||||
|
/// Private operation
|
||||||
|
SendNativeTokenTransferPrivateForeignAccount {
|
||||||
|
///from - valid 32 byte hex string
|
||||||
|
#[arg(long)]
|
||||||
|
from: String,
|
||||||
|
///to_npk - valid 32 byte hex string
|
||||||
|
#[arg(long)]
|
||||||
|
to_npk: String,
|
||||||
|
///to_ipk - valid 33 byte hex string
|
||||||
|
#[arg(long)]
|
||||||
|
to_ipk: String,
|
||||||
|
///amount - amount of balance to move
|
||||||
|
#[arg(long)]
|
||||||
|
amount: u128,
|
||||||
|
},
|
||||||
///Register new public account
|
///Register new public account
|
||||||
RegisterAccountPublic {},
|
RegisterAccountPublic {},
|
||||||
///Register new private account
|
///Register new private account
|
||||||
@ -240,6 +257,51 @@ pub async fn execute_subcommand(command: Command) -> Result<()> {
|
|||||||
println!("Transaction data is {:?}", tx.message);
|
println!("Transaction data is {:?}", tx.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Command::SendNativeTokenTransferPrivateForeignAccount { from, to_npk, to_ipk, amount } => {
|
||||||
|
let from = produce_account_addr_from_hex(from)?;
|
||||||
|
let to_npk_res = hex::decode(to_npk)?;
|
||||||
|
let mut to_npk = [0; 32];
|
||||||
|
to_npk.copy_from_slice(&to_npk_res);
|
||||||
|
let to_npk = nssa_core::NullifierPublicKey(to_npk);
|
||||||
|
|
||||||
|
let to_ipk_res = hex::decode(to_ipk)?;
|
||||||
|
let mut to_ipk = [0u8; 33];
|
||||||
|
to_ipk.copy_from_slice(&to_ipk_res);
|
||||||
|
let to_ipk = nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_ipk.to_vec());
|
||||||
|
|
||||||
|
let (res, secret) = wallet_core
|
||||||
|
.send_private_native_token_transfer_outer_account(from, to_npk, to_ipk, amount)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
println!("Results of tx send is {res:#?}");
|
||||||
|
|
||||||
|
let transfer_tx = wallet_core.poll_native_token_transfer(res.tx_hash).await?;
|
||||||
|
|
||||||
|
if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx {
|
||||||
|
let from_ebc = tx.message.encrypted_private_post_states[0].clone();
|
||||||
|
let from_comm = tx.message.new_commitments[0].clone();
|
||||||
|
|
||||||
|
let to_ebc = tx.message.encrypted_private_post_states[1].clone();
|
||||||
|
let to_comm = tx.message.new_commitments[1].clone();
|
||||||
|
|
||||||
|
let res_acc = nssa_core::EncryptionScheme::decrypt(
|
||||||
|
&from_ebc.ciphertext,
|
||||||
|
&secret,
|
||||||
|
&from_comm,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let res_acc_to =
|
||||||
|
nssa_core::EncryptionScheme::decrypt(&to_ebc.ciphertext, &secret, &to_comm, 1)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!("RES acc {res_acc:#?}");
|
||||||
|
println!("RES acc to {res_acc_to:#?}");
|
||||||
|
|
||||||
|
println!("Transaction data is {:?}", tx.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
Command::RegisterAccountPublic {} => {
|
Command::RegisterAccountPublic {} => {
|
||||||
let addr = wallet_core.create_new_account_public();
|
let addr = wallet_core.create_new_account_public();
|
||||||
|
|
||||||
|
|||||||
@ -1,479 +0,0 @@
|
|||||||
use common::{ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
|
||||||
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
|
||||||
use nssa::Address;
|
|
||||||
|
|
||||||
use crate::WalletCore;
|
|
||||||
|
|
||||||
impl WalletCore {
|
|
||||||
pub async fn send_public_native_token_transfer(
|
|
||||||
&self,
|
|
||||||
from: Address,
|
|
||||||
to: Address,
|
|
||||||
balance_to_move: u128,
|
|
||||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
|
||||||
let Ok(balance) = self.get_account_balance(from).await else {
|
|
||||||
return Err(ExecutionFailureKind::SequencerError);
|
|
||||||
};
|
|
||||||
|
|
||||||
if balance >= balance_to_move {
|
|
||||||
let Ok(nonces) = self.get_accounts_nonces(vec![from]).await else {
|
|
||||||
return Err(ExecutionFailureKind::SequencerError);
|
|
||||||
};
|
|
||||||
|
|
||||||
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 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 =
|
|
||||||
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]);
|
|
||||||
|
|
||||||
let tx = nssa::PublicTransaction::new(message, witness_set);
|
|
||||||
|
|
||||||
Ok(self.sequencer_client.send_tx_public(tx).await?)
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_private_native_token_transfer_maybe_outer_account(
|
|
||||||
&self,
|
|
||||||
from: Address,
|
|
||||||
to_npk: nssa_core::NullifierPublicKey,
|
|
||||||
to_ipk: nssa_core::encryption::IncomingViewingPublicKey,
|
|
||||||
balance_to_move: u128,
|
|
||||||
to_acc: Option<nssa_core::account::Account>,
|
|
||||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
|
||||||
let from_data = self.storage.user_data.get_private_account(&from);
|
|
||||||
|
|
||||||
let Some((from_keys, from_acc)) = from_data else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let to_acc = to_acc.unwrap_or_default();
|
|
||||||
|
|
||||||
if from_acc.balance >= balance_to_move {
|
|
||||||
let program = nssa::program::Program::authenticated_transfer_program();
|
|
||||||
let sender_commitment =
|
|
||||||
nssa_core::Commitment::new(&from_keys.nullifer_public_key, from_acc);
|
|
||||||
|
|
||||||
let sender_pre = nssa_core::account::AccountWithMetadata {
|
|
||||||
account: from_acc.clone(),
|
|
||||||
is_authorized: true,
|
|
||||||
};
|
|
||||||
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
|
||||||
account: to_acc.clone(),
|
|
||||||
is_authorized: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let eph_holder = EphemeralKeyHolder::new(
|
|
||||||
to_npk.clone(),
|
|
||||||
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
|
||||||
from_acc.nonce.try_into().unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
|
||||||
|
|
||||||
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[1, 2],
|
|
||||||
&[from_acc.nonce + 1, to_acc.nonce + 1],
|
|
||||||
&[
|
|
||||||
(from_keys.nullifer_public_key.clone(), shared_secret.clone()),
|
|
||||||
(to_npk.clone(), shared_secret),
|
|
||||||
],
|
|
||||||
&[(
|
|
||||||
from_keys.private_key_holder.nullifier_secret_key,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
)],
|
|
||||||
&program,
|
|
||||||
)
|
|
||||||
.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 witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
|
|
||||||
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
|
||||||
message,
|
|
||||||
witness_set,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(self.sequencer_client.send_tx_private(tx).await?)
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_shielded_native_token_transfer_maybe_outer_account(
|
|
||||||
&self,
|
|
||||||
from: Address,
|
|
||||||
to_npk: nssa_core::NullifierPublicKey,
|
|
||||||
to_ipk: nssa_core::encryption::IncomingViewingPublicKey,
|
|
||||||
balance_to_move: u128,
|
|
||||||
to_acc: Option<nssa_core::account::Account>,
|
|
||||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
|
||||||
let from_data = self.storage.user_data.get_private_account(&from);
|
|
||||||
|
|
||||||
let Some((from_keys, from_acc)) = from_data else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let to_acc = to_acc.unwrap_or_default();
|
|
||||||
|
|
||||||
if from_acc.balance >= balance_to_move {
|
|
||||||
let program = nssa::program::Program::authenticated_transfer_program();
|
|
||||||
|
|
||||||
let sender_pre = nssa_core::account::AccountWithMetadata {
|
|
||||||
account: from_acc.clone(),
|
|
||||||
is_authorized: true,
|
|
||||||
};
|
|
||||||
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
|
||||||
account: to_acc.clone(),
|
|
||||||
is_authorized: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let eph_holder = EphemeralKeyHolder::new(
|
|
||||||
to_npk.clone(),
|
|
||||||
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
|
||||||
from_acc.nonce.try_into().unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
|
||||||
|
|
||||||
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[0, 2],
|
|
||||||
&[to_acc.nonce + 1],
|
|
||||||
&[(to_npk.clone(), shared_secret)],
|
|
||||||
&[],
|
|
||||||
&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(),
|
|
||||||
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 =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[signing_key],
|
|
||||||
);
|
|
||||||
|
|
||||||
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
|
||||||
message,
|
|
||||||
witness_set,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(self.sequencer_client.send_tx_private(tx).await?)
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_deshielded_native_token_transfer_maybe_outer_account(
|
|
||||||
&self,
|
|
||||||
from: Address,
|
|
||||||
to_addr: Address,
|
|
||||||
to_npk: nssa_core::NullifierPublicKey,
|
|
||||||
to_ipk: nssa_core::encryption::IncomingViewingPublicKey,
|
|
||||||
balance_to_move: u128,
|
|
||||||
to_acc: Option<nssa_core::account::Account>,
|
|
||||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
|
||||||
let from_data = self.storage.user_data.get_private_account(&from);
|
|
||||||
|
|
||||||
let Some((from_keys, from_acc)) = from_data else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let to_acc = to_acc.unwrap_or_default();
|
|
||||||
|
|
||||||
if from_acc.balance >= balance_to_move {
|
|
||||||
let program = nssa::program::Program::authenticated_transfer_program();
|
|
||||||
let sender_commitment =
|
|
||||||
nssa_core::Commitment::new(&from_keys.nullifer_public_key, from_acc);
|
|
||||||
|
|
||||||
let sender_pre = nssa_core::account::AccountWithMetadata {
|
|
||||||
account: from_acc.clone(),
|
|
||||||
is_authorized: true,
|
|
||||||
};
|
|
||||||
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
|
||||||
account: to_acc.clone(),
|
|
||||||
is_authorized: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let eph_holder = EphemeralKeyHolder::new(
|
|
||||||
to_npk.clone(),
|
|
||||||
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
|
||||||
from_acc.nonce.try_into().unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
|
||||||
|
|
||||||
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[1, 0],
|
|
||||||
&[from_acc.nonce + 1],
|
|
||||||
&[(from_keys.nullifer_public_key.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 =
|
|
||||||
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
|
||||||
vec![to_addr],
|
|
||||||
vec![],
|
|
||||||
vec![(
|
|
||||||
from_keys.nullifer_public_key.clone(),
|
|
||||||
from_keys.incoming_viewing_public_key.clone(),
|
|
||||||
eph_holder.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,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(self.sequencer_client.send_tx_private(tx).await?)
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_private_native_token_transfer(
|
|
||||||
&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);
|
|
||||||
let to_data = self.storage.user_data.get_private_account(&to);
|
|
||||||
|
|
||||||
let Some((from_keys, from_acc)) = from_data else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some((to_keys, to_acc)) = to_data else {
|
|
||||||
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 = nssa::program::Program::authenticated_transfer_program();
|
|
||||||
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 = nssa_core::account::AccountWithMetadata {
|
|
||||||
account: from_acc.clone(),
|
|
||||||
is_authorized: true,
|
|
||||||
};
|
|
||||||
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
|
||||||
account: to_acc.clone(),
|
|
||||||
is_authorized: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
let eph_holder = EphemeralKeyHolder::new(
|
|
||||||
to_npk.clone(),
|
|
||||||
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
|
||||||
from_acc.nonce.try_into().unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
|
||||||
|
|
||||||
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
|
||||||
&[sender_pre, recipient_pre],
|
|
||||||
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
|
||||||
&[1, 1],
|
|
||||||
&[from_acc.nonce + 1, to_acc.nonce + 1],
|
|
||||||
&[
|
|
||||||
(from_keys.nullifer_public_key.clone(), shared_secret.clone()),
|
|
||||||
(to_npk.clone(), shared_secret.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,
|
|
||||||
self.sequencer_client
|
|
||||||
.get_proof_for_commitment(receiver_commitment)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
&program,
|
|
||||||
)
|
|
||||||
.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 witness_set =
|
|
||||||
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
|
||||||
&message,
|
|
||||||
proof,
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
|
|
||||||
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
|
||||||
message,
|
|
||||||
witness_set,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
self.sequencer_client.send_tx_private(tx).await?,
|
|
||||||
shared_secret,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Err(ExecutionFailureKind::InsufficientFundsError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_shiedled_native_token_transfer(
|
|
||||||
&self,
|
|
||||||
from: Address,
|
|
||||||
to: Address,
|
|
||||||
balance_to_move: u128,
|
|
||||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
|
||||||
let to_data = self.storage.user_data.get_private_account(&to);
|
|
||||||
|
|
||||||
let Some((to_keys, to_acc)) = to_data else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
self.send_shielded_native_token_transfer_maybe_outer_account(
|
|
||||||
from,
|
|
||||||
to_keys.nullifer_public_key.clone(),
|
|
||||||
to_keys.incoming_viewing_public_key.clone(),
|
|
||||||
balance_to_move,
|
|
||||||
Some(to_acc.clone()),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_deshielded_native_token_transfer(
|
|
||||||
&self,
|
|
||||||
from: Address,
|
|
||||||
to: Address,
|
|
||||||
balance_to_move: u128,
|
|
||||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
|
||||||
let to_data = self.storage.user_data.get_private_account(&to);
|
|
||||||
|
|
||||||
let Some((to_keys, to_acc)) = to_data else {
|
|
||||||
return Err(ExecutionFailureKind::KeyNotFoundError);
|
|
||||||
};
|
|
||||||
|
|
||||||
self.send_deshielded_native_token_transfer_maybe_outer_account(
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
to_keys.nullifer_public_key.clone(),
|
|
||||||
to_keys.incoming_viewing_public_key.clone(),
|
|
||||||
balance_to_move,
|
|
||||||
Some(to_acc.clone()),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
185
wallet/src/token_transfers/deshielded.rs
Normal file
185
wallet/src/token_transfers/deshielded.rs
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
use common::{ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
|
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||||
|
use nssa::Address;
|
||||||
|
|
||||||
|
use crate::WalletCore;
|
||||||
|
|
||||||
|
impl WalletCore {
|
||||||
|
pub async fn send_deshielded_native_token_transfer_maybe_outer_account(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to_addr: Address,
|
||||||
|
to_npk: nssa_core::NullifierPublicKey,
|
||||||
|
to_ipk: nssa_core::encryption::IncomingViewingPublicKey,
|
||||||
|
balance_to_move: u128,
|
||||||
|
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||||
|
let from_data = self.storage.user_data.get_private_account(&from);
|
||||||
|
|
||||||
|
let Some((from_keys, from_acc)) = from_data 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 sender_commitment =
|
||||||
|
nssa_core::Commitment::new(&from_keys.nullifer_public_key, from_acc);
|
||||||
|
|
||||||
|
let sender_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: from_acc.clone(),
|
||||||
|
is_authorized: true,
|
||||||
|
};
|
||||||
|
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: to_acc.clone(),
|
||||||
|
is_authorized: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(
|
||||||
|
to_npk.clone(),
|
||||||
|
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
||||||
|
from_acc.nonce.try_into().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
||||||
|
|
||||||
|
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||||
|
&[1, 0],
|
||||||
|
&[from_acc.nonce + 1],
|
||||||
|
&[(from_keys.nullifer_public_key.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 =
|
||||||
|
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
||||||
|
vec![to_addr],
|
||||||
|
vec![],
|
||||||
|
vec![(
|
||||||
|
from_keys.nullifer_public_key.clone(),
|
||||||
|
from_keys.incoming_viewing_public_key.clone(),
|
||||||
|
eph_holder.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,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(self.sequencer_client.send_tx_private(tx).await?)
|
||||||
|
} else {
|
||||||
|
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_deshielded_native_token_transfer(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
balance_to_move: u128,
|
||||||
|
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||||
|
let from_data = self.storage.user_data.get_private_account(&from);
|
||||||
|
let to_data = self.storage.user_data.get_private_account(&to);
|
||||||
|
|
||||||
|
let Some((from_keys, from_acc)) = from_data else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some((to_keys, to_acc)) = to_data else {
|
||||||
|
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 = nssa::program::Program::authenticated_transfer_program();
|
||||||
|
let sender_commitment =
|
||||||
|
nssa_core::Commitment::new(&from_keys.nullifer_public_key, from_acc);
|
||||||
|
|
||||||
|
let sender_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: from_acc.clone(),
|
||||||
|
is_authorized: true,
|
||||||
|
};
|
||||||
|
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: to_acc.clone(),
|
||||||
|
is_authorized: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(
|
||||||
|
to_npk.clone(),
|
||||||
|
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
||||||
|
from_acc.nonce.try_into().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
||||||
|
|
||||||
|
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||||
|
&[1, 0],
|
||||||
|
&[from_acc.nonce + 1],
|
||||||
|
&[(from_keys.nullifer_public_key.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 =
|
||||||
|
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(),
|
||||||
|
eph_holder.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,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(self.sequencer_client.send_tx_private(tx).await?)
|
||||||
|
} else {
|
||||||
|
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
wallet/src/token_transfers/mod.rs
Normal file
4
wallet/src/token_transfers/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub mod deshielded;
|
||||||
|
pub mod private;
|
||||||
|
pub mod public;
|
||||||
|
pub mod shielded;
|
||||||
222
wallet/src/token_transfers/private.rs
Normal file
222
wallet/src/token_transfers/private.rs
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
use common::{ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
|
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||||
|
use nssa::Address;
|
||||||
|
|
||||||
|
use crate::WalletCore;
|
||||||
|
|
||||||
|
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,
|
||||||
|
balance_to_move: u128,
|
||||||
|
) -> Result<(SendTxResponse, nssa_core::SharedSecretKey), ExecutionFailureKind> {
|
||||||
|
let from_data = self.storage.user_data.get_private_account(&from);
|
||||||
|
|
||||||
|
let Some((from_keys, from_acc)) = from_data 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 sender_commitment =
|
||||||
|
nssa_core::Commitment::new(&from_keys.nullifer_public_key, from_acc);
|
||||||
|
|
||||||
|
let sender_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: from_acc.clone(),
|
||||||
|
is_authorized: true,
|
||||||
|
};
|
||||||
|
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: to_acc.clone(),
|
||||||
|
is_authorized: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(
|
||||||
|
to_npk.clone(),
|
||||||
|
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
||||||
|
from_acc.nonce.try_into().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
||||||
|
|
||||||
|
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||||
|
&[1, 2],
|
||||||
|
&[from_acc.nonce + 1, to_acc.nonce + 1],
|
||||||
|
&[
|
||||||
|
(from_keys.nullifer_public_key.clone(), shared_secret.clone()),
|
||||||
|
(to_npk.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 =
|
||||||
|
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 witness_set =
|
||||||
|
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||||
|
&message,
|
||||||
|
proof,
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
|
||||||
|
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
||||||
|
message,
|
||||||
|
witness_set,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
self.sequencer_client.send_tx_private(tx).await?,
|
||||||
|
shared_secret,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_private_native_token_transfer(
|
||||||
|
&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);
|
||||||
|
let to_data = self.storage.user_data.get_private_account(&to);
|
||||||
|
|
||||||
|
let Some((from_keys, from_acc)) = from_data else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some((to_keys, to_acc)) = to_data else {
|
||||||
|
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 = nssa::program::Program::authenticated_transfer_program();
|
||||||
|
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 = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: from_acc.clone(),
|
||||||
|
is_authorized: true,
|
||||||
|
};
|
||||||
|
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: to_acc.clone(),
|
||||||
|
is_authorized: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(
|
||||||
|
to_npk.clone(),
|
||||||
|
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
||||||
|
from_acc.nonce.try_into().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
||||||
|
|
||||||
|
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||||
|
&[1, 1],
|
||||||
|
&[from_acc.nonce + 1, to_acc.nonce + 1],
|
||||||
|
&[
|
||||||
|
(from_keys.nullifer_public_key.clone(), shared_secret.clone()),
|
||||||
|
(to_npk.clone(), shared_secret.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,
|
||||||
|
self.sequencer_client
|
||||||
|
.get_proof_for_commitment(receiver_commitment)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
&program,
|
||||||
|
)
|
||||||
|
.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 witness_set =
|
||||||
|
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||||
|
&message,
|
||||||
|
proof,
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
|
||||||
|
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
||||||
|
message,
|
||||||
|
witness_set,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
self.sequencer_client.send_tx_private(tx).await?,
|
||||||
|
shared_secret,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
48
wallet/src/token_transfers/public.rs
Normal file
48
wallet/src/token_transfers/public.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use common::{ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
|
use nssa::Address;
|
||||||
|
|
||||||
|
use crate::WalletCore;
|
||||||
|
|
||||||
|
impl WalletCore {
|
||||||
|
pub async fn send_public_native_token_transfer(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
balance_to_move: u128,
|
||||||
|
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||||
|
let Ok(balance) = self.get_account_balance(from).await else {
|
||||||
|
return Err(ExecutionFailureKind::SequencerError);
|
||||||
|
};
|
||||||
|
|
||||||
|
if balance >= balance_to_move {
|
||||||
|
let Ok(nonces) = self.get_accounts_nonces(vec![from]).await else {
|
||||||
|
return Err(ExecutionFailureKind::SequencerError);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 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 =
|
||||||
|
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]);
|
||||||
|
|
||||||
|
let tx = nssa::PublicTransaction::new(message, witness_set);
|
||||||
|
|
||||||
|
Ok(self.sequencer_client.send_tx_public(tx).await?)
|
||||||
|
} else {
|
||||||
|
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
188
wallet/src/token_transfers/shielded.rs
Normal file
188
wallet/src/token_transfers/shielded.rs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
use common::{ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
|
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||||
|
use nssa::Address;
|
||||||
|
|
||||||
|
use crate::WalletCore;
|
||||||
|
|
||||||
|
impl WalletCore {
|
||||||
|
pub async fn send_shiedled_native_token_transfer(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to: Address,
|
||||||
|
balance_to_move: u128,
|
||||||
|
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||||
|
let from_data = self.storage.user_data.get_private_account(&from);
|
||||||
|
let to_data = self.storage.user_data.get_private_account(&to);
|
||||||
|
|
||||||
|
let Some((from_keys, from_acc)) = from_data else {
|
||||||
|
return Err(ExecutionFailureKind::KeyNotFoundError);
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some((to_keys, to_acc)) = to_data else {
|
||||||
|
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 = nssa::program::Program::authenticated_transfer_program();
|
||||||
|
|
||||||
|
let receiver_commitment =
|
||||||
|
nssa_core::Commitment::new(&to_keys.nullifer_public_key, to_acc);
|
||||||
|
|
||||||
|
let sender_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: from_acc.clone(),
|
||||||
|
is_authorized: true,
|
||||||
|
};
|
||||||
|
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: to_acc.clone(),
|
||||||
|
is_authorized: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(
|
||||||
|
to_npk.clone(),
|
||||||
|
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
||||||
|
from_acc.nonce.try_into().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
||||||
|
|
||||||
|
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||||
|
&[0, 1],
|
||||||
|
&[to_acc.nonce + 1],
|
||||||
|
&[(to_npk.clone(), shared_secret)],
|
||||||
|
&[(
|
||||||
|
to_keys.private_key_holder.nullifier_secret_key,
|
||||||
|
self.sequencer_client
|
||||||
|
.get_proof_for_commitment(receiver_commitment)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap(),
|
||||||
|
)],
|
||||||
|
&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(),
|
||||||
|
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 =
|
||||||
|
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||||
|
&message,
|
||||||
|
proof,
|
||||||
|
&[signing_key],
|
||||||
|
);
|
||||||
|
|
||||||
|
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
||||||
|
message,
|
||||||
|
witness_set,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(self.sequencer_client.send_tx_private(tx).await?)
|
||||||
|
} else {
|
||||||
|
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_shielded_native_token_transfer_maybe_outer_account(
|
||||||
|
&self,
|
||||||
|
from: Address,
|
||||||
|
to_npk: nssa_core::NullifierPublicKey,
|
||||||
|
to_ipk: nssa_core::encryption::IncomingViewingPublicKey,
|
||||||
|
balance_to_move: u128,
|
||||||
|
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||||
|
let from_data = self.storage.user_data.get_private_account(&from);
|
||||||
|
|
||||||
|
let Some((from_keys, from_acc)) = from_data 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 sender_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: from_acc.clone(),
|
||||||
|
is_authorized: true,
|
||||||
|
};
|
||||||
|
let recipient_pre = nssa_core::account::AccountWithMetadata {
|
||||||
|
account: to_acc.clone(),
|
||||||
|
is_authorized: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(
|
||||||
|
to_npk.clone(),
|
||||||
|
from_keys.private_key_holder.outgoing_viewing_secret_key,
|
||||||
|
from_acc.nonce.try_into().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let shared_secret = eph_holder.calculate_shared_secret_sender(to_ipk.clone());
|
||||||
|
|
||||||
|
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||||
|
&[sender_pre, recipient_pre],
|
||||||
|
&nssa::program::Program::serialize_instruction(balance_to_move).unwrap(),
|
||||||
|
&[0, 2],
|
||||||
|
&[to_acc.nonce + 1],
|
||||||
|
&[(to_npk.clone(), shared_secret)],
|
||||||
|
&[],
|
||||||
|
&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(),
|
||||||
|
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 =
|
||||||
|
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||||
|
&message,
|
||||||
|
proof,
|
||||||
|
&[signing_key],
|
||||||
|
);
|
||||||
|
|
||||||
|
let tx = nssa::privacy_preserving_transaction::PrivacyPreservingTransaction::new(
|
||||||
|
message,
|
||||||
|
witness_set,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(self.sequencer_client.send_tx_private(tx).await?)
|
||||||
|
} else {
|
||||||
|
Err(ExecutionFailureKind::InsufficientFundsError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user