diff --git a/plonky2/src/lib.rs b/plonky2/src/lib.rs index b4a4b6afc6..c2913023f5 100644 --- a/plonky2/src/lib.rs +++ b/plonky2/src/lib.rs @@ -12,7 +12,9 @@ pub mod gadgets; pub mod gates; pub mod hash; pub mod iop; -pub mod lookup_test; pub mod plonk; pub mod recursion; pub mod util; + +#[cfg(test)] +mod lookup_test; diff --git a/plonky2/src/lookup_test.rs b/plonky2/src/lookup_test.rs index 165d5dfecc..bca90d59e3 100644 --- a/plonky2/src/lookup_test.rs +++ b/plonky2/src/lookup_test.rs @@ -1,523 +1,477 @@ -#[cfg(test)] -mod tests { - static LOGGER_INITIALIZED: Once = Once::new(); - - use alloc::sync::Arc; - use std::sync::Once; - - use itertools::Itertools; - use log::{Level, LevelFilter}; - - use crate::gadgets::lookup::{OTHER_TABLE, SMALLER_TABLE, TIP5_TABLE}; - use crate::gates::lookup_table::LookupTable; - use crate::gates::noop::NoopGate; - use crate::plonk::prover::prove; - use crate::util::timing::TimingTree; - - #[test] - fn test_no_lookup() -> anyhow::Result<()> { - LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); - use crate::iop::witness::PartialWitness; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - builder.add_gate(NoopGate, vec![]); - let pw = PartialWitness::new(); - - let data = builder.build::(); - let mut timing = TimingTree::new("prove first", Level::Debug); - let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; - timing.print(); - data.verify(proof)?; - - Ok(()) - } +static LOGGER_INITIALIZED: Once = Once::new(); + +use alloc::sync::Arc; +use std::sync::Once; + +use itertools::Itertools; +use log::{Level, LevelFilter}; + +use crate::gadgets::lookup::{OTHER_TABLE, SMALLER_TABLE, TIP5_TABLE}; +use crate::gates::lookup_table::LookupTable; +use crate::gates::noop::NoopGate; +use crate::plonk::prover::prove; +use crate::util::timing::TimingTree; + +#[test] +fn test_no_lookup() -> anyhow::Result<()> { + LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); + use crate::iop::witness::PartialWitness; + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + builder.add_gate(NoopGate, vec![]); + let pw = PartialWitness::new(); + + let data = builder.build::(); + let mut timing = TimingTree::new("prove first", Level::Debug); + let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; + timing.print(); + data.verify(proof)?; + + Ok(()) +} - #[should_panic] - #[test] - fn test_lookup_table_not_used() { - LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; +#[should_panic] +#[test] +fn test_lookup_table_not_used() { + LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); - let tip5_table = TIP5_TABLE.to_vec(); - let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); - builder.add_lookup_table_from_pairs(table); + let tip5_table = TIP5_TABLE.to_vec(); + let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); + builder.add_lookup_table_from_pairs(table); - builder.build::(); - } + builder.build::(); +} - #[should_panic] - #[test] - fn test_lookup_without_table() { - LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; +#[should_panic] +#[test] +fn test_lookup_without_table() { + LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); - let dummy = builder.add_virtual_target(); - builder.add_lookup_from_index(dummy, 0); + let dummy = builder.add_virtual_target(); + builder.add_lookup_from_index(dummy, 0); - builder.build::(); - } + builder.build::(); +} - // Tests two lookups in one lookup table. - #[test] - fn test_one_lookup() -> anyhow::Result<()> { - use crate::field::types::Field; - use crate::iop::witness::{PartialWitness, WitnessWrite}; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - - LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); - let tip5_table = TIP5_TABLE.to_vec(); - let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - let initial_a = builder.add_virtual_target(); - let initial_b = builder.add_virtual_target(); - - let look_val_a = 1; - let look_val_b = 2; - - let out_a = table[look_val_a].1; - let out_b = table[look_val_b].1; - let table_index = builder.add_lookup_table_from_pairs(table); - let output_a = builder.add_lookup_from_index(initial_a, table_index); - - let output_b = builder.add_lookup_from_index(initial_b, table_index); - - builder.register_public_input(initial_a); - builder.register_public_input(initial_b); - builder.register_public_input(output_a); - builder.register_public_input(output_b); - - let mut pw = PartialWitness::new(); - - pw.set_target(initial_a, F::from_canonical_usize(look_val_a)); - pw.set_target(initial_b, F::from_canonical_usize(look_val_b)); - - let data = builder.build::(); - let mut timing = TimingTree::new("prove one lookup", Level::Debug); - let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; - timing.print(); - data.verify(proof.clone())?; - - assert!( - proof.public_inputs[2] == F::from_canonical_u16(out_a), - "First lookup, at index {} in the Tip5 table gives an incorrect output.", - proof.public_inputs[0] - ); - assert!( - proof.public_inputs[3] == F::from_canonical_u16(out_b), - "Second lookup, at index {} in the Tip5 table gives an incorrect output.", - proof.public_inputs[1] - ); - - Ok(()) - } +// Tests two lookups in one lookup table. +#[test] +fn test_one_lookup() -> anyhow::Result<()> { + use crate::field::types::Field; + use crate::iop::witness::{PartialWitness, WitnessWrite}; + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + + LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); + let tip5_table = TIP5_TABLE.to_vec(); + let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + + let initial_a = builder.add_virtual_target(); + let initial_b = builder.add_virtual_target(); + + let look_val_a = 1; + let look_val_b = 2; + + let out_a = table[look_val_a].1; + let out_b = table[look_val_b].1; + let table_index = builder.add_lookup_table_from_pairs(table); + let output_a = builder.add_lookup_from_index(initial_a, table_index); + + let output_b = builder.add_lookup_from_index(initial_b, table_index); + + builder.register_public_input(initial_a); + builder.register_public_input(initial_b); + builder.register_public_input(output_a); + builder.register_public_input(output_b); + + let mut pw = PartialWitness::new(); + + pw.set_target(initial_a, F::from_canonical_usize(look_val_a)); + pw.set_target(initial_b, F::from_canonical_usize(look_val_b)); + + let data = builder.build::(); + let mut timing = TimingTree::new("prove one lookup", Level::Debug); + let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; + timing.print(); + data.verify(proof.clone())?; + + assert!( + proof.public_inputs[2] == F::from_canonical_u16(out_a), + "First lookup, at index {} in the Tip5 table gives an incorrect output.", + proof.public_inputs[0] + ); + assert!( + proof.public_inputs[3] == F::from_canonical_u16(out_b), + "Second lookup, at index {} in the Tip5 table gives an incorrect output.", + proof.public_inputs[1] + ); + + Ok(()) +} - // Tests one lookup in two different lookup tables. - #[test] - pub fn test_two_luts() -> anyhow::Result<()> { - use crate::field::types::Field; - use crate::iop::witness::{PartialWitness, WitnessWrite}; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - - LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - let initial_a = builder.add_virtual_target(); - let initial_b = builder.add_virtual_target(); - - let look_val_a = 1; - let look_val_b = 2; - - let tip5_table = TIP5_TABLE.to_vec(); - - let first_out = tip5_table[look_val_a]; - let second_out = tip5_table[look_val_b]; - - let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); - - let other_table = OTHER_TABLE.to_vec(); - - let table_index = builder.add_lookup_table_from_pairs(table); - let output_a = builder.add_lookup_from_index(initial_a, table_index); - - let output_b = builder.add_lookup_from_index(initial_b, table_index); - let sum = builder.add(output_a, output_b); - - let s = first_out + second_out; - let final_out = other_table[s as usize]; - - let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect()); - let table2_index = builder.add_lookup_table_from_pairs(table2); - - let output_final = builder.add_lookup_from_index(sum, table2_index); - - builder.register_public_input(initial_a); - builder.register_public_input(initial_b); - builder.register_public_input(sum); - builder.register_public_input(output_a); - builder.register_public_input(output_b); - builder.register_public_input(output_final); - - let mut pw = PartialWitness::new(); - pw.set_target(initial_a, F::from_canonical_usize(look_val_a)); - pw.set_target(initial_b, F::from_canonical_usize(look_val_b)); - let data = builder.build::(); - let mut timing = TimingTree::new("prove two_luts", Level::Debug); - let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; - data.verify(proof.clone())?; - timing.print(); - - assert!( - proof.public_inputs[3] == F::from_canonical_u16(first_out), - "First lookup, at index {} in the Tip5 table gives an incorrect output.", - proof.public_inputs[0] - ); - assert!( - proof.public_inputs[4] == F::from_canonical_u16(second_out), - "Second lookup, at index {} in the Tip5 table gives an incorrect output.", - proof.public_inputs[1] - ); - assert!( - proof.public_inputs[2] == F::from_canonical_u16(s), - "Sum between the first two LUT outputs is incorrect." - ); - assert!( - proof.public_inputs[5] == F::from_canonical_u16(final_out), - "Output of the second LUT at index {} is incorrect.", - s - ); - - Ok(()) - } +// Tests one lookup in two different lookup tables. +#[test] +pub fn test_two_luts() -> anyhow::Result<()> { + use crate::field::types::Field; + use crate::iop::witness::{PartialWitness, WitnessWrite}; + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + + LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + + let initial_a = builder.add_virtual_target(); + let initial_b = builder.add_virtual_target(); + + let look_val_a = 1; + let look_val_b = 2; + + let tip5_table = TIP5_TABLE.to_vec(); + + let first_out = tip5_table[look_val_a]; + let second_out = tip5_table[look_val_b]; + + let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); + + let other_table = OTHER_TABLE.to_vec(); + + let table_index = builder.add_lookup_table_from_pairs(table); + let output_a = builder.add_lookup_from_index(initial_a, table_index); + + let output_b = builder.add_lookup_from_index(initial_b, table_index); + let sum = builder.add(output_a, output_b); + + let s = first_out + second_out; + let final_out = other_table[s as usize]; + + let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect()); + let table2_index = builder.add_lookup_table_from_pairs(table2); + + let output_final = builder.add_lookup_from_index(sum, table2_index); + + builder.register_public_input(initial_a); + builder.register_public_input(initial_b); + builder.register_public_input(sum); + builder.register_public_input(output_a); + builder.register_public_input(output_b); + builder.register_public_input(output_final); + + let mut pw = PartialWitness::new(); + pw.set_target(initial_a, F::from_canonical_usize(look_val_a)); + pw.set_target(initial_b, F::from_canonical_usize(look_val_b)); + let data = builder.build::(); + let mut timing = TimingTree::new("prove two_luts", Level::Debug); + let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; + data.verify(proof.clone())?; + timing.print(); + + assert!( + proof.public_inputs[3] == F::from_canonical_u16(first_out), + "First lookup, at index {} in the Tip5 table gives an incorrect output.", + proof.public_inputs[0] + ); + assert!( + proof.public_inputs[4] == F::from_canonical_u16(second_out), + "Second lookup, at index {} in the Tip5 table gives an incorrect output.", + proof.public_inputs[1] + ); + assert!( + proof.public_inputs[2] == F::from_canonical_u16(s), + "Sum between the first two LUT outputs is incorrect." + ); + assert!( + proof.public_inputs[5] == F::from_canonical_u16(final_out), + "Output of the second LUT at index {} is incorrect.", + s + ); + + Ok(()) +} - #[test] - pub fn test_different_inputs() -> anyhow::Result<()> { - use crate::field::types::Field; - use crate::iop::witness::{PartialWitness, WitnessWrite}; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - let initial_a = builder.add_virtual_target(); - let initial_b = builder.add_virtual_target(); - - let init_a = 1; - let init_b = 2; - - let tab: Vec = SMALLER_TABLE.to_vec(); - let table: LookupTable = Arc::new((2..10).zip_eq(tab).collect()); - - let other_table = OTHER_TABLE.to_vec(); - - let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect()); - let small_index = builder.add_lookup_table_from_pairs(table.clone()); - let output_a = builder.add_lookup_from_index(initial_a, small_index); - - let output_b = builder.add_lookup_from_index(initial_b, small_index); - let sum = builder.add(output_a, output_b); - - let other_index = builder.add_lookup_table_from_pairs(table2.clone()); - let output_final = builder.add_lookup_from_index(sum, other_index); - - builder.register_public_input(initial_a); - builder.register_public_input(initial_b); - builder.register_public_input(sum); - builder.register_public_input(output_a); - builder.register_public_input(output_b); - builder.register_public_input(output_final); - - let mut pw = PartialWitness::new(); - - let look_val_a = table[init_a].0; - let look_val_b = table[init_b].0; - pw.set_target(initial_a, F::from_canonical_u16(look_val_a)); - pw.set_target(initial_b, F::from_canonical_u16(look_val_b)); - - let data = builder.build::(); - let mut timing = TimingTree::new("prove different lookups", Level::Debug); - let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; - data.verify(proof.clone())?; - timing.print(); - - let out_a = table[init_a].1; - let out_b = table[init_b].1; - let s = out_a + out_b; - let out_final = table2[s as usize].1; - - assert!( - proof.public_inputs[3] == F::from_canonical_u16(out_a), - "First lookup, at index {} in the smaller LUT gives an incorrect output.", - proof.public_inputs[0] - ); - assert!( - proof.public_inputs[4] == F::from_canonical_u16(out_b), - "Second lookup, at index {} in the smaller LUT gives an incorrect output.", - proof.public_inputs[1] - ); - assert!( - proof.public_inputs[2] == F::from_canonical_u16(s), - "Sum between the first two LUT outputs is incorrect." - ); - assert!( - proof.public_inputs[5] == F::from_canonical_u16(out_final), - "Output of the second LUT at index {} is incorrect.", - s - ); - - Ok(()) - } +#[test] +pub fn test_different_inputs() -> anyhow::Result<()> { + use crate::field::types::Field; + use crate::iop::witness::{PartialWitness, WitnessWrite}; + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + + let initial_a = builder.add_virtual_target(); + let initial_b = builder.add_virtual_target(); + + let init_a = 1; + let init_b = 2; + + let tab: Vec = SMALLER_TABLE.to_vec(); + let table: LookupTable = Arc::new((2..10).zip_eq(tab).collect()); + + let other_table = OTHER_TABLE.to_vec(); + + let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect()); + let small_index = builder.add_lookup_table_from_pairs(table.clone()); + let output_a = builder.add_lookup_from_index(initial_a, small_index); + + let output_b = builder.add_lookup_from_index(initial_b, small_index); + let sum = builder.add(output_a, output_b); + + let other_index = builder.add_lookup_table_from_pairs(table2.clone()); + let output_final = builder.add_lookup_from_index(sum, other_index); + + builder.register_public_input(initial_a); + builder.register_public_input(initial_b); + builder.register_public_input(sum); + builder.register_public_input(output_a); + builder.register_public_input(output_b); + builder.register_public_input(output_final); + + let mut pw = PartialWitness::new(); + + let look_val_a = table[init_a].0; + let look_val_b = table[init_b].0; + pw.set_target(initial_a, F::from_canonical_u16(look_val_a)); + pw.set_target(initial_b, F::from_canonical_u16(look_val_b)); + + let data = builder.build::(); + let mut timing = TimingTree::new("prove different lookups", Level::Debug); + let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; + data.verify(proof.clone())?; + timing.print(); + + let out_a = table[init_a].1; + let out_b = table[init_b].1; + let s = out_a + out_b; + let out_final = table2[s as usize].1; + + assert!( + proof.public_inputs[3] == F::from_canonical_u16(out_a), + "First lookup, at index {} in the smaller LUT gives an incorrect output.", + proof.public_inputs[0] + ); + assert!( + proof.public_inputs[4] == F::from_canonical_u16(out_b), + "Second lookup, at index {} in the smaller LUT gives an incorrect output.", + proof.public_inputs[1] + ); + assert!( + proof.public_inputs[2] == F::from_canonical_u16(s), + "Sum between the first two LUT outputs is incorrect." + ); + assert!( + proof.public_inputs[5] == F::from_canonical_u16(out_final), + "Output of the second LUT at index {} is incorrect.", + s + ); + + Ok(()) +} + +// This test looks up over 514 values for one LookupTableGate, which means that several LookupGates are created. +#[test] +pub fn test_many_lookups() -> anyhow::Result<()> { + use crate::field::types::Field; + use crate::iop::witness::{PartialWitness, WitnessWrite}; + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - // This test looks up over 514 values for one LookupTableGate, which means that several LookupGates are created. - #[test] - pub fn test_many_lookups() -> anyhow::Result<()> { - use crate::field::types::Field; - use crate::iop::witness::{PartialWitness, WitnessWrite}; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - let initial_a = builder.add_virtual_target(); - let initial_b = builder.add_virtual_target(); - - let look_val_a = 1; - let look_val_b = 2; - - let tip5_table = TIP5_TABLE.to_vec(); - let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); - - let out_a = table[look_val_a].1; - let out_b = table[look_val_b].1; - - let tip5_index = builder.add_lookup_table_from_pairs(table); - let output_a = builder.add_lookup_from_index(initial_a, tip5_index); - - let output_b = builder.add_lookup_from_index(initial_b, tip5_index); - let sum = builder.add(output_a, output_b); - - for _ in 0..514 { - builder.add_lookup_from_index(initial_a, tip5_index); - } - - let other_table = OTHER_TABLE.to_vec(); - - let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect()); - - let s = out_a + out_b; - let out_final = table2[s as usize].1; - - let other_index = builder.add_lookup_table_from_pairs(table2); - let output_final = builder.add_lookup_from_index(sum, other_index); - - builder.register_public_input(initial_a); - builder.register_public_input(initial_b); - builder.register_public_input(sum); - builder.register_public_input(output_a); - builder.register_public_input(output_b); - builder.register_public_input(output_final); - - let mut pw = PartialWitness::new(); - - pw.set_target(initial_a, F::from_canonical_usize(look_val_a)); - pw.set_target(initial_b, F::from_canonical_usize(look_val_b)); - - let data = builder.build::(); - let mut timing = TimingTree::new("prove different lookups", Level::Debug); - let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; - - data.verify(proof.clone())?; - timing.print(); - - assert!( - proof.public_inputs[3] == F::from_canonical_u16(out_a), - "First lookup, at index {} in the Tip5 table gives an incorrect output.", - proof.public_inputs[0] - ); - assert!( - proof.public_inputs[4] == F::from_canonical_u16(out_b), - "Second lookup, at index {} in the Tip5 table gives an incorrect output.", - proof.public_inputs[1] - ); - assert!( - proof.public_inputs[2] == F::from_canonical_u16(s), - "Sum between the first two LUT outputs is incorrect." - ); - assert!( - proof.public_inputs[5] == F::from_canonical_u16(out_final), - "Output of the second LUT at index {} is incorrect.", - s - ); - - Ok(()) + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + + let initial_a = builder.add_virtual_target(); + let initial_b = builder.add_virtual_target(); + + let look_val_a = 1; + let look_val_b = 2; + + let tip5_table = TIP5_TABLE.to_vec(); + let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); + + let out_a = table[look_val_a].1; + let out_b = table[look_val_b].1; + + let tip5_index = builder.add_lookup_table_from_pairs(table); + let output_a = builder.add_lookup_from_index(initial_a, tip5_index); + + let output_b = builder.add_lookup_from_index(initial_b, tip5_index); + let sum = builder.add(output_a, output_b); + + for _ in 0..514 { + builder.add_lookup_from_index(initial_a, tip5_index); } - // Tests whether, when adding the same LUT to the circuit, the circuit only adds one copy, with the same index. - #[test] - pub fn test_same_luts() -> anyhow::Result<()> { - use crate::field::types::Field; - use crate::iop::witness::{PartialWitness, WitnessWrite}; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + let other_table = OTHER_TABLE.to_vec(); + + let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect()); + + let s = out_a + out_b; + let out_final = table2[s as usize].1; + + let other_index = builder.add_lookup_table_from_pairs(table2); + let output_final = builder.add_lookup_from_index(sum, other_index); + + builder.register_public_input(initial_a); + builder.register_public_input(initial_b); + builder.register_public_input(sum); + builder.register_public_input(output_a); + builder.register_public_input(output_b); + builder.register_public_input(output_final); + + let mut pw = PartialWitness::new(); + + pw.set_target(initial_a, F::from_canonical_usize(look_val_a)); + pw.set_target(initial_b, F::from_canonical_usize(look_val_b)); + + let data = builder.build::(); + let mut timing = TimingTree::new("prove different lookups", Level::Debug); + let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; + + data.verify(proof.clone())?; + timing.print(); + + assert!( + proof.public_inputs[3] == F::from_canonical_u16(out_a), + "First lookup, at index {} in the Tip5 table gives an incorrect output.", + proof.public_inputs[0] + ); + assert!( + proof.public_inputs[4] == F::from_canonical_u16(out_b), + "Second lookup, at index {} in the Tip5 table gives an incorrect output.", + proof.public_inputs[1] + ); + assert!( + proof.public_inputs[2] == F::from_canonical_u16(s), + "Sum between the first two LUT outputs is incorrect." + ); + assert!( + proof.public_inputs[5] == F::from_canonical_u16(out_final), + "Output of the second LUT at index {} is incorrect.", + s + ); + + Ok(()) +} - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; +// Tests whether, when adding the same LUT to the circuit, the circuit only adds one copy, with the same index. +#[test] +pub fn test_same_luts() -> anyhow::Result<()> { + use crate::field::types::Field; + use crate::iop::witness::{PartialWitness, WitnessWrite}; + use crate::plonk::circuit_builder::CircuitBuilder; + use crate::plonk::circuit_data::CircuitConfig; + use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; - let initial_a = builder.add_virtual_target(); - let initial_b = builder.add_virtual_target(); + LOGGER_INITIALIZED.call_once(|| init_logger().unwrap()); + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); - let look_val_a = 1; - let look_val_b = 2; + let initial_a = builder.add_virtual_target(); + let initial_b = builder.add_virtual_target(); - let tip5_table = TIP5_TABLE.to_vec(); - let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); + let look_val_a = 1; + let look_val_b = 2; - let table_index = builder.add_lookup_table_from_pairs(table.clone()); - let output_a = builder.add_lookup_from_index(initial_a, table_index); + let tip5_table = TIP5_TABLE.to_vec(); + let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect()); - let output_b = builder.add_lookup_from_index(initial_b, table_index); - let sum = builder.add(output_a, output_b); + let table_index = builder.add_lookup_table_from_pairs(table.clone()); + let output_a = builder.add_lookup_from_index(initial_a, table_index); - let table2_index = builder.add_lookup_table_from_pairs(table); + let output_b = builder.add_lookup_from_index(initial_b, table_index); + let sum = builder.add(output_a, output_b); - let output_final = builder.add_lookup_from_index(sum, table2_index); + let table2_index = builder.add_lookup_table_from_pairs(table); - builder.register_public_input(initial_a); - builder.register_public_input(initial_b); - builder.register_public_input(sum); - builder.register_public_input(output_a); - builder.register_public_input(output_b); - builder.register_public_input(output_final); + let output_final = builder.add_lookup_from_index(sum, table2_index); - let luts_length = builder.get_luts_length(); + builder.register_public_input(initial_a); + builder.register_public_input(initial_b); + builder.register_public_input(sum); + builder.register_public_input(output_a); + builder.register_public_input(output_b); + builder.register_public_input(output_final); - assert!( - luts_length == 1, - "There are {} LUTs when there should be only one", - luts_length - ); + let luts_length = builder.get_luts_length(); - let mut pw = PartialWitness::new(); + assert!( + luts_length == 1, + "There are {} LUTs when there should be only one", + luts_length + ); - pw.set_target(initial_a, F::from_canonical_usize(look_val_a)); - pw.set_target(initial_b, F::from_canonical_usize(look_val_b)); + let mut pw = PartialWitness::new(); - let data = builder.build::(); - let mut timing = TimingTree::new("prove two_luts", Level::Debug); - let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; - data.verify(proof)?; - timing.print(); + pw.set_target(initial_a, F::from_canonical_usize(look_val_a)); + pw.set_target(initial_b, F::from_canonical_usize(look_val_b)); - Ok(()) - } + let data = builder.build::(); + let mut timing = TimingTree::new("prove two_luts", Level::Debug); + let proof = prove(&data.prover_only, &data.common, pw, &mut timing)?; + data.verify(proof)?; + timing.print(); - #[test] - fn test_circuit_build_mock() { - // This code is taken from examples/fibonacci.rs - use crate::field::types::Field; - use crate::iop::witness::{PartialWitness, Witness, WitnessWrite}; - use crate::plonk::circuit_builder::CircuitBuilder; - use crate::plonk::circuit_data::CircuitConfig; - use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - - // The arithmetic circuit. - let initial_a = builder.add_virtual_target(); - let initial_b = builder.add_virtual_target(); - let mut prev_target = initial_a; - let mut cur_target = initial_b; - for _ in 0..99 { - let temp = builder.add(prev_target, cur_target); - prev_target = cur_target; - cur_target = temp; - } - - // Public inputs are the two initial values (provided below) and the result (which is generated). - builder.register_public_input(initial_a); - builder.register_public_input(initial_b); - builder.register_public_input(cur_target); - - // Provide initial values. - let mut pw = PartialWitness::new(); - pw.set_target(initial_a, F::ZERO); - pw.set_target(initial_b, F::ONE); - - let data = builder.mock_build::(); - let partition_witness = data.generate_witness(pw); - let result = partition_witness.try_get_target(cur_target).unwrap(); - assert_eq!(result, F::from_canonical_u64(3736710860384812976)); - } + Ok(()) +} - fn init_logger() -> anyhow::Result<()> { - let mut builder = env_logger::Builder::from_default_env(); - builder.format_timestamp(None); - builder.filter_level(LevelFilter::Debug); +fn init_logger() -> anyhow::Result<()> { + let mut builder = env_logger::Builder::from_default_env(); + builder.format_timestamp(None); + builder.filter_level(LevelFilter::Debug); - builder.try_init()?; - Ok(()) - } + builder.try_init()?; + Ok(()) }