liminal_ark_relations/shielder/
path_shape_var.rs1use core::{borrow::Borrow, ops::Index};
2
3use ark_r1cs_std::{
4 alloc::{AllocVar, AllocationMode},
5 boolean::Boolean,
6};
7use ark_relations::r1cs::{Namespace, SynthesisError};
8use ark_std::{vec, vec::Vec};
9#[cfg(feature = "std")]
10use {
11 ark_r1cs_std::R1CSVar,
12 std::fmt::{Display, Formatter},
13};
14
15use crate::environment::CircuitField;
16
17#[derive(Clone, Debug)]
18pub struct PathShapeVar {
19 shape: Vec<Boolean<CircuitField>>,
20}
21
22#[cfg(feature = "std")]
23impl Display for PathShapeVar {
24 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
25 write!(
26 f,
27 "{:?}",
28 self.shape
29 .iter()
30 .map(|b| b.value().map(|boo| if boo { "left" } else { "right" }))
31 .collect::<Vec<_>>()
32 )
33 }
34}
35
36impl PathShapeVar {
37 pub(super) fn len(&self) -> usize {
38 self.shape.len()
39 }
40}
41
42impl Index<usize> for PathShapeVar {
43 type Output = Boolean<CircuitField>;
44
45 fn index(&self, index: usize) -> &Self::Output {
46 &self.shape[index]
47 }
48}
49
50impl AllocVar<(u8, Result<u64, SynthesisError>), CircuitField> for PathShapeVar {
51 fn new_variable<T: Borrow<(u8, Result<u64, SynthesisError>)>>(
52 cs: impl Into<Namespace<CircuitField>>,
53 f: impl FnOnce() -> Result<T, SynthesisError>,
54 mode: AllocationMode,
55 ) -> Result<Self, SynthesisError> {
56 let ns = cs.into();
57 let cs = ns.cs();
58
59 let mut shape = vec![];
60
61 let (path_length, maybe_leaf_index) = *f()?.borrow();
62
63 for i in 0..path_length {
64 shape.push(Boolean::new_variable(
65 cs.clone(),
66 || {
67 let current_index = maybe_leaf_index? / (1 << i);
68 Ok(current_index & 1 != 1 || current_index == 1)
69 },
70 mode,
71 )?);
72 }
73
74 Ok(Self { shape })
75 }
76}