From 7bf61a0e94d7986c6a6eb4664247bed63a1a30bf Mon Sep 17 00:00:00 2001 From: sinka Date: Tue, 14 May 2024 21:42:08 +1000 Subject: [PATCH] moving context specific out for native env requirements --- .../host/src/context/ecc_helper/jubjub/mod.rs | 44 ++++++ .../src/context/ecc_helper/jubjub/sum/mod.rs | 102 ++++++++++++++ crates/host/src/context/ecc_helper/mod.rs | 17 +++ crates/host/src/context/hash_helper/mod.rs | 1 + .../host/src/context/hash_helper/poseidon.rs | 103 ++++++++++++++ .../src/context/merkle_helper/datacache.rs | 98 ++++++++++++++ .../host/src/context/merkle_helper/merkle.rs | 128 ++++++++++++++++++ crates/host/src/context/merkle_helper/mod.rs | 2 + crates/host/src/context/mod.rs | 3 + crates/host/src/host/ecc_helper/jubjub/mod.rs | 43 ------ .../src/host/ecc_helper/jubjub/sum/mod.rs | 107 +-------------- crates/host/src/host/hash_helper/poseidon.rs | 89 +----------- .../host/src/host/merkle_helper/datacache.rs | 96 +------------ crates/host/src/host/merkle_helper/merkle.rs | 128 +----------------- crates/host/src/lib.rs | 1 + 15 files changed, 508 insertions(+), 454 deletions(-) create mode 100644 crates/host/src/context/ecc_helper/jubjub/mod.rs create mode 100644 crates/host/src/context/ecc_helper/jubjub/sum/mod.rs create mode 100644 crates/host/src/context/ecc_helper/mod.rs create mode 100644 crates/host/src/context/hash_helper/mod.rs create mode 100644 crates/host/src/context/hash_helper/poseidon.rs create mode 100644 crates/host/src/context/merkle_helper/datacache.rs create mode 100644 crates/host/src/context/merkle_helper/merkle.rs create mode 100644 crates/host/src/context/merkle_helper/mod.rs create mode 100644 crates/host/src/context/mod.rs diff --git a/crates/host/src/context/ecc_helper/jubjub/mod.rs b/crates/host/src/context/ecc_helper/jubjub/mod.rs new file mode 100644 index 000000000..a9993ed46 --- /dev/null +++ b/crates/host/src/context/ecc_helper/jubjub/mod.rs @@ -0,0 +1,44 @@ +pub mod sum; +use ark_std::Zero; +use halo2_proofs::pairing::bn256::Fr as BabyJubjubFq; +use num_bigint::BigUint; +use num_traits::FromPrimitive; +use std::ops::AddAssign; +use std::ops::Shl; +use zkwasm_host_circuits::host::jubjub; + +const LIMBSZ: usize = 64; +const LIMBNB: usize = 4; + +use super::bn_to_field; +use super::field_to_bn; + +pub fn fetch_fq(limbs: &Vec, index: usize) -> BabyJubjubFq { + let mut bn = BigUint::zero(); + for i in 0..LIMBNB { + bn.add_assign(BigUint::from_u64(limbs[index * LIMBNB + i]).unwrap() << (i * LIMBSZ)) + } + bn_to_field(&bn) +} + +fn fetch_g1(limbs: &Vec) -> jubjub::Point { + jubjub::Point { + x: fetch_fq(limbs, 0), + y: fetch_fq(limbs, 1), + } +} + +pub fn babyjubjub_fq_to_limbs(result_limbs: &mut Vec, f: BabyJubjubFq) { + let mut bn = field_to_bn(&f); + for _ in 0..LIMBNB { + let d: BigUint = BigUint::from(1 as u64).shl(LIMBSZ); + let r = bn.clone() % d.clone(); + let value = if r == BigUint::from(0 as u32) { + 0 as u64 + } else { + r.to_u64_digits()[0] + }; + bn = bn / d; + result_limbs.append(&mut vec![value]); + } +} diff --git a/crates/host/src/context/ecc_helper/jubjub/sum/mod.rs b/crates/host/src/context/ecc_helper/jubjub/sum/mod.rs new file mode 100644 index 000000000..4d7b2ae97 --- /dev/null +++ b/crates/host/src/context/ecc_helper/jubjub/sum/mod.rs @@ -0,0 +1,102 @@ +use super::babyjubjub_fq_to_limbs; +use super::fetch_g1; +use super::LIMBNB; +use num_bigint::BigUint; +use zkwasm_host_circuits::host::jubjub; + +fn fetch_biguint(_limbs: &Vec) -> BigUint { + BigUint::from_bytes_le( + _limbs + .iter() + .map(|x| x.to_le_bytes()) + .flatten() + .collect::>() + .as_slice(), + ) +} + +pub struct BabyJubjubSumContext { + pub k: u32, + pub acc: jubjub::Point, + pub limbs: Vec, + pub coeffs: Vec, + pub result_limbs: Option>, + pub result_cursor: usize, + pub input_cursor: usize, + pub used_round: usize, +} + +impl BabyJubjubSumContext { + pub fn default(k: u32) -> Self { + BabyJubjubSumContext { + k, + acc: jubjub::Point::identity(), + limbs: vec![], + coeffs: vec![], + result_limbs: None, + result_cursor: 0, + input_cursor: 0, + used_round: 0, + } + } + + pub fn babyjubjub_sum_new(&mut self, new: usize) { + self.result_limbs = None; + self.result_cursor = 0; + self.limbs = vec![]; + self.input_cursor = 0; + self.coeffs = vec![]; + self.used_round += 1; + if new != 0 { + self.acc = jubjub::Point::identity(); + } + } + + pub fn babyjubjub_sum_push(&mut self, v: u64) { + if self.input_cursor < LIMBNB * 2 { + self.limbs.push(v); + self.input_cursor += 1; + } else if self.input_cursor < LIMBNB * 2 + 4 { + self.coeffs.push(v); + self.input_cursor += 1; + if self.input_cursor == LIMBNB * 2 + 4 { + self.input_cursor = 0; + } + } + } + + pub fn babyjubjub_sum_finalize(&mut self) -> u64 { + let limbs = self.result_limbs.clone(); + match limbs { + None => { + assert!(self.limbs.len() == LIMBNB * 2); + let coeff = fetch_biguint(&self.coeffs.to_vec()); + let g1 = fetch_g1(&self.limbs.to_vec()); + log::debug!("acc is {:?}", self.acc); + log::debug!("g1 is {:?}", g1); + log::debug!("coeff is {:?} {}", coeff, self.coeffs.len()); + self.acc = self + .acc + .projective() + .add(&g1.mul_scalar(&coeff).projective()) + .affine(); + log::debug!("msm result: {:?}", self.acc); + self.babyjubjub_result_to_limbs(self.acc.clone()); + } + _ => (), + }; + let ret = self.result_limbs.as_ref().unwrap()[self.result_cursor]; + self.result_cursor += 1; + + ret + } +} + +impl BabyJubjubSumContext { + fn babyjubjub_result_to_limbs(&mut self, g: jubjub::Point) { + let mut limbs = vec![]; + babyjubjub_fq_to_limbs(&mut limbs, g.x); + babyjubjub_fq_to_limbs(&mut limbs, g.y); + self.result_limbs = Some(limbs); + } +} diff --git a/crates/host/src/context/ecc_helper/mod.rs b/crates/host/src/context/ecc_helper/mod.rs new file mode 100644 index 000000000..8eab7e320 --- /dev/null +++ b/crates/host/src/context/ecc_helper/mod.rs @@ -0,0 +1,17 @@ +pub mod jubjub; + +use halo2_proofs::arithmetic::BaseExt; +use num_bigint::BigUint; + +pub fn bn_to_field(bn: &BigUint) -> F { + let mut bytes = bn.to_bytes_le(); + bytes.resize(48, 0); + let mut bytes = &bytes[..]; + F::read(&mut bytes).unwrap() +} + +pub fn field_to_bn(f: &F) -> BigUint { + let mut bytes: Vec = Vec::new(); + f.write(&mut bytes).unwrap(); + BigUint::from_bytes_le(&bytes[..]) +} diff --git a/crates/host/src/context/hash_helper/mod.rs b/crates/host/src/context/hash_helper/mod.rs new file mode 100644 index 000000000..4395ce1cd --- /dev/null +++ b/crates/host/src/context/hash_helper/mod.rs @@ -0,0 +1 @@ +pub mod poseidon; diff --git a/crates/host/src/context/hash_helper/poseidon.rs b/crates/host/src/context/hash_helper/poseidon.rs new file mode 100644 index 000000000..56fa2a35e --- /dev/null +++ b/crates/host/src/context/hash_helper/poseidon.rs @@ -0,0 +1,103 @@ +use ff::PrimeField; +use halo2_proofs::pairing::bn256::Fr; +use poseidon::Poseidon; +pub use zkwasm_host_circuits::host::poseidon::POSEIDON_HASHER; +use zkwasm_host_circuits::host::Reduce; +use zkwasm_host_circuits::host::ReduceRule; + +/// Foreign functions that supports the following C code library +/// +/// void poseidon(uint64_t* data, uint32_t size, uint64_t* r) +/// { +/// int i; +/// poseidon_new(size); +/// for(i=0; i, +} + +impl Generator { + pub fn gen(&mut self) -> u64 { + let r = self.values[self.cursor]; + self.cursor += 1; + if self.cursor == 4 { + self.cursor = 0; + } + r + } +} + +pub fn new_reduce(rules: Vec>) -> Reduce { + Reduce { cursor: 0, rules } +} + +pub struct PoseidonContext { + pub k: u32, + pub hasher: Option>, + pub generator: Generator, + pub buf: Vec, + pub fieldreducer: Reduce, + pub used_round: usize, +} + +impl PoseidonContext { + pub fn default(k: u32) -> Self { + PoseidonContext { + k, + hasher: None, + fieldreducer: new_reduce(vec![ReduceRule::Field(Fr::zero(), 64)]), + buf: vec![], + generator: Generator { + cursor: 0, + values: vec![], + }, + used_round: 0, + } + } + + pub fn poseidon_new(&mut self, new: usize) { + self.buf = vec![]; + if new != 0 { + self.hasher = Some(POSEIDON_HASHER.clone()); + self.used_round += 1; + } + } + + pub fn poseidon_push(&mut self, v: u64) { + self.fieldreducer.reduce(v); + if self.fieldreducer.cursor == 0 { + self.buf + .push(self.fieldreducer.rules[0].field_value().unwrap()) + } + } + + pub fn poseidon_finalize(&mut self) -> u64 { + assert!(self.buf.len() == 8); + if self.generator.cursor == 0 { + self.hasher.as_mut().map(|s| { + log::debug!("perform hash with {:?}", self.buf); + let r = s.update_exact(&self.buf.clone().try_into().unwrap()); + let dwords: Vec = r.to_repr().to_vec(); + self.generator.values = dwords + .chunks(8) + .map(|x| u64::from_le_bytes(x.to_vec().try_into().unwrap())) + .collect::>(); + }); + } + self.generator.gen() + } +} diff --git a/crates/host/src/context/merkle_helper/datacache.rs b/crates/host/src/context/merkle_helper/datacache.rs new file mode 100644 index 000000000..89c47fc37 --- /dev/null +++ b/crates/host/src/context/merkle_helper/datacache.rs @@ -0,0 +1,98 @@ +use halo2_proofs::pairing::bn256::Fr; +use std::cell::RefCell; +use std::rc::Rc; +use zkwasm_host_circuits::host::datahash as datahelper; +use zkwasm_host_circuits::host::datahash::DataHashRecord; +use zkwasm_host_circuits::host::db::TreeDB; +use zkwasm_host_circuits::host::Reduce; +use zkwasm_host_circuits::host::ReduceRule; + +const FETCH_MODE: u64 = 0; +const STORE_MODE: u64 = 1; + +pub struct CacheContext { + pub mode: u64, + pub hash: Reduce, + pub data: Vec, + pub fetch: bool, + pub mongo_datahash: datahelper::MongoDataHash, + pub tree_db: Option>>, +} + +fn new_reduce(rules: Vec>) -> Reduce { + Reduce { cursor: 0, rules } +} + +impl CacheContext { + pub fn new(tree_db: Option>>) -> Self { + CacheContext { + mode: 0, + hash: new_reduce(vec![ReduceRule::Bytes(vec![], 4)]), + fetch: false, + data: vec![], + mongo_datahash: datahelper::MongoDataHash::construct([0; 32], tree_db.clone()), + tree_db, + } + } + + pub fn set_mode(&mut self, v: u64) { + self.mode = v; + self.data = vec![]; + } + + pub fn set_data_hash(&mut self, v: u64) { + self.hash.reduce(v); + if self.hash.cursor == 0 { + let hash: [u8; 32] = self.hash.rules[0] + .bytes_value() + .unwrap() + .try_into() + .unwrap(); + if self.mode == FETCH_MODE { + let datahashrecord = self.mongo_datahash.get_record(&hash).unwrap(); + self.data = datahashrecord.map_or(vec![], |r| { + r.data + .chunks_exact(8) + .into_iter() + .into_iter() + .map(|x| u64::from_le_bytes(x.try_into().unwrap())) + .collect::>() + }); + self.fetch = false; + } else if self.mode == STORE_MODE { + // put data and hash into mongo_datahash + if !self.data.is_empty() { + self.mongo_datahash + .update_record({ + DataHashRecord { + hash, + data: self + .data + .iter() + .map(|x| x.to_le_bytes()) + .flatten() + .collect::>(), + } + }) + .unwrap(); + } + } + } + } + + pub fn fetch_data(&mut self) -> u64 { + if self.fetch == false { + self.fetch = true; + self.data.reverse(); + self.data.len() as u64 + } else { + self.data.pop().unwrap() + } + } + + pub fn store_data(&mut self, v: u64) { + self.data.push(v); + } +} + +impl CacheContext {} diff --git a/crates/host/src/context/merkle_helper/merkle.rs b/crates/host/src/context/merkle_helper/merkle.rs new file mode 100644 index 000000000..cc614dbfd --- /dev/null +++ b/crates/host/src/context/merkle_helper/merkle.rs @@ -0,0 +1,128 @@ +use halo2_proofs::pairing::bn256::Fr; +use std::cell::RefCell; +use std::rc::Rc; +use zkwasm_host_circuits::host::datahash as datahelper; +use zkwasm_host_circuits::host::db::TreeDB; +use zkwasm_host_circuits::host::merkle::MerkleTree; +use zkwasm_host_circuits::host::mongomerkle as merklehelper; +use zkwasm_host_circuits::host::Reduce; +use zkwasm_host_circuits::host::ReduceRule; + +pub const MERKLE_TREE_HEIGHT: usize = 32; + +pub struct MerkleContext { + pub k: u32, + pub set_root: Reduce, + pub get_root: Reduce, + pub address: Reduce, + pub set: Reduce, + pub data: [u64; 4], + pub data_cursor: usize, + pub fetch: bool, + pub mongo_merkle: Option>, + pub mongo_datahash: datahelper::MongoDataHash, + pub tree_db: Option>>, + pub used_round: usize, +} + +fn new_reduce(rules: Vec>) -> Reduce { + Reduce { cursor: 0, rules } +} + +impl MerkleContext { + pub fn new(k: u32, tree_db: Option>>) -> Self { + MerkleContext { + k, + set_root: new_reduce(vec![ReduceRule::Bytes(vec![], 4)]), + get_root: new_reduce(vec![ReduceRule::Bytes(vec![], 4)]), + address: new_reduce(vec![ReduceRule::U64(0)]), + set: new_reduce(vec![ReduceRule::Bytes(vec![], 4)]), + fetch: false, + data: [0; 4], + data_cursor: 0, + mongo_merkle: None, + mongo_datahash: datahelper::MongoDataHash::construct([0; 32], tree_db.clone()), + tree_db, + used_round: 0, + } + } + + pub fn merkle_setroot(&mut self, v: u64) { + self.set_root.reduce(v); + if self.set_root.cursor == 0 { + log::debug!("set root: {:?}", &self.set_root.rules[0].bytes_value()); + self.mongo_merkle = Some(merklehelper::MongoMerkle::construct( + [0; 32], + self.set_root.rules[0] + .bytes_value() + .unwrap() + .try_into() + .unwrap(), + self.tree_db.clone(), + )); + } + } + + pub fn merkle_getroot(&mut self) -> u64 { + let mt = self + .mongo_merkle + .as_ref() + .expect("merkle db not initialized"); + let hash = mt.get_root_hash(); + let values = hash + .chunks(8) + .into_iter() + .map(|x| u64::from_le_bytes(x.to_vec().try_into().unwrap())) + .collect::>(); + let cursor = self.get_root.cursor; + self.get_root.reduce(values[self.get_root.cursor]); + values[cursor] + } + + /// reset the address of merkle op together with the data and data_cursor + pub fn merkle_address(&mut self, v: u64) { + if self.address.cursor == 0 { + self.used_round += 1; + } + self.data = [0; 4]; + self.fetch = false; + self.data_cursor = 0; + self.address.reduce(v); + } + + pub fn merkle_set(&mut self, v: u64) { + self.set.reduce(v); + if self.set.cursor == 0 { + let address = self.address.rules[0].u64_value().unwrap() as u32; + let index = (address as u64) + (1u64 << MERKLE_TREE_HEIGHT) - 1; + let mt = self + .mongo_merkle + .as_mut() + .expect("merkle db not initialized"); + let hash = self.set.rules[0].bytes_value().unwrap(); + mt.update_leaf_data_with_proof(index, &hash) + .expect("Unexpected failure: update leaf with proof fail"); + } + } + + pub fn merkle_get(&mut self) -> u64 { + let address = self.address.rules[0].u64_value().unwrap() as u32; + let index = (address as u64) + (1u64 << MERKLE_TREE_HEIGHT) - 1; + let mt = self + .mongo_merkle + .as_ref() + .expect("merkle db not initialized"); + let (leaf, _) = mt + .get_leaf_with_proof(index) + .expect("Unexpected failure: get leaf fail"); + let values = leaf.data_as_u64(); + if self.data_cursor == 0 { + self.data = values; + } + let v = values[self.data_cursor]; + self.data_cursor += 1; + return v; + } +} + +impl MerkleContext {} diff --git a/crates/host/src/context/merkle_helper/mod.rs b/crates/host/src/context/merkle_helper/mod.rs new file mode 100644 index 000000000..d6b71bb10 --- /dev/null +++ b/crates/host/src/context/merkle_helper/mod.rs @@ -0,0 +1,2 @@ +pub mod datacache; +pub mod merkle; diff --git a/crates/host/src/context/mod.rs b/crates/host/src/context/mod.rs new file mode 100644 index 000000000..9b9534c06 --- /dev/null +++ b/crates/host/src/context/mod.rs @@ -0,0 +1,3 @@ +pub mod ecc_helper; +pub mod hash_helper; +pub mod merkle_helper; diff --git a/crates/host/src/host/ecc_helper/jubjub/mod.rs b/crates/host/src/host/ecc_helper/jubjub/mod.rs index a9993ed46..dce785d95 100644 --- a/crates/host/src/host/ecc_helper/jubjub/mod.rs +++ b/crates/host/src/host/ecc_helper/jubjub/mod.rs @@ -1,44 +1 @@ pub mod sum; -use ark_std::Zero; -use halo2_proofs::pairing::bn256::Fr as BabyJubjubFq; -use num_bigint::BigUint; -use num_traits::FromPrimitive; -use std::ops::AddAssign; -use std::ops::Shl; -use zkwasm_host_circuits::host::jubjub; - -const LIMBSZ: usize = 64; -const LIMBNB: usize = 4; - -use super::bn_to_field; -use super::field_to_bn; - -pub fn fetch_fq(limbs: &Vec, index: usize) -> BabyJubjubFq { - let mut bn = BigUint::zero(); - for i in 0..LIMBNB { - bn.add_assign(BigUint::from_u64(limbs[index * LIMBNB + i]).unwrap() << (i * LIMBSZ)) - } - bn_to_field(&bn) -} - -fn fetch_g1(limbs: &Vec) -> jubjub::Point { - jubjub::Point { - x: fetch_fq(limbs, 0), - y: fetch_fq(limbs, 1), - } -} - -pub fn babyjubjub_fq_to_limbs(result_limbs: &mut Vec, f: BabyJubjubFq) { - let mut bn = field_to_bn(&f); - for _ in 0..LIMBNB { - let d: BigUint = BigUint::from(1 as u64).shl(LIMBSZ); - let r = bn.clone() % d.clone(); - let value = if r == BigUint::from(0 as u32) { - 0 as u64 - } else { - r.to_u64_digits()[0] - }; - bn = bn / d; - result_limbs.append(&mut vec![value]); - } -} diff --git a/crates/host/src/host/ecc_helper/jubjub/sum/mod.rs b/crates/host/src/host/ecc_helper/jubjub/sum/mod.rs index 648d033c6..c83c5d6ac 100644 --- a/crates/host/src/host/ecc_helper/jubjub/sum/mod.rs +++ b/crates/host/src/host/ecc_helper/jubjub/sum/mod.rs @@ -1,118 +1,16 @@ use delphinus_zkwasm::runtime::host::host_env::HostEnv; use delphinus_zkwasm::runtime::host::ForeignContext; use delphinus_zkwasm::runtime::host::ForeignStatics; -use num_bigint::BigUint; use std::rc::Rc; +use crate::context::ecc_helper::jubjub::sum::BabyJubjubSumContext; +use specs::external_host_call_table::ExternalHostCallSignature; use zkwasm_host_circuits::circuits::babyjub::AltJubChip; use zkwasm_host_circuits::circuits::host::HostOpSelector; use zkwasm_host_circuits::host::ForeignInst::JubjubSumNew; use zkwasm_host_circuits::host::ForeignInst::JubjubSumPush; use zkwasm_host_circuits::host::ForeignInst::JubjubSumResult; -use zkwasm_host_circuits::host::jubjub; - -use super::babyjubjub_fq_to_limbs; -use super::fetch_g1; -use super::LIMBNB; - -fn fetch_biguint(_limbs: &Vec) -> BigUint { - BigUint::from_bytes_le( - _limbs - .iter() - .map(|x| x.to_le_bytes()) - .flatten() - .collect::>() - .as_slice(), - ) -} - -pub struct BabyJubjubSumContext { - pub k: u32, - pub acc: jubjub::Point, - pub limbs: Vec, - pub coeffs: Vec, - pub result_limbs: Option>, - pub result_cursor: usize, - pub input_cursor: usize, - pub used_round: usize, -} - -impl BabyJubjubSumContext { - pub fn default(k: u32) -> Self { - BabyJubjubSumContext { - k, - acc: jubjub::Point::identity(), - limbs: vec![], - coeffs: vec![], - result_limbs: None, - result_cursor: 0, - input_cursor: 0, - used_round: 0, - } - } - - pub fn babyjubjub_sum_new(&mut self, new: usize) { - self.result_limbs = None; - self.result_cursor = 0; - self.limbs = vec![]; - self.input_cursor = 0; - self.coeffs = vec![]; - self.used_round += 1; - if new != 0 { - self.acc = jubjub::Point::identity(); - } - } - - pub fn babyjubjub_sum_push(&mut self, v: u64) { - if self.input_cursor < LIMBNB * 2 { - self.limbs.push(v); - self.input_cursor += 1; - } else if self.input_cursor < LIMBNB * 2 + 4 { - self.coeffs.push(v); - self.input_cursor += 1; - if self.input_cursor == LIMBNB * 2 + 4 { - self.input_cursor = 0; - } - } - } - - pub fn babyjubjub_sum_finalize(&mut self) -> u64 { - let limbs = self.result_limbs.clone(); - match limbs { - None => { - assert!(self.limbs.len() == LIMBNB * 2); - let coeff = fetch_biguint(&self.coeffs.to_vec()); - let g1 = fetch_g1(&self.limbs.to_vec()); - log::debug!("acc is {:?}", self.acc); - log::debug!("g1 is {:?}", g1); - log::debug!("coeff is {:?} {}", coeff, self.coeffs.len()); - self.acc = self - .acc - .projective() - .add(&g1.mul_scalar(&coeff).projective()) - .affine(); - log::debug!("msm result: {:?}", self.acc); - self.babyjubjub_result_to_limbs(self.acc.clone()); - } - _ => (), - }; - let ret = self.result_limbs.as_ref().unwrap()[self.result_cursor]; - self.result_cursor += 1; - - ret - } -} - -impl BabyJubjubSumContext { - fn babyjubjub_result_to_limbs(&mut self, g: jubjub::Point) { - let mut limbs = vec![]; - babyjubjub_fq_to_limbs(&mut limbs, g.x); - babyjubjub_fq_to_limbs(&mut limbs, g.y); - self.result_limbs = Some(limbs); - } -} - impl ForeignContext for BabyJubjubSumContext { fn get_statics(&self) -> Option { Some(ForeignStatics { @@ -122,7 +20,6 @@ impl ForeignContext for BabyJubjubSumContext { } } -use specs::external_host_call_table::ExternalHostCallSignature; pub fn register_babyjubjubsum_foreign(env: &mut HostEnv) { let foreign_babyjubjubsum_plugin = env.external_env.register_plugin( "foreign_babyjubjubsum", diff --git a/crates/host/src/host/hash_helper/poseidon.rs b/crates/host/src/host/hash_helper/poseidon.rs index 953fa3748..63614d392 100644 --- a/crates/host/src/host/hash_helper/poseidon.rs +++ b/crates/host/src/host/hash_helper/poseidon.rs @@ -1,17 +1,12 @@ +use crate::context::hash_helper::poseidon::PoseidonContext; use delphinus_zkwasm::runtime::host::host_env::HostEnv; use delphinus_zkwasm::runtime::host::ForeignContext; use delphinus_zkwasm::runtime::host::ForeignStatics; -use ff::PrimeField; -use halo2_proofs::pairing::bn256::Fr; -use poseidon::Poseidon; +use specs::external_host_call_table::ExternalHostCallSignature; use std::rc::Rc; -pub use zkwasm_host_circuits::host::poseidon::POSEIDON_HASHER; - -use zkwasm_host_circuits::host::Reduce; -use zkwasm_host_circuits::host::ReduceRule; - use zkwasm_host_circuits::circuits::host::HostOpSelector; use zkwasm_host_circuits::circuits::poseidon::PoseidonChip; +pub use zkwasm_host_circuits::host::poseidon::POSEIDON_HASHER; use zkwasm_host_circuits::host::ForeignInst::PoseidonFinalize; use zkwasm_host_circuits::host::ForeignInst::PoseidonNew; use zkwasm_host_circuits::host::ForeignInst::PoseidonPush; @@ -36,83 +31,6 @@ use zkwasm_host_circuits::host::ForeignInst::PoseidonPush; /// wasm_dbg(r[3]); /// } -pub struct Generator { - pub cursor: usize, - pub values: Vec, -} - -impl Generator { - pub fn gen(&mut self) -> u64 { - let r = self.values[self.cursor]; - self.cursor += 1; - if self.cursor == 4 { - self.cursor = 0; - } - r - } -} - -pub fn new_reduce(rules: Vec>) -> Reduce { - Reduce { cursor: 0, rules } -} - -pub struct PoseidonContext { - pub k: u32, - pub hasher: Option>, - pub generator: Generator, - pub buf: Vec, - pub fieldreducer: Reduce, - pub used_round: usize, -} - -impl PoseidonContext { - pub fn default(k: u32) -> Self { - PoseidonContext { - k, - hasher: None, - fieldreducer: new_reduce(vec![ReduceRule::Field(Fr::zero(), 64)]), - buf: vec![], - generator: Generator { - cursor: 0, - values: vec![], - }, - used_round: 0, - } - } - - pub fn poseidon_new(&mut self, new: usize) { - self.buf = vec![]; - if new != 0 { - self.hasher = Some(POSEIDON_HASHER.clone()); - self.used_round += 1; - } - } - - pub fn poseidon_push(&mut self, v: u64) { - self.fieldreducer.reduce(v); - if self.fieldreducer.cursor == 0 { - self.buf - .push(self.fieldreducer.rules[0].field_value().unwrap()) - } - } - - pub fn poseidon_finalize(&mut self) -> u64 { - assert!(self.buf.len() == 8); - if self.generator.cursor == 0 { - self.hasher.as_mut().map(|s| { - log::debug!("perform hash with {:?}", self.buf); - let r = s.update_exact(&self.buf.clone().try_into().unwrap()); - let dwords: Vec = r.to_repr().to_vec(); - self.generator.values = dwords - .chunks(8) - .map(|x| u64::from_le_bytes(x.to_vec().try_into().unwrap())) - .collect::>(); - }); - } - self.generator.gen() - } -} - impl ForeignContext for PoseidonContext { fn get_statics(&self) -> Option { Some(ForeignStatics { @@ -122,7 +40,6 @@ impl ForeignContext for PoseidonContext { } } -use specs::external_host_call_table::ExternalHostCallSignature; pub fn register_poseidon_foreign(env: &mut HostEnv) { let foreign_poseidon_plugin = env.external_env.register_plugin( "foreign_poseidon", diff --git a/crates/host/src/host/merkle_helper/datacache.rs b/crates/host/src/host/merkle_helper/datacache.rs index fe6079272..1f046211d 100644 --- a/crates/host/src/host/merkle_helper/datacache.rs +++ b/crates/host/src/host/merkle_helper/datacache.rs @@ -1,108 +1,14 @@ +use crate::context::merkle_helper::datacache::CacheContext; use delphinus_zkwasm::runtime::host::host_env::HostEnv; use delphinus_zkwasm::runtime::host::ForeignContext; use delphinus_zkwasm::runtime::host::ForeignStatics; -use halo2_proofs::pairing::bn256::Fr; use std::cell::RefCell; use std::rc::Rc; -use zkwasm_host_circuits::host::datahash as datahelper; -use zkwasm_host_circuits::host::datahash::DataHashRecord; use zkwasm_host_circuits::host::db::TreeDB; use zkwasm_host_circuits::host::ForeignInst::CacheFetchData; use zkwasm_host_circuits::host::ForeignInst::CacheSetHash; use zkwasm_host_circuits::host::ForeignInst::CacheSetMode; use zkwasm_host_circuits::host::ForeignInst::CacheStoreData; -use zkwasm_host_circuits::host::Reduce; -use zkwasm_host_circuits::host::ReduceRule; - -const FETCH_MODE: u64 = 0; -const STORE_MODE: u64 = 1; - -pub struct CacheContext { - pub mode: u64, - pub hash: Reduce, - pub data: Vec, - pub fetch: bool, - pub mongo_datahash: datahelper::MongoDataHash, - pub tree_db: Option>>, -} - -fn new_reduce(rules: Vec>) -> Reduce { - Reduce { cursor: 0, rules } -} - -impl CacheContext { - pub fn new(tree_db: Option>>) -> Self { - CacheContext { - mode: 0, - hash: new_reduce(vec![ReduceRule::Bytes(vec![], 4)]), - fetch: false, - data: vec![], - mongo_datahash: datahelper::MongoDataHash::construct([0; 32], tree_db.clone()), - tree_db, - } - } - - pub fn set_mode(&mut self, v: u64) { - self.mode = v; - self.data = vec![]; - } - - pub fn set_data_hash(&mut self, v: u64) { - self.hash.reduce(v); - if self.hash.cursor == 0 { - let hash: [u8; 32] = self.hash.rules[0] - .bytes_value() - .unwrap() - .try_into() - .unwrap(); - if self.mode == FETCH_MODE { - let datahashrecord = self.mongo_datahash.get_record(&hash).unwrap(); - self.data = datahashrecord.map_or(vec![], |r| { - r.data - .chunks_exact(8) - .into_iter() - .into_iter() - .map(|x| u64::from_le_bytes(x.try_into().unwrap())) - .collect::>() - }); - self.fetch = false; - } else if self.mode == STORE_MODE { - // put data and hash into mongo_datahash - if !self.data.is_empty() { - self.mongo_datahash - .update_record({ - DataHashRecord { - hash, - data: self - .data - .iter() - .map(|x| x.to_le_bytes()) - .flatten() - .collect::>(), - } - }) - .unwrap(); - } - } - } - } - - pub fn fetch_data(&mut self) -> u64 { - if self.fetch == false { - self.fetch = true; - self.data.reverse(); - self.data.len() as u64 - } else { - self.data.pop().unwrap() - } - } - - pub fn store_data(&mut self, v: u64) { - self.data.push(v); - } -} - -impl CacheContext {} impl ForeignContext for CacheContext { fn get_statics(&self) -> Option { diff --git a/crates/host/src/host/merkle_helper/merkle.rs b/crates/host/src/host/merkle_helper/merkle.rs index 2bb187748..4a25d97c0 100644 --- a/crates/host/src/host/merkle_helper/merkle.rs +++ b/crates/host/src/host/merkle_helper/merkle.rs @@ -1,141 +1,20 @@ +use crate::context::merkle_helper::merkle::MerkleContext; +use crate::context::merkle_helper::merkle::MERKLE_TREE_HEIGHT; use delphinus_zkwasm::runtime::host::host_env::HostEnv; use delphinus_zkwasm::runtime::host::ForeignContext; use delphinus_zkwasm::runtime::host::ForeignStatics; use halo2_proofs::pairing::bn256::Fr; +use specs::external_host_call_table::ExternalHostCallSignature; use std::cell::RefCell; use std::rc::Rc; use zkwasm_host_circuits::circuits::host::HostOpSelector; use zkwasm_host_circuits::circuits::merkle::MerkleChip; -use zkwasm_host_circuits::host::datahash as datahelper; use zkwasm_host_circuits::host::db::TreeDB; -use zkwasm_host_circuits::host::merkle::MerkleTree; -use zkwasm_host_circuits::host::mongomerkle as merklehelper; use zkwasm_host_circuits::host::ForeignInst::MerkleAddress; use zkwasm_host_circuits::host::ForeignInst::MerkleGet; use zkwasm_host_circuits::host::ForeignInst::MerkleGetRoot; use zkwasm_host_circuits::host::ForeignInst::MerkleSet; use zkwasm_host_circuits::host::ForeignInst::MerkleSetRoot; -use zkwasm_host_circuits::host::Reduce; -use zkwasm_host_circuits::host::ReduceRule; - -const MERKLE_TREE_HEIGHT: usize = 32; - -pub struct MerkleContext { - pub k: u32, - pub set_root: Reduce, - pub get_root: Reduce, - pub address: Reduce, - pub set: Reduce, - pub data: [u64; 4], - pub data_cursor: usize, - pub fetch: bool, - pub mongo_merkle: Option>, - pub mongo_datahash: datahelper::MongoDataHash, - pub tree_db: Option>>, - pub used_round: usize, -} - -fn new_reduce(rules: Vec>) -> Reduce { - Reduce { cursor: 0, rules } -} - -impl MerkleContext { - pub fn new(k: u32, tree_db: Option>>) -> Self { - MerkleContext { - k, - set_root: new_reduce(vec![ReduceRule::Bytes(vec![], 4)]), - get_root: new_reduce(vec![ReduceRule::Bytes(vec![], 4)]), - address: new_reduce(vec![ReduceRule::U64(0)]), - set: new_reduce(vec![ReduceRule::Bytes(vec![], 4)]), - fetch: false, - data: [0; 4], - data_cursor: 0, - mongo_merkle: None, - mongo_datahash: datahelper::MongoDataHash::construct([0; 32], tree_db.clone()), - tree_db, - used_round: 0, - } - } - - pub fn merkle_setroot(&mut self, v: u64) { - self.set_root.reduce(v); - if self.set_root.cursor == 0 { - log::debug!("set root: {:?}", &self.set_root.rules[0].bytes_value()); - self.mongo_merkle = Some(merklehelper::MongoMerkle::construct( - [0; 32], - self.set_root.rules[0] - .bytes_value() - .unwrap() - .try_into() - .unwrap(), - self.tree_db.clone(), - )); - } - } - - pub fn merkle_getroot(&mut self) -> u64 { - let mt = self - .mongo_merkle - .as_ref() - .expect("merkle db not initialized"); - let hash = mt.get_root_hash(); - let values = hash - .chunks(8) - .into_iter() - .map(|x| u64::from_le_bytes(x.to_vec().try_into().unwrap())) - .collect::>(); - let cursor = self.get_root.cursor; - self.get_root.reduce(values[self.get_root.cursor]); - values[cursor] - } - - /// reset the address of merkle op together with the data and data_cursor - pub fn merkle_address(&mut self, v: u64) { - if self.address.cursor == 0 { - self.used_round += 1; - } - self.data = [0; 4]; - self.fetch = false; - self.data_cursor = 0; - self.address.reduce(v); - } - - pub fn merkle_set(&mut self, v: u64) { - self.set.reduce(v); - if self.set.cursor == 0 { - let address = self.address.rules[0].u64_value().unwrap() as u32; - let index = (address as u64) + (1u64 << MERKLE_TREE_HEIGHT) - 1; - let mt = self - .mongo_merkle - .as_mut() - .expect("merkle db not initialized"); - let hash = self.set.rules[0].bytes_value().unwrap(); - mt.update_leaf_data_with_proof(index, &hash) - .expect("Unexpected failure: update leaf with proof fail"); - } - } - - pub fn merkle_get(&mut self) -> u64 { - let address = self.address.rules[0].u64_value().unwrap() as u32; - let index = (address as u64) + (1u64 << MERKLE_TREE_HEIGHT) - 1; - let mt = self - .mongo_merkle - .as_ref() - .expect("merkle db not initialized"); - let (leaf, _) = mt - .get_leaf_with_proof(index) - .expect("Unexpected failure: get leaf fail"); - let values = leaf.data_as_u64(); - if self.data_cursor == 0 { - self.data = values; - } - let v = values[self.data_cursor]; - self.data_cursor += 1; - return v; - } -} - -impl MerkleContext {} impl ForeignContext for MerkleContext { fn get_statics(&self) -> Option { @@ -146,7 +25,6 @@ impl ForeignContext for MerkleContext { } } -use specs::external_host_call_table::ExternalHostCallSignature; pub fn register_merkle_foreign(env: &mut HostEnv, tree_db: Option>>) { let foreign_merkle_plugin = env.external_env.register_plugin( "foreign_merkle", diff --git a/crates/host/src/lib.rs b/crates/host/src/lib.rs index 275ffaf78..761685690 100644 --- a/crates/host/src/lib.rs +++ b/crates/host/src/lib.rs @@ -1,5 +1,6 @@ #![deny(warnings)] +pub mod context; pub mod host; use std::cell::RefCell; use std::rc::Rc;