diff --git a/nssa/core/src/account.rs b/nssa/core/src/account.rs index 58d2bec..5b9995a 100644 --- a/nssa/core/src/account.rs +++ b/nssa/core/src/account.rs @@ -6,7 +6,9 @@ pub type Nonce = u128; pub type Data = Vec; /// Account to be used both in public and private contexts -#[derive(Serialize, Deserialize, Clone, Default, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +#[derive( + Serialize, Deserialize, Clone, Default, PartialEq, Eq, BorshSerialize, BorshDeserialize, +)] #[cfg_attr(any(feature = "host", test), derive(Debug))] pub struct Account { pub program_owner: ProgramId, diff --git a/nssa/src/encoding/privacy_preserving_transaction.rs b/nssa/src/encoding/privacy_preserving_transaction.rs index a488e7b..8647a32 100644 --- a/nssa/src/encoding/privacy_preserving_transaction.rs +++ b/nssa/src/encoding/privacy_preserving_transaction.rs @@ -1,209 +1,15 @@ -use std::io::{Cursor, Read}; - -use nssa_core::{ - Commitment, Nullifier, - account::Account, - encryption::{Ciphertext, EphemeralPublicKey}, -}; - use crate::{ - Address, PrivacyPreservingTransaction, PublicKey, Signature, - error::NssaError, - privacy_preserving_transaction::{ - circuit::Proof, - message::{EncryptedAccountData, Message}, - witness_set::WitnessSet, - }, + PrivacyPreservingTransaction, error::NssaError, + privacy_preserving_transaction::message::Message, }; -const MESSAGE_ENCODING_PREFIX_LEN: usize = 32; -const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] = - b"/NSSA/v0.2/TxMessage/Private/\x00\x00\x00"; - -impl EncryptedAccountData { - pub fn to_bytes(&self) -> Vec { - let mut bytes = self.ciphertext.to_bytes(); - bytes.extend_from_slice(&self.epk.to_bytes()); - bytes.push(self.view_tag); - bytes - } - - pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { - let ciphertext = Ciphertext::from_cursor(cursor)?; - let epk = EphemeralPublicKey::from_cursor(cursor)?; - - let mut tag_bytes = [0; 1]; - cursor.read_exact(&mut tag_bytes)?; - let view_tag = tag_bytes[0]; - - Ok(Self { - ciphertext, - epk, - view_tag, - }) - } -} - impl Message { - pub(crate) fn to_bytes(&self) -> Vec { - let mut bytes = MESSAGE_ENCODING_PREFIX.to_vec(); - - // Public addresses - let public_addresses_len: u32 = self.public_addresses.len() as u32; - bytes.extend_from_slice(&public_addresses_len.to_le_bytes()); - for address in &self.public_addresses { - bytes.extend_from_slice(address.value()); - } - // Nonces - let nonces_len = self.nonces.len() as u32; - bytes.extend(&nonces_len.to_le_bytes()); - for nonce in &self.nonces { - bytes.extend(&nonce.to_le_bytes()); - } - // Public post states - let public_post_states_len: u32 = self.public_post_states.len() as u32; - bytes.extend_from_slice(&public_post_states_len.to_le_bytes()); - for account in &self.public_post_states { - bytes.extend_from_slice(&account.to_bytes()); - } - - // Encrypted post states - let encrypted_accounts_post_states_len: u32 = - self.encrypted_private_post_states.len() as u32; - bytes.extend_from_slice(&encrypted_accounts_post_states_len.to_le_bytes()); - for encrypted_account in &self.encrypted_private_post_states { - bytes.extend_from_slice(&encrypted_account.to_bytes()); - } - - // New commitments - let new_commitments_len: u32 = self.new_commitments.len() as u32; - bytes.extend_from_slice(&new_commitments_len.to_le_bytes()); - for commitment in &self.new_commitments { - bytes.extend_from_slice(&commitment.to_byte_array()); - } - - // New nullifiers - let new_nullifiers_len: u32 = self.new_nullifiers.len() as u32; - bytes.extend_from_slice(&new_nullifiers_len.to_le_bytes()); - for (nullifier, commitment_set_digest) in &self.new_nullifiers { - bytes.extend_from_slice(&nullifier.to_byte_array()); - bytes.extend_from_slice(commitment_set_digest); - } - - bytes + pub fn to_bytes(&self) -> Vec { + borsh::to_vec(&self).unwrap() } - #[allow(unused)] - pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { - let prefix = { - let mut this = [0u8; MESSAGE_ENCODING_PREFIX_LEN]; - cursor.read_exact(&mut this)?; - this - }; - if &prefix != MESSAGE_ENCODING_PREFIX { - return Err(NssaError::TransactionDeserializationError( - "Invalid privacy preserving message prefix".to_string(), - )); - } - - let mut len_bytes = [0u8; 4]; - - // Public addresses - cursor.read_exact(&mut len_bytes)?; - let public_addresses_len = u32::from_le_bytes(len_bytes) as usize; - let mut public_addresses = Vec::with_capacity(public_addresses_len); - for _ in 0..public_addresses_len { - let mut value = [0u8; 32]; - cursor.read_exact(&mut value)?; - public_addresses.push(Address::new(value)) - } - - // Nonces - cursor.read_exact(&mut len_bytes)?; - let nonces_len = u32::from_le_bytes(len_bytes) as usize; - let mut nonces = Vec::with_capacity(nonces_len); - for _ in 0..nonces_len { - let mut buf = [0u8; 16]; - cursor.read_exact(&mut buf)?; - nonces.push(u128::from_le_bytes(buf)) - } - - // Public post states - cursor.read_exact(&mut len_bytes)?; - let public_post_states_len = u32::from_le_bytes(len_bytes) as usize; - let mut public_post_states = Vec::with_capacity(public_post_states_len); - for _ in 0..public_post_states_len { - public_post_states.push(Account::from_cursor(cursor)?); - } - - // Encrypted private post states - cursor.read_exact(&mut len_bytes)?; - let encrypted_len = u32::from_le_bytes(len_bytes) as usize; - let mut encrypted_private_post_states = Vec::with_capacity(encrypted_len); - for _ in 0..encrypted_len { - encrypted_private_post_states.push(EncryptedAccountData::from_cursor(cursor)?); - } - - // New commitments - cursor.read_exact(&mut len_bytes)?; - let new_commitments_len = u32::from_le_bytes(len_bytes) as usize; - let mut new_commitments = Vec::with_capacity(new_commitments_len); - for _ in 0..new_commitments_len { - new_commitments.push(Commitment::from_cursor(cursor)?); - } - - // New nullifiers - cursor.read_exact(&mut len_bytes)?; - let new_nullifiers_len = u32::from_le_bytes(len_bytes) as usize; - let mut new_nullifiers = Vec::with_capacity(new_nullifiers_len); - for _ in 0..new_nullifiers_len { - let nullifier = Nullifier::from_cursor(cursor)?; - let mut commitment_set_digest = [0; 32]; - cursor.read_exact(&mut commitment_set_digest)?; - new_nullifiers.push((nullifier, commitment_set_digest)); - } - - Ok(Self { - public_addresses, - nonces, - public_post_states, - encrypted_private_post_states, - new_commitments, - new_nullifiers, - }) - } -} - -impl WitnessSet { - pub(crate) fn to_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - let size = self.signatures_and_public_keys().len() as u32; - bytes.extend_from_slice(&size.to_le_bytes()); - for (signature, public_key) in self.signatures_and_public_keys() { - bytes.extend_from_slice(signature.to_bytes()); - bytes.extend_from_slice(public_key.to_bytes()); - } - bytes.extend_from_slice(&self.proof.to_bytes()); - bytes - } - - pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { - let num_signatures: u32 = { - let mut buf = [0u8; 4]; - cursor.read_exact(&mut buf)?; - u32::from_le_bytes(buf) - }; - let mut signatures_and_public_keys = Vec::with_capacity(num_signatures as usize); - for _i in 0..num_signatures { - let signature = Signature::from_cursor(cursor)?; - let public_key = PublicKey::from_cursor(cursor)?; - signatures_and_public_keys.push((signature, public_key)) - } - let proof = Proof::from_cursor(cursor)?; - Ok(Self { - signatures_and_public_keys, - proof, - }) + pub fn from_bytes(bytes: &[u8]) -> Result { + Ok(borsh::from_slice(bytes)?) } } @@ -216,34 +22,3 @@ impl PrivacyPreservingTransaction { Ok(borsh::from_slice(bytes)?) } } - -impl Proof { - pub fn to_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - let proof_len = self.0.len() as u32; - bytes.extend_from_slice(&proof_len.to_le_bytes()); - bytes.extend_from_slice(&self.0); - bytes - } - - pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { - let proof_len = u32_from_cursor(cursor) as usize; - let mut proof = Vec::with_capacity(proof_len); - - for _ in 0..proof_len { - let mut one_byte_buf = [0u8]; - - cursor.read_exact(&mut one_byte_buf)?; - - proof.push(one_byte_buf[0]); - } - Ok(Self(proof)) - } -} - -// TODO: Improve error handling. Remove unwraps. -pub fn u32_from_cursor(cursor: &mut Cursor<&[u8]>) -> u32 { - let mut word_buf = [0u8; 4]; - cursor.read_exact(&mut word_buf).unwrap(); - u32::from_le_bytes(word_buf) -} diff --git a/nssa/src/encoding/program_deployment_transaction.rs b/nssa/src/encoding/program_deployment_transaction.rs index 2dc91b4..0cf00e0 100644 --- a/nssa/src/encoding/program_deployment_transaction.rs +++ b/nssa/src/encoding/program_deployment_transaction.rs @@ -1,77 +1,17 @@ -// TODO: Consider switching to deriving Borsh - -use std::io::{Cursor, Read}; - -use crate::{ - ProgramDeploymentTransaction, error::NssaError, program_deployment_transaction::Message, -}; - -const MESSAGE_ENCODING_PREFIX_LEN: usize = 32; -const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] = - b"/NSSA/v0.2/TxMessage/Program/\x00\x00\x00"; - -impl Message { - /// Serializes a `Message` into bytes in the following layout: - /// PREFIX || bytecode_len (4 bytes LE) || - /// Integers are encoded in little-endian byte order, and fields appear in the above order. - pub(crate) fn to_bytes(&self) -> Vec { - let mut bytes = MESSAGE_ENCODING_PREFIX.to_vec(); - let bytecode_len = self.bytecode.len() as u32; - bytes.extend(&bytecode_len.to_le_bytes()); - bytes.extend(&self.bytecode); - bytes - } - - pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { - let prefix = { - let mut this = [0u8; MESSAGE_ENCODING_PREFIX_LEN]; - cursor.read_exact(&mut this)?; - this - }; - if &prefix != MESSAGE_ENCODING_PREFIX { - return Err(NssaError::TransactionDeserializationError( - "Invalid public message prefix".to_string(), - )); - } - let bytecode_len = u32_from_cursor(cursor)?; - let mut bytecode = vec![0; bytecode_len as usize]; - let num_bytes = cursor.read(&mut bytecode)?; - if num_bytes != bytecode_len as usize { - println!("num bytes: {}", num_bytes); - return Err(NssaError::TransactionDeserializationError( - "Invalid number of bytes".to_string(), - )); - } - Ok(Self { bytecode }) - } -} +use crate::{ProgramDeploymentTransaction, error::NssaError}; impl ProgramDeploymentTransaction { pub fn to_bytes(&self) -> Vec { - self.message.to_bytes() + borsh::to_vec(&self).unwrap() } pub fn from_bytes(bytes: &[u8]) -> Result { - let mut cursor = Cursor::new(bytes); - Self::from_cursor(&mut cursor) + Ok(borsh::from_slice(bytes)?) } - - pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { - let message = Message::from_cursor(cursor)?; - Ok(Self::new(message)) - } -} - -fn u32_from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { - let mut word_buf = [0u8; 4]; - cursor.read_exact(&mut word_buf)?; - Ok(u32::from_le_bytes(word_buf)) } #[cfg(test)] mod tests { - use std::io::Cursor; - use crate::{ProgramDeploymentTransaction, program_deployment_transaction::Message}; #[test] @@ -79,8 +19,7 @@ mod tests { let message = Message::new(vec![0xca, 0xfe, 0xca, 0xfe, 0x01, 0x02, 0x03]); let tx = ProgramDeploymentTransaction::new(message); let bytes = tx.to_bytes(); - let mut cursor = Cursor::new(bytes.as_ref()); - let tx_from_cursor = ProgramDeploymentTransaction::from_cursor(&mut cursor).unwrap(); - assert_eq!(tx, tx_from_cursor); + let tx_from_bytes = ProgramDeploymentTransaction::from_bytes(&bytes).unwrap(); + assert_eq!(tx, tx_from_bytes); } } diff --git a/nssa/src/privacy_preserving_transaction/message.rs b/nssa/src/privacy_preserving_transaction/message.rs index 10244a1..626e03e 100644 --- a/nssa/src/privacy_preserving_transaction/message.rs +++ b/nssa/src/privacy_preserving_transaction/message.rs @@ -91,8 +91,6 @@ impl Message { #[cfg(test)] pub mod tests { - use std::io::Cursor; - use nssa_core::{ Commitment, EncryptionScheme, Nullifier, NullifierPublicKey, SharedSecretKey, account::Account, @@ -141,17 +139,6 @@ pub mod tests { } } - #[test] - fn test_message_serialization_roundtrip() { - let message = message_for_tests(); - - let bytes = message.to_bytes(); - let mut cursor = Cursor::new(bytes.as_ref()); - let message_from_cursor = Message::from_cursor(&mut cursor).unwrap(); - - assert_eq!(message, message_from_cursor); - } - #[test] fn test_encrypted_account_data_constructor() { let npk = NullifierPublicKey::from(&[1; 32]); diff --git a/nssa/src/program_deployment_transaction/message.rs b/nssa/src/program_deployment_transaction/message.rs index 6a5c670..65e9ec2 100644 --- a/nssa/src/program_deployment_transaction/message.rs +++ b/nssa/src/program_deployment_transaction/message.rs @@ -1,4 +1,6 @@ -#[derive(Debug, Clone, PartialEq, Eq)] +use borsh::{BorshDeserialize, BorshSerialize}; + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] pub struct Message { pub(crate) bytecode: Vec, } diff --git a/nssa/src/program_deployment_transaction/transaction.rs b/nssa/src/program_deployment_transaction/transaction.rs index 4ec2e10..c5f31a1 100644 --- a/nssa/src/program_deployment_transaction/transaction.rs +++ b/nssa/src/program_deployment_transaction/transaction.rs @@ -1,8 +1,10 @@ +use borsh::{BorshDeserialize, BorshSerialize}; + use crate::{ V02State, error::NssaError, program::Program, program_deployment_transaction::message::Message, }; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] pub struct ProgramDeploymentTransaction { pub(crate) message: Message, } diff --git a/nssa/src/signature/encoding.rs b/nssa/src/signature/encoding.rs deleted file mode 100644 index 999e4a1..0000000 --- a/nssa/src/signature/encoding.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::io::{Cursor, Read}; - -use crate::{PublicKey, Signature, error::NssaError}; - -impl PublicKey { - pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { - let mut value = [0u8; 32]; - cursor.read_exact(&mut value)?; - Self::try_new(value) - } - - pub(crate) fn to_bytes(&self) -> &[u8] { - self.value() - } -} - -impl Signature { - pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { - let mut value = [0u8; 64]; - cursor.read_exact(&mut value)?; - Ok(Self { value }) - } - - pub(crate) fn to_bytes(&self) -> &[u8] { - &self.value - } -} diff --git a/nssa/src/signature/mod.rs b/nssa/src/signature/mod.rs index 97c8117..1081d9c 100644 --- a/nssa/src/signature/mod.rs +++ b/nssa/src/signature/mod.rs @@ -1,4 +1,3 @@ -mod encoding; mod private_key; mod public_key; diff --git a/nssa/src/signature/public_key.rs b/nssa/src/signature/public_key.rs index 181ea97..d7f8d2e 100644 --- a/nssa/src/signature/public_key.rs +++ b/nssa/src/signature/public_key.rs @@ -20,7 +20,7 @@ impl PublicKey { Self(value) } - pub(super) fn try_new(value: [u8; 32]) -> Result { + pub fn try_new(value: [u8; 32]) -> Result { // Check point is valid let _ = secp256k1::XOnlyPublicKey::from_byte_array(value) .map_err(|_| NssaError::InvalidPublicKey)?;