pub fn verify<CS: ConstraintSystem<F>>(&self, 
        mut cs: CS, 
        path: &[Boolean], 
        root: FG, 
        auth_path: &[FG], 
        leaf: &[FG]) -> Result<(), SynthesisError>
    {
        let leafHash = self.leafHasher.hash(&mut cs.ns(|| "leafhash"), leaf)?;
        let mut curHash = leafHash;

        // To traverse up a MT, we iterate over the path in reverse.
        let mut rev_path = path.to_vec();
        rev_path.reverse();
        let mut auth_path_rev = auth_path.to_vec();
        auth_path_rev.reverse();
        assert_eq!(auth_path_rev.len(), path.len());

        for i in (0..auth_path_rev.len()) {
            let mut cs_i = cs.ns(|| format!("MT layer {:?}", i));
            let bit = rev_path[i];
            // At any given bit, the bit being 0 indicates our currently hashed value is the left,
            // and the bit being 1 indicates our currently hashed value is on the right.
            // so we set left_hash = mux(bit, [curHash, authPathHash]), and similarly,
            // right_hash = mux(not bit, [curHash, authPathHash])
            // It is straight forward to generalize this to higher arity trees

            let curVec = vec![curHash.clone(), auth_path_rev[i].clone()];
            let left_hash = mux(&mut cs_i.ns(|| "left mux"), 
                &curVec, &[bit])?;
            let right_hash = mux(&mut cs_i.ns(|| "right mux"), 
                &curVec, &[bit.not()])?;

            curHash = self.nodeHasher.hash(&mut cs_i, left_hash, right_hash)?;
        }

        curHash.enforce_equal(&mut cs, &root)?;
        Ok(())
    }
// We don't use the Zexe API for MTs.
// The Zexe API for an authentication path requires the caller to pass in both the left and right hash
// at every level. This is both computationally wasteful, and a pain for the caller to use.
// Furthermore it requires a boolean should_enforce, which is a concern that can be handled 
// at a higher level of abstraction.
//
// The path passed in should be the index of the leaf in the MT, represented in ?-endian bits. 
// The trailing bit of the Path should be index % 2.
// TODO: Recall which endianness is which
// 
// The authentication path should be given according to the same endianness.
//  <TODO: Add proper explanation and diagram>, import prior diagram from Tendermint
We don't use the Zexe API for MTs.
The Zexe API for an authentication path requires the caller to pass in both the left and right hash
at every level. This is both computationally wasteful, and a pain for the caller to use.
Furthermore it requires a boolean should_enforce, which is a concern that can be handled
at a higher level of abstraction.

The path passed in should be the index of the leaf in the MT, represented in ?-endian bits.
The trailing bit of the Path should be index % 2.
TODO: Recall which endianness is which

The authentication path should be given according to the same endianness.
, import prior diagram from Tendermint
We don ' t use the Zexe API for MTs . The Zexe API for an authentication path requires the caller to pass in both the left and right hash at every level . This is both computationally wasteful and a pain for the caller to use . Furthermore it requires a boolean should_enforce which is a concern that can be handled at a higher level of abstraction . The path passed in should be the index of the leaf in the MT represented in ? - endian bits . The trailing bit of the Path should be index % 2 . TODO : Recall which endianness is which The authentication path should be given according to the same endianness . import prior diagram from Tendermint
pub fn verify<CS: ConstraintSystem<F>>(&self, 
        mut cs: CS, 
        path: &[Boolean], 
        root: FG, 
        auth_path: &[FG], 
        leaf: &[FG]) -> Result<(), SynthesisError>
    {
        let leafHash = self.leafHasher.hash(&mut cs.ns(|| "leafhash"), leaf)?;
        let mut curHash = leafHash;
        // To traverse up a MT, we iterate over the path in reverse.
        let mut rev_path = path.to_vec();
        rev_path.reverse();
        let mut auth_path_rev = auth_path.to_vec();
        auth_path_rev.reverse();
        assert_eq!(auth_path_rev.len(), path.len());
        for i in (0..auth_path_rev.len()) {
            let mut cs_i = cs.ns(|| format!("MT layer {:?}", i));
            let bit = rev_path[i];
            // At any given bit, the bit being 0 indicates our currently hashed value is the left,
            // and the bit being 1 indicates our currently hashed value is on the right.
            // so we set left_hash = mux(bit, [curHash, authPathHash]), and similarly,
            // right_hash = mux(not bit, [curHash, authPathHash])
            // It is straight forward to generalize this to higher arity trees
            let curVec = vec![curHash.clone(), auth_path_rev[i].clone()];
            let left_hash = mux(&mut cs_i.ns(|| "left mux"), 
                &curVec, &[bit])?;
            let right_hash = mux(&mut cs_i.ns(|| "right mux"), 
                &curVec, &[bit.not()])?;
            curHash = self.nodeHasher.hash(&mut cs_i, left_hash, right_hash)?;
        }
        curHash.enforce_equal(&mut cs, &root)?;
        Ok(())
    }
pub fn verify < CS : ConstraintSystem < F > > ( & self , mut cs : CS , path : & [ Boolean ] , root : FG , auth_path : & [ FG ] , leaf : & [ FG ] ) -> Result < ( ) , SynthesisError > { let leafHash = self . leafHasher . hash ( & mut cs . ns ( | | " " ) , leaf ) ? ; let mut curHash = leafHash ; // To traverse up a MT, we iterate over the path in reverse. let mut rev_path = path . to_vec ( ) ; rev_path . reverse ( ) ; let mut auth_path_rev = auth_path . to_vec ( ) ; auth_path_rev . reverse ( ) ; assert_eq ! ( auth_path_rev len ( ) path len ( ) ) ; for i in ( 0 .. auth_path_rev . len ( ) ) { let mut cs_i = cs . ns ( | | format ! ( " " i ) ) ; let bit = rev_path [ i ] ; // At any given bit, the bit being 0 indicates our currently hashed value is the left, // and the bit being 1 indicates our currently hashed value is on the right. // so we set left_hash = mux(bit, [curHash, authPathHash]), and similarly, // right_hash = mux(not bit, [curHash, authPathHash]) // It is straight forward to generalize this to higher arity trees let curVec = vec ! [ curHash clone ( ) auth_path_rev [ i ] clone ( ) ] ; let left_hash = mux ( & mut cs_i . ns ( | | " " ) , & curVec , & [ bit ] ) ? ; let right_hash = mux ( & mut cs_i . ns ( | | " " ) , & curVec , & [ bit . not ( ) ] ) ? ; curHash = self . nodeHasher . hash ( & mut cs_i , left_hash , right_hash ) ? ; } curHash . enforce_equal ( & mut cs , & root ) ? ; Ok ( ( ) ) }
We don't use the Zexe API for MTs.
We don ' t use the Zexe API for MTs .
&self
cs
CS
path
&[Boolean]
root
FG
auth_path
&[FG]
leaf
&[FG]