#[macro_export]
macro_rules! witness {
(| $($circuit:ident),* | $block:block) => {{
let mode = witness_mode!($( $circuit ),*);
E::new_witness(mode, || {
$( let rename_selfs!($circuit) = $circuit.eject_value(); )*
rename_selfs!($block)
})
}};
(| $($circuit:ident),* | $logic:expr) => {{
witness!(| $($circuit),* | { $logic })
}};
}
#[macro_export]
macro_rules! witness_mode {
($($circuit:ident),*) => {{
match $( $circuit.is_constant() & )* true {
true => Mode::Constant,
false => Mode::Private
}
}}
}
#[cfg(test)]
mod tests {
use crate::*;
pub struct Foo(Mode, u8);
impl Inject for Foo {
type Primitive = u8;
fn new(mode: Mode, value: Self::Primitive) -> Self {
Self(mode, value)
}
}
impl Eject for Foo {
type Primitive = u8;
fn eject_mode(&self) -> Mode {
self.0
}
fn eject_value(&self) -> Self::Primitive {
self.1
}
}
fn check_witness<E: Environment>(expected_mode: Mode, mode_a: Mode, mode_b: Mode) {
let x = Foo::new(mode_a, 3);
let y = Foo::new(mode_b, 5);
let z: Foo = witness!(|x, y| { x + y });
assert_eq!(expected_mode, z.eject_mode());
assert_eq!(8, z.eject_value());
}
#[test]
fn test_witness_constant() {
check_witness::<Circuit>(Mode::Constant, Mode::Constant, Mode::Constant);
}
#[test]
fn test_witness_private() {
check_witness::<Circuit>(Mode::Private, Mode::Constant, Mode::Private);
}
}