mirror of https://github.com/zcash/halo2.git
Optimise location of Poseidon within Action circuit
- Move Poseidon into the right-hand advice columns. The Action circuit has 33 Sinsemilla invocations with 510-bit inputs (the 32 Merkle path hashes, and Commit^ivk). Poseidon fits within the row count of one of these invocations, so we can run it in parallel with these. - Share fixed columns between ECC and Poseidon chips. Poseidon requires four advice columns, while ECC incomplete addition requires six, so we could choose to configure them in parallel. However, we only use a single Poseidon invocation, and we have the rows to accomodate it serially with fixed-base scalar mul. Sharing the ECC chip's 8 Lagrange coefficient fixed columns instead reduces the proof size. - We position Poseidon in the right-most 6 fixed columns, anticipating a further optimisation to Sinsemilla that will occupy the left-most 2 fixed columns.
This commit is contained in:
parent
d80333799d
commit
5e6c8ae380
|
@ -203,16 +203,36 @@ impl plonk::Circuit<pallas::Base> for Circuit {
|
|||
meta.enable_equality((*advice).into());
|
||||
}
|
||||
|
||||
// Poseidon requires four advice columns, while ECC incomplete addition requires
|
||||
// six, so we could choose to configure them in parallel. However, we only use a
|
||||
// single Poseidon invocation, and we have the rows to accomodate it serially.
|
||||
// Instead, we reduce the proof size by sharing fixed columns between the ECC and
|
||||
// Poseidon chips.
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
|
||||
let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
|
||||
|
||||
// Configuration for curve point operations.
|
||||
// This uses 10 advice columns and spans the whole circuit.
|
||||
let ecc_config = EccChip::configure(meta, advices, table_idx);
|
||||
let ecc_config = EccChip::configure(meta, advices, table_idx, lagrange_coeffs);
|
||||
|
||||
// Configuration for the Poseidon hash.
|
||||
let poseidon_config = PoseidonChip::configure(
|
||||
meta,
|
||||
poseidon::OrchardNullifier,
|
||||
[advices[0], advices[1], advices[2]],
|
||||
advices[3],
|
||||
advices[5..8].try_into().unwrap(),
|
||||
advices[8],
|
||||
rc_a,
|
||||
rc_b,
|
||||
);
|
||||
|
||||
// Configuration for standard PLONK (addition and multiplication).
|
||||
|
|
|
@ -433,11 +433,21 @@ mod tests {
|
|||
meta.advice_column(),
|
||||
];
|
||||
let lookup_table = meta.fixed_column();
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
// Shared fixed column for loading constants
|
||||
let constants = meta.fixed_column();
|
||||
meta.enable_constant(constants);
|
||||
|
||||
EccChip::configure(meta, advices, lookup_table)
|
||||
EccChip::configure(meta, advices, lookup_table, lagrange_coeffs)
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
|
|
|
@ -153,6 +153,7 @@ impl EccChip {
|
|||
meta: &mut ConstraintSystem<pallas::Base>,
|
||||
advices: [Column<Advice>; 10],
|
||||
lookup_table: Column<Fixed>,
|
||||
lagrange_coeffs: [Column<Fixed>; 8],
|
||||
) -> <Self as Chip<pallas::Base>>::Config {
|
||||
// The following columns need to be equality-enabled for their use in sub-configs:
|
||||
//
|
||||
|
@ -193,16 +194,7 @@ impl EccChip {
|
|||
|
||||
let config = EccConfig {
|
||||
advices,
|
||||
lagrange_coeffs: [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
],
|
||||
lagrange_coeffs,
|
||||
fixed_z: meta.fixed_column(),
|
||||
q_add_incomplete: meta.selector(),
|
||||
q_add: meta.selector(),
|
||||
|
|
|
@ -405,12 +405,22 @@ pub mod tests {
|
|||
meta.advice_column(),
|
||||
];
|
||||
let lookup_table = meta.fixed_column();
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
// Shared fixed column for loading constants
|
||||
let constants = meta.fixed_column();
|
||||
meta.enable_constant(constants);
|
||||
|
||||
EccChip::configure(meta, advices, lookup_table)
|
||||
EccChip::configure(meta, advices, lookup_table, lagrange_coeffs)
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
|
|
|
@ -53,6 +53,8 @@ impl<F: FieldExt> Pow5T3Chip<F> {
|
|||
spec: S,
|
||||
state: [Column<Advice>; WIDTH],
|
||||
partial_sbox: Column<Advice>,
|
||||
rc_a: [Column<Fixed>; WIDTH],
|
||||
rc_b: [Column<Fixed>; WIDTH],
|
||||
) -> Pow5T3Config<F> {
|
||||
// Generate constants for the Poseidon permutation.
|
||||
// This gadget requires R_F and R_P to be even.
|
||||
|
@ -62,17 +64,6 @@ impl<F: FieldExt> Pow5T3Chip<F> {
|
|||
let half_partial_rounds = S::partial_rounds() / 2;
|
||||
let (round_constants, m_reg, m_inv) = spec.constants();
|
||||
|
||||
let rc_a = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
let rc_b = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
// This allows state words to be initialized (by constraining them equal to fixed
|
||||
// values), and used in a permutation from an arbitrary region. rc_a is used in
|
||||
// every permutation round, while rc_b is empty in the initial and final full
|
||||
|
@ -645,7 +636,18 @@ mod tests {
|
|||
];
|
||||
let partial_sbox = meta.advice_column();
|
||||
|
||||
Pow5T3Chip::configure(meta, OrchardNullifier, state, partial_sbox)
|
||||
let rc_a = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
let rc_b = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
Pow5T3Chip::configure(meta, OrchardNullifier, state, partial_sbox, rc_a, rc_b)
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
|
@ -741,7 +743,18 @@ mod tests {
|
|||
];
|
||||
let partial_sbox = meta.advice_column();
|
||||
|
||||
Pow5T3Chip::configure(meta, OrchardNullifier, state, partial_sbox)
|
||||
let rc_a = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
let rc_b = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
Pow5T3Chip::configure(meta, OrchardNullifier, state, partial_sbox, rc_a, rc_b)
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
|
|
|
@ -459,11 +459,21 @@ mod tests {
|
|||
meta.enable_constant(constants);
|
||||
|
||||
let table_idx = meta.fixed_column();
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
// Fixed columns for the Sinsemilla generator lookup table
|
||||
let lookup = (table_idx, meta.fixed_column(), meta.fixed_column());
|
||||
|
||||
let ecc_config = EccChip::configure(meta, advices, table_idx);
|
||||
let ecc_config = EccChip::configure(meta, advices, table_idx, lagrange_coeffs);
|
||||
|
||||
let config1 = SinsemillaChip::configure(meta, advices[..5].try_into().unwrap(), lookup);
|
||||
let config2 = SinsemillaChip::configure(meta, advices[5..].try_into().unwrap(), lookup);
|
||||
|
|
|
@ -685,13 +685,23 @@ mod tests {
|
|||
|
||||
let table_idx = meta.fixed_column();
|
||||
let lookup = (table_idx, meta.fixed_column(), meta.fixed_column());
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
let sinsemilla_config =
|
||||
SinsemillaChip::configure(meta, advices[..5].try_into().unwrap(), lookup);
|
||||
let commit_ivk_config =
|
||||
CommitIvkConfig::configure(meta, advices, sinsemilla_config);
|
||||
|
||||
let ecc_config = EccChip::configure(meta, advices, table_idx);
|
||||
let ecc_config = EccChip::configure(meta, advices, table_idx, lagrange_coeffs);
|
||||
|
||||
(commit_ivk_config, ecc_config)
|
||||
}
|
||||
|
|
|
@ -1347,12 +1347,23 @@ mod tests {
|
|||
|
||||
let table_idx = meta.fixed_column();
|
||||
let lookup = (table_idx, meta.fixed_column(), meta.fixed_column());
|
||||
let lagrange_coeffs = [
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
let sinsemilla_config =
|
||||
SinsemillaChip::configure(meta, advices[..5].try_into().unwrap(), lookup);
|
||||
let note_commit_config =
|
||||
NoteCommitConfig::configure(meta, advices, sinsemilla_config);
|
||||
|
||||
let ecc_config = EccChip::configure(meta, advices, table_idx);
|
||||
let ecc_config = EccChip::configure(meta, advices, table_idx, lagrange_coeffs);
|
||||
|
||||
(note_commit_config, ecc_config)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue