From bf8780b27b4fa1ff4eb1b0586f1c3db500336a42 Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Fri, 3 Mar 2023 15:39:56 -0800 Subject: [PATCH] Move insertion to its own repo --- Cargo.toml | 2 +- README.md | 1 + insertion/Cargo.toml | 13 - insertion/LICENSE-APACHE | 202 --------------- insertion/LICENSE-MIT | 21 -- insertion/README.md | 13 - insertion/src/insert_gadget.rs | 112 --------- insertion/src/insertion_gate.rs | 424 -------------------------------- insertion/src/lib.rs | 12 - 9 files changed, 2 insertions(+), 798 deletions(-) delete mode 100644 insertion/Cargo.toml delete mode 100644 insertion/LICENSE-APACHE delete mode 100644 insertion/LICENSE-MIT delete mode 100644 insertion/README.md delete mode 100644 insertion/src/insert_gadget.rs delete mode 100644 insertion/src/insertion_gate.rs delete mode 100644 insertion/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index f52dd5e7..2d8e3402 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["ecdsa", "evm", "field", "insertion", "maybe_rayon", "plonky2", "starky", "u32", "util"] +members = ["ecdsa", "evm", "field", "maybe_rayon", "plonky2", "starky", "u32", "util"] [profile.release] opt-level = 3 diff --git a/README.md b/README.md index e6961d5e..4f07da0b 100644 --- a/README.md +++ b/README.md @@ -60,3 +60,4 @@ Plonky2's default hash function is Poseidon, configured with 8 full rounds, 22 p - [System Zero](https://github.com/mir-protocol/system-zero), a zkVM built on top of Starky (no longer maintained) - [Waksman](https://github.com/mir-protocol/waksman), Plonky2 gadgets for permutation checking using Waksman networks (no longer maintained) +- [Insertion](https://github.com/mir-protocol/insertion), Plonky2 gadgets for insertion into a list (no longer maintained) diff --git a/insertion/Cargo.toml b/insertion/Cargo.toml deleted file mode 100644 index 125e72e3..00000000 --- a/insertion/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "plonky2_insertion" -description = "Circuit implementation of list insertion" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = { version = "1.0.40", default-features = false } -plonky2 = { version = "0.1.2", default-features = false } - -[dev-dependencies] -plonky2 = { version = "0.1.2" } - diff --git a/insertion/LICENSE-APACHE b/insertion/LICENSE-APACHE deleted file mode 100644 index 1e5006dc..00000000 --- a/insertion/LICENSE-APACHE +++ /dev/null @@ -1,202 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - diff --git a/insertion/LICENSE-MIT b/insertion/LICENSE-MIT deleted file mode 100644 index 86d690b2..00000000 --- a/insertion/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2022 The Plonky2 Authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/insertion/README.md b/insertion/README.md deleted file mode 100644 index bb4e2d8a..00000000 --- a/insertion/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## License - -Licensed under either of - -* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - -at your option. - - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/insertion/src/insert_gadget.rs b/insertion/src/insert_gadget.rs deleted file mode 100644 index 1574d8fb..00000000 --- a/insertion/src/insert_gadget.rs +++ /dev/null @@ -1,112 +0,0 @@ -use alloc::vec; -use alloc::vec::Vec; - -use plonky2::field::extension::Extendable; -use plonky2::hash::hash_types::RichField; -use plonky2::iop::ext_target::ExtensionTarget; -use plonky2::iop::target::Target; -use plonky2::plonk::circuit_builder::CircuitBuilder; - -use crate::insertion_gate::InsertionGate; - -pub trait CircuitBuilderInsert, const D: usize> { - /// Inserts a `Target` in a vector at a non-deterministic index. - /// Note: `index` is not range-checked. - fn insert( - &mut self, - index: Target, - element: ExtensionTarget, - v: Vec>, - ) -> Vec>; -} - -impl, const D: usize> CircuitBuilderInsert - for CircuitBuilder -{ - fn insert( - &mut self, - index: Target, - element: ExtensionTarget, - v: Vec>, - ) -> Vec> { - let gate = InsertionGate::new(v.len()); - let row = self.add_gate(gate.clone(), vec![]); - - v.iter().enumerate().for_each(|(i, &val)| { - self.connect_extension( - val, - ExtensionTarget::from_range(row, gate.wires_original_list_item(i)), - ); - }); - self.connect(index, Target::wire(row, gate.wires_insertion_index())); - self.connect_extension( - element, - ExtensionTarget::from_range(row, gate.wires_element_to_insert()), - ); - - (0..=v.len()) - .map(|i| ExtensionTarget::from_range(row, gate.wires_output_list_item(i))) - .collect::>() - } -} - -#[cfg(test)] -mod tests { - use anyhow::Result; - use plonky2::field::types::{Field, Sample}; - use plonky2::iop::witness::PartialWitness; - use plonky2::plonk::circuit_data::CircuitConfig; - use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - use super::*; - - fn real_insert( - index: usize, - element: ExtensionTarget, - v: &[ExtensionTarget], - ) -> Vec> { - let mut res = v.to_vec(); - res.insert(index, element); - res - } - - fn test_insert_given_len(len_log: usize) -> Result<()> { - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - type FF = >::FE; - let len = 1 << len_log; - let config = CircuitConfig::standard_recursion_config(); - let pw = PartialWitness::new(); - let mut builder = CircuitBuilder::::new(config); - let v = (0..len - 1) - .map(|_| builder.constant_extension(FF::rand())) - .collect::>(); - - for i in 0..len { - let it = builder.constant(F::from_canonical_usize(i)); - let elem = builder.constant_extension(FF::rand()); - let inserted = real_insert(i, elem, &v); - let purported_inserted = builder.insert(it, elem, v.clone()); - - assert_eq!(inserted.len(), purported_inserted.len()); - - for (x, y) in inserted.into_iter().zip(purported_inserted) { - builder.connect_extension(x, y); - } - } - - let data = builder.build::(); - let proof = data.prove(pw)?; - - data.verify(proof) - } - - #[test] - fn test_insert() -> Result<()> { - for len_log in 1..3 { - test_insert_given_len(len_log)?; - } - Ok(()) - } -} diff --git a/insertion/src/insertion_gate.rs b/insertion/src/insertion_gate.rs deleted file mode 100644 index f9dc5fce..00000000 --- a/insertion/src/insertion_gate.rs +++ /dev/null @@ -1,424 +0,0 @@ -use alloc::boxed::Box; -use alloc::string::String; -use alloc::vec::Vec; -use alloc::{format, vec}; -use core::marker::PhantomData; -use core::ops::Range; - -use plonky2::field::extension::{Extendable, FieldExtension}; -use plonky2::field::types::Field; -use plonky2::gates::gate::Gate; -use plonky2::gates::util::StridedConstraintConsumer; -use plonky2::hash::hash_types::RichField; -use plonky2::iop::ext_target::ExtensionTarget; -use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; -use plonky2::iop::target::Target; -use plonky2::iop::wire::Wire; -use plonky2::iop::witness::{PartitionWitness, Witness, WitnessWrite}; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; - -/// A gate for inserting a value into a list at a non-deterministic location. -#[derive(Clone, Debug)] -pub(crate) struct InsertionGate, const D: usize> { - pub vec_size: usize, - _phantom: PhantomData, -} - -impl, const D: usize> InsertionGate { - pub fn new(vec_size: usize) -> Self { - Self { - vec_size, - _phantom: PhantomData, - } - } - - pub fn wires_insertion_index(&self) -> usize { - 0 - } - - pub fn wires_element_to_insert(&self) -> Range { - 1..D + 1 - } - - pub fn wires_original_list_item(&self, i: usize) -> Range { - debug_assert!(i < self.vec_size); - let start = (i + 1) * D + 1; - start..start + D - } - - fn start_of_output_wires(&self) -> usize { - (self.vec_size + 1) * D + 1 - } - - pub fn wires_output_list_item(&self, i: usize) -> Range { - debug_assert!(i <= self.vec_size); - let start = self.start_of_output_wires() + i * D; - start..start + D - } - - fn start_of_intermediate_wires(&self) -> usize { - self.start_of_output_wires() + (self.vec_size + 1) * D - } - - /// An intermediate wire for a dummy variable used to show equality. - /// The prover sets this to 1/(x-y) if x != y, or to an arbitrary value if - /// x == y. - pub fn wire_equality_dummy_for_round_r(&self, r: usize) -> usize { - self.start_of_intermediate_wires() + r - } - - // An intermediate wire for the "insert_here" variable (1 if the current index is the index at - /// which to insert the new value, 0 otherwise). - pub fn wire_insert_here_for_round_r(&self, r: usize) -> usize { - self.start_of_intermediate_wires() + (self.vec_size + 1) + r - } -} - -impl, const D: usize> Gate for InsertionGate { - fn id(&self) -> String { - format!("{self:?}") - } - - fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let insertion_index = vars.local_wires[self.wires_insertion_index()]; - let list_items = (0..self.vec_size) - .map(|i| vars.get_local_ext_algebra(self.wires_original_list_item(i))) - .collect::>(); - let output_list_items = (0..=self.vec_size) - .map(|i| vars.get_local_ext_algebra(self.wires_output_list_item(i))) - .collect::>(); - let element_to_insert = vars.get_local_ext_algebra(self.wires_element_to_insert()); - - let mut constraints = Vec::with_capacity(self.num_constraints()); - let mut already_inserted = F::Extension::ZERO; - for r in 0..=self.vec_size { - let cur_index = F::Extension::from_canonical_usize(r); - let difference = cur_index - insertion_index; - let equality_dummy = vars.local_wires[self.wire_equality_dummy_for_round_r(r)]; - let insert_here = vars.local_wires[self.wire_insert_here_for_round_r(r)]; - - // The two equality constraints. - constraints.push(difference * equality_dummy - (F::Extension::ONE - insert_here)); - constraints.push(insert_here * difference); - - let mut new_item = element_to_insert.scalar_mul(insert_here); - if r > 0 { - new_item += list_items[r - 1].scalar_mul(already_inserted); - } - already_inserted += insert_here; - if r < self.vec_size { - new_item += list_items[r].scalar_mul(F::Extension::ONE - already_inserted); - } - - // Output constraint. - constraints.extend((new_item - output_list_items[r]).to_basefield_array()); - } - - constraints - } - - fn eval_unfiltered_base_one( - &self, - vars: EvaluationVarsBase, - mut yield_constr: StridedConstraintConsumer, - ) { - let insertion_index = vars.local_wires[self.wires_insertion_index()]; - let list_items = (0..self.vec_size) - .map(|i| vars.get_local_ext(self.wires_original_list_item(i))) - .collect::>(); - let output_list_items = (0..=self.vec_size) - .map(|i| vars.get_local_ext(self.wires_output_list_item(i))) - .collect::>(); - let element_to_insert = vars.get_local_ext(self.wires_element_to_insert()); - - let mut already_inserted = F::ZERO; - for r in 0..=self.vec_size { - let cur_index = F::from_canonical_usize(r); - let difference = cur_index - insertion_index; - let equality_dummy = vars.local_wires[self.wire_equality_dummy_for_round_r(r)]; - let insert_here = vars.local_wires[self.wire_insert_here_for_round_r(r)]; - - // The two equality constraints. - yield_constr.one(difference * equality_dummy - (F::ONE - insert_here)); - yield_constr.one(insert_here * difference); - - let mut new_item = element_to_insert.scalar_mul(insert_here); - if r > 0 { - new_item += list_items[r - 1].scalar_mul(already_inserted); - } - already_inserted += insert_here; - if r < self.vec_size { - new_item += list_items[r].scalar_mul(F::ONE - already_inserted); - } - - // Output constraint. - yield_constr.many((new_item - output_list_items[r]).to_basefield_array()); - } - } - - fn eval_unfiltered_circuit( - &self, - builder: &mut CircuitBuilder, - vars: EvaluationTargets, - ) -> Vec> { - let insertion_index = vars.local_wires[self.wires_insertion_index()]; - let list_items = (0..self.vec_size) - .map(|i| vars.get_local_ext_algebra(self.wires_original_list_item(i))) - .collect::>(); - let output_list_items = (0..=self.vec_size) - .map(|i| vars.get_local_ext_algebra(self.wires_output_list_item(i))) - .collect::>(); - let element_to_insert = vars.get_local_ext_algebra(self.wires_element_to_insert()); - - let mut constraints = Vec::with_capacity(self.num_constraints()); - let mut already_inserted = builder.constant_extension(F::Extension::ZERO); - for r in 0..=self.vec_size { - let cur_index_ext = F::Extension::from_canonical_usize(r); - let cur_index = builder.constant_extension(cur_index_ext); - - let difference = builder.sub_extension(cur_index, insertion_index); - let equality_dummy = vars.local_wires[self.wire_equality_dummy_for_round_r(r)]; - let insert_here = vars.local_wires[self.wire_insert_here_for_round_r(r)]; - - // The two equality constraints. - let prod = builder.mul_extension(difference, equality_dummy); - let one = builder.constant_extension(F::Extension::ONE); - let not_insert_here = builder.sub_extension(one, insert_here); - let first_equality_constraint = builder.sub_extension(prod, not_insert_here); - constraints.push(first_equality_constraint); - - let second_equality_constraint = builder.mul_extension(insert_here, difference); - constraints.push(second_equality_constraint); - - let mut new_item = builder.scalar_mul_ext_algebra(insert_here, element_to_insert); - if r > 0 { - new_item = builder.scalar_mul_add_ext_algebra( - already_inserted, - list_items[r - 1], - new_item, - ); - } - already_inserted = builder.add_extension(already_inserted, insert_here); - if r < self.vec_size { - let not_already_inserted = builder.sub_extension(one, already_inserted); - new_item = builder.scalar_mul_add_ext_algebra( - not_already_inserted, - list_items[r], - new_item, - ); - } - - // Output constraint. - let diff = builder.sub_ext_algebra(new_item, output_list_items[r]); - constraints.extend(diff.to_ext_target_array()); - } - - constraints - } - - fn generators(&self, row: usize, _local_constants: &[F]) -> Vec>> { - let gen = InsertionGenerator:: { - row, - gate: self.clone(), - }; - vec![Box::new(gen.adapter())] - } - - fn num_wires(&self) -> usize { - self.wire_insert_here_for_round_r(self.vec_size) + 1 - } - - fn num_constants(&self) -> usize { - 0 - } - - fn degree(&self) -> usize { - 2 - } - - fn num_constraints(&self) -> usize { - (self.vec_size + 1) * (2 + D) - } -} - -#[derive(Debug)] -struct InsertionGenerator, const D: usize> { - row: usize, - gate: InsertionGate, -} - -impl, const D: usize> SimpleGenerator for InsertionGenerator { - fn dependencies(&self) -> Vec { - let local_target = |column| Target::wire(self.row, column); - - let local_targets = |columns: Range| columns.map(local_target); - - let mut deps = vec![local_target(self.gate.wires_insertion_index())]; - deps.extend(local_targets(self.gate.wires_element_to_insert())); - for i in 0..self.gate.vec_size { - deps.extend(local_targets(self.gate.wires_original_list_item(i))); - } - deps - } - - fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { - let local_wire = |column| Wire { - row: self.row, - column, - }; - - let get_local_wire = |column| witness.get_wire(local_wire(column)); - - let get_local_ext = |wire_range: Range| { - debug_assert_eq!(wire_range.len(), D); - let values = wire_range.map(get_local_wire).collect::>(); - let arr = values.try_into().unwrap(); - F::Extension::from_basefield_array(arr) - }; - - // Compute the new vector and the values for equality_dummy and insert_here - let vec_size = self.gate.vec_size; - let orig_vec = (0..vec_size) - .map(|i| get_local_ext(self.gate.wires_original_list_item(i))) - .collect::>(); - let to_insert = get_local_ext(self.gate.wires_element_to_insert()); - let insertion_index_f = get_local_wire(self.gate.wires_insertion_index()); - - let insertion_index = insertion_index_f.to_canonical_u64() as usize; - debug_assert!( - insertion_index <= vec_size, - "Insertion index {} is larger than the vector size {}", - insertion_index, - vec_size - ); - - let mut new_vec = orig_vec; - new_vec.insert(insertion_index, to_insert); - - let mut equality_dummy_vals = Vec::new(); - for i in 0..=vec_size { - equality_dummy_vals.push(if i == insertion_index { - F::ONE - } else { - (F::from_canonical_usize(i) - insertion_index_f).inverse() - }); - } - - let mut insert_here_vals = vec![F::ZERO; vec_size]; - insert_here_vals.insert(insertion_index, F::ONE); - - for i in 0..=vec_size { - let output_wires = self.gate.wires_output_list_item(i).map(local_wire); - out_buffer.set_ext_wires(output_wires, new_vec[i]); - let equality_dummy_wire = local_wire(self.gate.wire_equality_dummy_for_round_r(i)); - out_buffer.set_wire(equality_dummy_wire, equality_dummy_vals[i]); - let insert_here_wire = local_wire(self.gate.wire_insert_here_for_round_r(i)); - out_buffer.set_wire(insert_here_wire, insert_here_vals[i]); - } - } -} - -#[cfg(test)] -mod tests { - use anyhow::Result; - use plonky2::field::goldilocks_field::GoldilocksField; - use plonky2::field::types::Sample; - use plonky2::gates::gate_testing::{test_eval_fns, test_low_degree}; - use plonky2::hash::hash_types::HashOut; - use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - - use super::*; - - #[test] - fn wire_indices() { - let gate = InsertionGate:: { - vec_size: 3, - _phantom: PhantomData, - }; - - assert_eq!(gate.wires_insertion_index(), 0); - assert_eq!(gate.wires_element_to_insert(), 1..5); - assert_eq!(gate.wires_original_list_item(0), 5..9); - assert_eq!(gate.wires_original_list_item(2), 13..17); - assert_eq!(gate.wires_output_list_item(0), 17..21); - assert_eq!(gate.wires_output_list_item(3), 29..33); - assert_eq!(gate.wire_equality_dummy_for_round_r(0), 33); - assert_eq!(gate.wire_equality_dummy_for_round_r(3), 36); - assert_eq!(gate.wire_insert_here_for_round_r(0), 37); - assert_eq!(gate.wire_insert_here_for_round_r(3), 40); - } - - #[test] - fn low_degree() { - test_low_degree::(InsertionGate::new(4)); - } - - #[test] - fn eval_fns() -> Result<()> { - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - test_eval_fns::(InsertionGate::new(4)) - } - - #[test] - fn test_gate_constraint() { - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - type FF = >::FE; - - /// Returns the local wires for an insertion gate given the original vector, element to - /// insert, and index. - fn get_wires(orig_vec: Vec, insertion_index: usize, element_to_insert: FF) -> Vec { - let vec_size = orig_vec.len(); - - let mut v = vec![F::from_canonical_usize(insertion_index)]; - v.extend(element_to_insert.0); - for j in 0..vec_size { - v.extend(orig_vec[j].0); - } - - let mut new_vec = orig_vec; - new_vec.insert(insertion_index, element_to_insert); - let mut equality_dummy_vals = Vec::new(); - for i in 0..=vec_size { - equality_dummy_vals.push(if i == insertion_index { - F::ONE - } else { - (F::from_canonical_usize(i) - F::from_canonical_usize(insertion_index)) - .inverse() - }); - } - let mut insert_here_vals = vec![F::ZERO; vec_size]; - insert_here_vals.insert(insertion_index, F::ONE); - - for j in 0..=vec_size { - v.extend(new_vec[j].0); - } - v.extend(equality_dummy_vals); - v.extend(insert_here_vals); - - v.iter().map(|&x| x.into()).collect() - } - - let orig_vec = vec![FF::rand(); 3]; - let insertion_index = 1; - let element_to_insert = FF::rand(); - let gate = InsertionGate:: { - vec_size: 3, - _phantom: PhantomData, - }; - let vars = EvaluationVars { - local_constants: &[], - local_wires: &get_wires(orig_vec, insertion_index, element_to_insert), - public_inputs_hash: &HashOut::rand(), - }; - - assert!( - gate.eval_unfiltered(vars).iter().all(|x| x.is_zero()), - "Gate constraints are not satisfied." - ); - } -} diff --git a/insertion/src/lib.rs b/insertion/src/lib.rs deleted file mode 100644 index e71919dd..00000000 --- a/insertion/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![allow(clippy::new_without_default)] -#![allow(clippy::too_many_arguments)] -#![allow(clippy::type_complexity)] -#![allow(clippy::len_without_is_empty)] -#![allow(clippy::needless_range_loop)] -#![allow(clippy::return_self_not_must_use)] -#![no_std] - -extern crate alloc; - -pub mod insert_gadget; -pub mod insertion_gate;