diff --git a/Cargo.lock b/Cargo.lock index 6492610e..56181af5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1959,7 +1959,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de" dependencies = [ "data-encoding", - "syn 2.0.117", + "syn 1.0.109", ] [[package]] diff --git a/nssa/src/privacy_preserving_transaction/witness_set.rs b/nssa/src/privacy_preserving_transaction/witness_set.rs index 373bbc9c..cdd57f88 100644 --- a/nssa/src/privacy_preserving_transaction/witness_set.rs +++ b/nssa/src/privacy_preserving_transaction/witness_set.rs @@ -13,6 +13,8 @@ pub struct WitnessSet { impl WitnessSet { #[must_use] + // TODO: this generates signatures. + // However. we may need to get signatures from Keycard. pub fn for_message(message: &Message, proof: Proof, private_keys: &[&PrivateKey]) -> Self { let message_bytes = message.to_bytes(); let signatures_and_public_keys = private_keys diff --git a/nssa/src/public_transaction/witness_set.rs b/nssa/src/public_transaction/witness_set.rs index d6b32891..69b1dc80 100644 --- a/nssa/src/public_transaction/witness_set.rs +++ b/nssa/src/public_transaction/witness_set.rs @@ -8,6 +8,21 @@ pub struct WitnessSet { } impl WitnessSet { + #[must_use] + pub fn from_list(signatures: &[Signature], pub_keys: &[PublicKey]) -> Self { + assert_eq!(signatures.len(), pub_keys.len()); + + let signatures_and_public_keys = signatures + .iter() + .zip(pub_keys.iter()) + .map(|(sig, key)| (sig.clone(), key.clone())) + .collect(); + + Self { + signatures_and_public_keys, + } + } + #[must_use] pub fn for_message(message: &Message, private_keys: &[&PrivateKey]) -> Self { let message_bytes = message.to_bytes(); diff --git a/wallet/src/chain_storage.rs b/wallet/src/chain_storage.rs index 3699609b..cf6de5ce 100644 --- a/wallet/src/chain_storage.rs +++ b/wallet/src/chain_storage.rs @@ -56,7 +56,9 @@ impl WalletChainStore { .expect("Malformed persistent account data, must have private root"); let mut public_tree = KeyTreePublic::new_from_root(match public_root { - PersistentAccountData::Public(data) => data.data, + PersistentAccountData::Public(data) => { + data.data.expect("Expect valid public account keys") + } _ => unreachable!(), }); let mut private_tree = KeyTreePrivate::new_from_root(match private_root { @@ -67,7 +69,11 @@ impl WalletChainStore { for pers_acc_data in persistent_accounts { match pers_acc_data { PersistentAccountData::Public(data) => { - public_tree.insert(data.account_id, data.chain_index, data.data); + public_tree.insert( + data.account_id, + data.chain_index, + data.data.expect("Expect valid public account keys"), + ); } PersistentAccountData::Private(data) => { private_tree.insert(data.account_id, data.chain_index, data.data); @@ -225,7 +231,7 @@ mod tests { PersistentAccountData::Public(PersistentAccountDataPublic { account_id: public_data.account_id(), chain_index: ChainIndex::root(), - data: public_data, + data: Some(public_data), }), PersistentAccountData::Private(Box::new(PersistentAccountDataPrivate { account_id: private_data.account_id(), diff --git a/wallet/src/config.rs b/wallet/src/config.rs index 33527009..4c008979 100644 --- a/wallet/src/config.rs +++ b/wallet/src/config.rs @@ -23,7 +23,7 @@ use url::Url; pub struct PersistentAccountDataPublic { pub account_id: nssa::AccountId, pub chain_index: ChainIndex, - pub data: ChildKeysPublic, + pub data: Option, // `None` when Keycard is used. } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/wallet/src/helperfunctions.rs b/wallet/src/helperfunctions.rs index 37a27409..3e304253 100644 --- a/wallet/src/helperfunctions.rs +++ b/wallet/src/helperfunctions.rs @@ -158,7 +158,7 @@ pub fn produce_data_for_storage( PersistentAccountDataPublic { account_id: *account_id, chain_index: key.clone(), - data: data.clone(), + data: Some(data.clone()), } .into(), ); diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 63ea8611..2b0861e5 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -20,7 +20,8 @@ use log::info; use nssa::{ Account, AccountId, PrivacyPreservingTransaction, privacy_preserving_transaction::{ - circuit::ProgramWithDependencies, message::EncryptedAccountData, + circuit::{ProgramWithDependencies, Proof}, + message::EncryptedAccountData, }, }; use nssa_core::{ @@ -413,12 +414,8 @@ impl WalletCore { ) .unwrap(); - let witness_set = - nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message( - &message, - proof, - &acc_manager.public_account_auth(), - ); + let witness_set = Self::sign_privacy_message(&message, &proof, &acc_manager) + .expect("Expect a valid witness set"); let tx = PrivacyPreservingTransaction::new(message, witness_set); let shared_secrets: Vec<_> = private_account_keys @@ -550,4 +547,41 @@ impl WalletCore { pub const fn config_overrides(&self) -> &Option { &self.config_overrides } + + pub fn sign_public_message( + wallet: &Self, + message: &nssa::public_transaction::Message, + account_ids: &[AccountId], + ) -> Result { + let mut private_keys = Vec::new(); + + for &account_id in account_ids { + let key = wallet + .storage + .user_data + .get_pub_account_signing_key(account_id) + .ok_or(ExecutionFailureKind::KeyNotFoundError)?; + private_keys.push(key); + } + + Ok(nssa::public_transaction::WitnessSet::for_message( + message, + &private_keys, + )) + } + + pub fn sign_privacy_message( + message: &nssa::privacy_preserving_transaction::Message, + proof: &Proof, + acc_manager: &privacy_preserving_tx::AccountManager, + ) -> Result + { + Ok( + nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message( + message, + proof.clone(), + &acc_manager.public_account_auth(), + ), + ) + } } diff --git a/wallet/src/program_facades/native_token_transfer/public.rs b/wallet/src/program_facades/native_token_transfer/public.rs index 2d936d3f..7705c268 100644 --- a/wallet/src/program_facades/native_token_transfer/public.rs +++ b/wallet/src/program_facades/native_token_transfer/public.rs @@ -7,7 +7,7 @@ use nssa::{ use sequencer_service_rpc::RpcClient as _; use super::NativeTokenTransfer; -use crate::ExecutionFailureKind; +use crate::{ExecutionFailureKind, WalletCore}; impl NativeTokenTransfer<'_> { pub async fn send_public_transfer( @@ -26,22 +26,17 @@ impl NativeTokenTransfer<'_> { let account_ids = vec![from, to]; let program_id = Program::authenticated_transfer_program().id(); + let mut sign_ids = Vec::new(); + sign_ids.push(from); + let mut nonces = self .0 .get_accounts_nonces(vec![from]) .await .map_err(ExecutionFailureKind::SequencerError)?; - - let mut private_keys = Vec::new(); - let from_signing_key = self.0.storage.user_data.get_pub_account_signing_key(from); - let Some(from_signing_key) = from_signing_key else { - return Err(ExecutionFailureKind::KeyNotFoundError); - }; - private_keys.push(from_signing_key); - let to_signing_key = self.0.storage.user_data.get_pub_account_signing_key(to); - if let Some(to_signing_key) = to_signing_key { - private_keys.push(to_signing_key); + if let Some(_to_signing_key) = to_signing_key { + sign_ids.push(to); let to_nonces = self .0 .get_accounts_nonces(vec![to]) @@ -56,7 +51,9 @@ impl NativeTokenTransfer<'_> { let message = Message::try_new(program_id, account_ids, nonces, balance_to_move).unwrap(); - let witness_set = WitnessSet::for_message(&message, &private_keys); + + let witness_set = WalletCore::sign_public_message(self.0, &message, &sign_ids) + .expect("Expect a valid signature"); let tx = PublicTransaction::new(message, witness_set);