Skip to content

Commit

Permalink
chore: factor out StoreCore
Browse files Browse the repository at this point in the history
`StoreCore` is a data structure that can encode data as DAGs of
tagged pointers, which can be content-addressed with a custom
hasher. The tag type as well as the digest type are generic.

To accomplish this, all pointer types are now unified in a single
type hierarchy.
  • Loading branch information
arthurpaulino committed Apr 17, 2024
1 parent bab22ba commit aed8503
Show file tree
Hide file tree
Showing 35 changed files with 1,314 additions and 1,280 deletions.
10 changes: 5 additions & 5 deletions benches/common/fib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub(crate) fn fib_limit(n: usize, rc: usize) -> usize {
rc * (frame / rc + usize::from(frame % rc != 0))
}

fn lurk_fib<F: LurkField>(store: &Store<F>, n: usize) -> Ptr {
fn lurk_fib<F: LurkField>(store: &Store<F>, n: usize) -> &Ptr {
let frame_idx = fib_frame(n);
let limit = frame_idx;
let fib_expr = fib_expr(store);
Expand All @@ -59,7 +59,7 @@ fn lurk_fib<F: LurkField>(store: &Store<F>, n: usize) -> Ptr {
// body: (.lurk.user.fib), continuation: Outermost }

let [_, _, rest_bindings] = store.pop_binding(target_env).unwrap();
let [_, val, _] = store.pop_binding(&rest_bindings).unwrap();
let [_, val, _] = store.pop_binding(rest_bindings).unwrap();
val
}

Expand Down Expand Up @@ -109,7 +109,7 @@ pub(crate) fn test_fib_io_matches() {
let fib_9 = store.num_u64(34);
let fib_10 = store.num_u64(55);
let fib_11 = store.num_u64(89);
assert_eq!(fib_9, lurk_fib(&store, 9));
assert_eq!(fib_10, lurk_fib(&store, 10));
assert_eq!(fib_11, lurk_fib(&store, 11));
assert_eq!(&fib_9, lurk_fib(&store, 9));
assert_eq!(&fib_10, lurk_fib(&store, 10));
assert_eq!(&fib_11, lurk_fib(&store, 11));
}
22 changes: 11 additions & 11 deletions chain-server/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,22 +173,22 @@ where

// produce the data for the response
let chain_response_data = ser(ChainResponseData::new(
&result,
&next_callable,
result,
next_callable,
&self.store,
compressed_proof,
))
.map_err(|e| Status::internal(e.to_string()))?;

// save the session
if let Some(session) = &self.session {
let session_data = SessionData::pack_standalone(self, &next_callable);
let session_data = SessionData::pack_standalone(self, next_callable);
dump(session_data, session).map_err(|e| Status::internal(e.to_string()))?;
}

// now it's safe to set the new callable state since no error
// has occurred so far
*callable_state = next_callable;
*callable_state = *next_callable;

Ok(Response::new(ChainResponse {
chain_response_data,
Expand Down Expand Up @@ -371,8 +371,8 @@ where

// produce the data for the response
let chain_response_data = ser(ChainResponseData::new(
&result,
&next_callable,
result,
next_callable,
&self.store,
compressed_proof,
))
Expand All @@ -382,16 +382,16 @@ where
if let Some(session) = &self.session {
let session_data = SessionData::pack_stream(
self,
&next_callable,
Some((&result, recursive_proof.clone())),
next_callable,
Some((result, recursive_proof.clone())),
);
dump(session_data, session).map_err(|e| Status::internal(e.to_string()))?;
}

// now it's safe to set the new state since no error has occurred so far
*state = StreamState {
callable: next_callable,
result_and_proof: Some((result, recursive_proof)),
callable: *next_callable,
result_and_proof: Some((*result, recursive_proof)),
};

Ok(Response::new(ChainResponse {
Expand Down Expand Up @@ -643,7 +643,7 @@ fn get_service_and_address<
let callable = if init_args.comm {
let hash_ptr = store.read_with_default_state(&init_args.callable)?;
let hash = store
.fetch_f(&hash_ptr)
.fetch_f_by_val(hash_ptr.val())
.ok_or("Failed to parse callable hash")?;
fetch_comm(hash, &store)?;
hash_ptr.cast(Tag::Expr(lurk::tag::ExprTag::Comm))
Expand Down
4 changes: 2 additions & 2 deletions examples/keccak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ impl<F: LurkField> CircomGadget<F> for CircomKeccak<F> {
let bytes_to_hash = bits_to_bytes(
&z_bits
.iter()
.map(|ptr| ptr.value() != &F::ZERO)
.map(|ptr| ptr.hash() != &F::ZERO)
.collect::<Vec<_>>(),
);

Expand Down Expand Up @@ -371,7 +371,7 @@ fn main() {
.unwrap()
.0
.iter()
.map(|ptr| ptr.raw().get_atom().unwrap() == 1)
.map(|ptr| ptr.val().get_atom_idx().unwrap() == 1)
.collect::<Vec<_>>(),
);

Expand Down
10 changes: 5 additions & 5 deletions foil/src/coil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ fn lookup_vertex_id<F: LurkField>(store: &Store<F>, env: &Ptr, var: &Ptr) -> Res
return Ok(None);
};

if *var == bound_var {
match store.fetch_num(&id) {
if var == bound_var {
match store.fetch_num(id) {
Some(f) => Ok(f.to_u64().map(|u| {
let n = u as Id;
info!("found {n}");
Expand All @@ -97,7 +97,7 @@ fn lookup_vertex_id<F: LurkField>(store: &Store<F>, env: &Ptr, var: &Ptr) -> Res
}
}
} else {
lookup_vertex_id(store, &rest_env, var)
lookup_vertex_id(store, rest_env, var)
}
}

Expand Down Expand Up @@ -127,9 +127,9 @@ impl Context {
let [_var, id, rest_env] = store
.pop_binding(&self.env)
.ok_or(anyhow!("failed to pop binding"))?;
self.env = rest_env;
self.env = *rest_env;

Ok(match store.fetch_num(&id) {
Ok(match store.fetch_num(id) {
Some(f) => f
.to_u64()
.map(|u| u as Id)
Expand Down
23 changes: 12 additions & 11 deletions src/circuit/gadgets/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use ff::PrimeField;

use crate::{
field::LurkField,
lem::pointers::ZPtr,
tag::{ExprTag, Tag},
z_ptr::{ZContPtr, ZExprPtr, ZPtr},
z_ptr::{ZContPtr, ZExprPtr},
};

use super::{
Expand Down Expand Up @@ -50,17 +51,17 @@ impl<F: LurkField> Debug for AllocatedPtr<F> {
}

impl<F: LurkField> AllocatedPtr<F> {
pub fn alloc<Fo, CS: ConstraintSystem<F>, T: Tag>(
pub fn alloc<Fo, CS: ConstraintSystem<F>>(
cs: &mut CS,
value: Fo,
) -> Result<Self, SynthesisError>
where
Fo: FnOnce() -> Result<ZPtr<T, F>, SynthesisError>,
Fo: FnOnce() -> Result<ZPtr<F>, SynthesisError>,
{
let mut hash = None;
let alloc_tag = AllocatedNum::alloc(ns!(cs, "tag"), || {
let ptr = value()?;
hash = Some(*ptr.value());
hash = Some(*ptr.hash());
Ok(ptr.tag_field())
})?;

Expand All @@ -74,14 +75,14 @@ impl<F: LurkField> AllocatedPtr<F> {
})
}

pub fn alloc_infallible<Fo, CS: ConstraintSystem<F>, T: Tag>(cs: &mut CS, value: Fo) -> Self
pub fn alloc_infallible<Fo, CS: ConstraintSystem<F>>(cs: &mut CS, value: Fo) -> Self
where
Fo: FnOnce() -> ZPtr<T, F>,
Fo: FnOnce() -> ZPtr<F>,
{
let mut hash = None;
let alloc_tag = AllocatedNum::alloc_infallible(ns!(cs, "tag"), || {
let ptr = value();
hash = Some(*ptr.value());
hash = Some(*ptr.hash());
ptr.tag_field()
});

Expand All @@ -106,12 +107,12 @@ impl<F: LurkField> AllocatedPtr<F> {
})
}

pub fn alloc_constant<CS: ConstraintSystem<F>, T: Tag>(
pub fn alloc_constant<CS: ConstraintSystem<F>>(
cs: &mut CS,
value: ZPtr<T, F>,
value: ZPtr<F>,
) -> Result<Self, SynthesisError> {
let alloc_tag = allocate_constant(ns!(cs, "tag"), value.tag_field());
let alloc_hash = allocate_constant(ns!(cs, "hash"), *value.value());
let alloc_hash = allocate_constant(ns!(cs, "hash"), *value.hash());

Ok(AllocatedPtr {
tag: alloc_tag,
Expand All @@ -131,7 +132,7 @@ impl<F: LurkField> AllocatedPtr<F> {
&self.hash
}

pub fn get_value<T: Tag>(&self) -> Option<ZPtr<T, F>> {
pub fn get_value(&self) -> Option<ZPtr<F>> {
self.tag.get_value().and_then(|tag| {
self.hash
.get_value()
Expand Down
15 changes: 7 additions & 8 deletions src/cli/repl/meta_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ use crate::{
field::LurkField,
lem::{
eval::evaluate_with_env_and_cont,
pointers::{Ptr, RawPtr},
store::expect_ptrs,
pointers::{IVal, Ptr},
tag::Tag,
},
package::{Package, SymbolRef},
Expand Down Expand Up @@ -272,7 +271,7 @@ where
let second_io = repl
.eval_expr(second)
.with_context(|| "evaluating second arg")?;
let (Tag::Expr(ExprTag::Num), RawPtr::Atom(secret)) = first_io[0].parts() else {
let (Tag::Expr(ExprTag::Num), IVal::Atom(secret)) = first_io[0].parts() else {
bail!(
"Secret must be a number. Got {}",
first_io[0].fmt_to_string(&repl.store, &repl.state.borrow())
Expand Down Expand Up @@ -589,7 +588,7 @@ where
.store
.fetch_cons(result)
.ok_or_else(|| anyhow!("Chained function must return a cons expression"))?;
let (Tag::Expr(ExprTag::Comm), RawPtr::Atom(hash)) = comm.parts() else {
let (Tag::Expr(ExprTag::Comm), IVal::Atom(hash)) = comm.parts() else {
bail!("Second component of a chain must be a commitment")
};
let hash = *repl.store.expect_f(*hash);
Expand All @@ -598,7 +597,7 @@ where
.store
.open(hash)
.expect("data must have been committed");
repl.hide(*secret, *fun)
repl.hide(secret.0, *fun)
},
};

Expand Down Expand Up @@ -822,7 +821,7 @@ where
};

let (car, _) = repl.store.car_cdr_simple(&rest)?;
let (Tag::Expr(ExprTag::Num), RawPtr::Atom(rc_idx)) = car.parts() else {
let (Tag::Expr(ExprTag::Num), IVal::Atom(rc_idx)) = car.parts() else {
bail!("Reduction count must be a Num")
};
let Some(rc) = repl.store.expect_f(*rc_idx).to_u64().map(|u| u as usize) else {
Expand Down Expand Up @@ -868,13 +867,13 @@ where
.eval_expr_with_env(apply_call, repl.store.intern_empty_env())
.with_context(|| "evaluating protocol function call")?;

let (Tag::Expr(ExprTag::Cons), RawPtr::Hash4(idx)) = &io[0].parts() else {
let (Tag::Expr(ExprTag::Cons), IVal::Tuple2(idx)) = &io[0].parts() else {
bail!(
"Protocol function must return a pair. Got {}",
io[0].fmt_to_string(&repl.store, &repl.state.borrow())
)
};
let [pre_verify, post_verify] = &expect_ptrs!(repl.store, 2, *idx);
let [pre_verify, post_verify] = repl.store.expect_tuple2(*idx);

if pre_verify.is_nil() {
bail!("Pre-verification predicate rejected the input")
Expand Down
10 changes: 6 additions & 4 deletions src/cli/repl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{
make_eval_step_from_config, EvalConfig,
},
interpreter::Frame,
pointers::{Ptr, RawPtr},
pointers::{IVal, Ptr},
store::Store,
tag::Tag,
Func,
Expand Down Expand Up @@ -322,7 +322,10 @@ where
&self.store,
(input[0], output[0]),
(input[1], output[1]),
(cont.parts(), cont_out.parts()),
(
(cont.tag_field(), *cont.hash()),
(cont_out.tag_field(), *cont_out.hash()),
),
);

let claim_comm = Commitment::new(None, claim, &self.store);
Expand Down Expand Up @@ -555,8 +558,7 @@ where
/// Errors when `hash_expr` doesn't reduce to a Num or Comm pointer
fn get_comm_hash(&mut self, hash_expr: Ptr) -> Result<&F> {
let io = self.eval_expr(hash_expr)?;
let (Tag::Expr(ExprTag::Num | ExprTag::Comm), RawPtr::Atom(hash_idx)) = io[0].parts()
else {
let (Tag::Expr(ExprTag::Num | ExprTag::Comm), IVal::Atom(hash_idx)) = io[0].parts() else {
bail!("Commitment hash expression must reduce to a Num or Comm pointer")
};
Ok(self.store.expect_f(*hash_idx))
Expand Down
Loading

0 comments on commit aed8503

Please sign in to comment.