diff --git a/common/src/block.rs b/common/src/block.rs index 72d6ab7b..3760d65f 100644 --- a/common/src/block.rs +++ b/common/src/block.rs @@ -4,7 +4,6 @@ use k256::ecdsa::Signature; use rs_merkle::Hasher; use crate::{merkle_tree_public::hasher::OwnHasher, transaction::AuthenticatedTransaction}; -use nssa; pub type BlockHash = [u8; 32]; pub type BlockId = u64; @@ -101,11 +100,18 @@ impl HashableBlockData { let mut prev_block_hash = [0u8; 32]; cursor.read_exact(&mut prev_block_hash).unwrap(); + let timestamp = u64_from_cursor(&mut cursor); + + let signature_bytes_len = u32_from_cursor(&mut cursor) as usize; + let mut signature_bytes = Vec::with_capacity(signature_bytes_len); + cursor.read_exact(&mut signature_bytes).unwrap(); + let signature = Signature::from_bytes(signature_bytes.as_slice().try_into().unwrap()).unwrap(); + let num_transactions = u32_from_cursor(&mut cursor) as usize; let mut transactions = Vec::with_capacity(num_transactions); for _ in 0..num_transactions { - let tx = nssa::PublicTransaction::from_cursor(&mut cursor).unwrap(); + let tx = AuthenticatedTransaction::from_cursor(&mut cursor); transactions.push(tx); } @@ -113,6 +119,8 @@ impl HashableBlockData { block_id, prev_block_id, prev_block_hash, + timestamp, + signature, transactions, } } diff --git a/common/src/test_utils.rs b/common/src/test_utils.rs index b956cd7d..7f8d8c1a 100644 --- a/common/src/test_utils.rs +++ b/common/src/test_utils.rs @@ -1,6 +1,8 @@ -use nssa; +use k256::{ecdsa::{signature::SignerMut, SigningKey}, FieldBytes}; +use nssa::{self, NSSATransaction}; +use rand::rngs::OsRng; -use crate::block::{Block, HashableBlockData}; +use crate::{block::{Block, HashableBlockData}, transaction::{Transaction, TransactionBody}}; //Dummy producers @@ -16,10 +18,25 @@ pub fn produce_dummy_block( prev_hash: Option<[u8; 32]>, transactions: Vec, ) -> Block { + let transactions = transactions.into_iter().map( + |tx| { + let tx_body = TransactionBody::from(NSSATransaction::Public(tx)); + //ToDo: Fix signing key + let transaction = Transaction::new(tx_body, SigningKey::random(&mut OsRng)); + transaction.into_authenticated().unwrap() + }).collect(); + + //ToDo: Fix signature + let key_bytes = FieldBytes::from_slice(&[37; 32]); + let mut private_key: SigningKey = SigningKey::from_bytes(key_bytes).unwrap(); + let signature = private_key.sign(&[1; 32]); + let block_data = HashableBlockData { block_id: id, prev_block_id: id.saturating_sub(1), prev_block_hash: prev_hash.unwrap_or_default(), + timestamp: 0, + signature, transactions, }; diff --git a/common/src/transaction.rs b/common/src/transaction.rs index f4514991..297841c3 100644 --- a/common/src/transaction.rs +++ b/common/src/transaction.rs @@ -1,16 +1,15 @@ -use std::io::Cursor; +use std::io::{Cursor, Read}; use k256::ecdsa::{ signature::{Signer, Verifier}, Signature, SigningKey, VerifyingKey, }; use log::info; -use secp256k1_zkp::{PedersenCommitment, Tweak}; use serde::{Deserialize, Serialize}; use sha2::{digest::FixedOutput, Digest}; -use crate::merkle_tree_public::TreeHashType; +use crate::{block::u32_from_cursor, merkle_tree_public::TreeHashType}; use elliptic_curve::{ consts::{B0, B1}, @@ -181,16 +180,13 @@ impl TransactionBody { serde_json::to_vec(&self).unwrap() } + fn from_bytes(bytes: Vec) -> Self { + serde_json::from_slice(&bytes).unwrap() + } + pub fn log(&self) { info!("Transaction hash is {:?}", hex::encode(self.hash())); info!("Transaction tx_kind is {:?}", self.tx_kind); - info!( - "Transaction encoded_data is {:?}", - self.encoded_data - .iter() - .map(|val| (hex::encode(val.0.clone()), hex::encode(val.1.clone()))) - .collect::>() - ); } } @@ -257,26 +253,33 @@ impl Transaction { bytes.extend_from_slice(&signature_bytes_len.to_le_bytes()); bytes.extend_from_slice(&public_key_bytes_len.to_le_bytes()); - bytes.extend_from_slice(&self.body.to_bytes()); - bytes.extend_from_slice(&self.signature.to_bytes()); - bytes.extend_from_slice(&self.public_key.to_sec1_bytes()); + bytes.extend_from_slice(&body_bytes); + bytes.extend_from_slice(&signature_bytes); + bytes.extend_from_slice(&public_key_bytes); bytes } // TODO: Improve error handling. Remove unwraps. - pub fn from_bytes(data: &[u8]) -> Self { - let mut cursor = Cursor::new(data); + pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self { + let body_bytes_len = u32_from_cursor(cursor) as usize; + let signature_bytes_len = u32_from_cursor(cursor) as usize; + let public_key_bytes_len = u32_from_cursor(cursor) as usize; - let body_bytes_len = u32_from_cursor(&mut cursor) as usize; - let signature_bytes_len = u32_from_cursor(&mut cursor) as usize; - let public_key_bytes_len = u32_from_cursor(&mut cursor) as usize; + let mut body_bytes = Vec::with_capacity(body_bytes_len); + let mut signature_bytes = Vec::with_capacity(signature_bytes_len); + let mut public_key_bytes = Vec::with_capacity(public_key_bytes_len); - let body_bytes = Vec::with_capacity(body_bytes_len); - let signature_bytes = Vec::with_capacity(signature_bytes_len); - let public_key_bytes = Vec::with_capacity(public_key_bytes_len); + cursor.read_exact(&mut body_bytes).unwrap(); + let body = TransactionBody::from_bytes(body_bytes); - + cursor.read_exact(&mut signature_bytes).unwrap(); + let signature = Signature::from_bytes(signature_bytes.as_slice().try_into().unwrap()).unwrap(); + + cursor.read_exact(&mut public_key_bytes).unwrap(); + let public_key = VerifyingKey::from_sec1_bytes(&public_key_bytes).unwrap(); + + Self { body, signature, public_key } } } @@ -312,13 +315,20 @@ impl AuthenticatedTransaction { bytes.extend_from_slice(&self.transaction.to_bytes()); bytes } + + // TODO: Improve error handling. Remove unwraps. + pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self { + let mut hash: [u8; 32] = [0; 32]; + cursor.read_exact(&mut hash).unwrap(); + let transaction = Transaction::from_cursor(cursor); + Self { hash, transaction } + } } #[cfg(test)] mod tests { use super::*; use k256::{ecdsa::signature::Signer, FieldBytes}; - use secp256k1_zkp::{constants::SECRET_KEY_SIZE, Tweak}; use sha2::{digest::FixedOutput, Digest}; use crate::{ diff --git a/nssa/src/address.rs b/nssa/src/address.rs index 7e4bc1ed..93304d59 100644 --- a/nssa/src/address.rs +++ b/nssa/src/address.rs @@ -1,5 +1,7 @@ use std::{fmt::Display, str::FromStr}; +use serde::{Deserialize, Serialize}; + use crate::signature::PublicKey; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] @@ -57,6 +59,28 @@ impl Display for Address { } } +impl Serialize for Address { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let hex_string = self.to_string(); + + hex_string.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for Address { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let hex_string = String::deserialize(deserializer)?; + + Address::from_str(&hex_string).map_err(serde::de::Error::custom) + } +} + #[cfg(test)] mod tests { use crate::{Address, address::AddressError}; diff --git a/nssa/src/privacy_preserving_transaction/circuit.rs b/nssa/src/privacy_preserving_transaction/circuit.rs index ed32f98f..4cd45268 100644 --- a/nssa/src/privacy_preserving_transaction/circuit.rs +++ b/nssa/src/privacy_preserving_transaction/circuit.rs @@ -1,3 +1,5 @@ +use std::io::{Cursor, Read}; + use nssa_core::{ MembershipProof, NullifierPublicKey, NullifierSecretKey, PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput, SharedSecretKey, @@ -20,6 +22,28 @@ impl Proof { let receipt = Receipt::new(inner, circuit_output.to_bytes()); receipt.verify(PRIVACY_PRESERVING_CIRCUIT_ID).is_ok() } + + 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); + cursor.read_exact(&mut proof)?; + 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) } /// Generates a proof of the execution of a NSSA program inside the privacy preserving execution diff --git a/nssa/src/privacy_preserving_transaction/encoding.rs b/nssa/src/privacy_preserving_transaction/encoding.rs index b3b70826..fe70e654 100644 --- a/nssa/src/privacy_preserving_transaction/encoding.rs +++ b/nssa/src/privacy_preserving_transaction/encoding.rs @@ -7,7 +7,7 @@ use nssa_core::{ }; use crate::{ - Address, error::NssaError, privacy_preserving_transaction::message::EncryptedAccountData, + error::NssaError, privacy_preserving_transaction::{circuit::Proof, message::EncryptedAccountData, witness_set::WitnessSet}, Address, PrivacyPreservingTransaction, PublicKey, Signature }; use super::message::Message; @@ -168,3 +168,55 @@ impl Message { }) } } + +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, + }) + } +} + +impl PrivacyPreservingTransaction { + pub fn to_bytes(&self) -> Vec { + let mut bytes = self.message().to_bytes(); + bytes.extend_from_slice(&self.witness_set().to_bytes()); + bytes + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + let mut cursor = Cursor::new(bytes); + Self::from_cursor(&mut cursor) + } + + pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result { + let message = Message::from_cursor(cursor)?; + let witness_set = WitnessSet::from_cursor(cursor)?; + Ok(PrivacyPreservingTransaction::new(message, witness_set)) + } +} diff --git a/storage/src/lib.rs b/storage/src/lib.rs index 0dd12b7f..3e612b99 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -92,7 +92,7 @@ impl RocksDBIO { if is_start_set { Ok(dbio) } else if let Some(block) = start_block { - let block_id = block.block_id; + let block_id = block.header.block_id; dbio.put_meta_first_block_in_db(block)?; dbio.put_meta_is_first_block_set()?; @@ -186,7 +186,7 @@ impl RocksDBIO { .put_cf( &cf_meta, DB_META_FIRST_BLOCK_IN_DB_KEY.as_bytes(), - block.block_id.to_be_bytes(), + block.header.block_id.to_be_bytes(), ) .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?; @@ -233,15 +233,15 @@ impl RocksDBIO { if !first { let last_curr_block = self.get_meta_last_block_in_db()?; - if block.block_id > last_curr_block { - self.put_meta_last_block_in_db(block.block_id)?; + if block.header.block_id > last_curr_block { + self.put_meta_last_block_in_db(block.header.block_id)?; } } self.db .put_cf( &cf_block, - block.block_id.to_be_bytes(), + block.header.block_id.to_be_bytes(), HashableBlockData::from(block).to_bytes(), ) .map_err(|rerr| DbError::rocksdb_cast_message(rerr, None))?;