mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-17 21:49:35 +00:00
refactor: implement universal interface for privacy-preserving transactions
This commit is contained in:
parent
aee6f45a8b
commit
df64f8864f
@ -317,21 +317,9 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate {
|
|||||||
let from: AccountId = from.parse().unwrap();
|
let from: AccountId = from.parse().unwrap();
|
||||||
let to: AccountId = to.parse().unwrap();
|
let to: AccountId = to.parse().unwrap();
|
||||||
|
|
||||||
let to_initialization = wallet_core.check_private_account_initialized(&to).await?;
|
let (res, [secret_from, secret_to]) = wallet_core
|
||||||
|
.send_private_native_token_transfer_owned_account(from, to, amount)
|
||||||
let (res, [secret_from, secret_to]) = if let Some(to_proof) = to_initialization {
|
.await?;
|
||||||
wallet_core
|
|
||||||
.send_private_native_token_transfer_owned_account_already_initialized(
|
|
||||||
from, to, amount, to_proof,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
} else {
|
|
||||||
wallet_core
|
|
||||||
.send_private_native_token_transfer_owned_account_not_initialized(
|
|
||||||
from, to, amount,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("Results of tx send is {res:#?}");
|
println!("Results of tx send is {res:#?}");
|
||||||
|
|
||||||
@ -413,19 +401,9 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
|
|||||||
let from: AccountId = from.parse().unwrap();
|
let from: AccountId = from.parse().unwrap();
|
||||||
let to: AccountId = to.parse().unwrap();
|
let to: AccountId = to.parse().unwrap();
|
||||||
|
|
||||||
let to_initialization = wallet_core.check_private_account_initialized(&to).await?;
|
let (res, secret) = wallet_core
|
||||||
|
.send_shielded_native_token_transfer(from, to, amount)
|
||||||
let (res, [secret]) = if let Some(to_proof) = to_initialization {
|
.await?;
|
||||||
wallet_core
|
|
||||||
.send_shielded_native_token_transfer_already_initialized(
|
|
||||||
from, to, amount, to_proof,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
} else {
|
|
||||||
wallet_core
|
|
||||||
.send_shielded_native_token_transfer_not_initialized(from, to, amount)
|
|
||||||
.await?
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("Results of tx send is {res:#?}");
|
println!("Results of tx send is {res:#?}");
|
||||||
|
|
||||||
@ -468,7 +446,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?;
|
||||||
|
|
||||||
@ -502,7 +480,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommand {
|
|||||||
let from: AccountId = from.parse().unwrap();
|
let from: AccountId = from.parse().unwrap();
|
||||||
let to: AccountId = to.parse().unwrap();
|
let to: AccountId = 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?;
|
||||||
|
|
||||||
|
|||||||
@ -389,7 +389,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
|
|||||||
let definition_account_id: AccountId = definition_account_id.parse().unwrap();
|
let definition_account_id: AccountId = definition_account_id.parse().unwrap();
|
||||||
let supply_account_id: AccountId = supply_account_id.parse().unwrap();
|
let supply_account_id: AccountId = supply_account_id.parse().unwrap();
|
||||||
|
|
||||||
let (res, [secret_supply]) = wallet_core
|
let (res, secret_supply) = wallet_core
|
||||||
.send_new_token_definition_private_owned(
|
.send_new_token_definition_private_owned(
|
||||||
definition_account_id,
|
definition_account_id,
|
||||||
supply_account_id,
|
supply_account_id,
|
||||||
@ -428,30 +428,14 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
|
|||||||
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
|
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
|
||||||
let recipient_account_id: AccountId = recipient_account_id.parse().unwrap();
|
let recipient_account_id: AccountId = recipient_account_id.parse().unwrap();
|
||||||
|
|
||||||
let recipient_initialization = wallet_core
|
let (res, [secret_sender, secret_recipient]) = wallet_core
|
||||||
.check_private_account_initialized(&recipient_account_id)
|
.send_transfer_token_transaction_private_owned_account(
|
||||||
|
sender_account_id,
|
||||||
|
recipient_account_id,
|
||||||
|
balance_to_move,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let (res, [secret_sender, secret_recipient]) =
|
|
||||||
if let Some(recipient_proof) = recipient_initialization {
|
|
||||||
wallet_core
|
|
||||||
.send_transfer_token_transaction_private_owned_account_already_initialized(
|
|
||||||
sender_account_id,
|
|
||||||
recipient_account_id,
|
|
||||||
balance_to_move,
|
|
||||||
recipient_proof,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
} else {
|
|
||||||
wallet_core
|
|
||||||
.send_transfer_token_transaction_private_owned_account_not_initialized(
|
|
||||||
sender_account_id,
|
|
||||||
recipient_account_id,
|
|
||||||
balance_to_move,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("Results of tx send is {res:#?}");
|
println!("Results of tx send is {res:#?}");
|
||||||
|
|
||||||
let tx_hash = res.tx_hash;
|
let tx_hash = res.tx_hash;
|
||||||
@ -545,7 +529,7 @@ impl WalletSubcommand for TokenProgramSubcommandDeshielded {
|
|||||||
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
|
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
|
||||||
let recipient_account_id: AccountId = recipient_account_id.parse().unwrap();
|
let recipient_account_id: AccountId = recipient_account_id.parse().unwrap();
|
||||||
|
|
||||||
let (res, [secret_sender]) = wallet_core
|
let (res, secret_sender) = wallet_core
|
||||||
.send_transfer_token_transaction_deshielded(
|
.send_transfer_token_transaction_deshielded(
|
||||||
sender_account_id,
|
sender_account_id,
|
||||||
recipient_account_id,
|
recipient_account_id,
|
||||||
@ -604,7 +588,7 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
|
|||||||
recipient_ipk.to_vec(),
|
recipient_ipk.to_vec(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = wallet_core
|
let (res, _) = wallet_core
|
||||||
.send_transfer_token_transaction_shielded_foreign_account(
|
.send_transfer_token_transaction_shielded_foreign_account(
|
||||||
sender_account_id,
|
sender_account_id,
|
||||||
recipient_npk,
|
recipient_npk,
|
||||||
@ -638,30 +622,14 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
|
|||||||
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
|
let sender_account_id: AccountId = sender_account_id.parse().unwrap();
|
||||||
let recipient_account_id: AccountId = recipient_account_id.parse().unwrap();
|
let recipient_account_id: AccountId = recipient_account_id.parse().unwrap();
|
||||||
|
|
||||||
let recipient_initialization = wallet_core
|
let (res, secret_recipient) = wallet_core
|
||||||
.check_private_account_initialized(&recipient_account_id)
|
.send_transfer_token_transaction_shielded_owned_account(
|
||||||
|
sender_account_id,
|
||||||
|
recipient_account_id,
|
||||||
|
balance_to_move,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let (res, [secret_recipient]) =
|
|
||||||
if let Some(recipient_proof) = recipient_initialization {
|
|
||||||
wallet_core
|
|
||||||
.send_transfer_token_transaction_shielded_owned_account_already_initialized(
|
|
||||||
sender_account_id,
|
|
||||||
recipient_account_id,
|
|
||||||
balance_to_move,
|
|
||||||
recipient_proof,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
} else {
|
|
||||||
wallet_core
|
|
||||||
.send_transfer_token_transaction_shielded_owned_account_not_initialized(
|
|
||||||
sender_account_id,
|
|
||||||
recipient_account_id,
|
|
||||||
balance_to_move,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("Results of tx send is {res:#?}");
|
println!("Results of tx send is {res:#?}");
|
||||||
|
|
||||||
let tx_hash = res.tx_hash;
|
let tx_hash = res.tx_hash;
|
||||||
|
|||||||
@ -4,19 +4,23 @@ use anyhow::Result;
|
|||||||
use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
|
use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
|
||||||
use chain_storage::WalletChainStore;
|
use chain_storage::WalletChainStore;
|
||||||
use common::{
|
use common::{
|
||||||
sequencer_client::SequencerClient,
|
error::ExecutionFailureKind,
|
||||||
|
sequencer_client::{SequencerClient, json::SendTxResponse},
|
||||||
transaction::{EncodedTransaction, NSSATransaction},
|
transaction::{EncodedTransaction, NSSATransaction},
|
||||||
};
|
};
|
||||||
use config::WalletConfig;
|
use config::WalletConfig;
|
||||||
use key_protocol::key_management::key_tree::chain_index::ChainIndex;
|
use key_protocol::key_management::key_tree::chain_index::ChainIndex;
|
||||||
use log::info;
|
use log::info;
|
||||||
use nssa::{Account, AccountId};
|
use nssa::{Account, AccountId, PrivacyPreservingTransaction, program::Program};
|
||||||
use nssa_core::{Commitment, MembershipProof};
|
use nssa_core::{Commitment, MembershipProof, SharedSecretKey, program::InstructionData};
|
||||||
|
pub use privacy_preserving_tx::PrivacyPreservingAccount;
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::PersistentStorage,
|
config::PersistentStorage,
|
||||||
helperfunctions::{fetch_persistent_storage, get_home, produce_data_for_storage},
|
helperfunctions::{
|
||||||
|
fetch_persistent_storage, get_home, produce_data_for_storage, produce_random_nonces,
|
||||||
|
},
|
||||||
poller::TxPoller,
|
poller::TxPoller,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -27,6 +31,7 @@ pub mod cli;
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod helperfunctions;
|
pub mod helperfunctions;
|
||||||
pub mod poller;
|
pub mod poller;
|
||||||
|
mod privacy_preserving_tx;
|
||||||
pub mod program_interactions;
|
pub mod program_interactions;
|
||||||
pub mod token_transfers;
|
pub mod token_transfers;
|
||||||
pub mod transaction_utils;
|
pub mod transaction_utils;
|
||||||
@ -144,6 +149,15 @@ impl WalletCore {
|
|||||||
Ok(response.account)
|
Ok(response.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_account_public_signing_key(
|
||||||
|
&self,
|
||||||
|
account_id: &AccountId,
|
||||||
|
) -> Option<&nssa::PrivateKey> {
|
||||||
|
self.storage
|
||||||
|
.user_data
|
||||||
|
.get_pub_account_signing_key(account_id)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_account_private(&self, account_id: &AccountId) -> Option<Account> {
|
pub fn get_account_private(&self, account_id: &AccountId) -> Option<Account> {
|
||||||
self.storage
|
self.storage
|
||||||
.user_data
|
.user_data
|
||||||
@ -206,4 +220,67 @@ impl WalletCore {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn send_privacy_preserving_tx(
|
||||||
|
&self,
|
||||||
|
accounts: Vec<PrivacyPreservingAccount>,
|
||||||
|
instruction_data: InstructionData,
|
||||||
|
tx_pre_check: impl FnOnce(&[&Account]) -> Result<(), ExecutionFailureKind>,
|
||||||
|
program: Program,
|
||||||
|
) -> Result<(SendTxResponse, Vec<SharedSecretKey>), ExecutionFailureKind> {
|
||||||
|
let payload = privacy_preserving_tx::Payload::new(self, accounts).await?;
|
||||||
|
|
||||||
|
let pre_states = payload.pre_states();
|
||||||
|
tx_pre_check(
|
||||||
|
&pre_states
|
||||||
|
.iter()
|
||||||
|
.map(|pre| &pre.account)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let private_account_keys = payload.private_account_keys();
|
||||||
|
let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove(
|
||||||
|
&pre_states,
|
||||||
|
&instruction_data,
|
||||||
|
payload.visibility_mask(),
|
||||||
|
&produce_random_nonces(private_account_keys.len()),
|
||||||
|
&private_account_keys
|
||||||
|
.iter()
|
||||||
|
.map(|keys| (keys.npk.clone(), keys.ssk.clone()))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
&payload.private_account_auth(),
|
||||||
|
&program,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let message =
|
||||||
|
nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output(
|
||||||
|
payload.public_account_ids(),
|
||||||
|
Vec::from_iter(payload.public_account_nonces()),
|
||||||
|
private_account_keys
|
||||||
|
.iter()
|
||||||
|
.map(|keys| (keys.npk.clone(), keys.ipk.clone(), keys.epk.clone()))
|
||||||
|
.collect(),
|
||||||
|
output,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let witness_set =
|
||||||
|
nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message(
|
||||||
|
&message,
|
||||||
|
proof,
|
||||||
|
&payload.witness_signing_keys(),
|
||||||
|
);
|
||||||
|
let tx = PrivacyPreservingTransaction::new(message, witness_set);
|
||||||
|
|
||||||
|
let shared_secrets = private_account_keys
|
||||||
|
.into_iter()
|
||||||
|
.map(|keys| keys.ssk)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
self.sequencer_client.send_tx_private(tx).await?,
|
||||||
|
shared_secrets,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
173
wallet/src/privacy_preserving_tx.rs
Normal file
173
wallet/src/privacy_preserving_tx.rs
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
use common::error::ExecutionFailureKind;
|
||||||
|
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||||
|
use nssa::{AccountId, PrivateKey};
|
||||||
|
use nssa_core::{
|
||||||
|
MembershipProof, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
|
||||||
|
account::{AccountWithMetadata, Nonce},
|
||||||
|
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{WalletCore, transaction_utils::AccountPreparedData};
|
||||||
|
|
||||||
|
pub enum PrivacyPreservingAccount {
|
||||||
|
Public(AccountId),
|
||||||
|
PrivateLocal(AccountId),
|
||||||
|
PrivateForeign {
|
||||||
|
npk: NullifierPublicKey,
|
||||||
|
ipk: IncomingViewingPublicKey,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PrivateAccountKeys {
|
||||||
|
pub npk: NullifierPublicKey,
|
||||||
|
pub ssk: SharedSecretKey,
|
||||||
|
pub ipk: IncomingViewingPublicKey,
|
||||||
|
pub epk: EphemeralPublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
Public {
|
||||||
|
account: AccountWithMetadata,
|
||||||
|
sk: Option<PrivateKey>,
|
||||||
|
},
|
||||||
|
Private(AccountPreparedData),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Payload {
|
||||||
|
states: Vec<State>,
|
||||||
|
visibility_mask: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Payload {
|
||||||
|
pub async fn new(
|
||||||
|
wallet: &WalletCore,
|
||||||
|
accounts: Vec<PrivacyPreservingAccount>,
|
||||||
|
) -> Result<Self, ExecutionFailureKind> {
|
||||||
|
let mut pre_states = Vec::with_capacity(accounts.len());
|
||||||
|
let mut visibility_mask = Vec::with_capacity(accounts.len());
|
||||||
|
|
||||||
|
for account in accounts {
|
||||||
|
let (state, mask) = match account {
|
||||||
|
PrivacyPreservingAccount::Public(account_id) => {
|
||||||
|
let acc = wallet
|
||||||
|
.get_account_public(account_id)
|
||||||
|
.await
|
||||||
|
.map_err(|_| ExecutionFailureKind::KeyNotFoundError)?;
|
||||||
|
|
||||||
|
let sk = wallet.get_account_public_signing_key(&account_id).cloned();
|
||||||
|
let account = AccountWithMetadata::new(acc.clone(), sk.is_some(), account_id);
|
||||||
|
|
||||||
|
(State::Public { account, sk }, 0)
|
||||||
|
}
|
||||||
|
PrivacyPreservingAccount::PrivateLocal(account_id) => {
|
||||||
|
let mut pre = wallet
|
||||||
|
.private_acc_preparation(account_id, true, true)
|
||||||
|
.await?;
|
||||||
|
let mut mask = 1;
|
||||||
|
|
||||||
|
if pre.proof.is_none() {
|
||||||
|
pre.auth_acc.is_authorized = false;
|
||||||
|
pre.nsk = None;
|
||||||
|
mask = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
(State::Private(pre), mask)
|
||||||
|
}
|
||||||
|
PrivacyPreservingAccount::PrivateForeign { npk, ipk } => {
|
||||||
|
let acc = nssa_core::account::Account::default();
|
||||||
|
let auth_acc = AccountWithMetadata::new(acc, false, &npk);
|
||||||
|
let pre = AccountPreparedData {
|
||||||
|
nsk: None,
|
||||||
|
npk,
|
||||||
|
ipk,
|
||||||
|
auth_acc,
|
||||||
|
proof: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
(State::Private(pre), 2)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pre_states.push(state);
|
||||||
|
visibility_mask.push(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
states: pre_states,
|
||||||
|
visibility_mask,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pre_states(&self) -> Vec<AccountWithMetadata> {
|
||||||
|
self.states
|
||||||
|
.iter()
|
||||||
|
.map(|state| match state {
|
||||||
|
State::Public { account, .. } => account.clone(),
|
||||||
|
State::Private(pre) => pre.auth_acc.clone(),
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visibility_mask(&self) -> &[u8] {
|
||||||
|
&self.visibility_mask
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn public_account_nonces(&self) -> Vec<Nonce> {
|
||||||
|
self.states
|
||||||
|
.iter()
|
||||||
|
.filter_map(|state| match state {
|
||||||
|
State::Public { account, .. } => Some(account.account.nonce),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn private_account_keys(&self) -> Vec<PrivateAccountKeys> {
|
||||||
|
self.states
|
||||||
|
.iter()
|
||||||
|
.filter_map(|state| match state {
|
||||||
|
State::Private(pre) => {
|
||||||
|
let eph_holder = EphemeralKeyHolder::new(&pre.npk);
|
||||||
|
|
||||||
|
Some(PrivateAccountKeys {
|
||||||
|
npk: pre.npk.clone(),
|
||||||
|
ssk: eph_holder.calculate_shared_secret_sender(&pre.ipk),
|
||||||
|
ipk: pre.ipk.clone(),
|
||||||
|
epk: eph_holder.generate_ephemeral_public_key(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn private_account_auth(&self) -> Vec<(NullifierSecretKey, MembershipProof)> {
|
||||||
|
self.states
|
||||||
|
.iter()
|
||||||
|
.filter_map(|state| match state {
|
||||||
|
State::Private(pre) => Some((pre.nsk?, pre.proof.clone()?)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn public_account_ids(&self) -> Vec<AccountId> {
|
||||||
|
self.states
|
||||||
|
.iter()
|
||||||
|
.filter_map(|state| match state {
|
||||||
|
State::Public { account, .. } => Some(account.account_id),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn witness_signing_keys(&self) -> Vec<&PrivateKey> {
|
||||||
|
self.states
|
||||||
|
.iter()
|
||||||
|
.filter_map(|state| match state {
|
||||||
|
State::Public { sk, .. } => sk.as_ref(),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +1,11 @@
|
|||||||
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
use nssa::{Account, AccountId, program::Program};
|
use nssa::{Account, AccountId, program::Program};
|
||||||
use nssa_core::{
|
use nssa_core::{
|
||||||
MembershipProof, NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey,
|
NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey,
|
||||||
program::InstructionData,
|
program::InstructionData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::WalletCore;
|
use crate::{PrivacyPreservingAccount, WalletCore};
|
||||||
|
|
||||||
impl WalletCore {
|
impl WalletCore {
|
||||||
pub fn token_program_preparation_transfer(
|
pub fn token_program_preparation_transfer(
|
||||||
@ -13,7 +13,7 @@ impl WalletCore {
|
|||||||
) -> (
|
) -> (
|
||||||
InstructionData,
|
InstructionData,
|
||||||
Program,
|
Program,
|
||||||
impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
impl FnOnce(&[&Account]) -> Result<(), ExecutionFailureKind>,
|
||||||
) {
|
) {
|
||||||
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 ||
|
// Instruction must be: [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 ||
|
||||||
// 0x00 || 0x00 || 0x00].
|
// 0x00 || 0x00 || 0x00].
|
||||||
@ -22,7 +22,7 @@ impl WalletCore {
|
|||||||
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
instruction[1..17].copy_from_slice(&amount.to_le_bytes());
|
||||||
let instruction_data = Program::serialize_instruction(instruction).unwrap();
|
let instruction_data = Program::serialize_instruction(instruction).unwrap();
|
||||||
let program = Program::token();
|
let program = Program::token();
|
||||||
let tx_pre_check = |_: &Account, _: &Account| Ok(());
|
let tx_pre_check = |_: &[&Account]| Ok(());
|
||||||
|
|
||||||
(instruction_data, program, tx_pre_check)
|
(instruction_data, program, tx_pre_check)
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ impl WalletCore {
|
|||||||
) -> (
|
) -> (
|
||||||
InstructionData,
|
InstructionData,
|
||||||
Program,
|
Program,
|
||||||
impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
impl FnOnce(&[&Account]) -> Result<(), ExecutionFailureKind>,
|
||||||
) {
|
) {
|
||||||
// Instruction must be: [0x00 || total_supply (little-endian 16 bytes) || name (6 bytes)]
|
// Instruction must be: [0x00 || total_supply (little-endian 16 bytes) || name (6 bytes)]
|
||||||
let mut instruction = [0; 23];
|
let mut instruction = [0; 23];
|
||||||
@ -41,7 +41,7 @@ impl WalletCore {
|
|||||||
instruction[17..].copy_from_slice(&name);
|
instruction[17..].copy_from_slice(&name);
|
||||||
let instruction_data = Program::serialize_instruction(instruction).unwrap();
|
let instruction_data = Program::serialize_instruction(instruction).unwrap();
|
||||||
let program = Program::token();
|
let program = Program::token();
|
||||||
let tx_pre_check = |_: &Account, _: &Account| Ok(());
|
let tx_pre_check = |_: &[&Account]| Ok(());
|
||||||
|
|
||||||
(instruction_data, program, tx_pre_check)
|
(instruction_data, program, tx_pre_check)
|
||||||
}
|
}
|
||||||
@ -80,20 +80,27 @@ impl WalletCore {
|
|||||||
supply_account_id: AccountId,
|
supply_account_id: AccountId,
|
||||||
name: [u8; 6],
|
name: [u8; 6],
|
||||||
total_supply: u128,
|
total_supply: u128,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::token_program_preparation_definition(name, total_supply);
|
WalletCore::token_program_preparation_definition(name, total_supply);
|
||||||
|
|
||||||
// Kind of non-obvious naming
|
self.send_privacy_preserving_tx(
|
||||||
// Basically this funtion is called because authentication mask is [0, 2]
|
vec![
|
||||||
self.shielded_two_accs_receiver_uninit(
|
PrivacyPreservingAccount::Public(definition_account_id),
|
||||||
definition_account_id,
|
PrivacyPreservingAccount::PrivateLocal(supply_account_id),
|
||||||
supply_account_id,
|
],
|
||||||
instruction_data,
|
instruction_data,
|
||||||
tx_pre_check,
|
tx_pre_check,
|
||||||
program,
|
program,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let first = secrets
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.expect("expected recipient's secret");
|
||||||
|
(resp, first)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction(
|
pub async fn send_transfer_token_transaction(
|
||||||
@ -135,28 +142,7 @@ impl WalletCore {
|
|||||||
Ok(self.sequencer_client.send_tx_public(tx).await?)
|
Ok(self.sequencer_client.send_tx_public(tx).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_private_owned_account_already_initialized(
|
pub async fn send_transfer_token_transaction_private_owned_account(
|
||||||
&self,
|
|
||||||
sender_account_id: AccountId,
|
|
||||||
recipient_account_id: AccountId,
|
|
||||||
amount: u128,
|
|
||||||
recipient_proof: MembershipProof,
|
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
|
||||||
let (instruction_data, program, tx_pre_check) =
|
|
||||||
WalletCore::token_program_preparation_transfer(amount);
|
|
||||||
|
|
||||||
self.private_tx_two_accs_all_init(
|
|
||||||
sender_account_id,
|
|
||||||
recipient_account_id,
|
|
||||||
instruction_data,
|
|
||||||
tx_pre_check,
|
|
||||||
program,
|
|
||||||
recipient_proof,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_private_owned_account_not_initialized(
|
|
||||||
&self,
|
&self,
|
||||||
sender_account_id: AccountId,
|
sender_account_id: AccountId,
|
||||||
recipient_account_id: AccountId,
|
recipient_account_id: AccountId,
|
||||||
@ -165,14 +151,22 @@ impl WalletCore {
|
|||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::token_program_preparation_transfer(amount);
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
|
|
||||||
self.private_tx_two_accs_receiver_uninit(
|
self.send_privacy_preserving_tx(
|
||||||
sender_account_id,
|
vec![
|
||||||
recipient_account_id,
|
PrivacyPreservingAccount::PrivateLocal(sender_account_id),
|
||||||
|
PrivacyPreservingAccount::PrivateLocal(recipient_account_id),
|
||||||
|
],
|
||||||
instruction_data,
|
instruction_data,
|
||||||
tx_pre_check,
|
tx_pre_check,
|
||||||
program,
|
program,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let mut iter = secrets.into_iter();
|
||||||
|
let first = iter.next().expect("expected sender's secret");
|
||||||
|
let second = iter.next().expect("expected recipient's secret");
|
||||||
|
(resp, [first, second])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_private_foreign_account(
|
pub async fn send_transfer_token_transaction_private_foreign_account(
|
||||||
@ -185,15 +179,25 @@ impl WalletCore {
|
|||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::token_program_preparation_transfer(amount);
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
|
|
||||||
self.private_tx_two_accs_receiver_outer(
|
self.send_privacy_preserving_tx(
|
||||||
sender_account_id,
|
vec![
|
||||||
recipient_npk,
|
PrivacyPreservingAccount::PrivateLocal(sender_account_id),
|
||||||
recipient_ipk,
|
PrivacyPreservingAccount::PrivateForeign {
|
||||||
|
npk: recipient_npk,
|
||||||
|
ipk: recipient_ipk,
|
||||||
|
},
|
||||||
|
],
|
||||||
instruction_data,
|
instruction_data,
|
||||||
tx_pre_check,
|
tx_pre_check,
|
||||||
program,
|
program,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let mut iter = secrets.into_iter();
|
||||||
|
let first = iter.next().expect("expected sender's secret");
|
||||||
|
let second = iter.next().expect("expected recipient's secret");
|
||||||
|
(resp, [first, second])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_deshielded(
|
pub async fn send_transfer_token_transaction_deshielded(
|
||||||
@ -201,58 +205,55 @@ impl WalletCore {
|
|||||||
sender_account_id: AccountId,
|
sender_account_id: AccountId,
|
||||||
recipient_account_id: AccountId,
|
recipient_account_id: AccountId,
|
||||||
amount: u128,
|
amount: u128,
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::token_program_preparation_transfer(amount);
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
|
|
||||||
self.deshielded_tx_two_accs(
|
self.send_privacy_preserving_tx(
|
||||||
sender_account_id,
|
vec![
|
||||||
recipient_account_id,
|
PrivacyPreservingAccount::PrivateLocal(sender_account_id),
|
||||||
|
PrivacyPreservingAccount::Public(recipient_account_id),
|
||||||
|
],
|
||||||
instruction_data,
|
instruction_data,
|
||||||
tx_pre_check,
|
tx_pre_check,
|
||||||
program,
|
program,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let first = secrets
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.expect("expected sender's secret");
|
||||||
|
(resp, first)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_shielded_owned_account_already_initialized(
|
pub async fn send_transfer_token_transaction_shielded_owned_account(
|
||||||
&self,
|
&self,
|
||||||
sender_account_id: AccountId,
|
sender_account_id: AccountId,
|
||||||
recipient_account_id: AccountId,
|
recipient_account_id: AccountId,
|
||||||
amount: u128,
|
amount: u128,
|
||||||
recipient_proof: MembershipProof,
|
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
|
||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::token_program_preparation_transfer(amount);
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
|
|
||||||
self.shielded_two_accs_all_init(
|
self.send_privacy_preserving_tx(
|
||||||
sender_account_id,
|
vec![
|
||||||
recipient_account_id,
|
PrivacyPreservingAccount::Public(sender_account_id),
|
||||||
instruction_data,
|
PrivacyPreservingAccount::PrivateLocal(recipient_account_id),
|
||||||
tx_pre_check,
|
],
|
||||||
program,
|
|
||||||
recipient_proof,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_shielded_owned_account_not_initialized(
|
|
||||||
&self,
|
|
||||||
sender_account_id: AccountId,
|
|
||||||
recipient_account_id: AccountId,
|
|
||||||
amount: u128,
|
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
|
||||||
let (instruction_data, program, tx_pre_check) =
|
|
||||||
WalletCore::token_program_preparation_transfer(amount);
|
|
||||||
|
|
||||||
self.shielded_two_accs_receiver_uninit(
|
|
||||||
sender_account_id,
|
|
||||||
recipient_account_id,
|
|
||||||
instruction_data,
|
instruction_data,
|
||||||
tx_pre_check,
|
tx_pre_check,
|
||||||
program,
|
program,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let first = secrets
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.expect("expected recipient's secret");
|
||||||
|
(resp, first)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_transfer_token_transaction_shielded_foreign_account(
|
pub async fn send_transfer_token_transaction_shielded_foreign_account(
|
||||||
@ -261,18 +262,29 @@ impl WalletCore {
|
|||||||
recipient_npk: NullifierPublicKey,
|
recipient_npk: NullifierPublicKey,
|
||||||
recipient_ipk: IncomingViewingPublicKey,
|
recipient_ipk: IncomingViewingPublicKey,
|
||||||
amount: u128,
|
amount: u128,
|
||||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::token_program_preparation_transfer(amount);
|
WalletCore::token_program_preparation_transfer(amount);
|
||||||
|
|
||||||
self.shielded_two_accs_receiver_outer(
|
self.send_privacy_preserving_tx(
|
||||||
sender_account_id,
|
vec![
|
||||||
recipient_npk,
|
PrivacyPreservingAccount::Public(sender_account_id),
|
||||||
recipient_ipk,
|
PrivacyPreservingAccount::PrivateForeign {
|
||||||
|
npk: recipient_npk,
|
||||||
|
ipk: recipient_ipk,
|
||||||
|
},
|
||||||
|
],
|
||||||
instruction_data,
|
instruction_data,
|
||||||
tx_pre_check,
|
tx_pre_check,
|
||||||
program,
|
program,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let first = secrets
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.expect("expected recipient's secret");
|
||||||
|
(resp, first)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
use nssa::AccountId;
|
use nssa::AccountId;
|
||||||
|
|
||||||
use crate::WalletCore;
|
use crate::{PrivacyPreservingAccount, WalletCore};
|
||||||
|
|
||||||
impl WalletCore {
|
impl WalletCore {
|
||||||
pub async fn send_deshielded_native_token_transfer(
|
pub async fn send_deshielded_native_token_transfer(
|
||||||
@ -9,11 +9,26 @@ impl WalletCore {
|
|||||||
from: AccountId,
|
from: AccountId,
|
||||||
to: AccountId,
|
to: AccountId,
|
||||||
balance_to_move: u128,
|
balance_to_move: u128,
|
||||||
) -> Result<(SendTxResponse, [nssa_core::SharedSecretKey; 1]), ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, nssa_core::SharedSecretKey), ExecutionFailureKind> {
|
||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::auth_transfer_preparation(balance_to_move);
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
|
|
||||||
self.deshielded_tx_two_accs(from, to, instruction_data, tx_pre_check, program)
|
self.send_privacy_preserving_tx(
|
||||||
.await
|
vec![
|
||||||
|
PrivacyPreservingAccount::PrivateLocal(from),
|
||||||
|
PrivacyPreservingAccount::Public(to),
|
||||||
|
],
|
||||||
|
instruction_data,
|
||||||
|
tx_pre_check,
|
||||||
|
program,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let first = secrets
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.expect("expected sender's secret");
|
||||||
|
(resp, first)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,11 +15,12 @@ impl WalletCore {
|
|||||||
) -> (
|
) -> (
|
||||||
InstructionData,
|
InstructionData,
|
||||||
Program,
|
Program,
|
||||||
impl FnOnce(&Account, &Account) -> Result<(), ExecutionFailureKind>,
|
impl FnOnce(&[&Account]) -> Result<(), ExecutionFailureKind>,
|
||||||
) {
|
) {
|
||||||
let instruction_data = Program::serialize_instruction(balance_to_move).unwrap();
|
let instruction_data = Program::serialize_instruction(balance_to_move).unwrap();
|
||||||
let program = Program::authenticated_transfer_program();
|
let program = Program::authenticated_transfer_program();
|
||||||
let tx_pre_check = move |from: &Account, _: &Account| {
|
let tx_pre_check = move |accounts: &[&Account]| {
|
||||||
|
let from = accounts[0];
|
||||||
if from.balance >= balance_to_move {
|
if from.balance >= balance_to_move {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
|
use std::vec;
|
||||||
|
|
||||||
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
use nssa::AccountId;
|
use nssa::AccountId;
|
||||||
use nssa_core::{
|
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey};
|
||||||
MembershipProof, NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::WalletCore;
|
use crate::{PrivacyPreservingAccount, 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(
|
||||||
@ -17,18 +17,28 @@ impl WalletCore {
|
|||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::auth_transfer_preparation(balance_to_move);
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
|
|
||||||
self.private_tx_two_accs_receiver_outer(
|
self.send_privacy_preserving_tx(
|
||||||
from,
|
vec![
|
||||||
to_npk,
|
PrivacyPreservingAccount::PrivateLocal(from),
|
||||||
to_ipk,
|
PrivacyPreservingAccount::PrivateForeign {
|
||||||
|
npk: to_npk,
|
||||||
|
ipk: to_ipk,
|
||||||
|
},
|
||||||
|
],
|
||||||
instruction_data,
|
instruction_data,
|
||||||
tx_pre_check,
|
tx_pre_check,
|
||||||
program,
|
program,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let mut secrets_iter = secrets.into_iter();
|
||||||
|
let first = secrets_iter.next().expect("expected sender's secret");
|
||||||
|
let second = secrets_iter.next().expect("expected receiver's secret");
|
||||||
|
(resp, [first, second])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_private_native_token_transfer_owned_account_not_initialized(
|
pub async fn send_private_native_token_transfer_owned_account(
|
||||||
&self,
|
&self,
|
||||||
from: AccountId,
|
from: AccountId,
|
||||||
to: AccountId,
|
to: AccountId,
|
||||||
@ -37,28 +47,21 @@ impl WalletCore {
|
|||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::auth_transfer_preparation(balance_to_move);
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
|
|
||||||
self.private_tx_two_accs_receiver_uninit(from, to, instruction_data, tx_pre_check, program)
|
self.send_privacy_preserving_tx(
|
||||||
.await
|
vec![
|
||||||
}
|
PrivacyPreservingAccount::PrivateLocal(from),
|
||||||
|
PrivacyPreservingAccount::PrivateLocal(to),
|
||||||
pub async fn send_private_native_token_transfer_owned_account_already_initialized(
|
],
|
||||||
&self,
|
|
||||||
from: AccountId,
|
|
||||||
to: AccountId,
|
|
||||||
balance_to_move: u128,
|
|
||||||
to_proof: MembershipProof,
|
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
|
||||||
let (instruction_data, program, tx_pre_check) =
|
|
||||||
WalletCore::auth_transfer_preparation(balance_to_move);
|
|
||||||
|
|
||||||
self.private_tx_two_accs_all_init(
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
instruction_data,
|
instruction_data,
|
||||||
tx_pre_check,
|
tx_pre_check,
|
||||||
program,
|
program,
|
||||||
to_proof,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let mut secrets_iter = secrets.into_iter();
|
||||||
|
let first = secrets_iter.next().expect("expected sender's secret");
|
||||||
|
let second = secrets_iter.next().expect("expected receiver's secret");
|
||||||
|
(resp, [first, second])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +1,36 @@
|
|||||||
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
use common::{error::ExecutionFailureKind, sequencer_client::json::SendTxResponse};
|
||||||
use nssa::AccountId;
|
use nssa::AccountId;
|
||||||
use nssa_core::{
|
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey};
|
||||||
MembershipProof, NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::WalletCore;
|
use crate::{PrivacyPreservingAccount, WalletCore};
|
||||||
|
|
||||||
impl WalletCore {
|
impl WalletCore {
|
||||||
pub async fn send_shielded_native_token_transfer_already_initialized(
|
pub async fn send_shielded_native_token_transfer(
|
||||||
&self,
|
&self,
|
||||||
from: AccountId,
|
from: AccountId,
|
||||||
to: AccountId,
|
to: AccountId,
|
||||||
balance_to_move: u128,
|
balance_to_move: u128,
|
||||||
to_proof: MembershipProof,
|
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
|
||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::auth_transfer_preparation(balance_to_move);
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
|
|
||||||
self.shielded_two_accs_all_init(from, to, instruction_data, tx_pre_check, program, to_proof)
|
self.send_privacy_preserving_tx(
|
||||||
.await
|
vec![
|
||||||
}
|
PrivacyPreservingAccount::Public(from),
|
||||||
|
PrivacyPreservingAccount::PrivateLocal(to),
|
||||||
pub async fn send_shielded_native_token_transfer_not_initialized(
|
],
|
||||||
&self,
|
instruction_data,
|
||||||
from: AccountId,
|
tx_pre_check,
|
||||||
to: AccountId,
|
program,
|
||||||
balance_to_move: u128,
|
)
|
||||||
) -> Result<(SendTxResponse, [SharedSecretKey; 1]), ExecutionFailureKind> {
|
.await
|
||||||
let (instruction_data, program, tx_pre_check) =
|
.map(|(resp, secrets)| {
|
||||||
WalletCore::auth_transfer_preparation(balance_to_move);
|
let first = secrets
|
||||||
|
.into_iter()
|
||||||
self.shielded_two_accs_receiver_uninit(from, to, instruction_data, tx_pre_check, program)
|
.next()
|
||||||
.await
|
.expect("expected sender's secret");
|
||||||
|
(resp, first)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_shielded_native_token_transfer_outer_account(
|
pub async fn send_shielded_native_token_transfer_outer_account(
|
||||||
@ -40,18 +39,29 @@ impl WalletCore {
|
|||||||
to_npk: NullifierPublicKey,
|
to_npk: NullifierPublicKey,
|
||||||
to_ipk: IncomingViewingPublicKey,
|
to_ipk: IncomingViewingPublicKey,
|
||||||
balance_to_move: u128,
|
balance_to_move: u128,
|
||||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||||
let (instruction_data, program, tx_pre_check) =
|
let (instruction_data, program, tx_pre_check) =
|
||||||
WalletCore::auth_transfer_preparation(balance_to_move);
|
WalletCore::auth_transfer_preparation(balance_to_move);
|
||||||
|
|
||||||
self.shielded_two_accs_receiver_outer(
|
self.send_privacy_preserving_tx(
|
||||||
from,
|
vec![
|
||||||
to_npk,
|
PrivacyPreservingAccount::Public(from),
|
||||||
to_ipk,
|
PrivacyPreservingAccount::PrivateForeign {
|
||||||
|
npk: to_npk,
|
||||||
|
ipk: to_ipk,
|
||||||
|
},
|
||||||
|
],
|
||||||
instruction_data,
|
instruction_data,
|
||||||
tx_pre_check,
|
tx_pre_check,
|
||||||
program,
|
program,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.map(|(resp, secrets)| {
|
||||||
|
let first = secrets
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.expect("expected sender's secret");
|
||||||
|
(resp, first)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
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 key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||||
use nssa::{
|
use nssa::{
|
||||||
Account, AccountId, PrivacyPreservingTransaction,
|
AccountId, PrivacyPreservingTransaction,
|
||||||
privacy_preserving_transaction::{circuit, message::Message, witness_set::WitnessSet},
|
privacy_preserving_transaction::{circuit, message::Message, witness_set::WitnessSet},
|
||||||
program::Program,
|
program::Program,
|
||||||
};
|
};
|
||||||
use nssa_core::{
|
use nssa_core::{
|
||||||
Commitment, MembershipProof, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
|
MembershipProof, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
|
||||||
account::AccountWithMetadata, encryption::IncomingViewingPublicKey, program::InstructionData,
|
account::AccountWithMetadata, encryption::IncomingViewingPublicKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
use crate::{WalletCore, helperfunctions::produce_random_nonces};
|
||||||
@ -42,8 +42,6 @@ impl WalletCore {
|
|||||||
let from_npk = from_keys.nullifer_public_key;
|
let from_npk = from_keys.nullifer_public_key;
|
||||||
let from_ipk = from_keys.incoming_viewing_public_key;
|
let from_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);
|
let sender_pre = AccountWithMetadata::new(from_acc.clone(), is_authorized, &from_npk);
|
||||||
|
|
||||||
if is_authorized {
|
if is_authorized {
|
||||||
@ -51,9 +49,9 @@ impl WalletCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if needs_proof {
|
if needs_proof {
|
||||||
|
// TODO: Remove this unwrap, error types must be compatible
|
||||||
proof = self
|
proof = self
|
||||||
.sequencer_client
|
.check_private_account_initialized(&account_id)
|
||||||
.get_proof_for_commitment(sender_commitment)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@ -67,480 +65,7 @@ impl WalletCore {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn private_tx_two_accs_all_init(
|
// TODO: Remove
|
||||||
&self,
|
|
||||||
from: AccountId,
|
|
||||||
to: AccountId,
|
|
||||||
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: AccountId,
|
|
||||||
to: AccountId,
|
|
||||||
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: AccountId,
|
|
||||||
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: AccountId,
|
|
||||||
to: AccountId,
|
|
||||||
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: AccountId,
|
|
||||||
to: AccountId,
|
|
||||||
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: AccountId,
|
|
||||||
to: AccountId,
|
|
||||||
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: AccountId,
|
|
||||||
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?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn register_account_under_authenticated_transfers_programs_private(
|
pub async fn register_account_under_authenticated_transfers_programs_private(
|
||||||
&self,
|
&self,
|
||||||
from: AccountId,
|
from: AccountId,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user