merkle: Replace l_plus_1 fixed column with q_decompose selector.

Previously, l_plus_1 was a non-binary fixed column, used to
1. provide the value of l + 1; and
2. toggle the decomposition gate.

Now, the value is copied in from the global constants column, and
the toggle is handled by a binary q_decompose selector.
This commit is contained in:
therealyingtong 2021-07-24 00:02:48 +08:00
parent f532ecec10
commit 29f185014f
3 changed files with 23 additions and 26 deletions

View File

@ -62,5 +62,5 @@ name = "small"
harness = false
[patch.crates-io]
halo2 = { git = "https://github.com/zcash/halo2.git", rev = "62f088e2f249dfce2c3bcab7321cba0d99697af9" }
halo2 = { git = "https://github.com/zcash/halo2.git", rev = "92645b6ee9a2a91649bf22caebe5b1017ff67198" }
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "cc533a9da4f6a7209a7be05f82b12a03969152c9" }

View File

@ -500,7 +500,7 @@ pub mod tests {
},
VerifyFailure::Permutation {
column: (Any::Fixed, 9).into(),
row: 2
row: 0
},
VerifyFailure::Permutation {
column: (Any::Advice, 4).into(),

View File

@ -1,6 +1,6 @@
use halo2::{
circuit::{Chip, Layouter},
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Fixed},
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector},
poly::Rotation,
};
use pasta_curves::{arithmetic::FieldExt, pallas};
@ -25,7 +25,7 @@ use std::array;
#[derive(Clone, Debug)]
pub struct MerkleConfig {
advices: [Column<Advice>; 5],
l_plus_1: Column<Fixed>,
q_decompose: Selector,
pub(super) cond_swap_config: CondSwapConfig,
pub(super) sinsemilla_config: SinsemillaConfig,
}
@ -57,13 +57,8 @@ impl MerkleChip {
let advices = sinsemilla_config.advices();
let cond_swap_config = CondSwapChip::configure(meta, advices);
// 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
// (i.e. replacing a Selector).
let l_plus_1 = meta.fixed_column();
// This selector enables the decomposition gate.
let q_decompose = meta.selector();
// Check that pieces have been decomposed correctly for Sinsemilla hash.
// <https://zips.z.cash/protocol/protocol.pdf#orchardmerklecrh>
@ -78,13 +73,14 @@ impl MerkleChip {
//
/*
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 | | |
| A_0 | A_1 | A_2 | A_3 | A_4 | q_decompose |
-------------------------------------------------------
| a | b | c | left | right | 1 |
| z1_a | z1_b | b_1 | b_2 | l + 1 | |
*/
meta.create_gate("Decomposition check", |meta| {
let l_plus_1_whole = meta.query_fixed(l_plus_1, Rotation::cur());
let q_decompose = meta.query_selector(q_decompose);
let l_plus_1_whole = meta.query_advice(advices[4], Rotation::next());
let two_pow_5 = pallas::Base::from_u64(1 << 5);
let two_pow_10 = two_pow_5.square();
@ -146,12 +142,12 @@ impl MerkleChip {
("right_check", right_check),
("b1_b2_check", b1_b2_check),
])
.map(move |(name, poly)| (name, l_plus_1_whole.clone() * poly))
.map(move |(name, poly)| (name, q_decompose.clone() * poly))
});
MerkleConfig {
advices,
l_plus_1,
q_decompose,
cond_swap_config,
sinsemilla_config,
}
@ -270,10 +266,10 @@ impl MerkleInstructions<pallas::Affine, MERKLE_DEPTH_ORCHARD, { sinsemilla::K },
// Check that the pieces have been decomposed properly.
/*
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 | | |
| A_0 | A_1 | A_2 | A_3 | A_4 | q_decompose |
-------------------------------------------------------
| a | b | c | left | right | 1 |
| z1_a | z1_b | b_1 | b_2 | l + 1 | |
*/
{
layouter.assign_region(
@ -283,11 +279,12 @@ impl MerkleInstructions<pallas::Affine, MERKLE_DEPTH_ORCHARD, { sinsemilla::K },
// Recall that l = MERKLE_DEPTH_ORCHARD - layer - 1.
// The layer with 2^n nodes is called "layer n".
let l_plus_1 = (l as u64) + 1;
region.assign_fixed(
config.q_decompose.enable(&mut region, 0)?;
region.assign_advice_from_constant(
|| format!("l_plus_1 {}", l_plus_1),
config.l_plus_1,
0,
|| Ok(pallas::Base::from_u64(l_plus_1)),
config.advices[4],
1,
pallas::Base::from_u64(l_plus_1),
)?;
// Offset 0