mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-08 16:23:12 +00:00
add encodings
This commit is contained in:
parent
1e1ab787bc
commit
a185e52203
@ -6,7 +6,7 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
risc0-zkvm = "2.3.1"
|
risc0-zkvm = "2.3.1"
|
||||||
nssa-core = { path = "core" }
|
nssa-core = { path = "core", features=["host"]}
|
||||||
program-methods = { path = "program_methods" }
|
program-methods = { path = "program_methods" }
|
||||||
serde = "1.0.219"
|
serde = "1.0.219"
|
||||||
sha2 = "0.10.9"
|
sha2 = "0.10.9"
|
||||||
|
|||||||
@ -6,3 +6,8 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
risc0-zkvm = "2.3.1"
|
risc0-zkvm = "2.3.1"
|
||||||
serde = { version = "1.0", default-features = false }
|
serde = { version = "1.0", default-features = false }
|
||||||
|
thiserror = { version = "2.0.12", optional = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
host = ["thiserror"]
|
||||||
|
|||||||
@ -13,7 +13,21 @@ impl Commitment {
|
|||||||
pub fn new(Npk: &NullifierPublicKey, account: &Account) -> Self {
|
pub fn new(Npk: &NullifierPublicKey, account: &Account) -> Self {
|
||||||
let mut bytes = Vec::new();
|
let mut bytes = Vec::new();
|
||||||
bytes.extend_from_slice(&Npk.to_byte_array());
|
bytes.extend_from_slice(&Npk.to_byte_array());
|
||||||
bytes.extend_from_slice(&account.to_bytes());
|
let account_bytes_with_hashed_data = {
|
||||||
|
let mut this = Vec::new();
|
||||||
|
for word in &account.program_owner {
|
||||||
|
this.extend_from_slice(&word.to_le_bytes());
|
||||||
|
}
|
||||||
|
this.extend_from_slice(&account.balance.to_le_bytes());
|
||||||
|
this.extend_from_slice(&account.nonce.to_le_bytes());
|
||||||
|
let hashed_data: [u8; 32] = Impl::hash_bytes(&account.data)
|
||||||
|
.as_bytes()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
this.extend_from_slice(&hashed_data);
|
||||||
|
this
|
||||||
|
};
|
||||||
|
bytes.extend_from_slice(&account_bytes_with_hashed_data);
|
||||||
Self(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap())
|
Self(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,14 @@
|
|||||||
use risc0_zkvm::{
|
use risc0_zkvm::sha::{Impl, Sha256};
|
||||||
serde::to_vec,
|
|
||||||
sha::{Impl, Sha256},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::account::{Account, Commitment, NullifierPublicKey};
|
#[cfg(feature = "host")]
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
use crate::account::{Account, Commitment, Nullifier, NullifierPublicKey};
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
use crate::error::NssaCoreError;
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
@ -13,28 +18,82 @@ impl Account {
|
|||||||
}
|
}
|
||||||
bytes.extend_from_slice(&self.balance.to_le_bytes());
|
bytes.extend_from_slice(&self.balance.to_le_bytes());
|
||||||
bytes.extend_from_slice(&self.nonce.to_le_bytes());
|
bytes.extend_from_slice(&self.nonce.to_le_bytes());
|
||||||
let hashed_data: [u8; 32] = Impl::hash_bytes(&self.data).as_bytes().try_into().unwrap();
|
let data_length: u32 = self.data.len() as u32;
|
||||||
bytes.extend_from_slice(&hashed_data);
|
bytes.extend_from_slice(&data_length.to_le_bytes());
|
||||||
|
bytes.extend_from_slice(self.data.as_slice());
|
||||||
bytes
|
bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaCoreError> {
|
||||||
|
let mut u32_bytes = [0u8; 4];
|
||||||
|
let mut u128_bytes = [0u8; 16];
|
||||||
|
|
||||||
|
// program owner
|
||||||
|
let mut program_owner = [0u32; 8];
|
||||||
|
for word in &mut program_owner {
|
||||||
|
cursor.read_exact(&mut u32_bytes)?;
|
||||||
|
*word = u32::from_le_bytes(u32_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// balance
|
||||||
|
cursor.read_exact(&mut u128_bytes)?;
|
||||||
|
let balance = u128::from_le_bytes(u128_bytes);
|
||||||
|
|
||||||
|
// nonce
|
||||||
|
cursor.read_exact(&mut u128_bytes)?;
|
||||||
|
let nonce = u128::from_le_bytes(u128_bytes);
|
||||||
|
|
||||||
|
//data
|
||||||
|
cursor.read_exact(&mut u32_bytes)?;
|
||||||
|
let data_length = u32::from_le_bytes(u32_bytes);
|
||||||
|
let mut data = vec![0; data_length as usize];
|
||||||
|
cursor.read_exact(&mut data)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
program_owner,
|
||||||
|
balance,
|
||||||
|
data,
|
||||||
|
nonce,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Commitment {
|
impl Commitment {
|
||||||
pub(crate) fn to_byte_array(&self) -> [u8; 32] {
|
pub fn to_byte_array(&self) -> [u8; 32] {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaCoreError> {
|
||||||
|
let mut bytes = [0u8; 32];
|
||||||
|
cursor.read_exact(&mut bytes)?;
|
||||||
|
Ok(Self(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NullifierPublicKey {
|
||||||
|
pub fn to_byte_array(&self) -> [u8; 32] {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
impl NullifierPublicKey {
|
impl Nullifier {
|
||||||
pub(crate) fn to_byte_array(&self) -> [u8; 32] {
|
pub fn to_byte_array(&self) -> [u8; 32] {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaCoreError> {
|
||||||
|
let mut bytes = [0u8; 32];
|
||||||
|
cursor.read_exact(&mut bytes)?;
|
||||||
|
Ok(Self(bytes))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::account::Account;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_enconding() {
|
fn test_enconding() {
|
||||||
@ -49,12 +108,64 @@ mod tests {
|
|||||||
let expected_bytes = [
|
let expected_bytes = [
|
||||||
1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8,
|
1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8,
|
||||||
0, 0, 0, 192, 186, 220, 114, 113, 65, 236, 234, 222, 15, 215, 191, 227, 198, 23, 0, 42,
|
0, 0, 0, 192, 186, 220, 114, 113, 65, 236, 234, 222, 15, 215, 191, 227, 198, 23, 0, 42,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 137, 65, 102, 211, 51, 100, 53, 200,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 104, 111, 108, 97, 32, 109,
|
||||||
0, 190, 163, 111, 242, 27, 41, 234, 168, 1, 165, 47, 88, 76, 0, 108, 73, 40, 154, 13,
|
117, 110, 100, 111,
|
||||||
207, 110, 47,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let bytes = account.to_bytes();
|
let bytes = account.to_bytes();
|
||||||
assert_eq!(bytes, expected_bytes);
|
assert_eq!(bytes, expected_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_commitment_to_bytes() {
|
||||||
|
let commitment = Commitment((0..32).collect::<Vec<u8>>().try_into().unwrap());
|
||||||
|
let expected_bytes: [u8; 32] = (0..32).collect::<Vec<u8>>().try_into().unwrap();
|
||||||
|
|
||||||
|
let bytes = commitment.to_byte_array();
|
||||||
|
assert_eq!(expected_bytes, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nullifier_to_bytes() {
|
||||||
|
let nullifier = Nullifier((0..32).collect::<Vec<u8>>().try_into().unwrap());
|
||||||
|
let expected_bytes: [u8; 32] = (0..32).collect::<Vec<u8>>().try_into().unwrap();
|
||||||
|
|
||||||
|
let bytes = nullifier.to_byte_array();
|
||||||
|
assert_eq!(expected_bytes, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
#[test]
|
||||||
|
fn test_commitment_to_bytes_roundtrip() {
|
||||||
|
let commitment = Commitment((0..32).collect::<Vec<u8>>().try_into().unwrap());
|
||||||
|
let bytes = commitment.to_byte_array();
|
||||||
|
let mut cursor = Cursor::new(bytes.as_ref());
|
||||||
|
let commitment_from_cursor = Commitment::from_cursor(&mut cursor).unwrap();
|
||||||
|
assert_eq!(commitment, commitment_from_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
#[test]
|
||||||
|
fn test_nullifier_to_bytes_roundtrip() {
|
||||||
|
let nullifier = Nullifier((0..32).collect::<Vec<u8>>().try_into().unwrap());
|
||||||
|
let bytes = nullifier.to_byte_array();
|
||||||
|
let mut cursor = Cursor::new(bytes.as_ref());
|
||||||
|
let nullifier_from_cursor = Nullifier::from_cursor(&mut cursor).unwrap();
|
||||||
|
assert_eq!(nullifier, nullifier_from_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
#[test]
|
||||||
|
fn test_account_to_bytes_roundtrip() {
|
||||||
|
let account = Account {
|
||||||
|
program_owner: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||||
|
balance: 123456789012345678901234567890123456,
|
||||||
|
nonce: 42,
|
||||||
|
data: b"hola mundo".to_vec(),
|
||||||
|
};
|
||||||
|
let bytes = account.to_bytes();
|
||||||
|
let mut cursor = Cursor::new(bytes.as_ref());
|
||||||
|
let account_from_cursor = Account::from_cursor(&mut cursor).unwrap();
|
||||||
|
assert_eq!(account, account_from_cursor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ impl From<&NullifierSecretKey> for NullifierPublicKey {
|
|||||||
pub type NullifierSecretKey = [u8; 32];
|
pub type NullifierSecretKey = [u8; 32];
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Nullifier([u8; 32]);
|
pub struct Nullifier(pub(super) [u8; 32]);
|
||||||
|
|
||||||
impl Nullifier {
|
impl Nullifier {
|
||||||
pub fn new(commitment: &Commitment, nsk: &NullifierSecretKey) -> Self {
|
pub fn new(commitment: &Commitment, nsk: &NullifierSecretKey) -> Self {
|
||||||
@ -53,12 +53,12 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_from_secret_key() {
|
fn test_from_secret_key() {
|
||||||
let nsk = [
|
let nsk = [
|
||||||
50, 139, 109, 225, 82, 86, 80, 108, 140, 248, 232, 229, 96, 80, 148, 250, 15, 9, 155,
|
57, 5, 64, 115, 153, 56, 184, 51, 207, 238, 99, 165, 147, 214, 213, 151, 30, 251, 30,
|
||||||
44, 196, 224, 115, 180, 160, 44, 113, 133, 15, 196, 253, 42,
|
196, 134, 22, 224, 211, 237, 120, 136, 225, 188, 220, 249, 28,
|
||||||
];
|
];
|
||||||
let expected_Npk = NullifierPublicKey([
|
let expected_Npk = NullifierPublicKey([
|
||||||
38, 90, 215, 216, 195, 66, 157, 77, 161, 59, 121, 18, 118, 37, 57, 199, 189, 251, 95,
|
202, 120, 42, 189, 194, 218, 78, 244, 31, 6, 108, 169, 29, 61, 22, 221, 69, 138, 197,
|
||||||
130, 12, 9, 171, 169, 140, 221, 87, 242, 46, 243, 111, 85,
|
161, 241, 39, 142, 242, 242, 50, 188, 201, 99, 28, 176, 238,
|
||||||
]);
|
]);
|
||||||
let Npk = NullifierPublicKey::from(&nsk);
|
let Npk = NullifierPublicKey::from(&nsk);
|
||||||
assert_eq!(Npk, expected_Npk);
|
assert_eq!(Npk, expected_Npk);
|
||||||
|
|||||||
12
nssa/core/src/error.rs
Normal file
12
nssa/core/src/error.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use std::io;
|
||||||
|
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum NssaCoreError {
|
||||||
|
#[error("Invalid transaction: {0}")]
|
||||||
|
DeserializationError(String),
|
||||||
|
|
||||||
|
#[error("IO error: {0}")]
|
||||||
|
Io(#[from] io::Error),
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
use crate::error::NssaCoreError;
|
||||||
use crate::{
|
use crate::{
|
||||||
account::{
|
account::{
|
||||||
Account, AccountWithMetadata, Commitment, Nonce, Nullifier, NullifierPublicKey,
|
Account, AccountWithMetadata, Commitment, Nonce, Nullifier, NullifierPublicKey,
|
||||||
@ -8,9 +10,15 @@ use crate::{
|
|||||||
program::{ProgramId, ProgramOutput},
|
program::{ProgramId, ProgramOutput},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
pub mod account;
|
pub mod account;
|
||||||
pub mod program;
|
pub mod program;
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
pub mod error;
|
||||||
|
|
||||||
pub type CommitmentSetDigest = [u32; 8];
|
pub type CommitmentSetDigest = [u32; 8];
|
||||||
pub type MembershipProof = Vec<[u8; 32]>;
|
pub type MembershipProof = Vec<[u8; 32]>;
|
||||||
pub fn verify_membership_proof(
|
pub fn verify_membership_proof(
|
||||||
@ -51,6 +59,18 @@ impl EncryptedAccountData {
|
|||||||
// TODO: implement
|
// TODO: implement
|
||||||
Self
|
Self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "host")]
|
||||||
|
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaCoreError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EncryptedAccountData {
|
||||||
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
// TODO: implement
|
||||||
|
vec![0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
|||||||
@ -31,4 +31,9 @@ pub enum NssaError {
|
|||||||
#[error("Risc0 error: {0}")]
|
#[error("Risc0 error: {0}")]
|
||||||
ProgramProveFailed(String),
|
ProgramProveFailed(String),
|
||||||
|
|
||||||
|
#[error("Invalid transaction: {0}")]
|
||||||
|
TransactionDeserializationError(String),
|
||||||
|
|
||||||
|
#[error("Core error")]
|
||||||
|
Core(#[from] nssa_core::error::NssaCoreError),
|
||||||
}
|
}
|
||||||
|
|||||||
140
nssa/src/privacy_preserving_transaction/encoding.rs
Normal file
140
nssa/src/privacy_preserving_transaction/encoding.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use std::io::{Cursor, Read};
|
||||||
|
|
||||||
|
use nssa_core::{
|
||||||
|
EncryptedAccountData,
|
||||||
|
account::{Account, Commitment, Nullifier},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{Address, error::NssaError};
|
||||||
|
|
||||||
|
use super::message::Message;
|
||||||
|
|
||||||
|
const MESSAGE_ENCODING_PREFIX_LEN: usize = 37;
|
||||||
|
const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] =
|
||||||
|
b"NSSA/v0.1/TxMessage/PrivacyPreserving";
|
||||||
|
|
||||||
|
impl Message {
|
||||||
|
pub(crate) fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
for nullifier in &self.new_nullifiers {
|
||||||
|
bytes.extend_from_slice(&nullifier.to_byte_array());
|
||||||
|
}
|
||||||
|
bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
|
||||||
|
let prefix = {
|
||||||
|
let mut this = [0u8; MESSAGE_ENCODING_PREFIX_LEN];
|
||||||
|
cursor.read_exact(&mut this)?;
|
||||||
|
this
|
||||||
|
};
|
||||||
|
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 as usize);
|
||||||
|
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 {
|
||||||
|
new_nullifiers.push(Nullifier::from_cursor(cursor)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
public_addresses,
|
||||||
|
nonces,
|
||||||
|
public_post_states,
|
||||||
|
encrypted_private_post_states,
|
||||||
|
new_commitments,
|
||||||
|
new_nullifiers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -36,7 +36,7 @@ impl Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
pub mod tests {
|
||||||
use nssa_core::account::{
|
use nssa_core::account::{
|
||||||
Account, Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey,
|
Account, Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
mod transaction;
|
mod transaction;
|
||||||
mod message;
|
mod message;
|
||||||
mod witness_set;
|
mod witness_set;
|
||||||
|
mod encoding;
|
||||||
|
|
||||||
pub use transaction::PrivacyPreservingTransaction;
|
pub use transaction::PrivacyPreservingTransaction;
|
||||||
|
|||||||
@ -146,3 +146,8 @@ fn n_unique<T: Eq + Hash>(data: &[T]) -> usize {
|
|||||||
let set: HashSet<&T> = data.iter().collect();
|
let set: HashSet<&T> = data.iter().collect();
|
||||||
set.len()
|
set.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ pub struct WitnessSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WitnessSet {
|
impl WitnessSet {
|
||||||
pub fn for_message(message: &Message, private_keys: &[&PrivateKey]) -> Self {
|
pub fn for_message(message: &Message, proof: Proof, private_keys: &[&PrivateKey]) -> Self {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,9 @@ use crate::{
|
|||||||
public_transaction::{Message, WitnessSet},
|
public_transaction::{Message, WitnessSet},
|
||||||
};
|
};
|
||||||
|
|
||||||
const MESSAGE_ENCODING_PREFIX_LEN: usize = 19;
|
const MESSAGE_ENCODING_PREFIX_LEN: usize = 37;
|
||||||
const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] = b"NSSA/v0.1/TxMessage";
|
const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] =
|
||||||
|
b"NSSA/v0.1/TxMessage/Public\0\0\0\0\0\0\0\0\0\0\0";
|
||||||
|
|
||||||
impl Message {
|
impl Message {
|
||||||
/// Serializes a `Message` into bytes in the following layout:
|
/// Serializes a `Message` into bytes in the following layout:
|
||||||
@ -52,7 +53,12 @@ impl Message {
|
|||||||
cursor.read_exact(&mut this)?;
|
cursor.read_exact(&mut this)?;
|
||||||
this
|
this
|
||||||
};
|
};
|
||||||
assert_eq!(&prefix, MESSAGE_ENCODING_PREFIX);
|
if &prefix != MESSAGE_ENCODING_PREFIX {
|
||||||
|
return Err(NssaError::TransactionDeserializationError(
|
||||||
|
"Invalid public message prefix".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let program_id: ProgramId = {
|
let program_id: ProgramId = {
|
||||||
let mut this = [0u32; 8];
|
let mut this = [0u32; 8];
|
||||||
for item in &mut this {
|
for item in &mut this {
|
||||||
|
|||||||
@ -21,6 +21,10 @@ impl CommitmentSet {
|
|||||||
// TODO: implement
|
// TODO: implement
|
||||||
[0; 8]
|
[0; 8]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn contains(&self, commitment: &Commitment) -> bool {
|
||||||
|
self.0.contains(commitment)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type NullifierSet = HashSet<Nullifier>;
|
type NullifierSet = HashSet<Nullifier>;
|
||||||
@ -139,14 +143,28 @@ impl V01State {
|
|||||||
&self,
|
&self,
|
||||||
new_commitments: &[Commitment],
|
new_commitments: &[Commitment],
|
||||||
) -> Result<(), NssaError> {
|
) -> Result<(), NssaError> {
|
||||||
todo!()
|
for commitment in new_commitments.iter() {
|
||||||
|
if self.private_state.0.contains(commitment) {
|
||||||
|
return Err(NssaError::InvalidInput(
|
||||||
|
"Commitment already seen".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_nullifiers_are_new(
|
pub(crate) fn check_nullifiers_are_new(
|
||||||
&self,
|
&self,
|
||||||
new_nullifiers: &[Nullifier],
|
new_nullifiers: &[Nullifier],
|
||||||
) -> Result<(), NssaError> {
|
) -> Result<(), NssaError> {
|
||||||
todo!()
|
for nullifier in new_nullifiers.iter() {
|
||||||
|
if self.private_state.1.contains(nullifier) {
|
||||||
|
return Err(NssaError::InvalidInput(
|
||||||
|
"Nullifier already seen".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user