diff --git a/src/circuit/gadget/sinsemilla/merkle/chip.rs b/src/circuit/gadget/sinsemilla/merkle/chip.rs index a0ce10e9..b67f197b 100644 --- a/src/circuit/gadget/sinsemilla/merkle/chip.rs +++ b/src/circuit/gadget/sinsemilla/merkle/chip.rs @@ -71,13 +71,13 @@ impl MerkleChip { // This fixed column serves two purposes: // - Fixing the value of l* for rows in which a Merkle path layer // is decomposed. - // - Disabling the entire decomposition gate (when set to zero) + // - Disabling the entire decomposition gate when set to zero // (i.e. replacing a Selector). let l_plus_1 = meta.fixed_column(); // Check that pieces have been decomposed correctly for Sinsemilla hash. - // + // // // a = a_0||a_1 = l_star || (bits 0..=239 of left) // b = b_0||b_1||b_2 @@ -87,6 +87,13 @@ impl MerkleChip { // The message pieces `a`, `b`, `c` are constrained by Sinsemilla to be // 250 bits, 20 bits, and 250 bits respectively. // + /* + The pieces and subpieces are arranged in the following configuration: + | A_0 | A_1 | A_2 | A_3 | A_4 | l_plus_1 | + ---------------------------------------------------- + | a | b | c | left | right | l + 1 | + | z1_a | z1_b | b_1 | b_2 | | | + */ meta.create_gate("Decomposition check", |meta| { let l_plus_1_whole = meta.query_fixed(l_plus_1, Rotation::cur()); @@ -115,6 +122,8 @@ impl MerkleChip { // b = b_0||b_1||b_2 // = (bits 240..=249 of left) || (bits 250..=254 of left) || (bits 0..=4 of right) + // The Orchard specification allows this representation to be non-canonical. + // // // z_1 of SinsemillaHash(b) = b_1 + 2^5 b_2 // => b_0 = b - (z1_b * 2^10) @@ -132,18 +141,23 @@ impl MerkleChip { let left_check = { let reconstructed = { let two_pow_240 = pallas::Base::from_u128(1 << 120).square(); - let b0_shifted = b_0 * two_pow_240; - let b1_shifted = b_1 * two_pow_240 * two_pow_10; - a_1 + b0_shifted + b1_shifted + a_1 + (b_0 + b_1 * two_pow_10) * two_pow_240 }; reconstructed - left_node }; // Check that right = b_2 (5 bits) || c (250 bits) + // The Orchard specification allows this representation to be non-canonical. + // let right_check = b_2 + c_whole * two_pow_5 - right_node; - array::IntoIter::new([l_star_check, left_check, right_check, b1_b2_check]) - .map(move |poly| l_plus_1_whole.clone() * poly) + array::IntoIter::new([ + ("l_star_check", l_star_check), + ("left_check", left_check), + ("right_check", right_check), + ("b1_b2_check", b1_b2_check), + ]) + .map(move |(name, poly)| (name, l_plus_1_whole.clone() * poly)) }); MerkleConfig { @@ -169,13 +183,14 @@ impl MerkleInstructions, Q: pallas::Affine, - l_star: usize, - left: >::Var, - right: >::Var, - ) -> Result<>::Var, Error> { + // l = MERKLE_DEPTH_ORCHARD - layer - 1 + l: usize, + left: Self::Var, + right: Self::Var, + ) -> Result { let config = self.config().clone(); - // + // // We need to hash `l_star || left || right`, where `l_star` is a 10-bit value. // We allow `left` and `right` to be non-canonical 255-bit encodings. // @@ -184,11 +199,11 @@ impl MerkleInstructions(l_star as u64); + let l_star = i2lebsp::<10>(l as u64); let left: Vec<_> = left .to_le_bits() .iter()