Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

moving context specific out for native env requirements #258

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions crates/host/src/context/ecc_helper/jubjub/mod.rs
Original file line number Diff line number Diff line change
@@ -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<u64>, 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<u64>) -> jubjub::Point {
jubjub::Point {
x: fetch_fq(limbs, 0),
y: fetch_fq(limbs, 1),
}
}

pub fn babyjubjub_fq_to_limbs(result_limbs: &mut Vec<u64>, 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]);
}
}
102 changes: 102 additions & 0 deletions crates/host/src/context/ecc_helper/jubjub/sum/mod.rs
Original file line number Diff line number Diff line change
@@ -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<u64>) -> BigUint {
BigUint::from_bytes_le(
_limbs
.iter()
.map(|x| x.to_le_bytes())
.flatten()
.collect::<Vec<_>>()
.as_slice(),
)
}

pub struct BabyJubjubSumContext {
pub k: u32,
pub acc: jubjub::Point,
pub limbs: Vec<u64>,
pub coeffs: Vec<u64>,
pub result_limbs: Option<Vec<u64>>,
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);
}
}
17 changes: 17 additions & 0 deletions crates/host/src/context/ecc_helper/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
pub mod jubjub;

use halo2_proofs::arithmetic::BaseExt;
use num_bigint::BigUint;

pub fn bn_to_field<F: BaseExt>(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: BaseExt>(f: &F) -> BigUint {
let mut bytes: Vec<u8> = Vec::new();
f.write(&mut bytes).unwrap();
BigUint::from_bytes_le(&bytes[..])
}
1 change: 1 addition & 0 deletions crates/host/src/context/hash_helper/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod poseidon;
103 changes: 103 additions & 0 deletions crates/host/src/context/hash_helper/poseidon.rs
Original file line number Diff line number Diff line change
@@ -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<size; i=++) {
/// uint64_t* a = data[i];
/// poseidon_push(data[i]);
/// }
/// r[0] = poseidon_finalize();
/// r[1] = poseidon_finalize();
/// r[2] = poseidon_finalize();
/// r[3] = poseidon_finalize();
/// wasm_dbg(r[0]);
/// wasm_dbg(r[1]);
/// wasm_dbg(r[2]);
/// wasm_dbg(r[3]);
/// }

pub struct Generator {
pub cursor: usize,
pub values: Vec<u64>,
}

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<ReduceRule<Fr>>) -> Reduce<Fr> {
Reduce { cursor: 0, rules }
}

pub struct PoseidonContext {
pub k: u32,
pub hasher: Option<Poseidon<Fr, 9, 8>>,
pub generator: Generator,
pub buf: Vec<Fr>,
pub fieldreducer: Reduce<Fr>,
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<u8> = r.to_repr().to_vec();
self.generator.values = dwords
.chunks(8)
.map(|x| u64::from_le_bytes(x.to_vec().try_into().unwrap()))
.collect::<Vec<u64>>();
});
}
self.generator.gen()
}
}
98 changes: 98 additions & 0 deletions crates/host/src/context/merkle_helper/datacache.rs
Original file line number Diff line number Diff line change
@@ -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<Fr>,
pub data: Vec<u64>,
pub fetch: bool,
pub mongo_datahash: datahelper::MongoDataHash,
pub tree_db: Option<Rc<RefCell<dyn TreeDB>>>,
}

fn new_reduce(rules: Vec<ReduceRule<Fr>>) -> Reduce<Fr> {
Reduce { cursor: 0, rules }
}

impl CacheContext {
pub fn new(tree_db: Option<Rc<RefCell<dyn TreeDB>>>) -> 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::<Vec<u64>>()
});
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::<Vec<u8>>(),
}
})
.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 {}
Loading
Loading