Skip to content

Commit

Permalink
reuse original ZPtr to define LEM's; move CtrlTag to tag.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurpaulino committed Sep 13, 2023
1 parent 37585f4 commit 819b180
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 158 deletions.
31 changes: 17 additions & 14 deletions src/lem/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ fn allocate_ptr<F: LurkField, CS: ConstraintSystem<F>>(
var: &Var,
bound_allocations: &mut BoundAllocations<F>,
) -> Result<AllocatedPtr<F>> {
let allocated_tag = allocate_num(cs, &format!("allocate {var}'s tag"), z_ptr.tag.to_field())?;
let allocated_hash = allocate_num(cs, &format!("allocate {var}'s hash"), z_ptr.hash)?;
let allocated_tag = allocate_num(cs, &format!("allocate {var}'s tag"), z_ptr.tag_field())?;
let allocated_hash = allocate_num(cs, &format!("allocate {var}'s hash"), *z_ptr.value())?;
let allocated_ptr = AllocatedPtr::from_parts(allocated_tag, allocated_hash);
bound_allocations.insert(var.clone(), allocated_ptr.clone());
Ok(allocated_ptr)
Expand Down Expand Up @@ -253,7 +253,7 @@ fn allocate_slots<F: LurkField, CS: ConstraintSystem<F>>(
cs,
&slot,
component_idx,
z_ptr.tag.to_field(),
z_ptr.tag_field(),
)?);

component_idx += 1;
Expand All @@ -263,7 +263,7 @@ fn allocate_slots<F: LurkField, CS: ConstraintSystem<F>>(
cs,
&slot,
component_idx,
z_ptr.hash,
*z_ptr.value(),
)?);

component_idx += 1;
Expand All @@ -278,11 +278,14 @@ fn allocate_slots<F: LurkField, CS: ConstraintSystem<F>>(
cs,
&slot,
1,
z_ptr.tag.to_field(),
z_ptr.tag_field(),
)?);
// allocate third component
preallocated_preimg.push(allocate_preimg_component_for_slot(
cs, &slot, 2, z_ptr.hash,
cs,
&slot,
2,
*z_ptr.value(),
)?);
}
PreimageData::FPair(a, b) => {
Expand Down Expand Up @@ -340,8 +343,8 @@ impl Block {
Op::Lit(_, lit) => {
let lit_ptr = lit.to_ptr_cached(store);
let lit_z_ptr = store.hash_ptr(&lit_ptr).unwrap();
g.alloc_const(cs, lit_z_ptr.tag.to_field());
g.alloc_const(cs, lit_z_ptr.hash);
g.alloc_const(cs, lit_z_ptr.tag_field());
g.alloc_const(cs, *lit_z_ptr.value());
}
Op::Null(_, tag) => {
g.alloc_const(cs, tag.to_field());
Expand Down Expand Up @@ -674,11 +677,11 @@ impl Func {
Op::Lit(tgt, lit) => {
let lit_ptr = lit.to_ptr_cached(g.store);
let lit_tag = lit_ptr.tag().to_field();
let lit_hash = g.store.hash_ptr(&lit_ptr)?.hash;
let allocated_tag =
g.global_allocator.get_allocated_const_cloned(lit_tag)?;
let allocated_hash =
g.global_allocator.get_allocated_const_cloned(lit_hash)?;
let allocated_hash = g
.global_allocator
.get_allocated_const_cloned(*g.store.hash_ptr(&lit_ptr)?.value())?;
let allocated_ptr = AllocatedPtr::from_parts(allocated_tag, allocated_hash);
bound_allocations.insert(tgt.clone(), allocated_ptr);
}
Expand Down Expand Up @@ -1149,7 +1152,7 @@ impl Func {
.store
.interned_symbol(sym)
.expect("symbol must have been interned");
let sym_hash = g.store.hash_ptr(sym_ptr)?.hash;
let sym_hash = *g.store.hash_ptr(sym_ptr)?.value();
cases_vec.push((sym_hash, block));
}

Expand Down Expand Up @@ -1241,8 +1244,8 @@ impl Func {
Op::Lit(_, lit) => {
let lit_ptr = lit.to_ptr_cached(store);
let lit_z_ptr = store.hash_ptr(&lit_ptr).unwrap();
globals.insert(FWrap(lit_z_ptr.tag.to_field()));
globals.insert(FWrap(lit_z_ptr.hash));
globals.insert(FWrap(lit_z_ptr.tag_field()));
globals.insert(FWrap(*lit_z_ptr.value()));
}
Op::Cast(_, tag, _) => {
globals.insert(FWrap(tag.to_field()));
Expand Down
4 changes: 2 additions & 2 deletions src/lem/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1070,8 +1070,8 @@ mod tests {
use blstrs::Scalar as Fr;

const NUM_INPUTS: usize = 1;
const NUM_AUX: usize = 10744;
const NUM_CONSTRAINTS: usize = 13299;
const NUM_AUX: usize = 10748;
const NUM_CONSTRAINTS: usize = 13303;
const NUM_SLOTS: SlotsCounter = SlotsCounter {
hash2: 16,
hash3: 4,
Expand Down
4 changes: 1 addition & 3 deletions src/lem/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,7 @@ impl Block {
let b = bindings.get(b)?;
// In order to compare Ptrs, we *must* resolve the hashes. Otherwise, we risk failing to recognize equality of
// compound data with opaque data in either element's transitive closure.
let a_hash = store.hash_ptr(a)?.hash;
let b_hash = store.hash_ptr(b)?.hash;
let c = if a_hash == b_hash {
let c = if store.hash_ptr(a)?.value() == store.hash_ptr(b)?.value() {
Ptr::Atom(Tag::Expr(Num), F::ONE)
} else {
Ptr::Atom(Tag::Expr(Num), F::ZERO)
Expand Down
72 changes: 41 additions & 31 deletions src/lem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,19 @@ mod slot;
pub mod store;
mod var_map;
pub mod zstore;

use crate::coprocessor::Coprocessor;
use crate::eval::lang::Lang;
use crate::field::LurkField;
use crate::symbol::Symbol;
use crate::tag::{ContTag, ExprTag, Tag as TagTrait};
use anyhow::{bail, Result};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::sync::Arc;

use crate::{
coprocessor::Coprocessor,
eval::lang::Lang,
field::LurkField,
symbol::Symbol,
tag::{ContTag, CtrlTag, ExprTag, Tag as TagTrait},
};

use self::{pointers::Ptr, slot::SlotsCounter, store::Store, var_map::VarMap};

pub type AString = Arc<str>;
Expand Down Expand Up @@ -113,40 +115,47 @@ pub enum Tag {
Ctrl(CtrlTag),
}

#[derive(Copy, Debug, PartialEq, Clone, Eq, Hash, Serialize, Deserialize)]
pub enum CtrlTag {
Return,
MakeThunk,
ApplyContinuation,
Error,
impl From<u16> for Tag {
fn from(val: u16) -> Self {
if let Ok(tag) = ExprTag::try_from(val) {
Tag::Expr(tag)
} else if let Ok(tag) = ContTag::try_from(val) {
Tag::Cont(tag)
} else if let Ok(tag) = CtrlTag::try_from(val) {
Tag::Ctrl(tag)
} else {
panic!("Invalid u16 for Tag: {val}")
}
}
}

impl Tag {
#[inline]
pub fn to_field<F: LurkField>(self) -> F {
use Tag::*;
match self {
Expr(tag) => tag.to_field(),
Cont(tag) => tag.to_field(),
Ctrl(tag) => tag.to_field(),
impl From<Tag> for u16 {
fn from(val: Tag) -> Self {
match val {
Tag::Expr(tag) => tag.into(),
Tag::Cont(tag) => tag.into(),
Tag::Ctrl(tag) => tag.into(),
}
}
}

impl CtrlTag {
#[inline]
fn to_field<F: LurkField>(self) -> F {
F::from(self as u64)
impl TagTrait for Tag {
fn from_field<F: LurkField>(f: &F) -> Option<Self> {
Self::try_from(f.to_u16()?).ok()
}

fn to_field<F: LurkField>(&self) -> F {
Tag::to_field(self)
}
}

impl std::fmt::Display for CtrlTag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl Tag {
#[inline]
pub fn to_field<F: LurkField>(&self) -> F {
match self {
Self::Return => write!(f, "return#"),
Self::ApplyContinuation => write!(f, "apply-cont#"),
Self::MakeThunk => write!(f, "make-thunk#"),
Self::Error => write!(f, "error#"),
Tag::Expr(tag) => tag.to_field(),
Tag::Cont(tag) => tag.to_field(),
Tag::Ctrl(tag) => tag.to_field(),
}
}
}
Expand Down Expand Up @@ -456,10 +465,11 @@ impl Func {
let mut tags = HashSet::new();
let mut kind = None;
for (tag, block) in cases {
// make sure that this `MatchTag` doesn't have weird semantics
let tag_kind = match tag {
Tag::Expr(..) => 0,
Tag::Cont(..) => 1,
Tag::Ctrl(..) => 4,
Tag::Ctrl(..) => 2,
};
if let Some(kind) = kind {
if kind != tag_kind {
Expand Down
33 changes: 1 addition & 32 deletions src/lem/pointers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,31 +137,7 @@ impl<F: LurkField> Ptr<F> {
/// An important note is that computing the respective `ZPtr` of a `Ptr` can be
/// expensive because of the Poseidon hashes. That's why we operate on `Ptr`s
/// when interpreting LEMs and delay the need for `ZPtr`s as much as possible.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct ZPtr<F: LurkField> {
pub tag: Tag,
pub hash: F,
}

impl<F: LurkField> PartialOrd for ZPtr<F> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
(
self.tag.to_field::<F>().to_repr().as_ref(),
self.hash.to_repr().as_ref(),
)
.partial_cmp(&(
other.tag.to_field::<F>().to_repr().as_ref(),
other.hash.to_repr().as_ref(),
))
}
}

impl<F: LurkField> Ord for ZPtr<F> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.partial_cmp(other)
.expect("ZPtr::cmp: partial_cmp domain invariant violation")
}
}
pub type ZPtr<F> = crate::z_data::z_ptr::ZPtr<Tag, F>;

/// `ZChildren` keeps track of the children of `ZPtr`s, in case they have any.
/// This information is saved during hydration and is needed to content-address
Expand All @@ -173,10 +149,3 @@ pub enum ZChildren<F: LurkField> {
Tuple3(ZPtr<F>, ZPtr<F>, ZPtr<F>),
Tuple4(ZPtr<F>, ZPtr<F>, ZPtr<F>, ZPtr<F>),
}

impl<F: LurkField> std::hash::Hash for ZPtr<F> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tag.hash(state);
self.hash.to_repr().as_ref().hash(state);
}
}
73 changes: 35 additions & 38 deletions src/lem/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ impl<F: LurkField> Store<F> {
let z_ptr = self.hash_ptr(&payload)?;
let hash = self
.poseidon_cache
.hash3(&[secret, z_ptr.tag.to_field(), z_ptr.hash]);
.hash3(&[secret, z_ptr.tag_field(), *z_ptr.value()]);
self.comms.insert(FWrap::<F>(hash), (secret, payload));
Ok(Ptr::comm(hash))
}
Expand All @@ -329,7 +329,7 @@ impl<F: LurkField> Store<F> {
let z_ptr = self.hash_ptr(&payload)?;
let hash = self
.poseidon_cache
.hash3(&[secret, z_ptr.tag.to_field(), z_ptr.hash]);
.hash3(&[secret, z_ptr.tag_field(), *z_ptr.value()]);
self.comms.insert(FWrap::<F>(hash), (secret, payload));
Ok((hash, z_ptr))
}
Expand Down Expand Up @@ -462,10 +462,7 @@ impl<F: LurkField> Store<F> {
/// depth limit. This limitation is circumvented by calling `hydrate_z_cache`.
pub fn hash_ptr(&self, ptr: &Ptr<F>) -> Result<ZPtr<F>> {
match ptr {
Ptr::Atom(tag, x) => Ok(ZPtr {
tag: *tag,
hash: *x,
}),
Ptr::Atom(tag, x) => Ok(ZPtr::from_parts(*tag, *x)),
Ptr::Tuple2(tag, idx) => match self.z_cache.get(ptr) {
Some(z_ptr) => Ok(*z_ptr),
None => {
Expand All @@ -474,15 +471,15 @@ impl<F: LurkField> Store<F> {
};
let a = self.hash_ptr(a)?;
let b = self.hash_ptr(b)?;
let z_ptr = ZPtr {
tag: *tag,
hash: self.poseidon_cache.hash4(&[
a.tag.to_field(),
a.hash,
b.tag.to_field(),
b.hash,
let z_ptr = ZPtr::from_parts(
*tag,
self.poseidon_cache.hash4(&[
a.tag_field(),
*a.value(),
b.tag_field(),
*b.value(),
]),
};
);
self.z_cache.insert(*ptr, Box::new(z_ptr));
Ok(z_ptr)
}
Expand All @@ -496,17 +493,17 @@ impl<F: LurkField> Store<F> {
let a = self.hash_ptr(a)?;
let b = self.hash_ptr(b)?;
let c = self.hash_ptr(c)?;
let z_ptr = ZPtr {
tag: *tag,
hash: self.poseidon_cache.hash6(&[
a.tag.to_field(),
a.hash,
b.tag.to_field(),
b.hash,
c.tag.to_field(),
c.hash,
let z_ptr = ZPtr::from_parts(
*tag,
self.poseidon_cache.hash6(&[
a.tag_field(),
*a.value(),
b.tag_field(),
*b.value(),
c.tag_field(),
*c.value(),
]),
};
);
self.z_cache.insert(*ptr, Box::new(z_ptr));
Ok(z_ptr)
}
Expand All @@ -521,19 +518,19 @@ impl<F: LurkField> Store<F> {
let b = self.hash_ptr(b)?;
let c = self.hash_ptr(c)?;
let d = self.hash_ptr(d)?;
let z_ptr = ZPtr {
tag: *tag,
hash: self.poseidon_cache.hash8(&[
a.tag.to_field(),
a.hash,
b.tag.to_field(),
b.hash,
c.tag.to_field(),
c.hash,
d.tag.to_field(),
d.hash,
let z_ptr = ZPtr::from_parts(
*tag,
self.poseidon_cache.hash8(&[
a.tag_field(),
*a.value(),
b.tag_field(),
*b.value(),
c.tag_field(),
*c.value(),
d.tag_field(),
*d.value(),
]),
};
);
self.z_cache.insert(*ptr, Box::new(z_ptr));
Ok(z_ptr)
}
Expand All @@ -554,8 +551,8 @@ impl<F: LurkField> Store<F> {
ptrs.iter()
.try_fold(Vec::with_capacity(2 * ptrs.len()), |mut acc, ptr| {
let z_ptr = self.hash_ptr(ptr)?;
acc.push(z_ptr.tag.to_field());
acc.push(z_ptr.hash);
acc.push(z_ptr.tag_field());
acc.push(*z_ptr.value());
Ok(acc)
})
}
Expand Down
Loading

0 comments on commit 819b180

Please sign in to comment.