Skip to content

Commit

Permalink
Merge pull request #84 from okx/chore/ruanpc/stringfy_json_num
Browse files Browse the repository at this point in the history
Chore/ruanpc/stringfy json num
  • Loading branch information
RUAN0007 authored Sep 11, 2024
2 parents ea88bba + 40ed444 commit 3e5baeb
Show file tree
Hide file tree
Showing 5 changed files with 321 additions and 131 deletions.
33 changes: 21 additions & 12 deletions crates/zk-por-cli/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use indicatif::ProgressBar;
use plonky2::hash::hash_types::HashOut;
use plonky2_field::types::PrimeField64;
use rayon::{iter::ParallelIterator, prelude::*};
use serde_json::json;

use std::{
fs,
fs::File,
io::Write,
io::{BufWriter, Write},
path::PathBuf,
str::FromStr,
sync::{Arc, RwLock},
Expand Down Expand Up @@ -362,12 +362,14 @@ fn dump_proofs(
let user_proof_output_dir_path = proof_output_dir_path.join(USER_PROOF_DIRNAME); // directory has been checked empty before.

let global_proof_output_path = proof_output_dir_path.join(GLOBAL_PROOF_FILENAME);
let mut global_proof_file =
let global_proof_file =
File::create(global_proof_output_path.clone()).map_err(|e| PoRError::Io(e))?;

global_proof_file
.write_all(json!(root_proof).to_string().as_bytes())
.map_err(|e| return PoRError::Io(e))?;
let mut global_proof_writer = BufWriter::new(global_proof_file);
serde_json::to_writer(&mut global_proof_writer, &root_proof).expect(
format!("fail to dump global proof file to {:?}", global_proof_output_path).as_str(),
);
global_proof_writer.flush()?;

///////////////////////////////////////////////
let hash_offset = RecursiveTargets::<RECURSION_BRANCHOUT_NUM>::pub_input_hash_offset();
Expand Down Expand Up @@ -395,12 +397,14 @@ fn dump_proofs(
};

let global_info_output_path = proof_output_dir_path.join(GLOBAL_INFO_FILENAME);
let mut global_info_file =
let global_info_file =
File::create(global_info_output_path.clone()).map_err(|e| PoRError::Io(e))?;

global_info_file
.write_all(json!(info).to_string().as_bytes())
.map_err(|e| return PoRError::Io(e))?;
let mut global_info_writer = BufWriter::new(global_info_file);
serde_json::to_writer(&mut global_info_writer, &info).expect(
format!("fail to dump global info file to {:?}", global_proof_output_path).as_str(),
);
global_info_writer.flush()?;

///////////////////////////////////////////////
// generate and dump proof for each user
Expand Down Expand Up @@ -447,15 +451,20 @@ fn dump_proofs(
let user_proof_output_path =
user_proof_output_dir_path.join(format!("{}.json", account.id));

let mut user_proof_file = File::create(user_proof_output_path).expect(
let user_proof_file = File::create(user_proof_output_path).expect(
format!("fail to create user proof file for account {}", user_proof.account.id)
.as_str(),
);

user_proof_file.write_all(json!(user_proof).to_string().as_bytes()).expect(
let mut user_proof_writer = BufWriter::new(user_proof_file);
serde_json::to_writer(&mut user_proof_writer, &user_proof).expect(
format!("fail to write user proof file for account {}", user_proof.account.id)
.as_str(),
);
user_proof_writer.flush().expect(
format!("fail to write user proof file for account {}", user_proof.account.id)
.as_str(),
)
});

bar.inc(chunk.len() as u64);
Expand Down
4 changes: 3 additions & 1 deletion crates/zk-por-cli/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ pub fn verify_user(
.map(|user_proof_path| {
let merkle_path = File::open(&user_proof_path).unwrap();
let reader = std::io::BufReader::new(merkle_path);
let proof: MerkleProof = from_reader(reader).unwrap();
let proof: MerkleProof = from_reader(reader).expect(
format!("fail to parse user proof from path {:?}", user_proof_path).as_str(),
);
let result = proof.verify_merkle_proof(root_hash);
if verbose {
bar.inc(1);
Expand Down
93 changes: 90 additions & 3 deletions crates/zk-por-core/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,78 @@ use plonky2::{
hash::{hash_types::HashOut, poseidon::PoseidonHash},
plonk::config::Hasher,
};
use plonky2_field::types::Field;
use plonky2_field::types::{Field, PrimeField64};
use rand::Rng;
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// A struct representing a users account. It represents their equity and debt as a Vector of goldilocks field elements.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone)]
pub struct Account {
pub id: String, // 256 bit hex string
pub equity: Vec<F>,
pub debt: Vec<F>,
}

impl Serialize for Account {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct("Account", 3)?;
state.serialize_field("id", &self.id)?;
// Custom serialization for equity and debt to ensure they are serialized in a specific format if needed
let equity_as_strings: Vec<String> = self
.equity
.iter()
.map(|e| {
let num = e.to_canonical_u64();
num.to_string()
})
.collect();
state.serialize_field("equity", &equity_as_strings)?;

let debt_as_strings: Vec<String> = self
.debt
.iter()
.map(|e| {
let num = e.to_canonical_u64();
num.to_string()
})
.collect();
state.serialize_field("debt", &debt_as_strings)?;
state.end()
}
}

impl<'de> Deserialize<'de> for Account {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct InnerAccount {
id: String,
equity: Vec<String>,
debt: Vec<String>,
}

let helper = InnerAccount::deserialize(deserializer)?;
let equity = helper
.equity
.iter()
.map(|e| F::from_canonical_u64(u64::from_str_radix(e, 10).unwrap()))
.collect();
let debt = helper
.debt
.iter()
.map(|e| F::from_canonical_u64(u64::from_str_radix(e, 10).unwrap()))
.collect();

Ok(Account { id: helper.id, equity: equity, debt: debt })
}
}

impl Account {
/// Gets the account hash for a given account.
pub fn get_hash(&self) -> HashOut<F> {
Expand Down Expand Up @@ -117,3 +177,30 @@ pub fn gen_empty_accounts(batch_size: usize, num_assets: usize) -> Vec<Account>
];
accounts
}

#[cfg(test)]
mod tests {
use super::*;
use serde_json;

#[test]
fn test_account_json_marshalling() {
// Step 1: Create an instance of `Account`
let original_account = Account {
id: "1".to_owned(), // Assuming `id` is of type that implements `Serialize` and `Deserialize`
equity: vec![F::from_canonical_u64(0), F::from_canonical_u64(1)],
debt: vec![F::from_canonical_u64(0), F::from_canonical_u64(2)],
};

// Step 2: Serialize the `Account` instance to a JSON string
let json_string = serde_json::to_string(&original_account).unwrap();

// Step 3: Deserialize the JSON string back into an `Account` instance
let deserialized_account: Account = serde_json::from_str(&json_string).unwrap();

// Step 4: Assert that the original and deserialized instances are equal
assert_eq!(original_account.id, deserialized_account.id);
assert_eq!(original_account.equity, deserialized_account.equity);
assert_eq!(original_account.debt, deserialized_account.debt);
}
}
Loading

0 comments on commit 3e5baeb

Please sign in to comment.